回答

收藏

[原创] 基于PCF8591的模数与数模转换模块应用

51单片机 51单片机 4476 人阅读 | 0 人回复 | 2018-01-16

PCF8591是一个集成了模数与数模转换功能的芯片,该芯片共有16个引脚,并采用IIC总线接口与外部交换信息。
对于模数转换功能来说,它供提供4个模拟量采集通道,分别由AIN0~AIN3引脚来输入。而数模转换功能只提供了一个通道,由Aout引脚来输出。
PCF8591的数据引脚为SDA,时钟引脚为SCL。在使用时,可使用普通的IO来模拟产生。就控制流程来讲,该芯片在使用时共分四步:
1)发送地址字节0x90,选择该器件。
2)发送控制字节,选择相应通道(0x40~0x43)。
3)重新发送地址字节,选择该器件。
4)接收目标通道的数据。
   模块的工作原理图如图1所示,其中的发光电阻可以指示Aout的输出电压,而在输入端AIN0处串接光敏二极管或热敏电阻的情况下,则可以检测亮度和温度信号。

1 模块原理图

为便于对该模块进行检测,可以通过51单片机及光敏电阻与其构成一个检测电路,
模块与51单片机的连接关系如下:
    SCL -- P2.3;
    SDA -- P2.2;
检测程序的处理流程为AD采样、DA转换、串口发送,其执行效果如图2所示。

2 执行效果

