一、PCF8591介绍
-
电路图
-
引脚介绍
AIN0-AlN1是模拟输入端,分别接光敏电阻,热敏电阻,滑动变阻器。输入模拟值(即电压)。在芯片输入端内部有一个A/D转换器,可以把模拟量转换成数字量。然后cpu主机通过数据线SDA读取这个数字量。然后主机把这个数字量再次写给模块,通过内部的D/A转换器,通过Aout端输出模拟量。51单片机的AD模块处有一个三端的跳线。用来设置模拟端口3的输入。 -
与AT24C02的区别
AT24C02在主机发送寻址命令之后,需要发送片内寻址。PCF8591在芯片地址寻址之后需要选择通道;
D7:特征位固定值0
D6:使能模拟输出AOUT有效(1位有效),当D/A转换时必须是高电平,A/D转换是爱谁谁反正也用不上
D5,D4:模拟量输入选择,就是4个模拟输入的连接方式。00为四路单端输入、01为三路差分输入、10为两路单端与一路差分输入、11为两路差分输入。现在我只用上了00.至于其他的咋用,为什么那么用等用到了再说。
D3 特征位:固定值为:0。
D1、D0 两位是A/D通道编号:00通道0,01通道1,10通道2,11通道3
D2 自动增量选择(0为禁止自动增量,1为允许自动增量),如果允许自动增量,则在每次A/D转换后,通道编号会自动递增。这个我也暂时不知道有什么用处。
下边是一个PCF8591与数码管的小实例。通过光的强弱控制数码管的数据;
思路过程:1)光敏电阻控制输入模拟电压的大小
2)PCF8591输入端A/D转换,生成数字量
3)主机读取数字量
4)数码管显示
5)主机又把数字量传给pcf8591,通过D/A转换位模拟量输出,通过与之相连的二极管可以看出模拟量的大小
- A/D转换
void READ_A_D(uchar chnnel_byte)//读PCF5891某通道的数字信息,在芯片内部已经把模拟电压转换为数字信息(A/D转换),送到数据线;等待主机读取
{
init();
start();
write_byte(0x90);//PCF的地址为0090
respons();
write_byte(chnnel_byte);//选择通道一,光敏电阻输入
respons();
start();
write_byte(0x91);
respons();
date=rec_byte();
respons();
stop();
}
- D/A转换
void sent_D_A(uchar date)//把主机从PCF8591读到的数据送给数据线,PCF8591捕获。然后经过内部DA转换从AOUT引脚输出模拟量
{
init();
start();
write_byte(0x90);
respons();
write_byte(0x40);//01000000,Aout使能
respons();
write_byte(date);
respons();
stop();
}
完整代码如下:这里用的是QX-MCS51的板子,个别引脚会与TX-1C有不同
#include<reg51.h>
#define uchar unsigned char
//#define fun(x) (int)(5*x/255.0*100+0.5)
sbit SCL=P2^1;
sbit SDA=P2^0;
sbit dula=P2^6;
sbit wela=P2^7;
uchar date;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7b,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay()
{;;}
void init()
{
SDA=1;
delay();
SCL=1;
delay();
}
void start()
{
SCL=1;
SDA=1;
delay();
SDA=0;
delay();
}
void stop()
{
SCL=1;
SDA=0;
delay();
SDA=1;
delay();
}
void respons()
{
SCL=1;
delay();
SDA=0;
delay();
SCL=0;
delay();
}
void write_byte(uchar byte)//主机发送数据
{
uchar i;
for(i=0;i<8;i++)
{
SCL=0;
delay();
if(byte & 0x80)
{
SDA=1;
delay();
}
else
{
SDA=0;
delay();
}
SCL=1;
delay();
byte=byte<<1;
}
SCL=0;
delay();
SDA=1;
delay();
}
uchar rec_byte()//主机接收数据
{
uchar i,k;
SCL=0;
delay();
SDA=1;
delay();
for(i=0;i<8;i++)
{
SCL=1;
delay();
if(SDA)
k=k|0x01;
k=k<<1;
delay();
SCL=0;
delay();
}
return k;
}
void READ_A_D(uchar chnnel_byte)//读PCF5891某通道的数字信息,在芯片内部已经把模拟电压转换为数字信息,从SDA输出到数据线;等待主机读取
{
init();
start();
write_byte(0x90);//PCF的地址为0090
respons();
write_byte(chnnel_byte);//选择通道一,光敏电阻输入
respons();
start();
write_byte(0x91);
respons();
date=rec_byte();
respons();
stop();
}
void sent_D_A(uchar date)//把从PCF8591读到的数据送给数据线,PCF8591捕获。然后经过内部DA转换从AOUT引脚输出模拟量
{
init();
start();
write_byte(0x90);
respons();
write_byte(0x40);
respons();
write_byte(date);
respons();
stop();
}
void delayms(uchar time_num)
{
uchar i,j;
for(i=time_num;i>0;i--)
for(j=110;j>0;j--);
}
void display(uchar num)
{
uchar bai,shi,ge,show_num;
show_num=num;
bai=show_num/100;
shi=(show_num%100)/10;
ge=show_num%10;
dula=1;
P0=table[bai];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
wela=0;
delayms(5);
dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delayms(5);
dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;
wela=0;
delayms(5);
}
void main()
{
init();
while(1)
{
READ_A_D(0x00);
sent_D_A(date);
delayms(50);
display(date);
}
}