PCF8591学习(二)AD转换,算法,串口打印

利用A/D,加上简单的计算,加上串口打印,我们就可以简单的测量电压了。就可以做简单的电压或电流表了。调节电位器,电压会变化,led灯也会变化,电脑显示实验现象如图:

源代码:
  1. 项目名称:PCF8591AD和串口打印 
  2. 项目内容:A/D转换,把转换的数字量 
  3. 送给P0口控制LED的亮灭 ; 
  4. 并把转换的数字逻辑 
  5. 运算,送给串口,打印到电脑上。 
  6. 这样就可以采样电压信号了,并处理。 
  7. 可以扩展做出电压表,电流表等。 
  8. 作者:YUAN 
  9. */  
  10.   
  11. #include <reg52.h>  
  12. #include <stdio.h>        //printf输出头文件  
  13. #include <intrins.h>  //_nop_()延时头文件  
  14. typedef unsigned char uChar8;  
  15. typedef unsigned int uInt16;  
  16. sbit SDA = P1^0;  
  17. sbit SCL = P1^1;  
  18. #define PCF8591Add 0x90 //PCF8591的器件地址和写操作  
  19. uChar8 gTemp;  
  20. float gfDataVal;    //用在转载计算的数值,并发送给计算机  
  21.   
  22. //延时函数  
  23. void DelayMS(uInt16 lValMS);  
  24. void Delay5us(void);  
  25. //IIC操作的几个函数  
  26. void IICInit(void);     //IIC初始化  
  27. void IICStart(void);    //起始信号  
  28. void IICStop(void);     //停止信号  
  29. void IICAck(void);      //应答信号  
  30. void IICReadAck(void);  //读应答信号  
  31. void IICWriteOneByte(uChar8 lByteVal);                  //写一个字节  
  32. uChar8 IICReadOneByte(void);        //读一个字节  
  33. void PCF8591WriteRegulate(uChar8 lREGVal);  //Regulate控制器,这里写控制函数  
  34. uChar8  ReadDataPCF8591(void);  
  35. //   
  36.   
  37. //串口的几个程序  
  38. void UartInit(void);        //串口初始化  
  39. void UartPrint(float iVal); //Printd打印,打印函数  
  40.                                   
  41. void main()  
  42. {  
  43.     IICInit();  
  44.     UartInit();  
  45.     while(1)  
  46.     {      
  47.         /*写入控制字00,即模拟量输出关闭,选择通道0, 
  48.         不自动增加通道,模拟量输入围方式0*/  
  49.          PCF8591WriteRegulate(0x00);  
  50.          P0 = ReadDataPCF8591();   
  51.          gTemp = P0;    //用来中转的存储区  
  52.          gfDataVal = (float)gTemp/255*5;   //强制转换  
  53.          DelayMS(1000);  
  54.          UartPrint(gfDataVal);  
  55.     }  
  56. }  
  57.   
  58. void DelayMS(uInt16 lValMS) //延时函数  
  59. {  
  60.     uInt16 luiVal,lujVal;  
  61.     for(luiVal = 0; luiVal < lValMS; luiVal++)  
  62.         for(lujVal = 0; lujVal < 113; lujVal++);  
  63. }  
  64. void Delay5us(void)  
  65. {  
  66.     _nop_();_nop_();_nop_();  
  67.     _nop_();_nop_();_nop_();  
  68. }  
  69. //IIC总线空闲时均为高电平  
  70. void IICInit(void)      //IIC初始化  
  71. {  
  72.     SCL = 0;  
  73.     SDA=1;  
  74.     Delay5us();  
  75.     SCL=1;  
  76. }  
  77. //SCL高电平期间SDA由高到低的变化为起始信号  
  78. void IICStart(void) //起始信号  
  79. {  
  80.     SCL = 0;  
  81.     Delay5us();  
  82.     SDA = 1;  
  83.     Delay5us();  
  84.     SCL = 1;  
  85.     Delay5us();  
  86.     SDA = 0;  
  87.     Delay5us();  
  88.     //防止接下来SDA数据变化导致IIC总线误判   
  89.     SCL = 0;       
  90. }  
  91. //SCL高电平期间SDA由低到高的变化为终止信号  
  92. void IICStop(void)      //停止信号  
  93. {  
  94.     SCL = 0;  
  95.     Delay5us();  
  96.     SDA = 0;  
  97.     Delay5us();  
  98.     SCL = 1;  
  99.     Delay5us();  
  100.     SDA = 1;  
  101.     Delay5us();  
  102.     //防止接下来SDA数据变化导致IIC总线误判   
  103.     SCL = 0;  
  104. }  
  105. //一个脉冲期间,SDA为低电平为应答  
  106. void IICAck(void)       //应答信号  
  107. {  
  108.     SCL = 0;  
  109.     Delay5us();  
  110.     SDA = 0;  
  111.     Delay5us();  
  112.     SCL = 1;  
  113.     Delay5us();  
  114.     SCL = 0;          
  115. }  
  116. /*cpu读应答信号,如果应答了则 
  117. 继续传输数据,否则在一定时间里, 
  118. 默认已经应答,继续传数据 
  119. */  
  120. void IICReadAck(void)   //读应答信号  
  121. {  
  122.     uChar8 li = 0;  
  123.     SCL = 0;  
  124.     SDA = 1;  //确保读出的值为0,因此先送1  
  125.     Delay5us();  
  126.     SCL = 1;  
  127.     Delay5us();  
  128.     //如果没有应答或时间没有超过预定时间则停在此处  
  129.     while((1 == SDA)&&(li<255))li++;  
  130.     SCL = 0;  
  131.     Delay5us();       
  132.     SDA = 1;              
  133. }  
  134. /* 
  135.     写1个字节,先写高位。 
  136. */  
  137. void IICWriteOneByte(uChar8 lByteVal)                   //写一个字节  
  138. {  
  139.     uChar8 li,liVal;  
  140.     liVal = lByteVal;  
  141.   
  142.     for(li=0;li<8;li++)      
  143.     {  
  144.           
  145.         SCL = 0;   
  146.         Delay5us();   
  147.         SDA = (bit)(liVal&0x80);    //把数据准备好等待传送  
  148.         Delay5us();   
  149.         SCL = 1;  
  150.         Delay5us();  
  151.         liVal <<= 1;  
  152.     }   
  153.     SCL = 0;   
  154.     Delay5us();   
  155.     SDA = 1;  
  156. }  
  157. /* 
  158. 读取一个字节并把读到的值返回 
  159. */  
  160. uChar8 IICReadOneByte(void)  
  161. {  
  162.     uChar8 li,liVal;  
  163.     SCL = 0;  
  164.     SDA = 1;  
  165.     for(li=0;li<8;li++)  
  166.     {  
  167.         liVal <<= 1;  
  168.         SCL = 0;  
  169.         Delay5us();  
  170.         SCL = 1;  
  171.         Delay5us();  
  172.         liVal = (liVal|SDA);  
  173.     }  
  174.     SCL = 0;   
  175.     return liVal;  
  176. }     
  177. //Regulate控制器,这里写控制函数  
  178. void PCF8591WriteRegulate(uChar8 lREGVal)  
  179. {  
  180.     IICStart();  
  181.     IICWriteOneByte(PCF8591Add);    //PCF8591的地址,写控制  
  182.     IICReadAck();  
  183.     IICWriteOneByte(lREGVal);       //写入控制字  
  184.     IICReadAck();  
  185.     IICStop();  
  186. }     
  187. uChar8  ReadDataPCF8591(void)  
  188. {  
  189.     uChar8 liVal;  
  190.     IICStart();  
  191.     IICWriteOneByte(PCF8591Add|0x01);   //PCF8591的地址,读控制      
  192.     liVal = IICReadOneByte();  
  193.     IICAck();  
  194.     IICStop();  
  195.     return liVal;     
  196. }   
  197. //串口的程序  
  198. void UartInit(void)  
  199. {  
  200.     TMOD &= 0x0f;    //只改变要改变的  
  201.     TMOD |= 0x20;   //设置定时器0为工作方式2  
  202.     TL1 = 0xfd;  
  203.     TH1 = 0xfd;     //设置波特率为9600bps  
  204.     TR1 = 1;        //允许T1开始计数  
  205.   
  206.     SCON &= 0x5f;  
  207.     SCON |= 0x50;   //设置串口工作在方式1,允许接收数据   
  208. }  
  209. //把读出来的值打印到计算机上  
  210. void UartPrint(float iVal)  
  211. {  
  212.     TI=1;  
  213.     printf("测得电压为:%f\n",iVal);  
  214.     while(!TI);  
  215.     TI=0;  
  216. }  
 
原文地址:https://www.cnblogs.com/yuanbao825/p/5107626.html