硬件部分
1.GD32F427R开发板
2.ds18b20温度传感器
详细原理及时序可参考CSDN论坛大佬博客
3.USB转TTL模块
软件部分
参考官方systick库实现delay毫秒函数
#include "gd32f4xx.h"
#include "systick.h"
volatile static uint32_t delay;
/*!
\brief configure systick
\param[in] none
\param[out] none
\retval none
*/
void systick_config(void)
{
/* setup systick timer for 1000Hz interrupts */
if(SysTick_Config(SystemCoreClock / 1000000U)) {
/* capture error */
while(1) {
}
}
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
/*!
\brief delay a time in milliseconds
\param[in] count: count in milliseconds
\param[out] none
\retval none
*/
void delay_1ms(uint32_t count)
{
delay = 1000*count;
while(0U != delay) {
}
}
/*!
\brief delay a time in microseconds
\param[in] count: count in microseconds
\param[out] none
\retval none
*/
void delay_1us(uint32_t count)
{
delay = count;
while(0U != delay) {
}
}
ds18b20.c代码
#include "ds18b20.h"
int DS18B20_Init(void)
{
int i=0;
DS_DIO(1); //GPIOA->ODR |= 1; //GPIOA-0输出高电平
DS18B20_Mode_OutPut();//令DQ口为输出模式
DS_DIO(0); //PAout(0)=0;
delay_1us(720);//延时480-960us
DS_DIO(0); //PAout(0)=1;
delay_1us(30);//等待15-60us
DS18B20_Mode_InPut();//改为输入模式
while(READ_DIO == 1) // //while(PAin(0)==1) //若DS18B20存在则会将总线拉低60-240us
{
delay_1us(1);
i++;
if(i>240) return 0; //时间大于240us总线仍为高电平则DS18B20不存在
}
return 1;
}
void DS18B20_WriteByte(uint8_t dat)
{
int i;
DS18B20_Mode_OutPut();
for(i=0;i<8;i++)
{
DS_DIO(0); // PAout(0)=0; //先拉低引脚
delay_1us(15); //等待15us,在第15-60us内DS18B20会获取总线电平
if(dat&0x01) DS_DIO(1); //PAout(0)=dat&0x01;
else DS_DIO(0);
delay_1us(60); //延时,使时序图完整
DS_DIO(1); // PAout(0)=1;
dat>>=1;
}
}
uint8_t DS18b20_ReadByte(void)
{
int j;
uint8_t dat,byte;
for(j=8;j>0;j--)
{
DS18B20_Mode_OutPut();
DS_DIO(0); //PAout(0)=0; //先拉低引脚
delay_1us(1); //延时至少大于1us
DS_DIO(1); //PAout(0)=1; //释放总线
delay_1us(10); //DS18B20会在15us发送数据
DS18B20_Mode_InPut();
dat=READ_DIO; //PAin(0);
byte=(byte>>1)|(dat<<7);
delay_1us(45); //使时序完整
DS18B20_Mode_OutPut();
DS_DIO(1); //PAout(0)=1;
}
return byte;
}
/*改变DS18B20的高温报警和低温报警以及分辨率*/
void DS18B20_Resolving_Temp(void)
{
DS18B20_Init();//单片机每次向DS18B20发送功能指令前都需要重新初始化DS18B20和写ROM指令
delay_1ms(1);
DS18B20_WriteByte(0xcc);
DS18B20_WriteByte(0xbe);//高温报警的上限
DS18B20_WriteByte(0x00);//低温报警的下限
DS18B20_WriteByte(0x7f);//改变温度分辨率
}
/*进行温度转化*/
void Ds18b20ChangeTemp(void)
{
DS18B20_Init();
delay_1ms(1);
DS18B20_WriteByte(0xcc);//跳过ROM
DS18B20_WriteByte(0x44);//发送指令RAM温度变换
}
/*读取温度*/
void Ds18b20ReadTempCom(void)
{
DS18B20_Init();
delay_1ms(1);
DS18B20_WriteByte(0xcc);//跳过ROM
DS18B20_WriteByte(0xbe);//发送指令RAM读暂时寄存器
}
int Ds18b20ReadTemp(void)
{
int temp;
float fp;
uint8_t tml,tmh;
DS18B20_Resolving_Temp();//改变高温报警和低温报警以及温度的分辨率
Ds18b20ChangeTemp();//进行温度转换
Ds18b20ReadTempCom();//读取温度
tml=DS18b20_ReadByte();//读低8位数据
tmh=DS18b20_ReadByte();//读高8位数据
temp=tmh;
temp<<=8;
temp|=tml;//拼接为16位数据
fp = temp;
if(temp < 0)//DS18B20存储数据为补码形式,当temp<0时需要转为原码
{
temp = ~temp;
temp += 1;
}
temp = fp*0.0625*10+0.5;//根据获得的温度所需的小数而改变,如果保留2位小数则乘100,+0.5是为了四舍五入
return temp;//返回数据
}
主函数
#include "gd32f4xx.h"
#include "gd32f427r_start.h"
#include "systick.h"
#include <stdio.h>
#include "ds18b20.h"
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* configure systick */
systick_config();
/* enable GPIO clock */
rcu_periph_clock_enable(RCU_GPIOA);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART1);
/* configure the USART0 TX pin and USART0 RX pin */
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_2);
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_3);
/* configure USART0 TX as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_2);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* configure USART0 RX as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_3);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
/* USART configure */
usart_deinit(USART1);
usart_baudrate_set(USART1, 115200U);
usart_receive_config(USART1, USART_RECEIVE_ENABLE);
usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
usart_enable(USART1);
/* enable the LEDs GPIO clock */
rcu_periph_clock_enable(RCU_GPIOC);
/* configure LED1 GPIO port */
gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
/* reset LED1 GPIO pin */
gpio_bit_set(GPIOC, GPIO_PIN_6);
DS18B20_Init();
while(1) {
float value = (float)Ds18b20ReadTemp()/10;
printf("\n\r%.1f\n\r", value);
}
}
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART1, (uint8_t)ch);
while(RESET == usart_flag_get(USART1, USART_FLAG_TBE));
return ch;
}
结果
用手握住DS18B20探头
温度数值上升