蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用


蓝桥杯单片机之PCF8591模块的使用

    • 简述
    • 原理图:
    • 引脚定义:
    • 相关地址
      • IIC寻址设备地址
      • 控制地址
    • IIC时序分析
    • 数模转换D/A
      • 模数转换公式
    • 代码:
      • 一:光敏电阻和可变电阻的AD转换,S4控制模式的切换
      • 二:输出定量的模拟电压

简述 PCF8591是一款单芯片、单电源、低功耗、8位CMOS数
据采集器件,具有四路模拟输入、一路模拟输出和一个
串行I2C总线接口。
通过I2C总线的串行输入/输出
原理图: 【蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用】蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

引脚定义:
SYMBOL PIN DESCRIPTION 译文
AIN0 1 analog inputs (A/D converter) 模拟输入
AIN1 2
AIN2 3
AIN3 4
A0 5 hardware address 硬件地址
A1 6
A2 7
VSS 8 negative supply voltage 负电压
SDA 9 I2C-bus data input/output IIC数据线
SCL 10 I2C-bus clock input IIC时间线
OSC 11 oscillator input/output 振荡器输入输出
EXT 12 external/internal switch for oscillator input 振荡器输入的外部/内部开关
AGND 13 analog ground 模拟接地
VREF 14 voltage reference input 基准电压(已经接了VCC)
AOUT 15 analog output (D/A converter) 模拟输出
VDD 16 positive supply voltage 正电压
相关地址 IIC寻址设备地址
蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

前四位固定为1001,根据原理图可以知道A2、A1、A0都是接地低电平0;所以PCF8591的写地址为 0X90,读地址为 0X91 ;
控制地址
蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

bit0-bit1:通道选择,00为AIN0通道,01为AIN1通道,10为AIN2通道,11为AIN3通道。根据蓝桥杯单片机开发板,其中AIN0接在J3排针的外部A/D输入通道,AIN1接在光敏电阻,AIN3接在RB2电位器(可调电阻)。
bit3:自动增量使能位(1有效): 如果自动增量(auto-increment)标志置1,每次A/D 转换后通道号将自动增加。
bit5-bit6:输入模式选择位:00为单端输入,01为三个差分输入,10为单端和差分混合输入,11为两个差分输入;一般设置为为单端输入00
bit7:运行模拟电压输出位,进行DA转换时需要置1;
IIC时序分析 写操作:
蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

起始(START)——>设备地址(Device Address)<写操作的地址>——>PCF8591的应答信号(ACK)——>写入控制字(Control Byte)——>PCF8591的应答信号(ACK)——>写入数据字(DATA)——>PCF8591应答信号(ACK)
读操作:
蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

单字节读取 :起始(START)——>设备地址(Device Address)<读操作的地址>——>PCF8591的应答信号(ACK)——>读取数据(Data Byte)——>主机的的应答信号(ACK)——>停止
数模转换D/A 将总线上接收到的数字量转换成模拟量在AOUT输出,主要利用IIC的写操作来实现数据写入,进而输出对应的模拟电压。
计算公式:
V O U T = 255 × D A T A V R E F {V}_{OUT}=255\times \frac {DATA} {{V}_{REF}} VOUT?=255×VREF?DATA?
蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

模数转换公式
将AINx端口输入的模拟电压转换成数字量并发送到总线,主要利用IIC的读操作来实现数据读取,进而显示对应的模拟电压。
数模转换公式:
蓝桥杯单片机|蓝桥杯单片机之PCF8591模块的使用
文章图片

代码: 一:光敏电阻和可变电阻的AD转换,S4控制模式的切换
#include "reg52.h" #include "iic.h"sbit S4 = P3^3; unsigned char Rd1 = 0; //光敏电阻AIN1 unsigned char Rd2 = 0; //可调电阻AIN3 unsigned char status = 0; //按键状态记录unsigned char SMG_NoDot[19] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f,0xff}; //0-9、A-F、'-'、'.'0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf}; //---------------------------------简单延时函数------------------------- void Delay(unsigned int t) { while(t--); }void Delay500us()//@12.000MHz { unsigned char i, j; i = 6; j = 211; do { while (--j); } while (--i); } void Digital_Tube(unsigned char Position,unsigned char Typeface)//Position是数码管第几位(从左到右,0开始),Typeface是显示的字样 { unsigned char Bit[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; P2 = P2 & 0x1f | 0xc0; P0=Bit[Position]; P2 = P2 & 0x1f | 0xe0; P0=Typeface; Delay500us(); P0=0XFF; P2 = P2 & 0x1f ; //数码管消影 } //---------------------------------数码管AD显示---------------------- void Display_PCF8591(unsigned char channel,unsigned char dat) { Digital_Tube(0,SMG_NoDot[16]); Digital_Tube(1,SMG_NoDot[channel]); Digital_Tube(2,SMG_NoDot[16]); Digital_Tube(3,0xff); Digital_Tube(4,0xff); Digital_Tube(5,SMG_NoDot[dat/100]); Digital_Tube(6,SMG_NoDot[dat/10%10]); Digital_Tube(7,SMG_NoDot[dat%10]); }//----------------------------读取光敏AD-----------------------------------//PCF8591的设备的读操作地址为:0x91;而写操作地址则为:0x90 //光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01。 //电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。 void Read_Rd1_Data(void) { IIC_Start(); //IIC总线起始信号 IIC_SendByte(0x90); //发送PCF8591设备地址 写操作 IIC_WaitAck(); //等待回应 IIC_SendByte(0x01); //发送AIN模拟通道号AIN3 IIC_WaitAck(); //等待回应 IIC_Stop(); //IIC总线停止信号Display_PCF8591(1,Rd1); IIC_Start(); //起始信号 IIC_SendByte(0x91); //发送PCF8591设备地址 读操作 IIC_WaitAck(); //等待回应 Rd1 = IIC_RecByte(); //读取数据 IIC_SendAck(1); //发送非应答信号 IIC_Stop(); //IIC总线停信号Display_PCF8591(1,Rd1); }//-----------------------------读取滑动电阻AD----------------------------- void Read_Rd2_Data(void) { IIC_Start(); //IIC总线起始信号 IIC_SendByte(0x90); //发送PCF8591设备地址 写操作 IIC_WaitAck(); //等待回应 IIC_SendByte(0x03); //发送AIN模拟通道号AIN3 IIC_WaitAck(); //等待回应 IIC_Stop(); //IIC总线停止信号Display_PCF8591(3,Rd2); IIC_Start(); //起始信号 IIC_SendByte(0x91); //发送PCF8591设备地址 读操作 IIC_WaitAck(); //等待回应 Rd2 = IIC_RecByte(); //读取数据 IIC_SendAck(1); //发送非应答信号 IIC_Stop(); //IIC总线停信号Display_PCF8591(3,Rd2); }//----------------------------------按键切换控制---------------------------- void Key_Tackle(void) { if(S4 == 0) { Delay(20); if(S4 == 0) { if(status == 0) { status = 1; while(S4 == 0) { Display_PCF8591(1,Rd1); } }else if(status == 1) { status = 0; while(S4 == 0) { Display_PCF8591(3,Rd2); }} } } }void main(void) { Read_Rd1_Data(); //上电默认进行光敏数据采集 while(1) { Key_Tackle(); if(status == 0) { Read_Rd1_Data(); } else { Read_Rd2_Data(); } } }

二:输出定量的模拟电压
在开发板右侧排针D/A引脚输出模拟电压,输出的电压跟芯片的基准电压相关,可能会比实际小一点,需要自己微调。
#include "reg52.h" #include "iic.h"void Analog_Out(unsigned char DATA) { IIC_Start(); //IIC总线起始信号 IIC_SendByte(0x90); //发送PCF8591设备地址 写操作 IIC_WaitAck(); //等待回应 IIC_SendByte(0X40); //发送AIN模拟通道号AIN0输出模式 IIC_WaitAck(); //等待回应 IIC_SendByte(DATA); //发送模拟电压对应的数据 IIC_WaitAck(); //等待回应 IIC_Stop(); //IIC总线停止信号 }void main(void) { while(1) { Analog_Out(256*3/5-1); } }

    推荐阅读