说明:控制器STM32L431RCT6 晶振12MHZ 配置时钟80MHZ
一、配置定时器(TIM6)
主要是用来做微秒级延时
相关微秒级延时函数
void DelayUs (uint16_t number)
{
__HAL_TIM_SET_COUNTER(&TIM_Handle, 0); //设置计数器的初值为0
__HAL_TIM_ENABLE(&TIM_Handle); //开启定时器
while (__HAL_TIM_GET_COUNTER(&TIM_Handle) < number); //比较计数器的值与要延时的时长
__HAL_TIM_DISABLE(&TIM_Handle); //关闭定时器
}
二、作者采用的是串口打印温度数值,所以要配置一个串口(USART1)
相关的发送函数如下,串口不能直接发送数字,所以要采用sprintf转换,同时引用同文件“stdio.h”
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM6_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
float Tem = 0.0;
char Data[20] = {0};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
Tem = Data_TransFormation();
sprintf(Data,"%f",Tem);
HAL_Delay(300);
if(Tem >= 100)
{
HAL_UART_Transmit(&huart1, (uint8_t *)Data, 8, HAL_MAX_DELAY); //串口发送函数
}
else
{
HAL_UART_Transmit(&huart1, (uint8_t *)Data, 7, HAL_MAX_DELAY);
}
}
/* USER CODE END 3 */
}
三、配置单总线的(DO)引脚;作者使用的是PA5引脚
只需要配置成推挽输出模式即可,初始电平为高电平
四、DS18B20.c和DS18B20.h文件如下:
/*
* DS18B20.c
*
* Created on: 2022年10月8日
* Author: LiangKeXue
*/
#include "DS18B20.h"
GPIO_InitTypeDef GPIO_Init;
/*
* 使用定时器延时1μS
* 时钟频率为80MHZ
* 预分频系数79
* 基本定时器为16位,最大延时65536μS
*/
extern TIM_HandleTypeDef htim6; //引入定时器6
#define TIM_Handle htim6 //宏定义,方便更改定时器
void DelayUs (uint16_t number)
{
__HAL_TIM_SET_COUNTER(&TIM_Handle, 0); //设置计数器的初值为0
__HAL_TIM_ENABLE(&TIM_Handle); //开启定时器
while (__HAL_TIM_GET_COUNTER(&TIM_Handle) < number); //比较计数器的值与要延时的时长
__HAL_TIM_DISABLE(&TIM_Handle); //关闭定时器
}
/*
* DS18B20初始化函数
* 向DS18B20发送ROM命令和功能性命令
*/
void DS18B20_Init(void)
{
uint8_t counte = 0;
GPIO_SET_OUT(); //DO引脚设置成输出模式
DSDO_RESET(); //主机发送低电平信号
DelayUs(750);
DSDO_SET(); //主机释放总线,等待DS18B20回应
GPIO_SET_IN(); //DO引脚设置成输入模式
while(ReadPin() == GPIO_PIN_SET && counte<60) //检测DS18B20是否回应低电平
{
counte++;
DelayUs(1);
}
counte = 0;
while(ReadPin() == GPIO_PIN_RESET && counte<240)//DS18B20回应脉冲信号
{
counte++;
DelayUs(1);
}
}
/*
* 向DS18B20写入数据
* pData 要传入的8位数据
*/
void DS18B20_Write(uint8_t pData)
{
GPIO_SET_OUT(); //DO引脚设置成输出模式
uint8_t Bit = 0;
for(Bit=0; Bit<8; Bit++) //字节数据传输
{
if((pData & (0x01<<Bit)) != 0) //按位写1
{
DSDO_RESET(); //DO引脚电平拉低
DelayUs(2);
DSDO_SET(); //DO引脚电平拉高
DelayUs(60);
}
else //按位写0
{
DSDO_RESET(); //DO引脚电平拉低
DelayUs(60);
DSDO_SET(); //DO引脚电平拉高
DelayUs(2);
}
}
}
/*
* 读取DS18B20函数
* pData 字节数据存放的位置
*/
uint16_t DS18B20_Read(void)
{
uint16_t pData = 0;
for(uint8_t Bit=0; Bit<16; Bit++)
{
GPIO_SET_OUT(); //DO引脚设置成输出模式
DSDO_RESET(); //DO引脚电平拉低
DelayUs(2);
DSDO_SET(); //DO引脚电平拉高
GPIO_SET_IN(); //DO引脚设置成输入模式
DelayUs(12);
if(ReadPin() == GPIO_PIN_SET) //读DO引脚的电平
{
pData = pData | (0x0001<<Bit); //按位置1
}
else
{
pData = pData & ((0xFFFE<<(16-Bit))|(0xFFFE>>Bit)); //按位清零
}
DelayUs(50);
}
return pData;
}
float Data_TransFormation(void)
{
float Tem;
uint16_t pData = 0;
DS18B20_Init(); //DS18B20初始化
DS18B20_Write(ROM_Skip); //发送ROM命令(ROM跳过)
DS18B20_Write(Temperature_Conversion); //发送功能性指令(温度转换)
HAL_Delay(750); //温度转换时间
DS18B20_Init();
DS18B20_Write(ROM_Skip);
DS18B20_Write(Read_Scratch_Reg); //读取暂存寄存器
pData = DS18B20_Read(); //读取温度的16位值
if((pData & 0xF000) == 0) //温度为零上时
{
Tem = pData*0.0625; //补码等于原码,计算温度,12位精度为0.0625
pData = 0;
return Tem;
}
else //温度为零下时
{
Tem = (65536-pData)*0.0625; //补码转换成原码,计算温度
pData = 0;
return -Tem;
}
}
/*
* DO(PA5)引脚设置成输入模式,接上拉电阻
*/
void GPIO_SET_IN(void)
{
GPIO_Init.Pin = GPIO_PIN_DO;
GPIO_Init.Mode = GPIO_MODE_INPUT;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIO_DO,&GPIO_Init);
}
/*
* DO(PA5)引脚设置成推挽输出模式,初始高电平
*/
void GPIO_SET_OUT(void)
{
GPIO_Init.Pin = GPIO_PIN_DO;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_WritePin(GPIO_DO, GPIO_PIN_DO, GPIO_PIN_SET);
HAL_GPIO_Init(GPIO_DO,&GPIO_Init);
}
/*
* DS18B20.h
*
* Created on: 2022年10月8日
* Author: 79482
*/
#ifndef INC_DS18B20_H_
#define INC_DS18B20_H_
#include "main.h"
#define GPIO_PIN_DO GPIO_PIN_5 //设置DO引脚
#define GPIO_DO GPIOA
#define DSDO_SET() HAL_GPIO_WritePin(GPIO_DO, GPIO_PIN_DO, GPIO_PIN_SET) //DO引脚置1
#define DSDO_RESET() HAL_GPIO_WritePin(GPIO_DO, GPIO_PIN_DO, GPIO_PIN_RESET) //DO引脚清零
#define ReadPin() HAL_GPIO_ReadPin(GPIO_DO, GPIO_PIN_DO) //读取DO引脚
/*
* ROM命令
*/
#define ROM_Search 0xF0 //ROM搜索
#define ROM_Read 0x33 //ROM读取
#define ROM_Matching 0x55 //ROM匹配
#define ROM_Skip 0xCC //ROM跳过
#define Alert_Search 0xEC //警报搜索
/*
* DS18B20功能命令
*/
#define Temperature_Conversion 0x44 //温度转换
#define Write_Scratch_Reg 0x4E //写入暂存寄存器
#define Read_Scratch_Reg 0xBE //读取暂存寄存器
#define Copy_Scrath_Reg 0x48 //拷贝暂存寄存器
#define Recall_EEPROM 0xB8 //召回EEPROM
#define Read_Power_Mode 0xB4 //读取供电模式
void DelayUs (uint16_t number);
void GPIO_SET_IN(void);
void GPIO_SET_OUT(void);
void DS18B20_Init(void);
void DS18B20_Write(uint8_t pData);
uint16_t DS18B20_Read(void);
float Data_TransFormation(void);
#endif /* INC_DS18B20_H_ */