PCF8591 Applications

Publisher:ching80790Latest update time:2016-12-24 Source: eefocusKeywords:PCF8591 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

The communication interface of PCF8591 is I2C, so programming must comply with this protocol. The microcontroller initializes PCF8591 by sending a total of three bytes. The first byte, similar to EEPROM, is the device address byte, of which 7 bits represent the address and 1 bit represents the read/write direction. The high 4 bits of the address are fixed to 0b1001, and the low 3 bits are A2, A1, and A0. These three bits are connected to GND in our circuit, so they are 0b000, as shown in Figure 17-5.

Figure 17-5 PCF8591 address byte

Figure 17-5 PCF8591 address byte


The second byte sent to PCF8591 will be stored in the control register to control the function of PCF8591. The third and seventh bits are fixed to 0, and the other six bits have their own functions, as shown in Figure 17-6. I will introduce them one by one.

Figure 17-6 PCF8591 control byte

Figure 17-6 PCF8591 control byte


The sixth bit of the control byte is the DA enable bit. This bit is set to 1 to enable the DA output pin, which will generate an analog voltage output function. The fourth and fifth bits can be used to configure the 4 analog inputs of PCF8591 into single-ended mode and differential mode. The difference between single-ended mode and differential mode is introduced in Section 17.5. Here, you only need to know that these two bits are the control bits for configuring the AD input mode, as shown in Figure 17-7.

Figure 17-7 PCF8591 analog input configuration

Figure 17-7 PCF8591 analog input configuration


The second bit of the control byte is the auto-increment control bit. The meaning of auto-increment is that, for example, if we have 4 channels in total, when we use all of them, after reading channel 0, the next time we read, it will automatically enter channel 1 for reading, and we don’t need to specify the next channel. Since the data read by A/D each time is the result of the previous conversion, students should pay special attention to the fact that the current value read is the value of the previous channel when using the auto-increment function. In order to maintain the versatility of the program, our code does not use this function, and directly makes a general program.


Bits 0 and 1 of the control byte are the channel selection bits. 00, 01, 10, and 11 represent a total of 4 channel selections from 0 to 3.


The third byte sent to PCF8591 is the D/A data register, which indicates the voltage value of the D/A analog output. We will introduce D/A simulation later, and you only need to know the function of this byte. If we only use the A/D function, we don't need to send the third byte.


Next, we use a program to display the voltage values ​​measured by AIN0, AIN1, and AIN3 on the LCD. At the same time, you can turn the potentiometer and find that the value of AIN0 changes.

/***************************Lcd1602.c file program source code********************************/

(Omitted here, please refer to the code in the previous section)

/********************************I2C.c file program source code*******************************/

(Omitted here, please refer to the code in the previous section)

/********************************main.c file program source code******************************/

#include

bit flag300ms = 1; //300ms timing flag

unsigned char T0RH = 0; //T0 high byte of reload value

unsigned char T0RL = 0; //Low byte of T0 reload value

void ConfigTimer0(unsigned int ms);

unsigned char GetADCValue(unsigned char chn);

void ValueToString(unsigned char *str, unsigned char val);

extern void I2CStart();

extern void I2CStop();

extern unsigned char I2CReadACK();

extern unsigned char I2CReadNAK();

extern bit I2CWrite(unsigned char dat);

extern void InitLcd1602();

extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);

void main(){

    unsigned char val;

    unsigned char str[10];

   

    EA = 1; // Enable general interrupt

    ConfigTimer0(10); //Configure T0 timing 10ms

    InitLcd1602(); //Initialize LCD

    LcdShowStr(0, 0, "AIN0 AIN1 AIN3"); //Show channel indication

   

    while (1){

        if (flag300ms){

            flag300ms = 0; //Display the voltage of channel 0

            val = GetADCValue(0); //Get the conversion value of ADC channel 0

            ValueToString(str, val); //Convert voltage value to string format

            LcdShowStr(0, 1, str); //Display on LCD

            //Display the voltage of channel 1

            val = GetADCValue(1);

            ValueToString(str, val);

            LcdShowStr(6, 1, str);

            //Display the voltage of channel 3

            val = GetADCValue(3);

            ValueToString(str, val);

            LcdShowStr(12, 1, str);

        }

    }

}

/* Read the current ADC conversion value, chn-ADC channel number 0~3 */

unsigned char GetADCValue(unsigned char chn){

    unsigned char val;

    I2CStart();

    if (!I2CWrite(0x48<<1)){ //Address PCF8591. If no response, stop the operation and return 0

        I2CStop();

        return 0;

    }

    I2CWrite(0x40|chn); //Write control byte and select conversion channel

    I2CStart();

    I2CWrite((0x48<<1)|0x01); //Address PCF8591, specify the subsequent read operation

    I2CReadACK(); //Read a byte first to provide sampling conversion time

    val = I2CReadNAK(); //Read the value just converted

    I2CStop();

    return val;

}

/* ADC conversion value is converted to the string form of the actual voltage value, str-string pointer, val-AD conversion value*/

void ValueToString(unsigned char *str, unsigned char val){

    //Voltage value = conversion result * 2.5V/255, where 25 implies a decimal place

    val = (val*25) / 255;

    str[0] = (val/10) + '0'; // integer character

    str[1] = '.'; //decimal point

    str[2] = (val%10) + '0'; //decimal character

    str[3] = 'V'; //voltage unit

    str[4] = '\0'; //Terminator

}

/* Configure and start T0, ms-T0 timing time*/

void ConfigTimer0(unsigned int ms){

    unsigned long tmp; //temporary variable

    tmp = 11059200 / 12; //Timer counting frequency

    tmp = (tmp * ms) / 1000; //Calculate the required count value

    tmp = 65536 - tmp; //Calculate the timer reload value

    tmp = tmp + 12; //Compensate for the error caused by interrupt response delay

    T0RH = (unsigned char)(tmp>>8); //Timer reload value is split into high and low bytes

    T0RL = (unsigned char)tmp;

    TMOD &= 0xF0; // Clear the control bit of T0

    TMOD |= 0x01; //Configure T0 to mode 1

    TH0 = T0RH; //Load T0 reload value

    TL0 = T0RL;

    ET0 = 1; // Enable T0 interrupt

    TR0 = 1; //Start T0

}

/* T0 interrupt service function, execute 300ms timing*/

void InterruptTimer0() interrupt 1{

    static unsigned char tmr300ms = 0;

    TH0 = T0RH; //Reload the reload value

    TL0 = T0RL;

    tmr300ms++;

    if (tmr300ms >= 30){ //timing 300ms

        tmr300ms = 0;

        flag300ms = 1;

    }

}

Students who read the program carefully will find that when the program performs A/D reading, it uses two programs to read 2 bytes: I2CReadACK(); val = I2CReadNAK(); The conversion clock of PCF8591 is the SCL of I2C, and 8 SCL cycles complete a conversion, so the current conversion result can only be read on the 8 SCL of the next byte. Therefore, the first statement here is used to generate an overall SCL clock to provide PCF8591 for A/D conversion, and the second is to read the current conversion result. If we only use the second statement, each time we read the previous conversion result.


Keywords:PCF8591 Reference address:PCF8591 Applications

Previous article:MCU SPI communication interface
Next article:A problem that needs attention in the multiplication operation of MSP430G2333 lower computer

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号