MQ5可以用按键模拟输入量,程序有的,提点建议,感谢各位大佬
为什么12单片机实物可以显示,但是用到51的仿真上温度也读取不了了啊
单片机源程序如下:
- #include "intrins.h"
- #include "temp.h"
- #include "lcd.h"
- #define FOSC 11059200L
- typedef unsigned char BYTE;
- typedef unsigned int WORD;
- idata unsigned char str1[]="T:";
- idata unsigned char str2[]="CO:";
- BYTE code smgduan[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
- 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//显示0~F的值
- /*12单片机基础寄存器负责产生pwm */
- sfr CCON = 0xD8; //PCA control register
- sbit CCF0 = CCON^0; //PCA module-0 interrupt flag
- sbit CCF1 = CCON^1; //PCA module-1 interrupt flag
- sbit CR = CCON^6; //PCA timer run control bit
- sbit CF = CCON^7; //PCA timer overflow flag
- sfr CMOD = 0xD9; //PCA mode register
- sfr CL = 0xE9; //PCA base timer LOW
- sfr CH = 0xF9; //PCA base timer HIGH
- sfr CCAPM0 = 0xDA; //PCA module-0 mode register
- sfr CCAP0L = 0xEA; //PCA module-0 capture register LOW
- sfr CCAP0H = 0xFA; //PCA module-0 capture register HIGH
- sfr CCAPM1 = 0xDB; //PCA module-1 mode register
- sfr CCAP1L = 0xEB; //PCA module-1 capture register LOW
- sfr CCAP1H = 0xFB; //PCA module-1 capture register HIGH
- sfr PCAPWM0 = 0xf2;
- sfr PCAPWM1 = 0xf3;
- /*12单片机基础寄存器负责数模转换*/
- sfr ADC_CONTR = 0xBC; //ADC control register
- sfr ADC_RES = 0xBD; //ADC high 8-bit result register
- sfr ADC_LOW2 = 0xBE; //ADC low 2-bit result register
- sfr P1ASF = 0x9D; //P1 secondary function control register
- #define ADC_POWER 0x80 //ADC power control bit
- #define ADC_FLAG 0x10 //ADC complete flag
- #define ADC_START 0x08 //ADC start control bit
- #define ADC_SPEEDLL 0x00 //420 clocks
- #define ADC_SPEEDL 0x20 //280 clocks
- #define ADC_SPEEDH 0x40 //140 clocks
- #define ADC_SPEEDHH 0x60 //70 clocks
- sbit key0=P3^0;
- sbit key1=P3^1;
- sbit key3=P3^2;
- sbit key4=P3^3;
- sbit key5=P3^4;
- sbit key6=P3^5;
- sbit beep=P3^6;
- BYTE flag=0,flag2=0,ppm=0,c=230,cw=0;//轮回扫描
- int pwm_pid,temp_1;
- WORD yus=150,baoj=190;
- void Delay(WORD n)
- {
- WORD x;
- while (n--)
- {
- x = 50;
- while (x--);
- }
- }
- void pwm_init()//初始化12C5A60单片机pwm寄存器
- {
-
- CCON = 0; //Initial PCA control register
- //PCA timer stop running
- //Clear CF flag
- //Clear all module interrupt flag
- CL = 0; //Reset PCA base timer
- CH = 0;
- CMOD = 0x02; //Set PCA timer clock source as Fosc/2
- //Disable PCA timer overflow interrupt
- CCAP0H = CCAP0L = 0xff; //PWM0 port output 50% duty cycle square wave
- CCAPM0 = 0x42; //PCA module-0 work in 8-bit PWM mode and no PCA interrupt
- CR = 1; //PCA timer start run
- }
- void pwm_set(WORD x)//调节pwm占空比
- {
- CCAP0H=x; //设置比较值
- CCAP0L=x;
- }
- /*----------------------------
- 数模转换获取通道1
- ----------------------------*/
- BYTE GetADCResult(BYTE ch)//获取adc数值这里使用P1.1引脚GetADCResult(1)
- {
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- _nop_(); //Must wait before inquiry
- _nop_();
- _nop_();
- _nop_();
- while (!(ADC_CONTR & ADC_FLAG));//Wait complete flag
- ADC_CONTR &= ~ADC_FLAG; //Close ADC
- return ADC_RES; //Return ADC result
- }
- /*----------------------------
- 数模转换初始化
- ----------------------------*/
- void InitADC()
- {
- P1ASF = 0x02; //Open 8 channels ADC function
- ADC_RES = 0; //Clear previous result
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
- Delay(2); //ADC power-on and delay
- }
- /*pid高级处理*/
- int Position_PID (int Encoder,int Target) //差速PID控制器//这里Encoder=实际CO浓度,Target=预期CO浓度;
- {
- float Position_KP=1.75,Position_KI=0.26,Position_KD=0.012;
- //Position_KI=c*0.01;
- static float Bias,Pwm,Integral_bias,Last_Bias;
- if(Encoder<=5)
- Integral_bias=0;
- Bias=Encoder-Target; //计算偏差
- Integral_bias+=Bias; //求出偏差的积分
- Pwm=Position_KP*Bias+Position_KI*Integral_bias+Position_KD*(Bias-Last_Bias); //位置式PID控制器
- Last_Bias=Bias; //保存上一次偏差
- return Pwm; //返回PWM值
- }
- int datapros(int temp) //温度的计算
- {
- float tp;
- if(temp< 0) //当温度值为负数
- {
- // -
- //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
- temp=temp-1;
- temp=~temp;
- tp=temp;
- temp=tp*0.0625*100+0.5;
- //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
- //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
- //算加上0.5,还是在小数点后面。
- }
- else
- {
- tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
- //如果温度是正的那么,那么正数的原码就是补码它本身
- temp=tp*0.0625*100+0.5;
- //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
- //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
- //算加上0.5,还是在小数点后面。
- }
- return temp;
- }
- void main()
- {
- pwm_init();//初始化pwm
- InitADC();
- Init_DS18B20();
- LcdInit();
- beep=0;//初始化关闭蜂鸣器
- LcdShowStr(0,0,str1);
- LcdShowStr(0,1,str2);
- DisplayOneChar(7,0,'C');
- DisplayOneChar(15,0,'C');
- Display_Ref_T(350);//预设温度
- P2=~smgduan[0];
- while (1)
- {
- ppm=GetADCResult(1);
- pwm_pid=Position_PID(ppm-135,yus-150);//传入pid变量
-
- if(pwm_pid>235)//限幅
- pwm_pid=235;
- if(pwm_pid<1)//限幅
- pwm_pid=1;
- pwm_set(pwm_pid);
-
-
-
-
-
-
- if(!key0)
- {
- Delay(100);
- if(!key0)
- {
- cw--;
- while(!key0);
- if(cw<1)
- cw=0;
- }
-
- }
- if(!key1)
- {
- Delay(100);
- if(!key1)
- {
- cw++;
- while(!key1);
- if(cw>9)
- cw=9;
- }
-
- }
-
- P2=~smgduan[cw];
-
- if(!key3)
- {
- Delay(100);
- if(!key3)
- {
- yus--;
- while(!key3);
- if(yus<1)
- yus=0;
- }
-
- }
- if(!key4)
- {
- Delay(100);
- if(!key4)
- {
- yus++;
- while(!key4);
- }
-
- }
-
- if(!key5)
- {
- Delay(100);
- if(!key5)
- {
- baoj--;
- while(!key5);
- if(baoj<1)
- baoj=0;
- }
-
- }
- if(!key6)
- {
- Delay(100);
- if(!key6)
- {
- baoj++;
- while(!key6);
- }
-
- }
-
-
-
- if(flag==10)
- {
- if(temp_1>350||ppm>baoj)
- {
- beep=1;
- }else
- {
- beep=0;
- }
- }
- if(flag==20)
- {
- temp_1=datapros(Ds18b20ReadTemp())*0.1;
- ppm=GetADCResult(1);
-
- }
- if(flag2==10)
- {
- Delay(100);
- Display_T(temp_1);//实时温度
- Display_Pre_CO(yus);
- Display_Warn_CO(baoj);
- Delay(100);
- if(245<ppm)
- ppm=240;
- Display_CO(ppm);
- }
-
- flag++;
- if(flag==21)
- {
- flag=0;
- flag2++;
- if(flag2==20)
- {
- flag2=0;
- }
- }
-
- }
- }
复制代码 |