单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 34|回复: 0
打印 上一主题 下一主题
收起左侧

51单片机MPX4115压力传感器+ADC0832仿真课设程序

[复制链接]
跳转到指定楼层
楼主
此课设基于ADC0832和压力传感器MPX4115,把传感器的值通过运放电路调整,送入AD转换,再经单片机编程实现压力的测量与显示;涉及PWM控制,串口,按键控制PWM占空比等。

仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include<math.h>
  2. #include<absacc.h>
  3. #include<intrins.h>
  4. #include<reg51.h>
  5. #define uchar unsigned char
  6. #define uint unsigned  int
  7. #define ulong unsigned long

  8. #define BUSY  0x80                  //常量定义            
  9. #define DATAPORT P0

  10. sbit Alarm_led_red =P1^6;          //超过压力表量程最大值红灯报警
  11. sbit Alarm_led_green=P1^7;         //低于压力表量程最小值路灯报警

  12. sbit LCM_RS=P2^0;
  13. sbit LCM_RW=P2^1;
  14. sbit LCM_EN=P2^2;
  15.                     
  16. sbit k1=P2^3;  
  17. sbit k2=P2^4;  
  18. sbit k3=P2^5;  
  19. sbit k4=P2^6;  

  20. sbit ADCS =P3^5;  //ADC0832 chip seclect
  21. sbit ADCLK =P3^6;  //ADC0832 clock signal
  22. sbit ADDI =P3^7;  //ADC0832 k in
  23. sbit ADDO =P3^7;  //ADC0832 k out





  24. uchar ad_data;                    //采样值存储
  25. unsigned char ad_alarm;           //报警值存储单元
  26. unsigned char press_bai=0;        //显示值百位
  27. unsigned char press_shi=0;        //显示值十位
  28. unsigned char press_ge=0;         //显示值个位
  29. unsigned char press_dot=0;        //显示值十分位
  30. uchar code str0[]={"Press:   .   kpa. "};
  31. uchar code str1[]={"ZKB:   00  %   "};
  32. uchar ZKB[2];
  33. uchar HighRH = 0;
  34. uchar HighRL = 0;
  35. uchar LowRH = 0;
  36. uchar LowRL = 0;
  37. unsigned int a;
  38. uchar rate;  
  39. sbit PWMOUT = P1^0;
  40. uchar step, rec_data,flag;
  41. uchar Adc0832(unsigned char channel);  
  42. void delay(uint);                        
  43. void lcd_wait(void);                      //检测忙子程序
  44. void delay_LCM(uint);                     //延时子程序
  45. void initLCM(void);                       //初始化子程序
  46. void WriteCommandLCM(uchar WCLCM,uchar BusyC);           //写指令到LCM子程序      
  47. void WriteDataLCM(uchar WDLCM);                          //写数据到LCM子程序
  48. void DisplayOneChar(uchar X,uchar Y,uchar DData);        //显示指定坐标的一个字符子函数
  49. void DisplayListChar(uchar X,uchar Y,uchar code *DData); //显示指定坐标的一串字符子函数
  50. void display(void);                                       //系统显示子函数
  51. void ConfigPWM(uchar rate);
  52. void alarm(void);
  53. void data_pro(void);
  54. void ConfigPWM(uchar dc);
  55. void key_setPWM(void);
  56. uchar duty_cycle(uchar ad_data);
  57. void display_zkb(void);
  58. void zkb_pro(void);
  59. void chuankou_init();

  60. /**********main funcation************/
  61. void main(void)
  62. {
  63.          
  64.         
  65.     delay(50);              
  66.     initLCM( );      
  67.                 chuankou_init();
  68.     WriteCommandLCM(0x01,1);           //清屏显示
  69.     DisplayListChar(0,0,str0);
  70.     DisplayListChar(0,1,str1);
  71.                
  72.                 delay(10);
  73.                 PWMOUT=1;
  74.                 EA = 1;
  75.                 ConfigPWM(rate);
  76.                 while(1)
  77.     {
  78.                         ad_data =Adc0832(0);                 //采样值存储单元初始化为0
  79.                         alarm();
  80.                         data_pro();
  81.                         zkb_pro();
  82.                         display();
  83.                         display_zkb();
  84.                         a=duty_cycle(ad_data);
  85.                         ConfigPWM(a);
  86.                         key_setPWM();
  87.                         if(a!=rate)
  88.                         {
  89.                         ConfigPWM(rate);
  90.                         }
  91.                         
  92.                                 if(RI==1)//串口
  93.                 {
  94.                         RI=0;
  95.                         rec_data=SBUF;
  96.                         step=rec_data*2;
  97.                         SBUF=rec_data;
  98.                 }
  99.                
  100.                 }
  101. }

  102. void TIME_INIT()
  103. {
  104. TMOD|=0X02;
  105. IT0=1;
  106. IT1=1;
  107. TR1=1;
  108. EX1=1;
  109. EX0=1;
  110. ET0=1;
  111. TR0=1;
  112. EA=1;
  113. }
  114. void chuankou_init()
  115. {
  116. SCON|=0X50;
  117. TMOD|=0X20;
  118. PCON|=0X80;
  119. TH1=0XFA;
  120. TL1=0XFA;
  121. TR1=1;

  122. SM0=0;
  123. SM1=1;
  124. REN=1;

  125. EA=1;
  126. ES=1;
  127. }

  128. /********延时K*1ms,12.000mhz**********/
  129. void delay(uint x)
  130. {
  131.     uchar i;
  132.          while(x--)
  133.          {
  134.                  for(i = 0;i < 120;i++)
  135.                  {;}
  136.          }
  137. }   
  138. /**********写数据到ICM子函数************/
  139. void WriteCommandLCM(uchar WCLCM,uchar BusyC)
  140. {
  141.     if(BusyC)
  142.                         lcd_wait();          //检测忙信号
  143.                 DATAPORT=WCLCM;
  144.     LCM_RS=0;               
  145.     LCM_RW=0;  
  146.     LCM_EN=1;   
  147.          _nop_();   
  148.          _nop_();
  149.          _nop_();
  150.     LCM_EN=0;
  151.    
  152. }
  153. /**********????LCM???************/
  154. void WriteDataLCM(uchar WDLCM)
  155. {
  156.     lcd_wait( );  
  157.                 DATAPORT=WDLCM;
  158.     LCM_RS=1;        //选中数据寄存器
  159.     LCM_RW=0;        //写模式
  160.     LCM_EN=1;
  161.     _nop_();
  162.                  _nop_();
  163.                  _nop_();
  164.     LCM_EN=0;
  165. }
  166. /***********lcm内部等待程序*************/
  167. void lcd_wait(void)
  168. {
  169.     DATAPORT=0xff;       //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
  170.                 LCM_EN=1;
  171.     LCM_RS=0;   
  172.     LCM_RW=1;   
  173.     _nop_();
  174.     _nop_();
  175.                 _nop_();
  176.     while(DATAPORT&BUSY)  
  177.                 {  
  178.                         LCM_EN=0;
  179.                         _nop_();
  180.                         _nop_();
  181.                         LCM_EN=1;
  182.                         _nop_();
  183.                         _nop_();
  184.     }  
  185.     LCM_EN=0;

  186. }
  187. /**********LCM??????***********/
  188. void initLCM( )
  189. {   
  190.          DATAPORT=0;
  191.          delay(15);
  192.          WriteCommandLCM(0x38,0);            //三次显示模式,不检测忙信号
  193.                 delay(5);
  194.     WriteCommandLCM(0x38,0);
  195.     delay(5);
  196.     WriteCommandLCM(0x38,0);
  197.     delay(5);
  198.     WriteCommandLCM(0x38,1);            //8bit数据传送,两行显示,5*7字型,检测忙信号
  199.     WriteCommandLCM(0x08,1);            //关闭显示,检测忙信号
  200.     WriteCommandLCM(0x01,1);            //清屏,检测忙信号
  201.     WriteCommandLCM(0x06,1);            //显示光标右移设置
  202.     WriteCommandLCM(0x0c,1);            //显示屏打开,光标不显示,不闪烁,检测忙信号
  203. }
  204. /****??????????????****/
  205. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  206. {
  207.     Y&=1;
  208.     X&=15;
  209.     if(Y)X|=0x40;                    //若Y为1(显示第二行)地址译码+0x40
  210.     X|=0x80;                          //指令码为地址码+0x80
  211.     WriteCommandLCM(X,0);
  212.     WriteDataLCM(DData);
  213. }
  214. /*******??????????????*****/

  215. void DisplayListChar(uchar X,uchar Y,uchar code *DData)
  216. {
  217.     uchar ListLength=0;
  218.     Y&=0x01;
  219.     X&=0x0f;
  220.     while(X<16)
  221.     {
  222.         DisplayOneChar(X,Y,DData[ListLength]);
  223.         ListLength++;
  224.         X++;
  225.     }
  226. }
  227. /*****************???????*****************/
  228. void display(void)
  229. {
  230.                 WriteCommandLCM(0x0c,1);               //显示屏打开,光标不显示,不闪烁,检测忙信号
  231.                 DisplayListChar(0,0,str0);
  232.                 DisplayListChar(0,1,str1);

  233.                 DisplayOneChar(7,0,press_bai+0x30);
  234.                 DisplayOneChar(8,0,press_shi+0x30);
  235.                 DisplayOneChar(9,0,press_ge +0x30);
  236.                 DisplayOneChar(10,0,056);
  237.     DisplayOneChar(11,0,press_dot+0x30);  
  238. }
  239. void display_zkb(void)
  240. {
  241.         WriteCommandLCM(0x0c,1);
  242.         DisplayListChar(0,1,str1);
  243.                 DisplayOneChar(7,1,ZKB[0]+0x30);
  244.                 DisplayOneChar(8,1,ZKB[1]+0x30);
  245.         delay(1000);                             //稳定显示
  246. }
  247. /************?ADC0832??************/
  248. uchar Adc0832(unsigned char channel)         //AD转换,并返回结果
  249. {
  250.     uchar i=0;
  251.     uchar j;
  252.     uint dat=0;
  253.     uchar ndat=0;
  254.     if(channel==0)channel=2;
  255.     if(channel==1)channel=3;
  256.     ADDI=1;
  257.     _nop_();
  258.     _nop_();
  259.     ADCS=0;                //拉低CS端
  260.     _nop_();
  261.     _nop_();
  262.     ADCLK=1;               //拉高CLK端
  263.     _nop_();
  264.     _nop_();
  265.     ADCLK=0;                //拉低CLK端,形成下降沿1
  266.     _nop_();
  267.     _nop_();
  268.     ADCLK=1;                 //拉高CLK端
  269.     ADDI=channel&0x1;
  270.     _nop_();
  271.     _nop_();
  272.     ADCLK=0;                   //拉低CLK端,形成下降沿2
  273.     _nop_();
  274.     _nop_();
  275.     ADCLK=1;                      //拉高CLK端
  276.     ADDI=(channel>>1)&0x1;
  277.     _nop_();
  278.     _nop_();
  279.     ADCLK=0;                         //拉低CLK端,形成下降沿3
  280.     ADDI=1;                 //控制命令结束
  281.     _nop_();
  282.     _nop_();
  283.     dat=0;
  284.     for(i=0;i<8;i++)
  285.     {
  286.         dat|=ADDO;          //收数据
  287.         ADCLK=1;
  288.         _nop_();
  289.         _nop_();
  290.         ADCLK=0;             //形成一次时钟脉冲
  291.         _nop_();
  292.         _nop_();
  293.         dat<<=1;
  294.         if(i==7)dat|=ADDO;
  295.     }  
  296.     for(i=0;i<8;i++)
  297.     {
  298.         j=0;
  299.         j=j|ADDO;             //收数据
  300.         ADCLK=1;
  301.         _nop_();
  302.         _nop_();
  303.         ADCLK=0;              //形成一次时钟脉冲
  304.         _nop_();
  305.         _nop_();
  306.         j=j<<7;
  307.         ndat=ndat|j;
  308.         if(i<7)ndat>>=1;
  309.     }
  310.     ADCS=1;               //拉低CS端
  311.     ADCLK=0;               //拉低CLK端
  312.     ADDO=1;                //拉高数据端,回到初始状态
  313.     dat<<=8;
  314.     dat|=ndat;
  315.     return(dat);
  316. }
  317. void zkb_pro(void)
  318. {
  319.         unsigned int temp;
  320.         temp=100*ad_data/256;
  321.         if(temp>0 && temp<100)
  322.         {
  323.                 ZKB[0]=temp/10;
  324.                 ZKB[1]=temp%10;
  325.         }
  326. }
  327. void data_pro(void)
  328. {
  329.       unsigned int temp;
  330.       float  press;      
  331.                  if(14<ad_data<243)                 //压力值介于15KPA,到115kpa之间,呈线性变化
  332.                  {      
  333.                                 int vary=ad_data;      //y=(115-15)/(243-13)*X+15kpa   
  334.                          //press=24+ad_data/2.67;
  335.                          press=((10.0/28.1)*vary)+9.3;        //测试时补偿值为9.3
  336.                          temp=(int)(press*10);                 //放大10倍,便于后面计算            
  337.                          press_bai=temp/1000;        
  338.                          press_shi=(temp%1000)/100;   
  339.                          press_ge=((temp%1000)%100)/10;  
  340.                          press_dot=((temp%1000)%100)%10;
  341.                         }     
  342.    
  343. }
  344. /*****************?????*******************/

  345. void alarm(void)
  346. {
  347.   if(ad_data>=243)  
  348.         
  349.         {  
  350.                 Alarm_led_red=0;
  351.     a=10000;
  352.     while(a--);
  353.     {
  354.     }
  355.                 Alarm_led_red=1;
  356.     a=10000;
  357.     while(a--);
  358.     {
  359.     }
  360.         }  
  361.    else
  362.       {   Alarm_led_red=1; }
  363.      

  364.    if(ad_data<=15)
  365.       {  Alarm_led_green=0;
  366.     a=10000;
  367.     while(a--);
  368.     {
  369.     }
  370.           Alarm_led_green=1;
  371.     a=10000;
  372.     while(a--);
  373.     {
  374.     }
  375.     }            
  376.       else
  377.       {   Alarm_led_green=1; }   
  378.          
  379. }
  380. uchar duty_cycle(uchar ad_data)
  381. {
  382.         uchar rate;
  383.         
  384.         rate= 100*ad_data/256;
  385.   return(rate);
  386. }

  387. /*  ??????*/
  388. void key_setPWM()
  389. {
  390. if(k1==0)
  391.   {
  392.      delay(20);
  393.          if(k1==0)
  394.          {
  395.          rate++;
  396.                 if(rate>99)rate=99;
  397.          while(!k2);
  398.          }
  399.   }
  400.          if(k2==0)
  401.   {
  402.      delay(20);
  403.          if(k2==0)
  404.          {
  405.                  rate--;
  406.                  if(rate<1)rate=1;
  407.            while(!k2);}
  408.   }
  409. if(k3==0)
  410.   {
  411.      delay(20);
  412.          if(k3==0)
  413.          {
  414.                  rate+=10;
  415.                  if(rate>99)rate=99;
  416.          while(!k3);}
  417.   }
  418.   if(k4==0)
  419.   {
  420.      delay(20);
  421.          if(k4==0)
  422.          {
  423.                  rate-=10;
  424.                  if(rate<1)rate=1;
  425.          while(!k4);
  426.          }
  427.   }
  428. }

  429. /*??????dc,??20Hz????*/
  430. void ConfigPWM(uchar dc)
  431. {
  432.         unsigned long tmp;          //临时变量
  433.         uint high, low;
  434.         tmp = 11059200/12/20;        //计算一个周期所需的计数值
  435.         high = (tmp*dc)/100;         //计算高电平所需计数值
  436.         low = tmp - high;             //计算低电平所需计数值
  437.         high = 65536 - high + 12;    //计算高电平的定时器重载值并补偿中断延时
  438.         low = 65536 - low + 12;          //计算低电平的定时器重载值并补偿中断延时
  439.         HighRH = (uchar)(high >>8);      //高电平重载值拆分为高低字节
  440.         HighRL = (uchar)high;
  441. ……………………

  442. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
11502测控课设.zip (30.52 KB, 下载次数: 3)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 转播转播 分享分享 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机.

Powered by 单片机教程网

快速回复 返回顶部 返回列表