一、A/D,D/A
A/D,D/A概念
- A/D:把模拟量转化为数字量;
- D/A:把数字量转化为模拟量。
A/D转换指标
- 转换时间:完成一次A/D转化主要的时间t.1/t为转化速率
- 分辨率: 衡量A/D转换器能分辨出输入模拟量最小变化程度的技术指标。取决于A/D转换器的位数。
- 量化误差:由于有限位数字量对模拟量进行量化而引起的误差,量化误差理论上规定单位分辨率的 正负1/2LSB。
- 转换精度:实际A/D转换器和理论转换器在量化值上的差值。
逐次逼近寄存器型(SAR) ADC
-
Vin 为输入采样电压,VDAC 为设为VREF 的一半,VREF 为基准电压。当Vin >VDAC ,out = 1,MSB =1;Vin <VDAC ,out = 0,MSB = 0。N为转换结果存在寄存器中。
-
例子
A/D转换流程
- 控制ADC开始转换-》得知转换结果-》输入转换结果
- XPT2046使用。
二、单总线系统的典型应用-DS18B20的温度测量系统
DS1820温度传感器
- 采集方式:现场温度的测量直接通过“单总线”以数字方式传输,不用单片机进行A/D转换。
第一和第二字节存放转换好的温度,低8位在前面,高八位在后。
TH和TL,用户写入的上下限报警值
配置是一个配置寄存器
第6-8字节都为1,未使用
CRC是前面八字节的CRC码
- 采集方式:现场温度的测量直接通过“单总线”以数字方式传输,不用单片机进行A/D转换。
配置寄存器
TM为0,不可更改
R1和R0用来设置分辨率,分辨率越大,转换速率越慢。
数据处理
以补码形式存在。前五位为符号位。要判断是否为负数,要取反+1。
工作时序
- 三个时序,初始化、写、读时序。
- 三个时序,初始化、写、读时序。
命令
三、代码解析和温度采集流程
- DS18B20温度传感器采集流程。写入温度转换命令->写入温度读取命令->读取温度
模块设计
- uchar Ds18b20Init()。初始化
- void Ds18b20WriteByte(uchar dat)。向DS18B20写入1字节命令
- uchar Ds18b20ReadByte()。向DSB20读取1字节数据
- void Ds18b20ChangTemp()。写入温度转换命令
- void Ds18b20ReadTempCom()。写入读取温度命令
- int Ds18b20ReadTemp()。读取温度数据(核心)
- datapros(int temp) 。输出最终温度值
初始化uchar Ds18b20Init(),先拉低电480~960us ,然后释放总线,等待DS应答(<=5ms),输出低电平.
uchar Ds18b20Init() { uchar i; DSPORT = 0; //拉低480us~960us i = 70; while(i--); //延时 DSPORT = 1; //释放总线 i = 0; while(DSPORT) //等待应答 { Delay1ms(1); i++; if(i>5)//>5ms 初始化失败,返回0 { return 0; } } return 1;//初始化成功 }
向DS写数据(命令)void Ds18b20WriteByte(uchar dat),拉低电平,从低位写入,延长70us左右。数据右移1位。总线拉高1us.
void Ds18b20WriteByte(uchar dat) { uint i, j; for(j=0; j<8; j++) //八位依次写入。 { DSPORT = 0; //拉低总线 i++; DSPORT = dat & 0x01; i=6; while(i--); //延时70us DSPORT = 1; //释放总线 dat >>= 1; //总线至少拉高1us } }
读取DS数据uchar Ds18b20ReadByte(),拉低电平
uchar Ds18b20ReadByte() { uchar byte, bi; uint i, j; for(j=8; j>0; j--) { DSPORT = 0;//拉低电平 i++; DSPORT = 1;//释放总线 i++; i++; //延时6us等待数据稳定 bi = DSPORT; //读取数据 byte = (byte >> 1) | (bi << 7); //先读取低位再读取高位,bi向左移七位,byte向右移1位,或 操作 i = 4; //延时48us左右后继续读取下一位 while(i--); } return byte; //返回数据 }
写入温度转换命令void Ds18b20ChangTemp()。 先初始化,延时1ms,写入0xcc指令。跳过ROM 操作命令,因为只用到了一份DS12B20。写入温度转换指令0x44.
void Ds18b20ChangTemp() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); Ds18b20WriteByte(0x44); }
写入读取温度命令void Ds18b20ReadTempCom()。先初始化,延时1ms,写入0xcc指令。。跳过ROM操作命令。写入读取温度指令0xBE.
void Ds18b20ReadTempCom() { Ds18b20Init(); //初始化 Delay1ms(1); //延时1ms Ds18b20WriteByte(0xcc); //写入跳过ROM操作命令 Ds18b20WriteByte(0xbe); //写入温度读取指令 }
温度采集的主函数。写入转换温度命令->写入读取温度命令->读取温度(先读取低八位,后读取高八位)。
int Ds18b20ReadTemp() { int temp = 0; //存取温度 uchar tmh, tml; //tml存低八位,tmh高八位 Ds18b20ChangTemp(); //转换温度 Ds18b20ReadTempCom();//写入读取温度命令 tml = Ds18b20ReadByte();//读取低8位 tmh = Ds18b20ReadByte(); //读取高八位 temp = tmh; temp <<= 8; //左移八位 temp |= tml; return temp; }
最终温度数据输出。温度小于0,取反+,1。因为前5位为符号位,所以要右移4位,因为设置精度0.01所以乘以100.+0.5是四舍五入
void datapros(int temp) { float tp; if(temp< 0) //小于0 { temp=~temp; temp=temp+1; tp=temp; temp=tp*0.0625*100+0.5; //右移四位,设置精度为0.01,四舍五入 } else { tp=temp; temp=tp*0.0625*100+0.5; ¡ } }