PCF8591引脚图与原理图
蓝桥杯比赛中,PCF8591用于进行AD/DA转换,有模拟输入通道AN1光敏电阻和AN3滑动变阻。
使用时需明细通道。
PCF8591如何使用及代码
蓝桥杯比赛中,PCF8591可以进行AD转换读取和DA转换写入操作。
以下介绍AD转换读取操作,即通过光敏电阻或滑变读取模拟量转换为数字量的过程。
一:发送地址字节:
系统中的每个PCF8591芯片都有I2C总线系统控制,使用第一步需要通过I2C总线发送地址字节来激活PCF8591芯片,通过翻阅芯片手册可知,地址字节如下:
由上述原理图可知,蓝桥杯比赛版上A2=A1=A0=0,系统中只有一个PCF8591芯片,故仅需改变最低位来控制芯片的读写操作,发送0x91 = 1001 0001为读取,发送0x90 = 1001 0000为写入。
二:发送控制字节
第二步需要通过总线发送控制字节来告诉芯片选用哪一通道,使用时需注意第0位,第1位,第6位。前两位负责选用AD通道,第六位是输出使能位,其余位蓝桥杯不涉及,暂未了解。蓝桥杯比赛中有channel1 光敏电阻,channel 3 变阻器。选用channel1 则发送0x41 = 0100 0001选用光敏,选用channel 3则发送 0x43 = 0100 0011选用滑动变阻器。
三:AD转换读取函数:
以上两步结合总结,可以得出AD转换读取函数的流程,即:
发送地址字节,告诉芯片需要写入数据->发送控制字节,告诉芯片要选用哪一通道
发送地址字节,告诉芯片需要读取数据->将数据从芯片中读出,通过变量传出函数。
具体代码如下:
unsigned char AD_Read(unsigned char addr)
{
unsigned char temp;
I2CStart();
I2CSendByte(0x90); //发送地址字节-写入
I2CWaitAck();
I2CSendByte(addr); //发送控制字节-选中通道
I2CWaitAck();
I2CStart();
I2CSendByte(0x91); //发送地址字节-读取
I2CWaitAck();
temp = I2CReceiveByte();//读取操作
I2CSendAck(1);
I2CStop();
return temp; //将读取结果传出
}
以上代码中I2CStart(),I2CWaitAck()等操作是I2C总线的使用要求,与本芯片无关。通过上述代码将数字量temp读取出,其范围为0-255,比赛板的电压为5v,若想将表示为模拟量电压显示在数码管上,需要进行一步转换操作:
temp = temp * (5.0 / 255);
四:DA转换写入函数:
DA转换的思路同AD转换,只不过在DA转换中不需要考虑发送控制字节选用哪一通道的问题,只需保证控制字节中第6位使能位为1即可。具体代码如下:
DA_Write(unsigned char dat)
{
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x41); //0x40也可,仅需保证D6 = 1
I2CWaitAck();
I2CSendByte(dat);
I2CSendAck(1);
I2CStop();
}
五:主函数中如何使用:
仅演示如何使用AD_Read函数:
unsigned char dat; //定义一变量存放读取后的数据
void Seg_Proc()
{
if(Seg_Slow_Down) return;
Seg_Slow_Down = 1;
/*** 信息读取区域 ***/
/* DS1302时钟 */
// RTC_Read(ucRTC);
/* DS18B20温度 */
// temperature = Temperature_Read();
/* PCF8591 AD/DA */
dat = AD_Read(0x43);
/*** 数据处理区域 ***/
/* DS1302时钟 */
// Seg_Buf[0] = ucRTC[0] / 16; //时第一位
// Seg_Buf[1] = ucRTC[0] % 16;
// Seg_Buf[2] = 11;
// Seg_Buf[3] = ucRTC[1] / 16; //分第一位
// Seg_Buf[4] = ucRTC[1] % 16;
// Seg_Buf[5] = 11;
// Seg_Buf[6] = ucRTC[2] / 16; //秒第一位
// Seg_Buf[7] = ucRTC[2] % 16;
/* DS18B20温度 */
// Seg_Buf[0] = (unsigned char)temperature / 10 % 10;
// Seg_Buf[1] = (unsigned char)temperature % 10;
// Seg_Point[1] = 1;
// Seg_Buf[2] = (unsigned int)(temperature * 100) % 10;
// Seg_Buf[3] = (unsigned int)(temperature * 10) % 10;
/* PCF8591 AD/DA */
Seg_Buf[0] = dat / 100 % 10; //这里显示的是未经处理的数字量,范围0-255
Seg_Buf[1] = dat / 10 % 10;
Seg_Buf[2] = dat % 10;
/* AT24C02 EEPROM存储 */
// Seg_Buf[0] = EEPROM_Dat[0] / 10;
// Seg_Buf[1] = EEPROM_Dat[0] % 10;
//
// Seg_Buf[6] = EEPROM_Dat[1] / 10;
// Seg_Buf[7] = EEPROM_Dat[1] % 10;
}