51单片机读取ADS1118及内部温度传感器数据(含电路图和C程序)
ADS1118超小型VSSOP-10封装,宽电压范围2-5.5V,SPI接口16位,内部自带基准电压和温度传感器,ADS1118 数据转换速率最高可达每秒 860 次采样(SPS)。即最高1.2ms就可以采集一次数据。PGA 的输入范围为 ±256mV 至 ±6.144V,能够以高分辨率测量大信号和小信号。可以测量双路差分输入或四路单端输入。内部高精度温度传感器在 0°C 至 70°C 范围内误差最大值为 0.5°C,可用来做系统温度监控或对热电偶进行冷结点补偿。
温度采集应用电路图,U6为热电偶差分输入,AIN0为正和AIN1为负。AIN2为热敏电阻单端输入。
SPI接口驱动时序,ADS1118有两种数据传输模式,分别为16位和32位,我用的是16位模式,ADS1118有两个寄存器,一个是转换寄存器用来读取转换数据,一个是配置寄存器用来配置操作模式、输入选择、数据速率等。写入配置寄存器以后就会有数据出来放入转换寄存器,通过SCLK时钟来同步,数据在SCLK时钟为下降沿时写入ADS1118,数据在时钟为上升沿时移出到单片机。16位模式下两次通信之间CS线要拉高一次复位SPI接口。来看看时序图:
按照时序图来写代码
void ADS1118_Init()
{
AD_CS=1;
AD_SCLK=0;
AD_DIN=0;
}
uint ADS1118_WR(uint wdata)
{
uchar i=0;
uint rdata=0;
AD_CS=0;
_nop_();_nop_();
for(i=0;i<16;i++)
{
if(wdata&0x8000) AD_DIN=1;
else AD_DIN=0;
wdata<<=1;
AD_SCLK=1;//数据在时钟为上升沿时移出到单片机
_nop_();
rdata<<=1;
if(AD_DOUT==1) rdata|=0x0001;
AD_SCLK=0;//数据在时钟为下降沿时写入ADS1118
_nop_();
}
AD_CS=1; //16位模式两次通信要拉高一次
_nop_();_nop_();
AD_DIN=0;
return rdata;
}
有了上面的函数,就可以对寄存器进行配置和读取了,16位的读取寄存器用来保存数据的如下:
16位的配置寄存器,用来配置的。
寄存器每个位的说明如下:
0 |
Reserved |
R |
1h |
将0或1写入该位没有任何影响。总是读回1。 |
|
2-1 |
NOP[1:0] |
R/W |
1h |
NOP[1:0]位控制数据是否写入配置寄存器。如果要将数据写入配置寄存器,NOP[1:0]位必须为'01'。任何其他值会导致一个NOP命令。在SCLK期间,DIN可以保持高电平或低电平。00 = 无效数据,不更新配置寄存器的内容。01 = 有效数据,更新配置寄存器(默认)。10 = 无效数据,不更新配置寄存器的内容。11 = 无效数据,不更新配置寄存器的内容。 |
|
3 |
PULL_UP_EN |
R/W |
1h |
上拉启用该位仅在DOUT/DRDY引脚上启用一个弱内部上拉电阻。当CS为高电平时,内部的400-kΩ电阻连接总线。当启用时,一个内部的400-kΩ电阻连接到总线上。当禁用时,DOUT/DRDY引脚浮动。0 = 禁用 DOUT/DRDY 引脚上的上拉电阻。1 = 在DOUT/DRDY引脚上启用上拉电阻(默认)。 |
|
4 |
TS_MODE |
R/W |
0h |
该位配置ADC转换温度或输入信号。0 = ADC模式(默认值1 = 温度传感器模式 |
|
7-5 |
DR[2:0] |
R/W |
4h |
控制数据速率设置。000 = 8 SPS
|
|
8 |
MODE |
R/W |
1h |
设备工作模式,控制ADS1118的工作模式。0 = 连续转换模式
|
|
11-9 |
PGA[2:0] |
R/W |
2h |
可编程增益放大器配置,这些位配置了可编程增益放大器。000 = FSR is ±6.144 V(1)
|
|
14:12 |
MUX[2:0] |
R/W |
0h |
配置测量通道(1)000 = AINP=AIN0,AINN=AIN1(默认)。001 = AINP=AIN0,AINN=AIN3。010 = AINP=AIN1,AINN=AIN3。011 = AINP=AIN2,AINN=AIN3。100 = AINP=AIN0,AINN=GND。101 = AINP=AIN1,AINN=GND。110 = AINP=AIN2,AINN=GND。111 = AINP=AIN3,AINN=GND。 |
|
15 |
SS |
R/W |
0h |
单发转换开始该位用于开始一次转换。只有当处于掉电状态,当转换正在进行时,没有影响。0 = 无影响1 = 启动单次转换(当处于断电状态时)。始终读回0(默认)。 |
看代码,MUX为通道选择,PGA为增益,TS_MODE ADC模式和内部温度传感器模式切换:
uint ADS1118_ConfigAndConversion(uchar MUX,uchar PGA,uchar TS_MODE)
{
uint ConfigRegister = 0x006a; //默认低8位,64sps,DOUT带上拉电阻//0 000 000 0 011 0 1 01 0
uint Rdata[4]=0,i=0;
uint Sum=0;
switch(MUX)
{
case 0: ConfigRegister += 0x0000;break; //AINP = AIN0 and AINN = AIN1 (default)
case 1: ConfigRegister += 0x1000;break; //AINP = AIN0 and AINN = AIN3
case 2: ConfigRegister += 0x2000;break; //AINP = AIN1 and AINN = AIN3
case 3: ConfigRegister += 0x3000;break; //AINP = AIN2 and AINN = AIN3
case 4: ConfigRegister += 0x4000;break; //AINP = AIN0 and AINN = GND
case 5: ConfigRegister += 0x5000;break; //AINP = AIN1 and AINN = GND
case 6: ConfigRegister += 0x6000;break; //AINP = AIN2 and AINN = GND
case 7: ConfigRegister += 0x7000;break; //AINP = AIN3 and AINN = GND
default : break;
}
switch(PGA)
{
case 0: ConfigRegister += 0x0000;break; //000 : FS = ±6.144V(1)
case 1: ConfigRegister += 0x0200;break; //001 : FS = ±4.096V(1)
case 2: ConfigRegister += 0x0400;break; //002 : FS = ±2.048V(1)
case 3: ConfigRegister += 0x0600;break; //003 : FS = ±1.024V(1)
case 4: ConfigRegister += 0x0800;break; //004 : FS = ±0.512V(1)
case 5: ConfigRegister += 0x0a00;break; //005 : FS = ±0.256V(1)
default : break;
}
switch(TS_MODE) //0000 0000 000 0 1010
{
case 0: ConfigRegister += 0x0000;break; //0 = ADC mode (default)
case 1: ConfigRegister += 0x0010;break; //1 = Temperature sensor mode
default : break;
}
Rdata[0]=ADS1118_WR(ConfigRegister);DelayMS(20);
Rdata[0]=ADS1118_WR(ConfigRegister);DelayMS(20);//舍弃前两次不稳定的值
Rdata[1]=ADS1118_WR(ConfigRegister);DelayMS(20);
Rdata[2]=ADS1118_WR(ConfigRegister);DelayMS(20);
Rdata[3]=ADS1118_WR(ConfigRegister);DelayMS(20);
Sum=(Rdata[1]+Rdata[2]+Rdata[3])/3;
return (uint)Sum;
}
调用上面这个函数就可以配置并返回ADC的值了,如:Thermocouple.AD=ADS1118_ConfigAndConversion(0,4,0);
外部通道电压转换:
bit11-9:设置测量电压的范围:例如 001 = ±4.96V
读取数据 为16bit,其中最高位为 符号位: 1:负电压,0:正电压
正电压转换:
例如bit11-9=001,电压范围为:±4.96V
读取数据为0x515B:
最高位为 0 ,所以是正电压, 电压 = 0x515B* (4.096 / 0x7FFF) >> 20827*(4.096/32767) = 2603mV = 2.603V
负电压转换:
例如bit11-9=001,电压范围为:±4.96V
读取数据为 0xFFD9: >>1111,1111,1101,1001 去掉最高位符号位 和 逐位取反: 0000,0000,0010,0110 =0x0026
结果再加1 : 0x26+1=0x27;
电压 = -(0x27*(4.096 / 0x7FFF)) = -4.875mV
ADS1118提供了一个集成的精密温度传感器。在配置寄存器中设置位TS_MODE = 1。温度数据表示为一个14位温度寄存器,它是左对齐的。在16位转换寄存器中,数据从最高有效字节(MSB)开始传输。当读取两个数据字节,前 14 位用于指示温度测量结果。1bit = 0.013125 度
例:读取数据为:0x0E00 >> 0000,1110,0000,0000
最高位为符号位:0000,1110,0000,0000 0:正温度,1:负温度
因为使用的是14bit ,所以实际数值:0000,1110,0000,0000 >>2 == 0000,0011,1000,0000 == 0x0380 == 896
当前温度 = 896 *0.031125 = 28℃
代码如下,调用这个函数就可以得到温度了,这里没做正负处理:
uint CoolTemperautre()
{
uint temp,wendu;
temp=ADS1118_ConfigAndConversion(0,0,1);
temp=temp>>2;
wendu=(uint)(temp*0.03125);
return wendu;
}
关于ADS1118更多的内容请看数据手册,上面的函数已经在板子上验证了,芯片为STC12C5a60s2。