⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 16f884.c

📁 PWM输出产生正玄波后经AD采集电压控制输出幅度,并显示电压等状态
💻 C
📖 第 1 页 / 共 2 页
字号:
/*功能描述
启动时,由按键选择程序代码或进入设置子程序(读写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 + -