
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实例程序
- #include "reg52.h"
- #include "intrins.h"
-
- #define DELAY_TIME 5
-
- /** 定义I2C总线时钟线和数据线 */
- sbit scl = P2^0;
- sbit sda = P2^1;
-
- /**
- * @brief I2C总线中一些必要的延时
- *
- * @param[in] i - 延时时间调整.
- * @return none
- */
- void i2c_delay(unsigned char i)
- {
- do
- {
- _nop_();
- }
- while(i--);
- }
-
- /**
- * @brief 产生I2C总线启动条件.
- *
- * @param[in] none
- * @param[out] none
- * @return none
- */
- void i2c_start(void)
- {
- sda = 1;
- scl = 1;
- i2c_delay(DELAY_TIME);
- sda = 0;
- i2c_delay(DELAY_TIME);
- scl = 0;
- }
-
- /**
- * @brief 产生I2C总线停止条件
- *
- * @param[in] none
- * @param[out] none.
- * @return none
- */
- void i2c_stop(void)
- {
- sda = 0;
- scl = 1;
- i2c_delay(DELAY_TIME);
- sda = 1;
- i2c_delay(DELAY_TIME);
- }
-
- /**
- * @brief I2C发送一个字节的数据
- *
- * @param[in] byt - 待发送的字节
- * @return none
- */
- void i2c_sendbyte(unsigned char byt)
- {
- unsigned char i;
- //
- EA = 0;
- for(i=0; i<8; i++){
- scl = 0;
- i2c_delay(DELAY_TIME);
- if(byt & 0x80){
- sda = 1;
- }
- else{
- sda = 0;
- }
- i2c_delay(DELAY_TIME);
- scl = 1;
- byt <<= 1;
- i2c_delay(DELAY_TIME);
- }
- EA = 1;
- //
- scl = 0;
- }
-
- /**
- * @brief 等待应答
- *
- * @param[in] none
- * @param[out] none
- * @return none
- */
- unsigned char i2c_waitack(void)
- {
- unsigned char ackbit;
-
- scl = 1;
- i2c_delay(DELAY_TIME);
- ackbit = sda; //while(sda); //wait ack
- scl = 0;
- i2c_delay(DELAY_TIME);
-
- return ackbit;
- }
-
- /**
- * @brief I2C接收一个字节数据
- *
- * @param[in] none
- * @param[out] da
- * @return da - 从I2C总线上接收到得数据
- */
- unsigned char i2c_receivebyte(void)
- {
- unsigned char da;
- unsigned char i;
- //
- EA = 0;
- for(i=0;i<8;i++){
- scl = 1;
- i2c_delay(DELAY_TIME);
- da <<= 1;
- if(sda)
- da |= 0x01;
- scl = 0;
- i2c_delay(DELAY_TIME);
- }
- EA = 1;
- //
- return da;
- }
-
- /**
- * @brief 发送应答
- *
- * @param[in] ackbit - 设定是否发送应答
- * @return - none
- */
- void i2c_sendack(unsigned char ackbit)
- {
- scl = 0;
- sda = ackbit; //0:发送应答信号;1:发送非应答信号
- i2c_delay(DELAY_TIME);
- scl = 1;
- i2c_delay(DELAY_TIME);
- scl = 0;
- sda = 1;
- i2c_delay(DELAY_TIME);
- }
-
- /**
- * @brief 读写操作过程中一些必要的延时
- *
- * @param[in] i - 指定延时时间
- * @return - none
- */
- void operate_delay(unsigned char t)
- {
- unsigned char i;
-
- while(t--){
- for(i=0; i<112; i++);
- }
- }
-
- /**
- * @brief PCF8591初始化
- *
- * @param[in] none
- * @param[out] none
- * @return none
- */
- void init_pcf8591(void)
- {
- i2c_start();
- i2c_sendbyte(0x90); //1001 0000
- i2c_waitack();
- i2c_sendbyte(0x03); //0000 0011
- i2c_waitack();
- i2c_stop();
- operate_delay(10);
- }
-
- /**
- * @brief 通过I2C总线读取ADC结果
- *
- * @param[in] none
- * @param[out] temp - AD转换结果
- * @return - temp
- */
- unsigned char adc_pcf8591(void)
- {
- unsigned char temp;
-
- i2c_start();
- i2c_sendbyte(0x91);//1001 0001
- i2c_waitack();
- temp = i2c_receivebyte();
- i2c_sendack(1);
- i2c_stop();
-
- return temp;
- }
-
DAC实例程序
- #include "reg52.h"
- #include "intrins.h"
-
- #define DELAY_TIME 5
-
- /** 定义I2C总线时钟线和数据线 */
- sbit scl = P2^0;
- sbit sda = P2^1;
-
- /**
- * @brief I2C总线中一些必要的延时
- *
- * @param[in] i - 延时时间调整.
- * @return none
- */
- void i2c_delay(unsigned char i)
- {
- do
- {
- _nop_();
- }
- while(i--);
- }
-
- /**
- * @brief 产生I2C总线启动条件.
- *
- * @param[in] none
- * @param[out] none
- * @return none
- */
- void i2c_start(void)
- {
- sda = 1;
- scl = 1;
- i2c_delay(DELAY_TIME);
- sda = 0;
- i2c_delay(DELAY_TIME);
- scl = 0;
- }
-
- /**
- * @brief 产生I2C总线停止条件
- *
- * @param[in] none
- * @param[out] none.
- * @return none
- */
- void i2c_stop(void)
- {
- sda = 0;
- scl = 1;
- i2c_delay(DELAY_TIME);
- sda = 1;
- i2c_delay(DELAY_TIME);
- }
-
- /**
- * @brief I2C发送一个字节的数据
- *
- * @param[in] byt - 待发送的字节
- * @return none
- */
- void i2c_sendbyte(unsigned char byt)
- {
- unsigned char i;
- //
- EA = 0;
- for(i=0; i<8; i++){
- scl = 0;
- i2c_delay(DELAY_TIME);
- if(byt & 0x80){
- sda = 1;
- }
- else{
- sda = 0;
- }
- i2c_delay(DELAY_TIME);
- scl = 1;
- byt <<= 1;
- i2c_delay(DELAY_TIME);
- }
- EA = 1;
- //
- scl = 0;
- }
-
- /**
- * @brief 等待应答
- *
- * @param[in] none
- * @param[out] none
- * @return none
- */
- unsigned char i2c_waitack(void)
- {
- unsigned char ackbit;
-
- scl = 1;
- i2c_delay(DELAY_TIME);
- ackbit = sda; //while(sda); //wait ack
- scl = 0;
- i2c_delay(DELAY_TIME);
-
- return ackbit;
- }
-
- /**
- * @brief I2C接收一个字节数据
- *
- * @param[in] none
- * @param[out] da
- * @return da - 从I2C总线上接收到得数据
- */
- //unsigned char i2c_receivebyte(void)
- //{
- // unsigned char da;
- // unsigned char i;
-
- // EA = 0;
- // for(i=0;i<8;i++){
- // scl = 1;
- // i2c_delay(DELAY_TIME);
- // da <<= 1;
- // if(sda)
- // da |= 0x01;
- // scl = 0;
- // i2c_delay(DELAY_TIME);
- // }
- // EA = 1;
-
- // return da;
- //}
-
- /**
- * @brief 发送应答
- *
- * @param[in] ackbit - 设定是否发送应答
- * @return - none
- */
- //void i2c_sendack(unsigned char ackbit)
- //{
- // scl = 0;
- // sda = ackbit; //0:发送应答信号;1:发送非应答信号
- // i2c_delay(DELAY_TIME);
- // scl = 1;
- // i2c_delay(DELAY_TIME);
- // scl = 0;
- // sda = 1;
- // i2c_delay(DELAY_TIME);
- //}
-
- /**
- * @brief 读写操作过程中一些必要的延时
- *
- * @param[in] i - 指定延时时间
- * @return - none
- */
- void operate_delay(unsigned char t)
- {
- unsigned char i;
-
- while(t--){
- for(i=0; i<112; i++);
- }
- }
-
- /**
- * @brief PCF8591初始化
- *
- * @param[in] none
- * @param[out] none
- * @return none
- */
- void init_pcf8591(void)
- {
- i2c_start();
- i2c_sendbyte(0x90);
- i2c_waitack();
- i2c_sendbyte(0x03); //ADC通道3
- i2c_waitack();
- i2c_stop();
- operate_delay(10);
- }
-
- /**
- * @brief 通过I2C总线读取ADC结果
- *
- * @param[in] none
- * @param[out] temp - AD转换结果
- * @return - temp
- */
- //unsigned char adc_pcf8591(void)
- //{
- // unsigned char temp;
- //
- // i2c_start();
- // i2c_sendbyte(0x91);
- // i2c_waitack();
- // temp = i2c_receivebyte();
- // i2c_sendack(1);
- // i2c_stop();
- //
- // return temp;
- //}
-
- /**
- * @brief DAC输出
- *
- * @param[in] dat - 输入进行数模转换的数据
- * @param[out] none
- * @return - temp
- */
- void dac_pcf8591(unsigned char dat)
- {
- i2c_start();
- i2c_sendbyte(0x90);
- i2c_waitack();
- i2c_sendbyte(0x40); //DAC输出模式 0100 0000
- i2c_waitack();
-
- i2c_sendbyte(dat);
- i2c_waitack();
- i2c_stop();
- }
-
-