STM32CubeMX | 33-使用GPIO读取温度传感器数据(DS18B20)

   日期:2020-09-01     浏览:207    评论:0    
核心提示:本篇详细的记录了如何使用STM32CubeMX配置 STM32103RET6 的硬件GPIO外设读取温度传感器DS18B20的数据。1. 准备工作硬件准备开发板首先需要准备一个开发板,这里我准备的是一个工业DTU,主控芯片为STM32103RBT6。DS18B20DTU开发板板载一颗DS18B20温度传感器。3. 使用STM32CubeMX生成工程选择芯片型号打开STM32CubeMX,打开MCU选择器:搜索并选中芯片STM32F103RET6:配置时钟源如果选择

本篇详细的记录了如何使用STM32CubeMX配置 STM32103RET6 的硬件GPIO外设读取温度传感器DS18B20的数据。

1. 准备工作

硬件准备

  • 开发板
    首先需要准备一个开发板,这里我准备的是一个工业DTU,主控芯片为STM32103RBT6。

  • DS18B20
    DTU开发板板载一颗DS18B20温度传感器。

3. 使用STM32CubeMX生成工程

选择芯片型号

打开STM32CubeMX,打开MCU选择器:

搜索并选中芯片STM32F103RET6:

配置时钟源

  • 如果选择使用外部高速时钟(HSE),则需要在System Core中配置RCC;
  • 如果使用默认内部时钟(HSI),这一步可以略过;

这里我都使用外部时钟:

配置调试选项

STM32CubMX配置默认没有开启调试选项,需要手动开启:

配置串口

开发板板载了一个CH340换串口,连接到USART1,可用于日志打印:

接下来开始配置USART1

配置DS18B20通信GPIO

查看开发板原理图,找到与DS18B20通信的GPIO:

配置PA1引脚:

配置时钟树

STM32F103RET6的最高主频到72M,使HCLK = 72Mhz即可:

生成工程设置

代码生成设置

最后设置生成独立的初始化文件:

生成代码

点击GENERATE CODE即可生成MDK-V5工程:

3. 重定向printf到串口1

在usart.c文件末尾添加重定向代码:


#if 1
#include <stdio.h>

int fputc(int ch, FILE *stream)
{
    
    while((USART1->SR & 0x40) == 0);

    
    USART1->DR = (uint8_t) ch;

    return ch;
}
#endif

详细说明请参考文章:STM32CubeMX_09 | 重定向printf函数到串口输出的多种方法。

4. 编写DS18B20驱动代码

4.1. STM32微妙级延时函数

DS18B20是单总线驱动,所以需要精确的us级延时函数,参考文章:

  • 一种Cortex-M内核中的精确延时方法

4.2. DS18B20底层操作函数封装

主要包括:

  • GPIO输出模式配置
  • GPIO输出高电平
  • GPIO输出低电平
  • GPIO输入模式配置
  • GPIO读取输入
  • us级延时函数

ds18b20.h中编写代码,使用宏来封装,便于驱动移植:

#include "stm32f1xx.h"
#include "core_delay/core_delay.h"


#define DS18B20_GPIO_PORT GPIOA
#define DS18B20_GPIO_PIN GPIO_PIN_1


#define DS18B20_OutPut_Mode() {DS18B20_GPIO_PORT->CRL &= 0x0FFFFFFF;DS18B20_GPIO_PORT->CRL |= 0x30000000;}
#define DS18B20_InPut_Mode() {DS18B20_GPIO_PORT->CRL &= 0x0FFFFFFF;DS18B20_GPIO_PORT->CRL |= 0x80000000;}


#define DS18B20_Out(n) (n?HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_SET):HAL_GPIO_WritePin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN,GPIO_PIN_RESET))
#define DS18B20_In() HAL_GPIO_ReadPin(DS18B20_GPIO_PORT,DS18B20_GPIO_PIN)


#define DS18B20_Delay_us(n) CPU_TS_Tmr_Delay_US(n)

4.3. DS18B20操作时序实现

DS18B20主要有几个操作时序,在ds18b20.c中实现:

① 复位信号:

实现代码如下:


static void DS18B20_Send_Reset_Single(void)
{
	DS18B20_OutPut_Mode();
    
    
	DS18B20_Out(0);
	DS18B20_Delay_us(750);
    
    
	DS18B20_Out(1);
	DS18B20_Delay_us(15);
}


