📄 16f884.c
字号:
/*功能描述
启动时,由按键选择程序代码或进入设置子程序(读写EEPROM程序需完善)
EEPROM读取完后载入EEPROM数据到RAM,初始显示代码,计算正玄表数据
正常工作时,根据正玄表产生PWM占空比,占空比为:PR2/2+range*正玄值
range是由PID控制更新的数据
正常工作过程中按下上下键,输出正玄波频率发生变化,按下退出键时,关断输出,再次按下退出键时,进入程序选择
正常工作过程中按下上下键,输出正玄波频率发生变化,按下退出键时,关断输出,按下OK键时,PWM正常输出
INT中断采集转速脉冲,连续采集N次后计算均值,由BCD转换程序后,更新显示缓冲数据
AD中断采集正玄波电压,以及外加的峰值取样电压,多路选择开关动态切换与2种状态,注意峰值取样电压需要大于1.45833V
该功能由比较器实现;
*/
#include<pic.h>
#include<pic16f887.h>//MCU选择16F884
#include<math.h>
__CONFIG(WDTEN & PWRTEN & MCLREN & DUNPROTECT & CP & HS & BORDIS & BORV21 & WP2 & DEBUGDIS & LVPDIS & FCMDIS & IESODIS);
#define Nop() asm("nop");
#define clrwdt() asm("clrwdt");
#define MIN_RANGE 9
#define MAX_RANGE 512
#define P_AC 5
#define I_AC 2
#define D_AC 1
#define work_led RB1
#define vpp_discharge RE1
#define pi 3.14159265
void initial_io(void);
void initial_tmr0(void);
void display(void);
void updata_data_buffer(void);
void key_identify(void);
void initial_pwm(void);
void initial_ad(void);
void intital_other(void);
void READEEPROM(unsigned char);
void WRITEEEPROM(unsigned char);
void temp_dis_buffer0(unsigned char,unsigned char,unsigned char,unsigned char);
void temp_dis_buffer1(unsigned char,unsigned char,unsigned char,unsigned char);
void temp_dis_buffer2(unsigned char,unsigned char,unsigned char,unsigned char);
void BIN_BCD_COUNTER(unsigned int);
void re_start_init(void);
unsigned int sin_table_calculate(unsigned char ,unsigned char);
bank1 unsigned char display_buffer[12],dis_i;//待显示的数据缓冲及指针
bank1 unsigned char EE_ZHUANSU[3],EE_VPP[3],EE_VOL[3];
bank2 unsigned char pwm_data[50];//通过计算生成正玄表
const unsigned char display_data[22]={63,48,91,79,102,109,125,7,127,111,115,83,119,109,121,49,113,56,0,119,62,55 };
/*0 1 2 3 4 5 6 7 8 9 P ? A S E T F L 空 R U N*/
/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21*/
bit R_W_OVER,RUN,RAB,READ_EE,WRITE_EE,ext,up,down,ok,ms_2,re_start,INT_OVER,update_zhuansu;
bit AD_VOL,AD_OVER,PWM_LAST,zhengbanzhou,update_range,start,check_vpp_over;
unsigned char T1_CARRY,INT_COUNTER=0,temp_i,cal_vpp_over,ms2_counter,i=0,dianshu,zhouqi;
volatile unsigned char key_data,key_data_temp,point=0;
bank2 volatile unsigned char zhuangtai=3,T1H[10],T1L[10];
bank1 volatile unsigned int AD_VOL_SUM=0,AD_VPP_SUM=0,new_pdc=99,range,RDY_RANGE=70;//RDY_RANGE{9--512}幅度控制
bank1 volatile unsigned int SAV_AD_VOL_SUM,SAV_AD_VPP_SUM;
bank1 unsigned int zhuansu[10],temp,result_data;
bank1 int AC_err,AC_errr[2],zhengliang=0,Sum_err=0;
bank1 unsigned char BCD_DATA[4],AD_VPP,set_zhuansu;
bank1 unsigned char rpm_h,rpm_l,voltage_h,voltage_l;//EEPROM数据内部预存周期及电压;
void main()
{
OSCCON=0x78;
clrwdt();
initial_io();
initial_tmr0();
zhengbanzhou=1;
temp_dis_buffer0(0,0,0,11);//初始化显示000?
RUN=0;RAB=0;
while(1)
{
while(!RUN)//
{clrwdt();
while(!R_W_OVER)//
{ clrwdt();
if(RAB)
{key_identify();
RAB=0;
if(up)
{i++;if(i>10)i=0;up=0;}
else if(down)
{i--;if(i>254)i=10;down=0;}
else if(ext)
{ext=0;}
else if(ok)
{if(i==9)
WRITE_EE=1;
else READ_EE=1;ok=0;}
else RAB=0;ok=0;
if(i==10) temp_dis_buffer0(13,14,15,11);//显示SET?
else temp_dis_buffer0(0,0,i,11); }
if(WRITE_EE)
{WRITE_EE=0;R_W_OVER=0;WRITEEEPROM(i);}
if(READ_EE)
{READ_EE=0;READEEPROM(i);R_W_OVER=1;temp_dis_buffer0(13,15,12,11);}//显示STA?;
if(ms_2)
{display();ms_2=0;}///3.2MS
}//{while(!R_W_OVER)
if(RAB)
{key_identify();
RAB=0;
if(ok){RUN=1;ok=0;}
else if(ext)
{R_W_OVER=0;ext=0;temp_dis_buffer0(0,0,0,11);
temp_dis_buffer1(18,18,18,18);temp_dis_buffer2(18,18,18,18);i=0;}
else if(up)up=0;
else if(down)down=0; }//if(RAB)
if(ms_2)
{display();ms_2=0;}
}//while(!RUN)
temp_dis_buffer2(19,20,21,21);////显示RUNN
temp_dis_buffer1(0,0,0,0);
temp_dis_buffer0(0,0,0,0);
/////////初始化AD,PWM等想关
set_zhuansu=sin_table_calculate(50,50);
BIN_BCD_COUNTER(set_zhuansu);
temp_dis_buffer2(BCD_DATA[3],BCD_DATA[2],BCD_DATA[1],BCD_DATA[0]);//更新显示转速数据
re_start_init();work_led=1;
while(RUN)//
{ clrwdt();
while(re_start)//测试完毕后的重新启动检测
{clrwdt();
if(PWM_LAST&&AD_OVER)//更新幅度寄存器
{SAV_AD_VOL_SUM=SAV_AD_VOL_SUM>>5;
AC_err=AD_VPP-SAV_AD_VOL_SUM;// VPP=3.5V;196
if(start)
{RDY_RANGE+=3;
if(RDY_RANGE>510)RDY_RANGE=510;
if(AC_err<70)start=0;}//开机时电压缓慢输出,稳定后受PID控制
else
{if(AC_err>50)AC_err=50;
if(AC_err<-50)AC_err=-50;
zhengliang=P_AC*AC_err+I_AC*Sum_err+D_AC*(AC_errr[1]-AC_errr[0]);//PID
zhengliang=zhengliang>>3;
AC_errr[1]=AC_errr[0];
AC_errr[0]=AC_err;
if(AC_err!=0)
Sum_err+=AC_err;//偏差累积
else Sum_err=0;
if(Sum_err>50)Sum_err=50;
if(Sum_err<-50)Sum_err=-50;
if(zhengliang>10)zhengliang=10;
if(zhengliang<-5) zhengliang=zhengliang+(zhengliang>>1);//卸载时,防止电压上冲,2.5倍速控制
RDY_RANGE=RDY_RANGE+zhengliang+(zhengliang>>1);
if(RDY_RANGE<MIN_RANGE)RDY_RANGE=MIN_RANGE;//限制最小幅度
if(RDY_RANGE>MAX_RANGE)RDY_RANGE=MAX_RANGE;//限制最大幅度
}
PWM_LAST=0;
if(cal_vpp_over){AD_OVER=0;cal_vpp_over=0;}
} /////////////////////////////////////////////
if(INT_OVER)//转速计算
{INT_OVER=0;
for(temp_i=0;temp_i<9;temp_i++)
zhuansu[temp_i]=T1H[temp_i]<<8+T1L[temp_i];
for(temp_i=0;temp_i<9;temp_i++)
{if(zhuansu[temp_i]>zhuansu[9])
{temp=zhuansu[9];zhuansu[9]=zhuansu[temp_i];zhuansu[temp_i]=temp;}//取最大值放入第9位
if(zhuansu[temp_i]<zhuansu[8])
{temp=zhuansu[8];zhuansu[8]=zhuansu[temp_i];zhuansu[temp_i]=temp;}//取最小值放入第8位
update_zhuansu=1;INTE=0;//关INT中断
}
}
if(update_zhuansu)//更新转速显示缓冲数据
{
update_zhuansu=0;result_data=0;
for(temp_i=0;temp_i<7;temp_i++)
result_data+=zhuansu[temp_i]>>3;//取平均值
result_data=37500000/result_data;
if(result_data<9999)
{BIN_BCD_COUNTER(result_data);//BCD码切换
temp_dis_buffer0(BCD_DATA[3],BCD_DATA[2],BCD_DATA[1],BCD_DATA[0]);}//更新转速缓冲区数据
else temp_dis_buffer0(14,14,14,14);//转速超出显示范围则显示EEEE
}
if(AD_OVER)//VPP计算
{
SAV_AD_VPP_SUM=SAV_AD_VPP_SUM>>5;
if(SAV_AD_VPP_SUM<9999)
{BIN_BCD_COUNTER(SAV_AD_VPP_SUM);
temp_dis_buffer1(BCD_DATA[3],BCD_DATA[2],BCD_DATA[1],BCD_DATA[0]);}//更新转速缓冲区数据
else temp_dis_buffer1(14,14,14,14);//电压超出显示范围则显示EEEE
if(PWM_LAST==0) AD_OVER=0;
else cal_vpp_over=1; }
if(ms_2)
{display();ms_2=0;}
if(RAB)
{ RAB=0;key_identify();
if(ext)
{re_start=0;ext=0;TMR2ON=0;ADIE=0;ADIF=0;TMR2IF=0;INTE=0;CCP1CON=0;work_led=0;C1ON=0;
temp_dis_buffer2(13,15,0,10);//STOP
temp_dis_buffer1(13,15,0,10);//STOP
temp_dis_buffer0(13,15,12,11);//STA?
}
else if(up)//zhuangtai是指输出正玄波的频率,更改的是pwm频率,占空比点数不变
{up=0;if(zhuangtai==0)zhuangtai=0;else zhuangtai--;T2CON=(zhuangtai<<3)+4;}
else if(down)
{down=0;if(zhuangtai==0xf)zhuangtai=0xf;else zhuangtai++;T2CON=(zhuangtai<<3)+4;}
else if(ok)ok=0; }
}//while(re_start)
if(RAB)
{RAB=0;key_identify();
if(ok)
{ok=0;
BIN_BCD_COUNTER(set_zhuansu);
temp_dis_buffer2(BCD_DATA[3],BCD_DATA[2],BCD_DATA[1],BCD_DATA[0]);//更新显示转速数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -