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.
Previous article:MCU SPI communication interface
Next article:A problem that needs attention in the multiplication operation of MSP430G2333 lower computer
- Popular Resources
- Popular amplifiers
- MCU C language programming and Proteus simulation technology (Xu Aijun)
- 51 Single Chip Microcomputer Basic Experiment and Comprehensive Practice (Edited by Li Zuojin, Nie Ling, and Zhai Yuan)
- AUTOSAR MCAL Principles and Practice
- 51 Single Chip Microcomputer C Language Programming Classic Examples (2nd Edition) (Hou Yubao)
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- 3m semi-anechoic chamber, 10m semi-anechoic chamber
- Talk about the development prospects of analog circuits
- Mobile revenue exceeds Telecom and Netcom; fixed-line operators eagerly await 3G
- [2022 Digi-Key Innovation Design Competition] Part 3: Understanding the setting of Chinese characters and TouchGFX with development board installed
- 【TouchGFX Design】+ Several problems encountered and attempts at button functions
- N32G430C8L7 development board ADC temperature test
- [Xianji HPM6750EVKMINI Review] 6# HPM6750 for SD Operation
- EEWORLD University ---- Computer Vision and Deep Learning
- [Erha Image Recognition Artificial Intelligence Vision Sensor] 2. Firmware upgrade & power-on experience face recognition and object recognition
- Multimeter and infrared thermometer are waiting for you to disassemble! —— EEWorld disassembles for you to play (Part 2)