static uint8_t DS18B20_Check_Ready_Single(void)
{
	uint8_t cnt = 0;
    
	
	DS18B20_InPut_Mode();
    
    //等待DS18B20 拉低总线 (60~240 us 响应复位信号)
	while (DS18B20_In() && cnt < 240) {
		DS18B20_Delay_us(1);
		cnt++;
	}
    
	if (cnt > 240) {
        return 1;
    }
    
		
	cnt = 0;
	DS18B20_InPut_Mode();
    
    //判断DS18B20是否释放总线(60~240 us 响应复位信号之后会释放总线)
	while ((!DS18B20_In()) && cnt<240) {
		DS18B20_Delay_us(1);
		cnt++;
	}
    
	if (cnt > 240) {
        return 2;
    } else {
        return 0;
    }
}


static uint8_t DS18B20_Check_Device(void)
{
    
	DS18B20_Send_Reset_Single();
    
    
	return DS18B20_Check_Ready_Single();
}


void DS18B20_Init(void)
{
	
    //在main函数中已经初始化,不需要再次重复。

	
	switch (DS18B20_Check_Device()) {
		case 0:	
            printf("DS18B20_Init OK!\n");
            break;
		case 1:
            printf("DS18B20设备响应复位信号失败!\n");
            break;
		case 2:
            printf("DS18B20设备释放总线失败!\n");
            break;
	}
}

② 向DS18B20写一个字节时序:


实现代码如下:


static uint8_t DS18B20_Write_Byte(uint8_t cmd)
{
	uint8_t i = 0;
    
    
	DS18B20_OutPut_Mode();
    
    
	for (i = 0; i < 8; i++) {
		DS18B20_Out(0);
		DS18B20_Delay_us(2);  
		DS18B20_Out(cmd & 0x01);
		DS18B20_Delay_us(60);
		DS18B20_Out(1);
		cmd >>= 1;
		DS18B20_Delay_us(2);
	}
    
	return 0;
}

③ 从DS18B20读取一个字节数据时序:

实现代码如下:


uint8_t DS18B20_Read_Byte(void)
{
	uint8_t i = 0;
    uint8_t data = 0;
    
    
	for (i  =0; i < 8; i++)	{
		DS18B20_OutPut_Mode();
		DS18B20_Out(0);  
		DS18B20_Delay_us(2);
		DS18B20_Out(1);
        
		DS18B20_InPut_Mode();
		DS18B20_Delay_us(10);
		data >>= 1 ;
		if (DS18B20_In()) {
            data |= 0x80;
        }
        
		DS18B20_Delay_us(60);
		DS18B20_Out(1);
	}
    
	return data;
}

4.4. DS18B20读取温度函数实现

DS18B20读取温度需要发送一些命令,

  • 温度转换指令:0x44(启动Ds18b20启动转换温度)
  • 读暂存器指令:0xBE(读取暂存器中的九字节数据)

实现代码如下:


uint16_t DS18B20_Read_Temperature(void)
{
    uint16_t temp = 0;
    uint8_t  temp_H, temp_L;

    DS18B20_Check_Device();
    
    DS18B20_Write_Byte(0xCC);
    DS18B20_Write_Byte(0x44);
    
    while (DS18B20_Read_Byte() != 0xFF);
    
    DS18B20_Check_Device();   //必须,不能省略
    
    DS18B20_Write_Byte(0xCC);
    DS18B20_Write_Byte(0xBE); 
    
    temp_L = DS18B20_Read_Byte(); 
    temp_H = DS18B20_Read_Byte(); 
    temp   = temp_L | (temp_H << 8);
    
    return temp;
}

至此,驱动编写完成,将两个供用户调用的函数在头文件中声明:

void DS18B20_Init(void);
uint16_t DS18B20_Read_Temperature(void);

4.5. 测试DS18B20温度值读取

在main.c中包含驱动头文件:



#include <stdio.h>
#include "ds18b20.h"

在main函数中定义存放温度数据的变量:


uint16_t temp;
int      intT, decT;

在main函数中调用DS18B20初始化函数:


printf("DS18B20 Test By Mculover666\r\n");
DS18B20_Init();

接着每隔1s读取一次数据,并打印:



while (1)
{
	
	
	
	temp = DS18B20_Read_Temperature();
	intT   = temp >> 4 ;           
	decT   = temp & 0xF ;         
	
	printf("Temp:%d.%d\r\n", intT, decT);
	  
	HAL_Delay(1000);
}

编译,下载,在串口助手中查看结果,如下:

更多精彩文章及资源,请关注我的微信公众号:『mculover666』。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服