PCF8591 应用程序
扫描二维码
随时随地手机看文章
PCF8591 的通信接口是 I2C,那么编程肯定是要符合这个协议的。单片机对 PCF8591 进行初始化,一共发送三个字节即可。第一个字节,和 EEPROM 类似,是器件地址字节,其中7位代表地址,1位代表读写方向。地址高4位固定是 0b1001,低三位是 A2,A1,A0,这三位我们电路上都接了 GND,因此也就是 0b000,如图17-5所示。
图17-5 PCF8591 地址字节
发送到 PCF8591 的第二个字节将被存储在控制寄存器,用于控制 PCF8591 的功能。其中第3位和第7位是固定的0,另外6位各自有各自的作用,如图17-6所示,我逐一介绍。
图17-6 PCF8591 控制字节
控制字节的第6位是 DA 使能位,这一位置1表示 DA 输出引脚使能,会产生模拟电压输出功能。第4位和第5位可以实现把 PCF8591 的4路模拟输入配置成单端模式和差分模式,单端模式和差分模式的区别,我们在17.5节有介绍,这里大家只需要知道这两位是配置 AD 输入方式的控制位即可,如图17-7所示。
图17-7 PCF8591 模拟输入配置方式
控制字节的第2位是自动增量控制位,自动增量的意思就是,比如我们一共有4个通道,当我们全部使用的时候,读完了通道0,下一次再读,会自动进入通道1进行读取,不需要我们指定下一个通道,由于 A/D 每次读到的数据,都是上一次的转换结果,所以同学们在使用自动增量功能的时候,要特别注意,当前读到的是上一个通道的值。为了保持程序的通用性,我们的代码没有使用这个功能,直接做了一个通用的程序。
控制字节的第0位和第1位就是通道选择位了,00、01、10、11代表了从0到3的一共4个通道选择。
发送给 PCF8591 的第三个字节 D/A 数据寄存器,表示 D/A 模拟输出的电压值。D/A 模拟我们一会介绍,大家知道这个字节的作用即可。我们如果仅仅使用 A/D 功能的话,就可以不发送第三个字节。
下面我们用一个程序,把 AIN0、AIN1、AIN3 测到的电压值显示在液晶上,同时大家可以转动电位器,会发现 AIN0 的值发生变化。 /*Lcd1602.c 文件程序源代码***/ (此处省略,可参考之前章节的代码) /*I2C.c 文件程序源代码***/ (此处省略,可参考之前章节的代码)
/*****************************main.c文件程序源代码******************************/#includebitflag300ms=1;//300ms定时标志unsignedcharT0RH=0;//T0重载值的高字节unsignedcharT0RL=0;//T0重载值的低字节voidConfigTimer0(unsignedintms);unsignedcharGetADCValue(unsignedcharchn);voidValueToString(unsignedchar*str,unsignedcharval);externvoidI2CStart();externvoidI2CStop();externunsignedcharI2CReadACK();externunsignedcharI2CReadNAK();externbitI2CWrite(unsignedchardat);externvoidInitLcd1602();externvoidLcdShowStr(unsignedcharx,unsignedchary,unsignedchar*str);voidmain(){unsignedcharval;unsignedcharstr[10];EA=1;//开总中断ConfigTimer0(10);//配置T0定时10msInitLcd1602();//初始化液晶LcdShowStr(0,0,"AIN0AIN1AIN3");//显示通道指示while(1){if(flag300ms){flag300ms=0;//显示通道0的电压val=GetADCValue(0);//获取ADC通道0的转换值ValueToString(str,val);//转为字符串格式的电压值LcdShowStr(0,1,str);//显示到液晶上//显示通道1的电压val=GetADCValue(1);ValueToString(str,val);LcdShowStr(6,1,str);//显示通道3的电压val=GetADCValue(3);ValueToString(str,val);LcdShowStr(12,1,str);}}}/*读取当前的ADC转换值,chn-ADC通道号0~3*/unsignedcharGetADCValue(unsignedcharchn){unsignedcharval;I2CStart();if(!I2CWrite(0x48<<1)){//寻址PCF8591,如未应答,则停止操作并返回0I2CStop();return0;}I2CWrite(0x40"chn);//写入控制字节,选择转换通道I2CStart();I2CWrite((0x48<<1)|0x01);//寻址PCF8591,指定后续为读操作I2CReadACK();//先空读一个字节,提供采样转换时间val=I2CReadNAK();//读取刚刚转换完的值I2CStop();returnval;}/*ADC转换值转为实际电压值的字符串形式,str-字符串指针,val-AD转换值*/voidValueToString(unsignedchar*str,unsignedcharval){//电压值=转换结果*2.5V/255,式中的25隐含了一位十进制小数val=(val*25)/255;str[0]=(val/10)+'0';//整数位字符str[1]='.';//小数点str[2]=(val%10)+'0';//小数位字符str[3]='V';//电压单位str[4]='