基于51单片机的adc0832双路电压表Proteus仿真和C程序代码

[复制链接]
查看5 | 回复0 | 2021-5-6 00:07:48 | 显示全部楼层 |阅读模式
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
1.png
部分单片机源程序如下:
  1. #include<reg51.h>    //包含单片机寄存器的头文件
  2. #include<intrins.h>  //包含_nop_()函数定义的头文件
  3. sbit CS=P3^4;       //将CS位定义为P3.4引脚
  4. sbit CLK=P1^0;      //将CLK位定义为P1.0引脚
  5. sbit DIO=P1^1;       //将DIO位定义为P1.1引脚
  6. //////////////////////////////////////////////////////////////////
  7. unsigned char code digit[10]={"0123456789"};   //定义字符数组显示数字
  8. unsigned char code Str[]={"Volt="};            //说明显示的是电压
  9. /*******************************************************************************
  10. 以下是对液晶模块的操作程序
  11. *******************************************************************************/
  12. sbit RS=P2^0;           //寄存器选择位,将RS位定义为P2.0引脚
  13. sbit RW=P2^1;           //读写选择位,将RW位定义为P2.1引脚
  14. sbit E=P2^2;            //使能信号位,将E位定义为P2.2引脚
  15. sbit BF=P0^7;           //忙碌标志位,,将BF位定义为P0.7引脚
  16. /*****************************************************
  17. 函数功能:延时1ms
  18. (3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
  19. ***************************************************/
  20. void delay1ms()
  21. {
  22.    unsigned char i,j;   
  23.      for(i=0;i<10;i++)
  24.       for(j=0;j<33;j++)
  25.        ;         
  26. }
  27. /*****************************************************
  28. 函数功能:延时若干毫秒
  29. 入口参数:n
  30. ***************************************************/
  31. void delaynms(unsigned char n)
  32. {
  33.    unsigned char i;
  34.     for(i=0;i<n;i++)
  35.        delay1ms();
  36. }
  37. /*****************************************************
  38. 函数功能:判断液晶模块的忙碌状态
  39. 返回值:result。result=1,忙碌;result=0,不忙
  40. ***************************************************/
  41. bit BusyTest(void)
  42.   {
  43.     bit result;
  44.     RS=0;       //根据规定,RS为低电平,RW为高电平时,可以读状态
  45.     RW=1;
  46.     E=1;        //E=1,才允许读写
  47.     _nop_();   //空操作
  48.     _nop_();
  49.     _nop_();
  50.     _nop_();   //空操作四个机器周期,给硬件反应时间   
  51.     result=BF;  //将忙碌标志电平赋给result
  52.    E=0;         //将E恢复低电平
  53.    return result;
  54.   }
  55. /*****************************************************
  56. 函数功能:将模式设置指令或显示地址写入液晶模块
  57. 入口参数:dictate
  58. ***************************************************/
  59. void WriteInstruction (unsigned char dictate)
  60. {   
  61.     while(BusyTest()==1);   //如果忙就等待
  62.      RS=0;                  //根据规定,RS和R/W同时为低电平时,可以写入指令
  63.      RW=0;   
  64.      E=0;                   //E置低电平(根据表8-6,写指令时,E为高脉冲,
  65.                            // 就是让E从0到1发生正跳变,所以应先置"0"
  66.      _nop_();
  67.      _nop_();               //空操作两个机器周期,给硬件反应时间
  68.      P0=dictate;            //将数据送入P0口,即写入指令或地址
  69.      _nop_();
  70.      _nop_();
  71.      _nop_();
  72.      _nop_();               //空操作四个机器周期,给硬件反应时间
  73.      E=1;                   //E置高电平
  74.      _nop_();
  75.      _nop_();
  76.      _nop_();
  77.      _nop_();               //空操作四个机器周期,给硬件反应时间
  78.       E=0;                  //当E由高电平跳变成低电平时,液晶模块开始执行命令
  79. }
  80. /*****************************************************
  81. 函数功能:指定字符显示的实际地址
  82. 入口参数:x
  83. ***************************************************/
  84. void WriteAddress(unsigned char x)
  85. {
  86.      WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"
  87. }
  88. /*****************************************************
  89. 函数功能:将数据(字符的标准ASCII码)写入液晶模块
  90. 入口参数:y(为字符常量)
  91. ***************************************************/
  92. void WriteData(unsigned char y)
  93. {
  94.     while(BusyTest()==1);  
  95.       RS=1;           //RS为高电平,RW为低电平时,可以写入数据
  96.       RW=0;
  97.       E=0;            //E置低电平(根据表8-6,写指令时,E为高脉冲,
  98.                      // 就是让E从0到1发生正跳变,所以应先置"0"
  99.       P0=y;           //将数据送入P0口,即将数据写入液晶模块
  100.       _nop_();
  101.       _nop_();
  102.        _nop_();
  103.      _nop_();       //空操作四个机器周期,给硬件反应时间
  104.       E=1;           //E置高电平
  105.       _nop_();
  106.       _nop_();
  107.       _nop_();
  108.      _nop_();        //空操作四个机器周期,给硬件反应时间
  109.      E=0;            //当E由高电平跳变成低电平时,液晶模块开始执行命令
  110. }
  111. /*****************************************************
  112. 函数功能:对LCD的显示模式进行初始化设置
  113. ***************************************************/
  114. void LcdInitiate(void)
  115. {
  116.     delaynms(15);               //延时15ms,首次写指令时应给LCD一段较长的反应时间
  117.     WriteInstruction(0x38);     //显示模式设置:16×2显示,5×7点阵,8位数据接口
  118.     delaynms(5);                //延时5ms ,给硬件一点反应时间
  119.     WriteInstruction(0x38);
  120.     delaynms(5);               //延时5ms ,给硬件一点反应时间
  121.     WriteInstruction(0x38);     //连续三次,确保初始化成功
  122.     delaynms(5);               //延时5ms ,给硬件一点反应时间
  123.     WriteInstruction(0x0c);     //显示模式设置:显示开,无光标,光标不闪烁
  124.     delaynms(5);               //延时5ms ,给硬件一点反应时间
  125.     WriteInstruction(0x06);     //显示模式设置:光标右移,字符不移
  126.     delaynms(5);                //延时5ms ,给硬件一点反应时间
  127.     WriteInstruction(0x01);     //清屏幕指令,将以前的显示内容清除
  128.     delaynms(5);             //延时5ms ,给硬件一点反应时间

  129. }
  130. /**************************************************************************
  131. 以下是电压显示的说明
  132. **************************************************************************/
  133. /*****************************************************
  134. 函数功能:显示电压符号
  135. ***************************************************/   
  136. void display_volt(void)
  137. {
  138.     unsigned char i;
  139.      WriteAddress(0x03);    //写显示地址,将在第2行第1列开始显示
  140.      i = 0;                //从第一个字符开始显示
  141.      while(Str[i] != '\0')  //只要没有写到结束标志,就继续写
  142.       {                        
  143.          WriteData(Str[i]);   //将字符常量写入LCD
  144.          i++;                 //指向下一个字符               
  145.         }   
  146. }
  147. void display_volt2(void)
  148. {
  149.     unsigned char i;
  150.      WriteAddress(0x43);    //写显示地址,将在第2行第1列开始显示
  151.      i = 0;                //从第一个字符开始显示
  152.      while(Str[i] != '\0')  //只要没有写到结束标志,就继续写
  153.       {                        
  154.          WriteData(Str[i]);   //将字符常量写入LCD
  155.          i++;                 //指向下一个字符               
  156.         }   
  157. }

  158. /*****************************************************
  159. 函数功能:显示电压的小数点
  160. ***************************************************/   
  161. void display_dot(void)
  162. {         
  163.      WriteAddress(0x09);      //写显示地址,将在第1行第10列开始显示           
  164.      WriteData('.');       //将小数点的字符常量写入LCD        
  165. }
  166. void display_dot2(void)
  167. {         
  168.      WriteAddress(0x49);      //写显示地址,将在第1行第10列开始显示           
  169.      WriteData('.');       //将小数点的字符常量写入LCD        
  170. }
  171. /*****************************************************
  172. 函数功能:显示电压的单位(V)
  173. ***************************************************/   
  174. void  display_V(void)
  175. {
  176.     WriteAddress(0x0c); //写显示地址,将在第2行第13列开始显示   
  177.      WriteData('V');     //将字符常量写入LCD            
  178.             
  179. }
  180. void  display_V2(void)
  181. {
  182.     WriteAddress(0x4c); //写显示地址,将在第2行第13列开始显示   
  183.      WriteData('V');     //将字符常量写入LCD            
  184.             
  185. }
  186. /*****************************************************
  187. 函数功能:显示电压的整数部分
  188. 入口参数:x
  189. ***************************************************/
  190. void display1(unsigned char x)
  191. {

  192.     WriteAddress(0x08);    //写显示地址,将在第2行第7列开始显示
  193.     WriteData(digit[x]);    //将百位数字的字符常量写入LCD
  194. }
  195. void display1_2(unsigned char x)
  196. {

  197.     WriteAddress(0x48);    //写显示地址,将在第2行第7列开始显示
  198.     WriteData(digit[x]);    //将百位数字的字符常量写入LCD
  199. }
  200. /*****************************************************
  201. 函数功能:显示电压的小数数部分
  202. 入口参数:x
  203. ***************************************************/
  204. void display2(unsigned char x)
  205. {
  206.      unsigned char i,j;
  207.     i=x/10;            //取十位(小数点后第一位)
  208.     j=x%10;            //取个位(小数点后第二位)
  209.    WriteAddress(0x0a);      //写显示地址,将在第1行第11列开始显示
  210.     WriteData(digit[i]);     //将小数部分的第一位数字字符常量写入LCD
  211.     WriteData(digit[j]);     //将小数部分的第一位数字字符常量写入LCD
  212. }
  213. void display2_2(unsigned char x)
  214. {
  215.      unsigned char i,j;
  216.     i=x/10;            //取十位(小数点后第一位)
  217.     j=x%10;            //取个位(小数点后第二位)
  218.    WriteAddress(0x4a);      //写显示地址,将在第1行第11列开始显示
  219.     WriteData(digit[i]);     //将小数部分的第一位数字字符常量写入LCD
  220.     WriteData(digit[j]);     //将小数部分的第一位数字字符常量写入LCD
  221. }
  222. /*****************************************************
  223. 函数功能:将模拟信号转换成数字信号
  224. ***************************************************/
  225. unsigned char  A_D()
  226. {
  227.   unsigned char i,dat;
  228.    CS=1;   //一个转换周期开始
  229.    CLK=0;  //为第一个脉冲作准备
  230.    CS=0;  //CS置0,片选有效

  231.    DIO=1;    //DIO置1,规定的起始信号  
  232.    CLK=1;   //第一个脉冲
  233.    CLK=0;   //第一个脉冲的下降沿,此前DIO必须是高电平
  234.    DIO=1;   //DIO置1, 通道选择信号  
  235.    CLK=1;   //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道CH0
  236.    CLK=0;   //第二个脉冲下降沿
  237.    DIO=0;   //DI置0,选择通道0
  238.    CLK=1;    //第三个脉冲
  239.    CLK=0;    //第三个脉冲下降沿
  240.    DIO=1;    //第三个脉冲下沉之后,输入端DIO失去作用,应置1
  241.    CLK=1;    //第四个脉冲
  242.    for(i=0;i<8;i++)  //高位在前
  243.     {
  244.       CLK=1;         //第四个脉冲
  245.       CLK=0;
  246.       dat<<=1;       //将下面储存的低位数据向右移
  247.         dat|=(unsigned char)DIO;      //将输出数据DIO通过或运算储存在dat最低位
  248.     }                     
  249.     CS=1;          //片选无效
  250.      return dat;     //将读书的数据返回     
  251.   }
复制代码
基于ADC0832的数字电压表源码和仿真文件.zip (80.01 KB, 售价: 2 工控币)
回复

使用道具 举报

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

本版积分规则