此课设基于ADC0832和压力传感器MPX4115,把传感器的值通过运放电路调整,送入AD转换,再经单片机编程实现压力的测量与显示;涉及PWM控制,串口,按键控制PWM占空比等。
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- #include<math.h>
- #include<absacc.h>
- #include<intrins.h>
- #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- #define BUSY 0x80 //常量定义
- #define DATAPORT P0
- sbit Alarm_led_red =P1^6; //超过压力表量程最大值红灯报警
- sbit Alarm_led_green=P1^7; //低于压力表量程最小值路灯报警
- sbit LCM_RS=P2^0;
- sbit LCM_RW=P2^1;
- sbit LCM_EN=P2^2;
-
- sbit k1=P2^3;
- sbit k2=P2^4;
- sbit k3=P2^5;
- sbit k4=P2^6;
- sbit ADCS =P3^5; //ADC0832 chip seclect
- sbit ADCLK =P3^6; //ADC0832 clock signal
- sbit ADDI =P3^7; //ADC0832 k in
- sbit ADDO =P3^7; //ADC0832 k out
-
- uchar ad_data; //采样值存储
- unsigned char ad_alarm; //报警值存储单元
- unsigned char press_bai=0; //显示值百位
- unsigned char press_shi=0; //显示值十位
- unsigned char press_ge=0; //显示值个位
- unsigned char press_dot=0; //显示值十分位
- uchar code str0[]={"Press: . kpa. "};
- uchar code str1[]={"ZKB: 00 % "};
- uchar ZKB[2];
- uchar HighRH = 0;
- uchar HighRL = 0;
- uchar LowRH = 0;
- uchar LowRL = 0;
- unsigned int a;
- uchar rate;
- sbit PWMOUT = P1^0;
- uchar step, rec_data,flag;
- uchar Adc0832(unsigned char channel);
- void delay(uint);
- void lcd_wait(void); //检测忙子程序
- void delay_LCM(uint); //延时子程序
- void initLCM(void); //初始化子程序
- void WriteCommandLCM(uchar WCLCM,uchar BusyC); //写指令到LCM子程序
- void WriteDataLCM(uchar WDLCM); //写数据到LCM子程序
- void DisplayOneChar(uchar X,uchar Y,uchar DData); //显示指定坐标的一个字符子函数
- void DisplayListChar(uchar X,uchar Y,uchar code *DData); //显示指定坐标的一串字符子函数
- void display(void); //系统显示子函数
- void ConfigPWM(uchar rate);
- void alarm(void);
- void data_pro(void);
- void ConfigPWM(uchar dc);
- void key_setPWM(void);
- uchar duty_cycle(uchar ad_data);
- void display_zkb(void);
- void zkb_pro(void);
- void chuankou_init();
- /**********main funcation************/
- void main(void)
- {
-
-
- delay(50);
- initLCM( );
- chuankou_init();
- WriteCommandLCM(0x01,1); //清屏显示
- DisplayListChar(0,0,str0);
- DisplayListChar(0,1,str1);
-
- delay(10);
- PWMOUT=1;
- EA = 1;
- ConfigPWM(rate);
- while(1)
- {
- ad_data =Adc0832(0); //采样值存储单元初始化为0
- alarm();
- data_pro();
- zkb_pro();
- display();
- display_zkb();
- a=duty_cycle(ad_data);
- ConfigPWM(a);
- key_setPWM();
- if(a!=rate)
- {
- ConfigPWM(rate);
- }
-
- if(RI==1)//串口
- {
- RI=0;
- rec_data=SBUF;
- step=rec_data*2;
- SBUF=rec_data;
- }
-
- }
- }
- void TIME_INIT()
- {
- TMOD|=0X02;
- IT0=1;
- IT1=1;
- TR1=1;
- EX1=1;
- EX0=1;
- ET0=1;
- TR0=1;
- EA=1;
- }
- void chuankou_init()
- {
- SCON|=0X50;
- TMOD|=0X20;
- PCON|=0X80;
- TH1=0XFA;
- TL1=0XFA;
- TR1=1;
-
- SM0=0;
- SM1=1;
- REN=1;
-
- EA=1;
- ES=1;
- }
-
- /********延时K*1ms,12.000mhz**********/
- void delay(uint x)
- {
- uchar i;
- while(x--)
- {
- for(i = 0;i < 120;i++)
- {;}
- }
- }
- /**********写数据到ICM子函数************/
- void WriteCommandLCM(uchar WCLCM,uchar BusyC)
- {
- if(BusyC)
- lcd_wait(); //检测忙信号
- DATAPORT=WCLCM;
- LCM_RS=0;
- LCM_RW=0;
- LCM_EN=1;
- _nop_();
- _nop_();
- _nop_();
- LCM_EN=0;
-
- }
- /**********????LCM???************/
- void WriteDataLCM(uchar WDLCM)
- {
- lcd_wait( );
- DATAPORT=WDLCM;
- LCM_RS=1; //选中数据寄存器
- LCM_RW=0; //写模式
- LCM_EN=1;
- _nop_();
- _nop_();
- _nop_();
- LCM_EN=0;
- }
- /***********lcm内部等待程序*************/
- void lcd_wait(void)
- {
- DATAPORT=0xff; //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
- LCM_EN=1;
- LCM_RS=0;
- LCM_RW=1;
- _nop_();
- _nop_();
- _nop_();
- while(DATAPORT&BUSY)
- {
- LCM_EN=0;
- _nop_();
- _nop_();
- LCM_EN=1;
- _nop_();
- _nop_();
- }
- LCM_EN=0;
-
- }
- /**********LCM??????***********/
- void initLCM( )
- {
- DATAPORT=0;
- delay(15);
- WriteCommandLCM(0x38,0); //三次显示模式,不检测忙信号
- delay(5);
- WriteCommandLCM(0x38,0);
- delay(5);
- WriteCommandLCM(0x38,0);
- delay(5);
- WriteCommandLCM(0x38,1); //8bit数据传送,两行显示,5*7字型,检测忙信号
- WriteCommandLCM(0x08,1); //关闭显示,检测忙信号
- WriteCommandLCM(0x01,1); //清屏,检测忙信号
- WriteCommandLCM(0x06,1); //显示光标右移设置
- WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
- }
- /****??????????????****/
- void DisplayOneChar(uchar X,uchar Y,uchar DData)
- {
- Y&=1;
- X&=15;
- if(Y)X|=0x40; //若Y为1(显示第二行)地址译码+0x40
- X|=0x80; //指令码为地址码+0x80
- WriteCommandLCM(X,0);
- WriteDataLCM(DData);
- }
- /*******??????????????*****/
-
- void DisplayListChar(uchar X,uchar Y,uchar code *DData)
- {
- uchar ListLength=0;
- Y&=0x01;
- X&=0x0f;
- while(X<16)
- {
- DisplayOneChar(X,Y,DData[ListLength]);
- ListLength++;
- X++;
- }
- }
- /*****************???????*****************/
- void display(void)
- {
- WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
- DisplayListChar(0,0,str0);
- DisplayListChar(0,1,str1);
- DisplayOneChar(7,0,press_bai+0x30);
- DisplayOneChar(8,0,press_shi+0x30);
- DisplayOneChar(9,0,press_ge +0x30);
- DisplayOneChar(10,0,056);
- DisplayOneChar(11,0,press_dot+0x30);
- }
- void display_zkb(void)
- {
- WriteCommandLCM(0x0c,1);
- DisplayListChar(0,1,str1);
- DisplayOneChar(7,1,ZKB[0]+0x30);
- DisplayOneChar(8,1,ZKB[1]+0x30);
- delay(1000); //稳定显示
- }
- /************?ADC0832??************/
- uchar Adc0832(unsigned char channel) //AD转换,并返回结果
- {
- uchar i=0;
- uchar j;
- uint dat=0;
- uchar ndat=0;
- if(channel==0)channel=2;
- if(channel==1)channel=3;
- ADDI=1;
- _nop_();
- _nop_();
- ADCS=0; //拉低CS端
- _nop_();
- _nop_();
- ADCLK=1; //拉高CLK端
- _nop_();
- _nop_();
- ADCLK=0; //拉低CLK端,形成下降沿1
- _nop_();
- _nop_();
- ADCLK=1; //拉高CLK端
- ADDI=channel&0x1;
- _nop_();
- _nop_();
- ADCLK=0; //拉低CLK端,形成下降沿2
- _nop_();
- _nop_();
- ADCLK=1; //拉高CLK端
- ADDI=(channel>>1)&0x1;
- _nop_();
- _nop_();
- ADCLK=0; //拉低CLK端,形成下降沿3
- ADDI=1; //控制命令结束
- _nop_();
- _nop_();
- dat=0;
- for(i=0;i<8;i++)
- {
- dat|=ADDO; //收数据
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0; //形成一次时钟脉冲
- _nop_();
- _nop_();
- dat<<=1;
- if(i==7)dat|=ADDO;
- }
- for(i=0;i<8;i++)
- {
- j=0;
- j=j|ADDO; //收数据
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0; //形成一次时钟脉冲
- _nop_();
- _nop_();
- j=j<<7;
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
- ADCS=1; //拉低CS端
- ADCLK=0; //拉低CLK端
- ADDO=1; //拉高数据端,回到初始状态
- dat<<=8;
- dat|=ndat;
- return(dat);
- }
- void zkb_pro(void)
- {
- unsigned int temp;
- temp=100*ad_data/256;
- if(temp>0 && temp<100)
- {
- ZKB[0]=temp/10;
- ZKB[1]=temp%10;
- }
- }
- void data_pro(void)
- {
- unsigned int temp;
- float press;
- if(14<ad_data<243) //压力值介于15KPA,到115kpa之间,呈线性变化
- {
- int vary=ad_data; //y=(115-15)/(243-13)*X+15kpa
- //press=24+ad_data/2.67;
- press=((10.0/28.1)*vary)+9.3; //测试时补偿值为9.3
- temp=(int)(press*10); //放大10倍,便于后面计算
- press_bai=temp/1000;
- press_shi=(temp%1000)/100;
- press_ge=((temp%1000)%100)/10;
- press_dot=((temp%1000)%100)%10;
- }
-
- }
- /*****************?????*******************/
- void alarm(void)
- {
- if(ad_data>=243)
-
- {
- Alarm_led_red=0;
- a=10000;
- while(a--);
- {
- }
- Alarm_led_red=1;
- a=10000;
- while(a--);
- {
- }
- }
- else
- { Alarm_led_red=1; }
-
-
- if(ad_data<=15)
- { Alarm_led_green=0;
- a=10000;
- while(a--);
- {
- }
- Alarm_led_green=1;
- a=10000;
- while(a--);
- {
- }
- }
- else
- { Alarm_led_green=1; }
-
- }
- uchar duty_cycle(uchar ad_data)
- {
- uchar rate;
-
- rate= 100*ad_data/256;
- return(rate);
- }
- /* ??????*/
- void key_setPWM()
- {
- if(k1==0)
- {
- delay(20);
- if(k1==0)
- {
- rate++;
- if(rate>99)rate=99;
- while(!k2);
- }
- }
- if(k2==0)
- {
- delay(20);
- if(k2==0)
- {
- rate--;
- if(rate<1)rate=1;
- while(!k2);}
- }
- if(k3==0)
- {
- delay(20);
- if(k3==0)
- {
- rate+=10;
- if(rate>99)rate=99;
- while(!k3);}
- }
- if(k4==0)
- {
- delay(20);
- if(k4==0)
- {
- rate-=10;
- if(rate<1)rate=1;
- while(!k4);
- }
- }
- }
- /*??????dc,??20Hz????*/
- void ConfigPWM(uchar dc)
- {
- unsigned long tmp; //临时变量
- uint high, low;
- tmp = 11059200/12/20; //计算一个周期所需的计数值
- high = (tmp*dc)/100; //计算高电平所需计数值
- low = tmp - high; //计算低电平所需计数值
- high = 65536 - high + 12; //计算高电平的定时器重载值并补偿中断延时
- low = 65536 - low + 12; //计算低电平的定时器重载值并补偿中断延时
- HighRH = (uchar)(high >>8); //高电平重载值拆分为高低字节
- HighRL = (uchar)high;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
11502测控课设.zip
(30.52 KB, 下载次数: 251)
|