pcf8591c语言编程,学51单片机-基于PCF8591的AD采样和DA输出

首先思考一个问题,我们的世界是数字的还是模拟的?

当然是模拟的了,所有的量都是在一定范围内连续变化的。我们为了能够更加方便的描述这些量,对它们进行了数字化。而数字量就不一样了,它是分立的的几个值。

举个例子,我们形容一个人的身高,模拟的说法是一米七到一米七五之间,数字的说法就是一米七三。

接下来说AD转换器,它的出现也是为了让我们能更方便、更直接的描述电压的高低。AD转换器,英文全称为Analog-to-Digital Converter,是模拟量到数字量的一个转换过程,主要用于电压的采集。它的出现就如同有了一把尺子,很容易就能量出电压的高低。

在电子设备中,经常要检测各种模拟量:温度、压力、速度、流量、重力加速度等等,这些模拟量都被相应的传感器转换为电压信号,我们只需要测量电压的高低,就能得到相应参数。

AD的主要参数有哪些?

1、AD的位数:表明这个AD共有2^n个刻度,8位AD,输出的刻度是0~255.

2、分辨率:就是AD能够分辨的最小的模拟量变化,假设5.10V的系统用8位的AD采样,那么它能分辨的最小电压就是5.10/255=0.02V。

3、INL:Interger NONliner 积分非线性度,表示了ADC器件在所有的数值点上对应的模拟值,和真实值之间误差最大的那一点的误差值。也就是,输出数值偏离线性最大的距离。单位是LSB(即最低位所表示的量)。比如12位ADC:TLC2543,INL值为1LSB。那么,如果基准4.095V,测某电压得的转换结果是1000,那么,真实电压值可能分布在0.999~1.001V之间。

4、DNL:Differencial NonLiner-差分非线性度,理论上说,模数器件相邻量个数据之间,模拟量的差值都是一样的。就相一把疏密均匀的尺子。但实际并不如此。一把分辨率1毫米的尺子,相邻两刻度之间也不可能都是1毫米整。那么,ADC相邻两刻度之间最大的差异就叫差分非线性值(Differencial NonLiner)。DNL值如果大于1,那么这个ADC甚至不能保证是单调的,输入电压增大,在某个点数值反而会减小。这种现象在SAR(逐位比较)型ADC中很常见。

5、基准源:有内部基准源、外部基准源等等。

6、转换速率:也就是转换周期的倒数,转换周期就是完成一次AD转换所需的时间。

今天要用到的器件是PCF8591,为什么选它?太多的开发板上用它做演示了,而且还是IIC总线通信的。既学习了AD采样,又学习了IIC总线。

先上应用电路:

888dce775788c7357337dc3a178d815f.png

如上图所示,PCF8591的9脚和10脚,一个是数据线SDA,一个是时钟线SCL。分别接到单片机的P2.0 , P2.1上面。

为什么选这两个引脚?因为51单片机上没有IIC总线接口,需要用普通的IO模拟,所以它随便选了两个IO接上就行。

VREF是什么?基准电压,也是它能测量的最大电压。

如何控制?今天先不说IIC总线,只说控制流程。

看器件手册可以知道:

6a79b0c360ccaea71d703b514f70fafb.png

d84c816d154e52dccdecfdf8a49ef135.png

cb0a38c537c65617cb4dd8c31576e88c.png

ba8565d146e274e6ad8d17c5133d5f60.png

1ac722ecc27a70a469793e7df8f730ef.png

0f87af43f7e62a4631d228dcbaedf52b.png

  • 6
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值