• PCF8591学习笔记


     PCF8591是一款AD、DA转换芯片,在这里我们主要介绍单片机用I2c与PCF8591通信并实现AD转换

    与 PCF8591要发送的第一个字节为地址地址 ,以下是地址的形式 前四位是固定的即fixed part,后三位的programmable part为用户字节控制的地址,如果你A0 A1 A2引脚全部接高电平programmable part就为111 如果A0接高电平 A1、A2接低电平programmable part就为100 依次类推,最后一位是读写位,这取决于你接下来是读取信息还是发送消息。

    第二个字节为控制字节

    第二位为模拟信号量输出使能,打开后相应的引脚会输出模拟量

    第三四两位控制的是模拟输入的模式,00为直连模式、01为三差分输入、10为直连与差分混合模式、11为两组的差分输入

    第六位控制的是通道数是否自加

    第七八两位控制的是AD的通道

    ADC实例程序

    1. #include "reg52.h"
    2. #include "intrins.h"
    3. #define DELAY_TIME 5
    4. /** 定义I2C总线时钟线和数据线 */
    5. sbit scl = P2^0;
    6. sbit sda = P2^1;
    7. /**
    8. * @brief I2C总线中一些必要的延时
    9. *
    10. * @param[in] i - 延时时间调整.
    11. * @return none
    12. */
    13. void i2c_delay(unsigned char i)
    14. {
    15. do
    16. {
    17. _nop_();
    18. }
    19. while(i--);
    20. }
    21. /**
    22. * @brief 产生I2C总线启动条件.
    23. *
    24. * @param[in] none
    25. * @param[out] none
    26. * @return none
    27. */
    28. void i2c_start(void)
    29. {
    30. sda = 1;
    31. scl = 1;
    32. i2c_delay(DELAY_TIME);
    33. sda = 0;
    34. i2c_delay(DELAY_TIME);
    35. scl = 0;
    36. }
    37. /**
    38. * @brief 产生I2C总线停止条件
    39. *
    40. * @param[in] none
    41. * @param[out] none.
    42. * @return none
    43. */
    44. void i2c_stop(void)
    45. {
    46. sda = 0;
    47. scl = 1;
    48. i2c_delay(DELAY_TIME);
    49. sda = 1;
    50. i2c_delay(DELAY_TIME);
    51. }
    52. /**
    53. * @brief I2C发送一个字节的数据
    54. *
    55. * @param[in] byt - 待发送的字节
    56. * @return none
    57. */
    58. void i2c_sendbyte(unsigned char byt)
    59. {
    60. unsigned char i;
    61. //
    62. EA = 0;
    63. for(i=0; i<8; i++){
    64. scl = 0;
    65. i2c_delay(DELAY_TIME);
    66. if(byt & 0x80){
    67. sda = 1;
    68. }
    69. else{
    70. sda = 0;
    71. }
    72. i2c_delay(DELAY_TIME);
    73. scl = 1;
    74. byt <<= 1;
    75. i2c_delay(DELAY_TIME);
    76. }
    77. EA = 1;
    78. //
    79. scl = 0;
    80. }
    81. /**
    82. * @brief 等待应答
    83. *
    84. * @param[in] none
    85. * @param[out] none
    86. * @return none
    87. */
    88. unsigned char i2c_waitack(void)
    89. {
    90. unsigned char ackbit;
    91. scl = 1;
    92. i2c_delay(DELAY_TIME);
    93. ackbit = sda; //while(sda); //wait ack
    94. scl = 0;
    95. i2c_delay(DELAY_TIME);
    96. return ackbit;
    97. }
    98. /**
    99. * @brief I2C接收一个字节数据
    100. *
    101. * @param[in] none
    102. * @param[out] da
    103. * @return da - 从I2C总线上接收到得数据
    104. */
    105. unsigned char i2c_receivebyte(void)
    106. {
    107. unsigned char da;
    108. unsigned char i;
    109. //
    110. EA = 0;
    111. for(i=0;i<8;i++){
    112. scl = 1;
    113. i2c_delay(DELAY_TIME);
    114. da <<= 1;
    115. if(sda)
    116. da |= 0x01;
    117. scl = 0;
    118. i2c_delay(DELAY_TIME);
    119. }
    120. EA = 1;
    121. //
    122. return da;
    123. }
    124. /**
    125. * @brief 发送应答
    126. *
    127. * @param[in] ackbit - 设定是否发送应答
    128. * @return - none
    129. */
    130. void i2c_sendack(unsigned char ackbit)
    131. {
    132. scl = 0;
    133. sda = ackbit; //0:发送应答信号;1:发送非应答信号
    134. i2c_delay(DELAY_TIME);
    135. scl = 1;
    136. i2c_delay(DELAY_TIME);
    137. scl = 0;
    138. sda = 1;
    139. i2c_delay(DELAY_TIME);
    140. }
    141. /**
    142. * @brief 读写操作过程中一些必要的延时
    143. *
    144. * @param[in] i - 指定延时时间
    145. * @return - none
    146. */
    147. void operate_delay(unsigned char t)
    148. {
    149. unsigned char i;
    150. while(t--){
    151. for(i=0; i<112; i++);
    152. }
    153. }
    154. /**
    155. * @brief PCF8591初始化
    156. *
    157. * @param[in] none
    158. * @param[out] none
    159. * @return none
    160. */
    161. void init_pcf8591(void)
    162. {
    163. i2c_start();
    164. i2c_sendbyte(0x90); //1001 0000
    165. i2c_waitack();
    166. i2c_sendbyte(0x03); //0000 0011
    167. i2c_waitack();
    168. i2c_stop();
    169. operate_delay(10);
    170. }
    171. /**
    172. * @brief 通过I2C总线读取ADC结果
    173. *
    174. * @param[in] none
    175. * @param[out] temp - AD转换结果
    176. * @return - temp
    177. */
    178. unsigned char adc_pcf8591(void)
    179. {
    180. unsigned char temp;
    181. i2c_start();
    182. i2c_sendbyte(0x91);//1001 0001
    183. i2c_waitack();
    184. temp = i2c_receivebyte();
    185. i2c_sendack(1);
    186. i2c_stop();
    187. return temp;
    188. }

    DAC实例程序

    1. #include "reg52.h"
    2. #include "intrins.h"
    3. #define DELAY_TIME 5
    4. /** 定义I2C总线时钟线和数据线 */
    5. sbit scl = P2^0;
    6. sbit sda = P2^1;
    7. /**
    8. * @brief I2C总线中一些必要的延时
    9. *
    10. * @param[in] i - 延时时间调整.
    11. * @return none
    12. */
    13. void i2c_delay(unsigned char i)
    14. {
    15. do
    16. {
    17. _nop_();
    18. }
    19. while(i--);
    20. }
    21. /**
    22. * @brief 产生I2C总线启动条件.
    23. *
    24. * @param[in] none
    25. * @param[out] none
    26. * @return none
    27. */
    28. void i2c_start(void)
    29. {
    30. sda = 1;
    31. scl = 1;
    32. i2c_delay(DELAY_TIME);
    33. sda = 0;
    34. i2c_delay(DELAY_TIME);
    35. scl = 0;
    36. }
    37. /**
    38. * @brief 产生I2C总线停止条件
    39. *
    40. * @param[in] none
    41. * @param[out] none.
    42. * @return none
    43. */
    44. void i2c_stop(void)
    45. {
    46. sda = 0;
    47. scl = 1;
    48. i2c_delay(DELAY_TIME);
    49. sda = 1;
    50. i2c_delay(DELAY_TIME);
    51. }
    52. /**
    53. * @brief I2C发送一个字节的数据
    54. *
    55. * @param[in] byt - 待发送的字节
    56. * @return none
    57. */
    58. void i2c_sendbyte(unsigned char byt)
    59. {
    60. unsigned char i;
    61. //
    62. EA = 0;
    63. for(i=0; i<8; i++){
    64. scl = 0;
    65. i2c_delay(DELAY_TIME);
    66. if(byt & 0x80){
    67. sda = 1;
    68. }
    69. else{
    70. sda = 0;
    71. }
    72. i2c_delay(DELAY_TIME);
    73. scl = 1;
    74. byt <<= 1;
    75. i2c_delay(DELAY_TIME);
    76. }
    77. EA = 1;
    78. //
    79. scl = 0;
    80. }
    81. /**
    82. * @brief 等待应答
    83. *
    84. * @param[in] none
    85. * @param[out] none
    86. * @return none
    87. */
    88. unsigned char i2c_waitack(void)
    89. {
    90. unsigned char ackbit;
    91. scl = 1;
    92. i2c_delay(DELAY_TIME);
    93. ackbit = sda; //while(sda); //wait ack
    94. scl = 0;
    95. i2c_delay(DELAY_TIME);
    96. return ackbit;
    97. }
    98. /**
    99. * @brief I2C接收一个字节数据
    100. *
    101. * @param[in] none
    102. * @param[out] da
    103. * @return da - 从I2C总线上接收到得数据
    104. */
    105. //unsigned char i2c_receivebyte(void)
    106. //{
    107. // unsigned char da;
    108. // unsigned char i;
    109. // EA = 0;
    110. // for(i=0;i<8;i++){
    111. // scl = 1;
    112. // i2c_delay(DELAY_TIME);
    113. // da <<= 1;
    114. // if(sda)
    115. // da |= 0x01;
    116. // scl = 0;
    117. // i2c_delay(DELAY_TIME);
    118. // }
    119. // EA = 1;
    120. // return da;
    121. //}
    122. /**
    123. * @brief 发送应答
    124. *
    125. * @param[in] ackbit - 设定是否发送应答
    126. * @return - none
    127. */
    128. //void i2c_sendack(unsigned char ackbit)
    129. //{
    130. // scl = 0;
    131. // sda = ackbit; //0:发送应答信号;1:发送非应答信号
    132. // i2c_delay(DELAY_TIME);
    133. // scl = 1;
    134. // i2c_delay(DELAY_TIME);
    135. // scl = 0;
    136. // sda = 1;
    137. // i2c_delay(DELAY_TIME);
    138. //}
    139. /**
    140. * @brief 读写操作过程中一些必要的延时
    141. *
    142. * @param[in] i - 指定延时时间
    143. * @return - none
    144. */
    145. void operate_delay(unsigned char t)
    146. {
    147. unsigned char i;
    148. while(t--){
    149. for(i=0; i<112; i++);
    150. }
    151. }
    152. /**
    153. * @brief PCF8591初始化
    154. *
    155. * @param[in] none
    156. * @param[out] none
    157. * @return none
    158. */
    159. void init_pcf8591(void)
    160. {
    161. i2c_start();
    162. i2c_sendbyte(0x90);
    163. i2c_waitack();
    164. i2c_sendbyte(0x03); //ADC通道3
    165. i2c_waitack();
    166. i2c_stop();
    167. operate_delay(10);
    168. }
    169. /**
    170. * @brief 通过I2C总线读取ADC结果
    171. *
    172. * @param[in] none
    173. * @param[out] temp - AD转换结果
    174. * @return - temp
    175. */
    176. //unsigned char adc_pcf8591(void)
    177. //{
    178. // unsigned char temp;
    179. //
    180. // i2c_start();
    181. // i2c_sendbyte(0x91);
    182. // i2c_waitack();
    183. // temp = i2c_receivebyte();
    184. // i2c_sendack(1);
    185. // i2c_stop();
    186. //
    187. // return temp;
    188. //}
    189. /**
    190. * @brief DAC输出
    191. *
    192. * @param[in] dat - 输入进行数模转换的数据
    193. * @param[out] none
    194. * @return - temp
    195. */
    196. void dac_pcf8591(unsigned char dat)
    197. {
    198. i2c_start();
    199. i2c_sendbyte(0x90);
    200. i2c_waitack();
    201. i2c_sendbyte(0x40); //DAC输出模式 0100 0000
    202. i2c_waitack();
    203. i2c_sendbyte(dat);
    204. i2c_waitack();
    205. i2c_stop();
    206. }

  • 相关阅读:
    干货分享:谷歌主动搜索开发客户的万能公式
    巧用抽象类与接口,打造高效Java程序(上)
    2.数据及其预处理
    解决无法获取到B站点赞数和播放量的解决办法
    2022/7/27 算力-价格明细
    ansible unarchive 模块
    linux磁盘操作、分区、挂载、配额、raid5
    Shell快捷键大全
    旁路openwrt启用ipv6
    字符串讲解
  • 原文地址:https://blog.csdn.net/qq_54278925/article/details/128063570