[GD32L233C] + 7.在RTthread下使用ds18b20温度传感器
[复制链接]
本帖最后由 chrisrh 于 2022-3-7 12:55 编辑
在RTT_Nano的基础上,增加对ds18b20传感器的读取:
①首先在头文件中进行宏定义,这里选用的是PB8口
#define DS18B20_CLK RCU_GPIOB
#define DS18B20_COM_GPIO_PORT GPIOB
#define DS18B20_COM_GPIO_PIN GPIO_PIN_8
#define DS18B20_IO_IN {GPIO_CTL(GPIOB)&=0xFFFFFFF3;GPIO_CTL(GPIOB)|=0<<8;}
#define DS18B20_IO_OUT {GPIO_CTL(GPIOB)&=0xFFFFFFF3;GPIO_CTL(GPIOB)|=1<<8;}
#define DS18B20_Pin_on gpio_bit_set(DS18B20_COM_GPIO_PORT, DS18B20_COM_GPIO_PIN)//GPIO_BOP(DS18B20_COM_GPIO_PORT) = DS18B20_COM_GPIO_PIN;
#define DS18B20_Pin_off gpio_bit_reset(DS18B20_COM_GPIO_PORT, DS18B20_COM_GPIO_PIN)//GPIO_BC(DS18B20_COM_GPIO_PORT) = DS18B20_COM_GPIO_PIN;
#define DS18B20_get gpio_input_bit_get(DS18B20_COM_GPIO_PORT, DS18B20_COM_GPIO_PIN)
void DS18B20_config_init();
②对IO进行初始化
/*!
\brief configure DS18B20_Pin
*/
void DS18B20_config_init()
{
/* enable the DS18B20 clock */
rcu_periph_clock_enable(DS18B20_CLK);
/* configure DS18B20 GPIO port */
gpio_mode_set(DS18B20_COM_GPIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, DS18B20_COM_GPIO_PIN);
gpio_output_options_set(DS18B20_COM_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DS18B20_COM_GPIO_PIN);
gpio_bit_set(DS18B20_COM_GPIO_PORT, DS18B20_COM_GPIO_PIN);//GPIO_BC(DS18B20_COM_GPIO_PORT) = DS18B20_COM_GPIO_PIN;
}
③使用了rtthread传感器中关于ds18b20相关的文件,头文件sensor_dallas_ds18b20.h如下:
#ifndef __DS18B20_H__
#define __DS18B20_H__
#include <rthw.h>
#include <rtthread.h>
#include "gd32l23x.h"
#include "gd32l233c_start.h"
#define CONNECT_SUCCESS 0
#define CONNECT_FAILED 1
struct ds18b20_device
{
rt_base_t pin;
rt_mutex_t lock;
};
typedef struct ds18b20_device *ds18b20_device_t;
void ds18b20_reset(void);
uint8_t ds18b20_connect(void);
uint8_t ds18b20_read_bit(void);
uint8_t ds18b20_read_byte(void);
void ds18b20_write_byte(uint8_t dat);
void ds18b20_start(void);
uint8_t ds18b20_init(void);
int32_t ds18b20_get_temperature(void);
#endif /* __DS18B20_H_ */
④使用了rtthread传感器中关于ds18b20相关的文件,驱动函数sensor_dallas_ds18b20.c如下:
#include "sensor_dallas_ds18b20.h"
#include <rtthread.h>
#include "gd32l23x.h"
#include "gd32l233c_start.h"
#include <rtdbg.h>
#include "systick.h"
#define DBG_TAG "sensor.dallas.ds18b20"
#define DBG_LVL DBG_INFO
#define SENSOR_TEMP_RANGE_MAX (125)
#define SENSOR_TEMP_RANGE_MIN (-55)
void ds18b20_reset(void)
{
DS18B20_IO_OUT;
DS18B20_Pin_off;
delay_1us(780); /* 480us - 960us */
DS18B20_Pin_on;
delay_1us(40); /* 15us - 60us*/
}
uint8_t ds18b20_connect(void)
{
uint8_t retry = 0;
DS18B20_IO_IN;
while (DS18B20_get && retry < 200)
{
retry++;
delay_1us(1);
};
if(retry >= 200)
return CONNECT_FAILED;
else
retry = 0;
while (!DS18B20_get && retry < 240)
{
retry++;
delay_1us(1);
};
if(retry >= 240)
return CONNECT_FAILED;
return CONNECT_SUCCESS;
}
uint8_t ds18b20_read_bit(void)
{
uint8_t data;
DS18B20_IO_OUT;
DS18B20_Pin_off;
delay_1us(2);
DS18B20_Pin_on;
DS18B20_IO_IN;
/* maybe 12us, maybe 5us, whatever...I have no idea */
delay_1us(5);
if(DS18B20_get)
data = 1;
else
data = 0;
delay_1us(50);
return data;
}
uint8_t ds18b20_read_byte(void)
{
uint8_t i, j, dat;
dat = 0;
for (i = 1; i <= 8; i++)
{
j = ds18b20_read_bit();
dat = (j << 7) | (dat >> 1);
}
return dat;
}
void ds18b20_write_byte(uint8_t dat)
{
uint8_t j;
uint8_t testb;
DS18B20_IO_OUT;
for (j = 1; j <= 8; j++)
{
testb = dat & 0x01;
dat = dat >> 1;
if(testb)
{
DS18B20_Pin_off;
delay_1us(2);
DS18B20_Pin_on;
delay_1us(60);
}
else
{
DS18B20_Pin_off;
delay_1us(60);
DS18B20_Pin_on;
delay_1us(2);
}
}
}
void ds18b20_start(void)
{
ds18b20_reset();
ds18b20_connect();
ds18b20_write_byte(0xcc); /* skip rom */
ds18b20_write_byte(0x44); /* convert */
}
uint8_t ds18b20_init(void)
{
uint8_t ret = 0;
ds18b20_reset();
ret = ds18b20_connect();
return ret;
}
int32_t ds18b20_get_temperature()
{
uint8_t TL, TH;
int32_t tem;
ds18b20_start();
ds18b20_init();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0xbe);
TL = ds18b20_read_byte(); /* LSB first */
TH = ds18b20_read_byte();
if (TH > 7)
{
TH =~ TH;
TL =~ TL;
tem = TH;
tem <<= 8;
tem += TL;
tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
return -tem;
}
else
{
tem = TH;
tem <<= 8;
tem += TL;
tem = (int32_t)(tem * 0.0625 * 10 + 0.5);
return tem;
}
}
⑤在main.c中定义线程和入口函数:
#include "gd32l23x.h"
#include "systick.h"
#include "rtthread.h"
#include "gd32l233c_start.h"
#include "stdio.h"
#include "sensor_dallas_ds18b20.h"
rt_thread_t temp_thread = RT_NULL;
static void temp_thread_entry(void *parameter);//temperature
int main(void)
{
temp_thread = rt_thread_create( "temp", /*线程名字*/
temp_thread_entry, /*线程入口函数*/
RT_NULL, /*线程入口函数参数*/
256, /*线程栈大小*/
6 , /*线程优先级*/
20); /*线程时间片*/
}
static void temp_thread_entry(void *parameter)
{ int temp;
while(1)
{
rt_kprintf("temp:");
temp = ds18b20_get_temperature();
printf("%d\r\n",temp);
rt_thread_delay(1000);
}
}
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART0, (uint8_t) ch ); //发送字符
while (usart_flag_get(USART0,USART_FLAG_TC) == RESET); //检查是否发送完毕
return (ch);
}
⑥在finsh_port.c中添加了如下函数,方便在finsh中调用:
void ds18b20_get_val(void)
{
extern rt_thread_t temp_thread;
rt_thread_startup (temp_thread);
rt_kprintf("temp_thread startup\r\n");
rt_thread_delay(1000);
}
MSH_CMD_EXPORT(ds18b20_get_val, control ds18b20 thread start);//将该函数添加进入finsh,方便以后调用
!!在rtthread中的一个关于us的延时函数,加入工程中即可使用us的延时
void rt_hw_us_delay(uint32_t us)
{
uint32_t start,now,delta,reload,us_tick;
start = SysTick->VAL;
reload = SysTick->LOAD;
us_tick = SystemCoreClock / 1000000UL;
do{
now = SysTick->VAL;
delta = start>now?start-now:reload + start -now;
}while(delta<us_tick*us);
}
|