承接上期的环境搭建篇,今儿周末,来测测此时南方室内的温度。体感不是很冷,不知道具体的温度值,赶紧用一个DS18B20简单模块来检测一下。
众所周知,DS18B20是一种单总线数字温度传感器,测试温度范围-55℃-125℃,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。单总线,意味着没有时钟线,只有一根通信线。单总线读写数据是靠控制起始时间和采样时间来完成,所以时序要求很严格,这也是DS18B20驱动编程的难点。
温度寄存器结构图展示如下:
温度寄存器由两个字节组成,分为低8位和高8位。一共16位。其中,第0位到第3位,存储的是温度值的小数部分。第4位到第10位存储的是温度值的整数部分。第11位到第15位为符号位。全0表示是正温度,全1表示是负温度。表格中的数值,如果相应的位为1,表示存在。如果相应的位为0,表示不存在。
DS18B20的单总线协议初始化过程中的复位与应答脉冲时序图。
初始化时序包括:主机发出的复位脉冲和从机发出的应答脉冲。主机通过拉低单总线480-960μs产生复位脉冲;然后由主机释放总线,并进入接收模式。主机释放总线时,会产生一由低电平跳变为高电平的上升沿,单总线器件检测到该上升沿后,延时15~60μs,接着单总线器件通过拉低总线60~240μsμ来产生应答脉冲。主机接收到从机的以应答脉冲后,说明有单总线器件在线,到此初始化完成。然后主机就可以开始对从机进行ROM命令和功能命令操作。
DS18B20的写时序图如下:
写时隙:当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。有两种写时间隙:写1的时间隙和写0时间隙。所有写时间隙必须最少持续60us,包括两个写周期间至少1us的恢复时间。DQ引脚上的电平变低后,DS18B20在一个15us到60us的时间窗口内对DQ引脚采样。如果DQ引脚是高电平,就是写1,如果DQ引脚是低电平,就是写0。主机要生成一个写1时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15us内允许数据线拉到高电平。主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60us。
DS18B20的读时序图如下:
当主机把总线从高电平拉低,并保持至少1us后释放总线;并在15us内读取从DS18B20输出的数据。
硬件电路上的连线如下图所示,DS18B20的DQ数据脚与开发板上的GPIOD3引脚相连接。
部分的参考代码展示如下:
- #include "at32f423_board.h"
- #include "at32f423_clock.h"
- #include "ds18b20.h"
- int main(void)
- {
- uint8_t i, DS18B20ID[8];
- char str[50];
- uint8_t t = 0;
- float temperature;
- system_clock_config();
- at32_board_init();
- uart_print_init(115200);
-
- while (DS18B20_Init()) /* DS18B20初始化 */
- {
- printf("DS18B20 Init Error\r\n");
- delay_ms(1000);
- }
- DS18B20_ReadId(DS18B20ID);
- printf("DS18B20的序列号是: 0x");
- for ( i = 0; i < 8; i ++ )
- printf ( "%.2X", DS18B20ID[i]);
- printf("\n");
- sprintf(str,"DS18B20的序列号是:0x%02X%02X%02X%02X%02X%02X%02X%02X",DS18B20ID[0],DS18B20ID[1],DS18B20ID[2],DS18B20ID[3],
- DS18B20ID[4],DS18B20ID[5],DS18B20ID[6],DS18B20ID[7]);
- printf("DS18B20 OK\r\n");
- while(1)
- {
- temperature=DS18B20_GetTemp_MatchRom(DS18B20ID);
- /* 打印通过 DS18B20 序列号获取的温度值 */
- printf("获取该序列号器件的温度:%.1f\n",temperature);
- sprintf(str,"当前温度值为:%0.3f℃",temperature);
- delay_ms(800);
- t++;
- if (t == 100)
- {
- t = 0;
- at32_led_toggle(LED2);
- delay_ms(10);
- at32_led_toggle(LED3);
- delay_ms(10);
- at32_led_toggle(LED4);
- delay_ms(10);
- }
- }
- }
- #ifndef __ONEWIRE_DS18B20_H__
- #define __ONEWIRE_DS18B20_H__
- #include "at32f423_board.h"
- #include "at32f423_clock.h"
- /************************** DS18B20 连接引脚定义****************************/
- #define DS18B20_DQ_SCK_APBxClock_FUN crm_periph_clock_enable
- #define DS18B20_DQ_GPIO_CLK CRM_GPIOD_PERIPH_CLOCK
- #define DS18B20_DQ_GPIO_PORT GPIOD
- #define DS18B20_DQ_GPIO_PIN GPIO_PINS_3
- /************************** DS18B20 函数宏定义*****************************/
- #define DS18B20_DQ_0 gpio_bits_reset(DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN)
- #define DS18B20_DQ_1 gpio_bits_set(DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN)
- #define DS18B20_DQ_IN() gpio_input_data_bit_read(DS18B20_DQ_GPIO_PORT,DS18B20_DQ_GPIO_PIN)
- /************************* DS18B20 函数声明 ******************************/
- uint8_t DS18B20_Init(void);
- void DS18B20_ReadId( uint8_t * ds18b20_id);
- float DS18B20_GetTemp_SkipRom(void);
- float DS18B20_GetTemp_MatchRom(uint8_t *ds18b20_id);
- #endif /* __ONEWIRE_DS18B20_H__ */
编译完成后,下载到开发板中,检测过程中,使用手指靠近DS18B20模块,则温度会随之增加,手指离开DS18B20模块,则温度值回落。串口打印效果如下:
|