检测程序如下:
  1. #include <reg52.h>
  2. #include <51hei.h>
  3. #include <intrins.h>
  4. typedef unsigned char uint8;
  5. typedef unsigned int uint16;
  6. #define PCF8591 0x90
  7. #define  NOP() _nop_()
  8. #define _Nop() _nop_()

  9. unsigned char AD_CHANNEL;
  10. unsigned long xdata  Out[8];
  11. unsigned int D[32];

  12. sbit SCL = P2^3;
  13. sbit SDA = P2^2;
  14. bit ack;

  15. void Start_I2c()
  16. {
  17. SDA=1;
  18. _Nop();
  19. SCL=1;
  20. _Nop();  /*4.7us*/
  21. _Nop();
  22. _Nop();
  23. _Nop();
  24. _Nop();
  25. SDA=0;
  26. _Nop();
  27. _Nop();
  28. _Nop();
  29. _Nop();
  30. _Nop();
  31. SCL=0;
  32. _Nop();
  33. _Nop();
  34. }

  35. void Stop_I2c()
  36. {
  37. SDA=0;
  38. _Nop();
  39. SCL=1;
  40. _Nop();
  41. _Nop();
  42. _Nop();
  43. _Nop();
  44. _Nop();
  45. SDA=1;
  46. _Nop();
  47. _Nop();
  48. _Nop();
  49. _Nop();
  50. }

  51. void SendByte(unsigned char c)
  52. {
  53. unsigned char BitCnt;

  54. for(BitCnt=0;BitCnt<8;BitCnt++)
  55. {
  56. if((c<<BitCnt)&0x80) SDA=1;
  57. else SDA=0;
  58. _Nop();
  59. SCL=1;
  60. _Nop();
  61. _Nop();
  62. _Nop();
  63. _Nop();
  64. _Nop();
  65. SCL=0;
  66. }
  67. _Nop();
  68. _Nop();
  69. SDA=1;
  70. _Nop();
  71. _Nop();
  72. SCL=1;
  73. _Nop();
  74. _Nop();
  75. _Nop();
  76. if(SDA==1)ack=0;
  77. else ack=1;
  78. SCL=0;
  79. _Nop();
  80. _Nop();
  81. }

  82. unsigned char RcvByte()
  83. {
  84. unsigned char retc;
  85. unsigned char BitCnt;
  86. retc=0;
  87. SDA=1;
  88. for(BitCnt=0;BitCnt<8;BitCnt++)
  89. {
  90. _Nop();
  91. SCL=0;
  92. _Nop();
  93. _Nop();
  94. _Nop();
  95. _Nop();
  96. _Nop();
  97. SCL=1;
  98. _Nop();
  99. _Nop();
  100. retc=retc<<1;
  101. if(SDA==1) retc=retc+1;
  102. _Nop();
  103. _Nop();
  104. }
  105. SCL=0;
  106. _Nop();
  107. _Nop();
  108. return(retc);
  109. }

  110. void Ack_I2c(bit a)
  111. {
  112. if(a==0) SDA=0;
  113. else SDA=1;
  114. _Nop();
  115. _Nop();
  116. _Nop();
  117. SCL=1;
  118. _Nop();
  119. _Nop();
  120. _Nop();
  121. _Nop();
  122. _Nop();
  123. SCL=0;
  124. _Nop();
  125. _Nop();
  126. }


  127. bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
  128. {
  129. Start_I2c();
  130. SendByte(sla);
  131. if(ack==0)return(0);
  132. SendByte(c);
  133. if(ack==0)return(0);
  134. SendByte(Val);
  135. if(ack==0)return(0);
  136. Stop_I2c();
  137. return(1);
  138. }

  139. bit ISendByte(unsigned char sla,unsigned char c)
  140. {
  141. Start_I2c();
  142. SendByte(sla);
  143. if(ack==0) return(0);
  144. SendByte(c);
  145. if(ack==0) return(0);
  146. Stop_I2c();
  147. return(1);
  148. }

  149. unsigned char IRcvByte(unsigned char sla)
  150. {
  151. unsigned char c;
  152. Start_I2c();
  153. SendByte(sla+1);
  154. if(ack==0)return(0);
  155. c=RcvByte();
  156. Ack_I2c(1);
  157. Stop_I2c();
  158. return(c);
  159. }

  160. void uart_init(void)
  161. {
  162. ET1=0;
  163. TMOD = 0x21;
  164. SCON = 0x50;
  165. TH1 = 0xFD;     //    11.0592   9600bps
  166. TL1 = 0xFD;
  167. TR1 = 1;
  168. }

  169. void UART_Send_Byte(uint8 dat)
  170. {
  171. SBUF = dat;
  172. while(TI == 0);
  173. TI = 0;
  174. }

  175. void delay(uint16 n)
  176. {
  177.           while(n--);
  178. }
  179. void main()
  180. {
  181. char i,j;
  182. uart_init();
  183. while(1)
  184. {
  185. switch(AD_CHANNEL)
  186. {
  187. case 0: ISendByte(PCF8591,0x41);
  188.         D[0]=IRcvByte(PCF8591)*2;  //ADC0  0~0xff  0~510 ( 5.1V )
  189.         break;
  190. case 1: ISendByte(PCF8591,0x42);
  191.         D[1]=IRcvByte(PCF8591)*2;  //ADC1
  192.         break;
  193. case 2: ISendByte(PCF8591,0x43);
  194.         D[2]=IRcvByte(PCF8591)*2;  //ADC2
  195.         break;
  196. case 3: ISendByte(PCF8591,0x40);
  197.         D[3]=IRcvByte(PCF8591)*2;  //ADC3
  198.         break;
  199. case 4: DACconversion(PCF8591,0x40, 0xff);
  200.       break;
  201. }
  202.         D[4]=D[3];
  203. if(++AD_CHANNEL>4)   AD_CHANNEL=0;

  204. Out[0]=D[0]%10000/1000;  
  205. Out[1]=D[0]%1000/100;
  206. Out[2]=D[0]%100/10;   
  207. Out[3]=D[0]%10;

  208. Out[4]=D[1]%10000/1000;  
  209. Out[5]=D[1]%1000/100;
  210. Out[6]=D[1]%100/10;   
  211. Out[7]=D[1]%10;

  212. UART_Send_Byte('A');
  213. UART_Send_Byte('D');
  214. UART_Send_Byte('C');       
  215. UART_Send_Byte('0');
  216. UART_Send_Byte(':');

  217. for( i=0; i<4; i++)
  218. {
  219.    UART_Send_Byte(Out[i]+'0');
  220. }
  221. UART_Send_Byte(0X0D);
  222. UART_Send_Byte(0X0A);

  223. UART_Send_Byte('A');
  224. UART_Send_Byte('D');
  225. UART_Send_Byte('C');       
  226. UART_Send_Byte('1');
  227. UART_Send_Byte(':');

  228. for( i=4; i<8; i++)
  229. {
  230.    UART_Send_Byte(Out[i]+'0');
  231. }
  232. UART_Send_Byte(0X0D);
  233. UART_Send_Byte(0X0A);

  234. Out[0]=D[2]%10000/1000;   
  235. Out[1]=D[2]%1000/100;
  236. Out[2]=D[2]%100/10;   
  237. Out[3]=D[2]%10;

  238. Out[4]=D[3]%10000/1000;   
  239. Out[5]=D[3]%1000/100;
  240. Out[6]=D[3]%100/10;   
  241. Out[7]=D[3]%10;

  242. UART_Send_Byte('A');
  243. UART_Send_Byte('D');
  244. UART_Send_Byte('C');       
  245. UART_Send_Byte('2');
  246. UART_Send_Byte(':');

  247. for( i=0; i<4; i++)
  248. {
  249.    UART_Send_Byte(Out[i]+'0');         
  250. }
  251. UART_Send_Byte(0X0D);
  252. UART_Send_Byte(0X0A);

  253. UART_Send_Byte('A');
  254. UART_Send_Byte('D');
  255. UART_Send_Byte('C');       
  256. UART_Send_Byte('3');
  257. UART_Send_Byte(':');

  258. for( i=4; i<8; i++)
  259. {
  260.    UART_Send_Byte(Out[i]+'0');
  261. }
  262. UART_Send_Byte(0X0D);
  263. UART_Send_Byte(0X0A);
  264. delay(50000);
  265. }
  266. }
复制代码
分享到:
回复

使用道具 举报

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

本版积分规则

关闭

站长推荐上一条 /3 下一条