基于STM32L431RCT6,配置时钟为80MHZ。
DS18B20系列芯片的使用难点在于时序的把控,时序的话需要我们通过芯片手册去了解,我搜索芯片手册的方式是通过嘉立创去搜索对应芯片里面会提供芯片手册嘉立创商城链接。
DS18B20系列芯片对时序有着比较高的要求,我们先来设置延迟函数,这里是通过定时器来完成延迟函数。
一.配置时钟和延迟函数
void MX_TIM6_Init(void)
{
/* USER CODE BEGIN TIM6_Init 0 */
/* USER CODE END TIM6_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM6_Init 1 */
/* USER CODE END TIM6_Init 1 */
htim6.Instance = TIM6;
htim6.Init.Prescaler = 79;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 65535;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM6_Init 2 */
/* USER CODE END TIM6_Init 2 */
}
void delay_us(uint16_t t)
{
__HAL_TIM_SET_COUNTER(&htim6,0);
__HAL_TIM_ENABLE(&htim6);
while(__HAL_TIM_GET_COUNTER(&htim6) < t);
/* Disable the Peripheral */
__HAL_TIM_DISABLE(&htim6);
}
void delay_ms(uint16_t t)
{
int i = 0;
for(; i<t; i++)
{
delay_us(1000);
}
}
/* USER CODE END 1 */
二.例程代码
#ifndef INC_DS18B20_H_
#define INC_DS18B20_H_
#include "main.h"
#define GPIO_PIN_DO GPIO_PIN_13 //设置DQ引脚
#define GPIO_DO GPIOB
#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 Temp_Read(void);
float Data_TransFormation(void);
#endif /* INC_DS18B20_H_ */
#include "ds18b20.h"
#include "usart.h"
#include "tim.h"
#include "main.h"
GPIO_InitTypeDef GPIO_Init;
void DS18B20_Init(void)
{
//uint8_t counte = 0;
GPIO_SET_OUT(); //DO引脚设置成输出模式
DSDO_RESET(); //主机发送低电平信号
delay_us(1000);
DSDO_SET(); //主机释放总线,等待DS18B20回应
GPIO_SET_IN(); //DO引脚设置成输入模式
delay_us(1000);
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13) ==RESET)
{
//printf("\r\nsuccess\r\n");
}
}
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引脚电平拉低
delay_us(6);
DSDO_SET(); //DO引脚电平拉高
delay_us(70);
}
else //按位写0
{
DSDO_RESET(); //DO引脚电平拉低
delay_us(70);
DSDO_SET(); //DO引脚电平拉高
delay_us(6);
}
}
}
uint8_t DS18B20_ReadBit(void)
{
uint8_t bit;
GPIO_SET_OUT();//输出模式
DSDO_RESET(); //拉低总线
delay_us(2);
DSDO_SET(); //释放总线
GPIO_SET_IN(); //输入模式
delay_us(4);
bit = ReadPin();
delay_us(15);
return (bit);
}
uint8_t DS18B20_Read_Char(void)
{
uint8_t i,uctemp,ucData=0;
for(i = 1;i<=8;i++)
{
uctemp = DS18B20_ReadBit();
ucData = (uctemp <<7 ) |(ucData >>1);
}
return(ucData);
}
float Temp_Read(void)
{
float fTemp;
uint8_t ucTemp1, ucTemp2;
DS18B20_Init(); /* 初始化 DS18B20 */
DS18B20_Write(0xcc); /* 跳过序列号命令 */
DS18B20_Write(0x44); /* 发送温度转换命令 */
DS18B20_Init();
delay_us(1);
/*
* 发送读取数据命令
*/
DS18B20_Write(0xcc);
DS18B20_Write(0xbe);
//HAL_Delay(750);
//DS18B20_Init();
ucTemp1 = DS18B20_Read_Char(); //读温度低字节
ucTemp2 = DS18B20_Read_Char(); //读温度高字节
//debug_out(ucTemp1); debug_out(ucTemp2);
if((ucTemp2 & 0xf8) == 0xf8) //判断温度值正负
{
ucTemp2 = ~ucTemp2; //温度值为负时temp1的高4位置0001
ucTemp1 = ~ucTemp1;
ucTemp1 = ucTemp1 + 1;
if(ucTemp1 == 0x00)
ucTemp2++;
}
fTemp = (ucTemp1 & 0x0F);
fTemp = fTemp /4; /* 小数位 */
fTemp += ((ucTemp2 & 0x07) << 4); /* S S S S S 64 32 16*/
fTemp += ((ucTemp1 & 0xF0) >> 4);
if((ucTemp2 & 0xF8) == 0xF8) //判断温度值正负
{
fTemp = -fTemp;
}
return fTemp;
}
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);
}
实验结果:
记录自己学习过程,没有好好阅读芯片手册,导致自己之前一直没弄好时序,在此记录,警示自己阅读芯片手册的重要性。