找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2086|回复: 1
收起左侧

C51单片机数字电压表设计

[复制链接]
ID:622357 发表于 2019-10-11 16:57 | 显示全部楼层 |阅读模式
20181115132243219 (1).png
  1. #include<reg52.h>   
  2. #include <intrins.h>

  3. #define  AddWr 0x90    //PCF8591 地址

  4. sbit scl=P2^0;       //I2C  时钟
  5. sbit sda=P2^1;       //I2C  数据
  6. bit ack;             //应答标志位

  7. unsigned char date;
  8. sbit C1=P2^6;//数码管1
  9. sbit C2=P2^7;//数码管2
  10. sbit Dp=P2^5;//小数点
  11. table[10]=
  12. {0x3f,0x06,0x5B,0x4F,0x66,
  13. 0x6D,0x7D,0x07,0x7F,0x6F};//0~9
  14. unsigned int data dis[3]={0x00,0x00,0x00};
  15. unsigned int getData;
  16. /*******************************************************************
  17.                      起动总线函数               
  18. 函数原型: void  Start_I2c();  
  19. 功能:     启动I2C总线,即发送I2C起始条件.  
  20. ********************************************************************/
  21. void Start_I2c()
  22. {
  23.   sda=1;         /*发送起始条件的数据信号*/
  24.   _nop_();
  25.   scl=1;
  26.   _nop_();        /*起始条件建立时间大于4.7us,延时*/
  27.   _nop_();
  28.   _nop_();
  29.   _nop_();
  30.   _nop_();   
  31.   sda=0;         /*发送起始信号*/
  32.   _nop_();        /* 起始条件锁定时间大于4μs*/
  33.   _nop_();
  34.   _nop_();
  35.   _nop_();
  36.   _nop_();      
  37.   scl=0;       /*钳住I2C总线,准备发送或接收数据 */
  38.   _nop_();
  39.   _nop_();
  40. }

  41. /*******************************************************************
  42.                       结束总线函数               
  43. 函数原型: void  Stop_I2c();  
  44. 功能:     结束I2C总线,即发送I2C结束条件.  
  45. ********************************************************************/
  46. void Stop_I2c()
  47. {
  48.   sda=0;      /*发送结束条件的数据信号*/
  49.   _nop_();       /*发送结束条件的时钟信号*/
  50.   scl=1;      /*结束条件建立时间大于4μs*/
  51.   _nop_();
  52.   _nop_();
  53.   _nop_();
  54.   _nop_();
  55.   _nop_();
  56.   sda=1;      /*发送I2C总线结束信号*/
  57.   _nop_();
  58.   _nop_();
  59.   _nop_();
  60.   _nop_();
  61. }

  62. /*******************************************************************
  63.                  字节数据发送函数               
  64. 函数原型: void  I2C_SendByte(UCHAR c);
  65. 功能:     将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
  66.           此状态位进行操作.(不应答或非应答都使ack=0)     
  67.            发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
  68. ********************************************************************/
  69. void  I2C_SendByte(unsigned char  c)
  70. {
  71. unsigned char  i;

  72. for(i=0;i<8;i++)  /*要传送的数据长度为8位*/
  73.     {
  74.      if((c<<i)&0x80)sda=1;   /*判断发送位*/
  75.        else  sda=0;               
  76.      _nop_();
  77.      scl=1;               /*置时钟线为高,通知被控器开始接收数据位*/
  78.       _nop_();
  79.       _nop_();             /*保证时钟高电平周期大于4μs*/
  80.       _nop_();
  81.       _nop_();
  82.       _nop_();         
  83.      scl=0;
  84.     }
  85.    
  86.     _nop_();
  87.     _nop_();
  88.     sda=1;                /*8位发送完后释放数据线,准备接收应答位*/
  89.     _nop_();
  90.     _nop_();   
  91.     scl=1;
  92.     _nop_();
  93.     _nop_();
  94.     _nop_();
  95.     if(sda==1)ack=0;     
  96.        else ack=1;        /*判断是否接收到应答信号*/
  97.     scl=0;
  98.     _nop_();
  99.     _nop_();
  100. }

  101. /*******************************************************************
  102.                  字节数据接收函数               
  103. 函数原型: UCHAR  I2C_RcvByte();
  104. 功能:        用来接收从器件传来的数据,并判断总线错误(不发应答信号),
  105.           发完后请用应答函数应答从机。  
  106. ********************************************************************/   
  107. unsigned char   I2C_RcvByte()
  108. {
  109.   unsigned char  retc=0,i;
  110.   sda=1;                     /*置数据线为输入方式*/
  111.   for(i=0;i<8;i++)
  112.       {
  113.         _nop_();           
  114.         scl=0;                  /*置时钟线为低,准备接收数据位*/
  115.         _nop_();
  116.         _nop_();                 /*时钟低电平周期大于4.7μs*/
  117.         _nop_();
  118.         _nop_();
  119.         _nop_();
  120.         scl=1;                  /*置时钟线为高使数据线上数据有效*/
  121.         _nop_();
  122.         _nop_();
  123.         retc=retc<<1;
  124.         if(sda==1)retc=retc+1;  /*读数据位,接收的数据位放入retc中 */
  125.         _nop_();
  126.         _nop_();
  127.       }
  128.   scl=0;   
  129.   _nop_();
  130.   _nop_();
  131.   return(retc);
  132. }

  133. /********************************************************************
  134.                      应答子函数
  135. 函数原型:  void Ack_I2c(bit a);
  136. 功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
  137. ********************************************************************/
  138. void Ack_I2c(bit a)
  139. {  
  140.   if(a==0)sda=0;              /*在此发出应答或非应答信号 */
  141.   else sda=1;                                  /*0为发出应答,1为非应答信号 */
  142.   _nop_();
  143.   _nop_();
  144.   _nop_();      
  145.   scl=1;
  146.   _nop_();
  147.   _nop_();                    /*时钟低电平周期大于4μs*/
  148.   _nop_();
  149.   _nop_();
  150.   _nop_();  
  151.   scl=0;                     /*清时钟线,住I2C总线以便继续接收*/
  152.   _nop_();
  153.   _nop_();   
  154. }

  155. /************************************************************
  156. * 函数名        : Pcf8591_DaConversion
  157. * 函数功能      : PCF8591的输出端输出模拟量
  158. * 输入          : addr(器件地址),channel(转换通道),value(转换的数值)
  159. * 输出                 : 无
  160. ******************* *****************************************/
  161. bit Pcf8591_DaConversion(unsigned char addr,unsigned char channel,  unsigned char Val)
  162. {
  163.    Start_I2c();              //启动总线
  164.    I2C_SendByte(addr);            //发送器件地址
  165.    if(ack==0)return(0);
  166.    I2C_SendByte(0x40|channel);              //发送控制字节
  167.    if(ack==0)return(0);
  168.    I2C_SendByte(Val);            //发送DAC的数值  
  169.    if(ack==0)return(0);
  170.    Stop_I2c();               //结束总线
  171.    return(1);
  172. }

  173. /************************************************************
  174. * 函数名        : Pcf8591_SendByte
  175. * 函数功能                : 写入一个控制命令
  176. * 输入          : addr(器件地址),channel(转换通道)
  177. * 输出                 : 无
  178. ************************************************************/
  179. bit PCF8591_SendByte(unsigned char addr,unsigned char channel)
  180. {
  181.    Start_I2c();              //启动总线
  182.    I2C_SendByte(addr);            //发送器件地址
  183.    if(ack==0)return(0);
  184.    I2C_SendByte(0x40|channel);              //发送控制字节
  185.    if(ack==0)return(0);
  186.    Stop_I2c();               //结束总线
  187.    return(1);
  188. }

  189. /************************************************************
  190. * 函数名               : PCF8591_RcvByte
  191. * 函数功能           : 读取一个转换值
  192. * 输入          :
  193. * 输出          : dat
  194. ************************************************************/
  195. unsigned char PCF8591_RcvByte(unsigned char addr)
  196. {  
  197.    unsigned char dat;

  198.    Start_I2c();          //启动总线
  199.    I2C_SendByte(addr+1);      //发送器件地址
  200.    if(ack==0)return(0);
  201.    dat=I2C_RcvByte();          //读取数据0

  202.    Ack_I2c(1);           //发送非应答信号
  203.    Stop_I2c();           //结束总线
  204.    return(dat);
  205. }
  206. /*------------------------------------------------
  207.                  串口初始化函数
  208. ------------------------------------------------*/
  209. void init_com(void)
  210. {
  211. EA=1;        //开总中断
  212. ES=1;        //允许串口中断
  213. ET1=1;
  214. TMOD=0x22;   //定时器T1,在方式2中断产生波特率
  215. PCON=0x00;   //SMOD=0
  216. SCON=0x50;   // 方式1 由定时器控制
  217. TH1=0xfd;    //波特率设置为9600
  218. TL1=0xfd;
  219. TR1=1;       //开定时器T1运行控制位


  220. }
  221. /*------------------------------------------------
  222.                   延时函数
  223. ------------------------------------------------*/
  224. void delay(unsigned char i)
  225. {
  226.   unsigned char j,k;
  227.   for(j=i;j>0;j--)
  228.     for(k=125;k>0;k--);
  229. }
  230. /*------------------------------------------------
  231. 把读取值转换成一个一个的字符,给串口显示
  232. ------------------------------------------------*/
  233. void To_ascii(unsigned char num)
  234. {        
  235.          SBUF=num/100+'0';                              
  236.          delay(200);                  
  237.          SBUF=num/10%10+'0';                           
  238.          delay(200);        
  239.          SBUF=num%10+'0';
  240.          delay(200);
  241. }
  242. /*------------------------------------------------
  243.                     主函数
  244. ------------------------------------------------*/
  245. int main()
  246. {  
  247.         while(1)
  248.         {
  249.                  PCF8591_SendByte(AddWr,0);         //启动转换
  250.                  getData=PCF8591_RcvByte(AddWr);  //读转换完的数字信号
  251.                  dis[1]=getData/51;   //整数位
  252.                 dis[2]=getData%51;   //dis[2]位中间暂存数据位
  253.                 dis[2]=dis[2]*10;   
  254.                 dis[0]=dis[2]/51;    //计算输出电压的小数值        
  255.         C1=1;                                                
  256.         Dp=0;                //打开小数点
  257.         P0=table[dis[0]];    //显示整数部分及小数点
  258.                              
  259.         C1=0;
  260.         delay(10);   
  261.                         
  262.         C2=1;                //打开第二位数码管
  263.         Dp=1;                //关闭小数点
  264.         P0=table[dis[1]];     //显示小数部分
  265.         C2=0;        
  266.         }
  267. }
  268. ————————————————
  269. 版权声明:本文为CSDN博主「俊俊~」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
  270. 原文链接:https://blog.csdn.net/qq_40602000/article/details/84102765
复制代码


回复

使用道具 举报

ID:522731 发表于 2019-10-16 17:12 | 显示全部楼层
量程为多少
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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