首先思考一个问题,我们的世界是数字的还是模拟的?
当然是模拟的了,所有的量都是在一定范围内连续变化的。我们为了能够更加方便的描述这些量,对它们进行了数字化。而数字量就不一样了,它是分立的的几个值。
举个例子,我们形容一个人的身高,模拟的说法是一米七到一米七五之间,数字的说法就是一米七三。
接下来说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总线。
先上应用电路:
如上图所示,PCF8591的9脚和10脚,一个是数据线SDA,一个是时钟线SCL。分别接到单片机的P2.0 , P2.1上面。
为什么选这两个引脚?因为51单片机上没有IIC总线接口,需要用普通的IO模拟,所以它随便选了两个IO接上就行。
VREF是什么?基准电压,也是它能测量的最大电压。
如何控制?今天先不说IIC总线,只说控制流程。
看器件手册可以知道:
分四步:
1、发送地址字节,选择该器件。
2、发送控制字节,选择相应通道。 //
3、重新发送地址字节,选择该器件。
4、接收目标通道的数据。
这次的程序流程是:AD采样,串口发送,循环执行。
下面是AD采样源代码:
/**********************51单片机学习例程************************
* 平台:Keil U4 + STC89C52
* 名称:AD采样+串口发送
* 编写:起航
* 晶体:11.0592MHZ
******************************************************************/
#include #include typedef unsigned char uint8; typedef unsigned int uint16; #define SLAVEADDR 0x90 //定义器件地址 #define nops() do{_nop_();_nop_();_nop_();_nop_();_nop_();} while(0) //定义空指令 sbit SCL = P2^1; //I2C 时钟 sbit SDA = P2^0; //I2C 数据 void delay(uint16 n) { while (n--); } /** * 函数: i2c_start() * 功能: 启动i2c 起始信号 */ void i2c_start() { SCL = 1; nops(); SDA = 1; nops(); SDA = 0; nops(); SCL = 0; } /** * 函数: i2c_stop() * 功能: 停止i2c */ void i2c_stop() { SCL = 0; nops(); SDA = 0; nops(); SCL = 1; nops(); SDA = 1; nops(); } /** * 函数: i2c_ACK(bit ck) * 功能: ck为1时发送应答信号ACK, * ck为0时不发送ACK */ void i2c_ACK(bit ck) { if (ck) SDA = 0; else SDA = 1; nops(); SCL = 1; nops(); SCL = 0; nops(); SDA = 1; nops(); } /** * 函数: i2c_waitACK() * 功能: 返回为0时收到ACK * 返回为1时没收到ACK */ bit i2c_waitACK() { SDA = 1; nops(); SCL = 1; nops(); if (SDA) { SCL = 0; i2c_stop(); return 1; } else { SCL = 0; return 0; } } /** * 函数: i2c_sendbyte(uint8 bt) * 功能: 将输入的一字节数据bt发送 */ void i2c_sendbyte(uint8 bt) { uint8 i; for(i=0; i<8; i++) { if (bt & 0x80) SDA = 1; else SDA = 0; nops(); SCL = 1; bt <<= 1; nops(); SCL = 0; } } /** * 函数: i2c_recbyte( ) * 功能: 从总线上接收1字节数据 */ uint8 i2c_recbyte() { uint8 dee, i; for (i=0; i<8; i++) { SCL = 1; nops(); dee <<= 1; if (SDA) dee = dee | 0x01; SCL = 0; nops(); } return dee; } /** * 函数: i2c_readbyte * 输入: addr * 功能: 读出一字节数据 * 返回值: 0->成功 1->失败 */ bit i2c_readbyte(uint8 com, uint8 *dat) { i2c_start(); i2c_sendbyte(SLAVEADDR); //地址 if (i2c_waitACK()) return 1; i2c_sendbyte(com); //控制字节 if (i2c_waitACK()) return 1; i2c_start(); i2c_sendbyte(SLAVEADDR+1); //地址 if (i2c_waitACK()) return 1; *dat = i2c_recbyte(); //读数据 i2c_ACK(0); //因为只读一字节数据,不发送ACK信号 i2c_stop(); return 0; } /** * UART初始化 * 波特率:9600 */ void uart_init(void) { ET1=0; TMOD = 0x21; // 定时器1工作在方式2(自动重装) SCON = 0x50; // 10位uart,允许串行接受 TH1 = 0xFD; TL1 = 0xFD; TR1 = 1; } /** * UART 发送一字节 */ void UART_Send_Byte(uint8 dat) { SBUF = dat; while (TI == 0); TI = 0; } main() { uint8 ans; uart_init(); while(1) { i2c_readbyte(0x43, &ans); UART_Send_Byte(ans); delay(50000); } }
上一篇:学51单片机-IIC总线与时序
下一篇:学51单片机-UART口发送一串字符
推荐阅读最新更新时间:2024-11-16 20:24
设计资源 培训 开发板 精华推荐
- 非常见问题解答第223期:如何在没有软启动方程的情况下测量和确定软启动时序?
- 兆易创新GD25/55全系列车规级SPI NOR Flash荣获ISO 26262 ASIL D功能安全认证证书
- 新型IsoVu™ 隔离电流探头:为电流测量带来全新维度
- 英飞凌推出简化电机控制开发的ModusToolbox™电机套件
- 意法半导体IO-Link执行器电路板为工业监控和设备厂商带来一站式参考设计
- Melexis采用无磁芯技术缩小电流感测装置尺寸
- 千丘智能侍淳博:用数字疗法,点亮“孤独症”儿童的光
- 数药智能冯尚:ADHD数字疗法正为儿童“多动症”提供更有效便捷服务
- Vicor高性能电源模块助力低空航空电子设备和 EVTOL的发展
- 创实技术electronica 2024首秀:加速国内分销商海外拓展之路