PCF8591数模转换模块与数码管的小实例

一、PCF8591介绍

  1. 电路图
    在这里插入图片描述

  2. 引脚介绍
    AIN0-AlN1是模拟输入端,分别接光敏电阻,热敏电阻,滑动变阻器。输入模拟值(即电压)。在芯片输入端内部有一个A/D转换器,可以把模拟量转换成数字量。然后cpu主机通过数据线SDA读取这个数字量。然后主机把这个数字量再次写给模块,通过内部的D/A转换器,通过Aout端输出模拟量。51单片机的AD模块处有一个三端的跳线。用来设置模拟端口3的输入。

  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);
	}
}


  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
基于PCF8591芯片AD DA实验例程C51单片机KEIL源码工程文件5个合集: PCF8591 1602液晶显示 PCF8591 1路AD数码管显示 PCF8591 4路AD数码管显示 PCF8591 DA输出模拟 PCF8591 输出锯齿波 main() { unsigned char num=0,i; unsigned char temp[7];//定义显示区域临时存储数组 float Voltage; //定义浮点变量 LCD_Init(); //初始化液晶 DelayMs(20); //延时有助于稳定 LCD_Clear(); //清屏 while (1) //主循环 { for(i=0;i<5;i++)//连续读5次,取最后一次,以便读取稳定值 num=ReadADC(0); //读取第1路电压值,范围是0-255 Voltage=(float)num*5/256; //根据参考电源VREF算出时间电压,float是强制转换符号,用于将结果转换成浮点型 sprintf(temp,"V0 %3.2f ",Voltage);//格式输出电压值,%3.2f 表示浮点输出,共3位数,小数点后2位 LCD_Write_String(0,0,temp); for(i=0;i<5;i++) num=ReadADC(1); Voltage=(float)num*5/256; sprintf(temp,"V1 %3.2f ",Voltage); LCD_Write_String(8,0,temp); for(i=0;i<5;i++) num=ReadADC(2); Voltage=(float)num*5/256; sprintf(temp,"V2 %3.2f ",Voltage); LCD_Write_String(0,1,temp); for(i=0;i<5;i++) num=ReadADC(3); Voltage=(float)num*5/256; sprintf(temp,"V3 %3.2f ",Voltage); LCD_Write_String(8,1,temp); //主循环中添加其他需要一直工作的程序 DelayMs(200); } } /*------------------------------------------------ 读AD转值程序 输入参数 Chl 表示需要转换的通道,范围从0-3 返回值范围0-255 ------------------------------------------------*/ unsigned char ReadADC(unsigned char Chl) { unsigned char Val; Start_I2c(); //启动总线 SendByte(AddWr); //发送器件地址 if(ack==0)return(0); SendByte(0x40|Chl); //发送器件子地址 if(ack==0)return(0); Start_I2c(); SendByte(AddWr+1); if(ack==0)return(0); Val=RcvByte(); NoAck_I2c(); //发送非应位 Stop_I2c(); //结束总线 return(Val); } /*------------------------------------------------ 写入DA转换数值 输入参数:dat 表示需要转换的DA数值,范围是0-255 ------------------------------------------------*/ /*bit WriteDAC(unsigned char dat) { Start_I2c(); //启动总线 SendByte(AddWr); //发送器件地址 if(ack==0)return(0); SendByte(0x40); //发送器件子地址 if(ack==0)return

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星光技术人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值