1.单总线温度传感器DS18B20的基本操作
DS18B20温度模块使用单总线,只有一个数据口,与单片机P14相连。
1.关于DS18B20你应该知道
在DS18B20的内部结构中,有一块高速暂存存储器,用于总线的数据交互。高速暂存存储器由9个字节组成,当温度转换命令发布后,经转换所得的温度值以二字节补码的形式存放在高速暂存存储器的第0和第1个字节,单片机可通过单线接口可以读取到该数据,读取时低位在前,高位在后。
通过单线总线端口访问DS18B20操作流程如下:
1.初始化:从机复位,主机判断从机是否响应。
2.ROM操作:ROM指令+本指令需要的读写操作。
3.功能操作:功能指令+本指令需要的读写操作。
DS18B20单线通信功能是分时完成的,它有严格的时隙概念,如果出现序列混乱,器件将不响应主机,因此读写时序很重要。下面分别对其进行介绍:
1.1.1初始化
主机将总线拉低至少480us,然后释放总线,等待15-60us后,存在的从机将会拉低总线60-240us以响应主机,之后从机将释放总线。
底层驱动代码如下:
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
1.1.2发送一位
主机将总线拉低60-120us,然后释放总线,表示发送0;主机将总线拉低1-15us,然后释放总线,表示发送1。从机将在总线拉低30us后读取电平,整个时间片应大于60us。
发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)。底层驱动代码如下:
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
1.1.3接收1位
主机将总线拉低1-15us,然后释放总线,并在拉低后15us内读取总线电平,读取为低电平则为接收0,读取为高电平则为接收1,整个时间片选应大于60us。
接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)。底层驱动代码如下:
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(50);
}
return dat;
}
2.重要的DS18B20指令
1.CCH:跳过ROM指令,直接向DS18B20发起各种温度转换指令。
2.44H:温度转换指令,启动DS18B20进行温度转换,结果保存在高速RAM中。
3.BEH:读暂存器指令,读取高速暂存存储器9个字节的内容。
3.读取1次DS18B20温度的基本操作
1.主机对DS18B20进行复位初始化。
2.主机向DS18B20写0XCC命令,跳过ROM。
3.主机向DS18B20写0X44命令,开始进行温度转换。
4.等待温度转换完成。
5.主机对DS18B20进行复位初始化。
6.主机向DS18B20写0XCC命令,跳过ROM。
7.主机向DS18B20写0XBE指令,依次读取DS18B20发出的第0-8,共9个字节的数据。
具体代码如下:
unsigned long Temp_get(void)
{
unsigned char low,high;
unsigned long temp;
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
low=Read_DS18B20();
high=Read_DS18B20();
//精度为0.0625摄氏度
temp = (high&0x0f);
temp <<= 8;
temp |= low;
return temp;
}
因为我们只需要读取温度数据,所以我们在读完第0个和第1个数据后就不再读取DS18B20发出的数据。
高字节的5个S为符号位,温度为正值时S=1,温度为负值时S=0;剩下的11位为温度数据位。
当温度为正值时,直接将后面的11位二进制数转换为十进制,再乘以0.0625(12位分辨率),就可以得到温度值。
温度存储格式
2.实时时钟DS1302的基本操作
DS1302时钟芯片的接线为SCLK,IO,RST三线,分别与单片机的P17,P23,P13相连。
1.什么是DS1302
DS1302是美国DALLAS公司推出的高性能、低功耗的实时时钟,附加31字节的静态RAM,采用SP三线接口与MCU进行同步通信,并可采用突发方式一次传送多个字节的时钟参数和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小于31天时可以自动调整,并具有润年补偿功能。
简单来说,DS1302可以理解为一个电子手表,里面带有一个31字节的内存。当然,基本的使用方法和我们平时使用电子手表差不多,你可以设定时间,也可以读取时间,只不过这些工作是通过SPI接口有MCU去完成而已。
在DS1302中有两块存储器:日历时钟寄存器和今天RAM存储器。前者用于记录实时时间,后者用于记录其他数据。对于基本计时应用,重点关注的是日历时钟寄存器。设定时间参数就是往这些寄存器写入内容,读取实时时间也是从这些寄存器读出数据。
在程序的最开始首先对需要用到的位变量进行定义,此外还定义了一个存储时间的全局变量Get_Time[i]。具体代码如下:
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
extern unsigned char Get_Time[7];
extern unsigned char Time_Set[7];
2.日历时钟寄存器
DS1302有关日历和时钟的寄存器有12个,我们最常用的有7个。
什么是BCD码?
就是用十六进制来表示十进制。什么意思?怎么理解?
例如,十六进制数0x13的值为整数19,但BCD码表示的是整数13。
3.控制字的格式
DS1302将地址和读写控制放到一个字节里面,形成一个控制字,格式如下:
DS1302将地址和读写控制放到一个字节中,形成一个控制字,由于控制字中包含了读写控制位,所以DS1302读寄存器和写寄存器的地址是不一样的。
4.接口时序的实现
DS1302的基本操作只有两个:其一是设定时间参数,其二是读取实时时间。不管是哪个操作,MCU都需要通过SPI接口进行数据交互,而SPI接口有其规定的时序。
控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟信号的上升沿,数据被写入DS1302,数据的输入从最低位开始;在控制字指令输入后的下一个SCLK时钟信号的下降沿,数据从DS1302读出,数据的读出也是从最低位到最高位。下面分别对其进行介绍。
2.4.1单字节写的时序
底层驱动代码如下:
函数第一个参数表示操作指令,第二个参数表示待写入的数据,两个8位数据从低位一次一位一位的通过I/O引脚写入DS1302。
2.4.2单字节读的时序
底层驱动代码如下:
函数的参数是操作指令,返回值为读取到的数据。
有了上面两个底层的SPI接口数据读写代码,那么DS1302的基本操作就很容易实现了。
2.4.3设置时间与读取时间函数
在实际调用上面两个函数时,指令实参一般是DS1302中写寄存器和读寄存器的地址,数据实参一般是数组中的元素。具体代码如下:
由于时间在DS18B20芯片中是以BCD码的形式存储的,而在数组中的元素是十进制,所以我们要把十进制转化为BCD码再写入DS1302,读取时间则反过来把BCD码转化为十进制。