功能
硬件连接:GD32F330 PA5 连接DS18B20的OUT
功能:死循环while(1),每秒读一次数据,并通过串口打印出来
DS18B20初始化
首先,由于GD32库并没有位操作,改变IO口的输入输出方向,为了简化操作,写了以下函数
/*!
\brief set GPIO_pinx mode in
\param[in] gpio_periph: GPIOx(x = A,B,C,D,F)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,F)
\param[in] pin: GPIO pin
pin=1,2,3,4...
\param[out] none
\retval none
*/
void gpio_mode_set_in(uint32_t gpio_periph,u8 pin)
{
uint32_t ctl, pupd;
ctl = GPIO_CTL(gpio_periph);
pupd = GPIO_PUD(gpio_periph);
/* clear the specified pin pupd bits */
ctl &= ~GPIO_MODE_MASK(pin);
/* set the specified pin mode in bits */
ctl |= GPIO_MODE_SET(pin, GPIO_MODE_INPUT);
/* clear the specified pin pupd bits */
pupd &= ~GPIO_PUPD_MASK(pin);
/* set the specified pin pupd bits */
pupd |= GPIO_PUPD_SET(pin, GPIO_PUPD_PULLUP);
GPIO_CTL(gpio_periph) = ctl;
GPIO_PUD(gpio_periph) = pupd;
}
/*!
\brief set GPIO_pinx mode out
\param[in] gpio_periph: GPIOx(x = A,B,C,D,F)
only one parameter can be selected which is shown as below:
\arg GPIOx(x = A,B,C,D,F)
\param[in] pin: GPIO pin
pin=1,2,3,4...
\arg
\param[out] none
\retval none
*/
void gpio_mode_set_out(uint32_t gpio_periph,u8 pin)
{
uint32_t ctl, pupd;
ctl = GPIO_CTL(gpio_periph);
pupd = GPIO_PUD(gpio_periph);
ctl &= ~GPIO_MODE_MASK(pin);
ctl |= GPIO_MODE_SET(pin, GPIO_MODE_OUTPUT);
/* clear the specified pin pupd bits */
pupd &= ~GPIO_PUPD_MASK(pin);
/* set the specified pin pupd bits */
pupd |= GPIO_PUPD_SET(pin, GPIO_PUPD_PULLUP);
// GPIO_OMODE(gpio_periph) &= (uint32_t)(~(1<<pin)); //上电之后,初始化过输出模式,可省略
GPIO_CTL(gpio_periph) = ctl;
GPIO_PUD(gpio_periph) = pupd;
}
然后添加delay_1ms(),delay_1us()
#include "gd32f3x0.h"
#include "systick.h"
#include "delay.h"
volatile static float count_1us = 0;
volatile static float count_1ms = 0;
/*!
\brief configure systick
\param[in] none
\param[out] none
\retval none
*/
void systick_config(void)
{
/* systick clock source is from HCLK/8 */
systick_clksource_set(SYSTICK_CLKSOURCE_HCLK_DIV8);
count_1us = (float)SystemCoreClock/8000000;
count_1ms = (float)count_1us * 1000;
}
/*!
\brief delay a time in microseconds in polling mode
\param[in] count: count in microseconds
\param[out] none
\retval none
*/
void delay_1us(uint32_t count)
{
uint32_t ctl;
/* reload the count value */
SysTick->LOAD = (uint32_t)(count * count_1us);
/* clear the current count value */
SysTick->VAL = 0x0000U;
/* enable the systick timer */
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
/* wait for the COUNTFLAG flag set */
do{
ctl = SysTick->CTRL;
}while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
/* disable the systick timer */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
/* clear the current count value */
SysTick->VAL = 0x0000U;
}
/*!
\brief delay a time in milliseconds in polling mode
\param[in] count: count in milliseconds
\param[out] none
\retval none
*/
void delay_1ms(uint32_t count)
{
uint32_t ctl;
/* reload the count value */
SysTick->LOAD = (uint32_t)(count * count_1ms);
/* clear the current count value */
SysTick->VAL = 0x0000U;
/* enable the systick timer */
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
/* wait for the COUNTFLAG flag set */
do{
ctl = SysTick->CTRL;
}while((ctl&SysTick_CTRL_ENABLE_Msk)&&!(ctl & SysTick_CTRL_COUNTFLAG_Msk));
/* disable the systick timer */
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
/* clear the current count value */
SysTick->VAL = 0x0000U;
}
初始化
u8 ds18b20_init(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 );
gpio_bit_set(GPIOA, GPIO_PIN_5);
ds18b20_rst();
return ds18b20_check();
}
复位DS18B20
//复位DS18B20
void ds18b20_rst(void)
{
gpio_mode_set_out(GPIOA,5);
gpio_bit_reset(GPIOA,GPIO_PIN_5);
delay_1us(750);
gpio_bit_set(GPIOA,GPIO_PIN_5);
delay_1us(15);
}
自检DS18B20
//等待DS18B20的回应
//返回1:未检测到DS18B20的存在
//返回0:存在
u8 ds18b20_check(void)
{
u8 retry = 0;
gpio_mode_set_in(GPIOA,5);
while(gpio_input_bit_get(GPIOA,GPIO_PIN_5)&&retry<200)
{
retry++;
delay_1us(1);
};
if(retry>=200)return 1;
else retry=0;
while(!gpio_input_bit_get(GPIOA,GPIO_PIN_5)&&retry<240)
{
retry++;
delay_1us(1);
};
if(retry>=240)return 1;
return 0;
}
读一个位
//从DS18B20读取一个位
//返回值:1/0
u8 ds18b20_read_bit(void)
{
u8 data;
gpio_mode_set_out(GPIOA,5);
gpio_bit_reset(GPIOA,GPIO_PIN_5);
delay_1us(2);
gpio_bit_set(GPIOA,GPIO_PIN_5);
gpio_mode_set_in(GPIOA,5);
delay_1us(12);
if(gpio_input_bit_get(GPIOA,GPIO_PIN_5))data=1;
else data=0;
delay_1us(50);
return data;
}
读一个字节
//从DS18B20读取一个字节
//返回值:读到的数据
u8 ds18b20_read_byte(void)
{
u8 i,j,dat;
dat=0;
for (i=1;i<=8;i++)
{
j=ds18b20_read_bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}
写一个字节
//写一个字节到DS18B20
//dat:要写入的字节
void ds18b20_write_byte(u8 dat)
{
u8 j;
u8 testb;
gpio_mode_set_out(GPIOA,5); //SET PG11 OUTPUT;
for (j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if (testb)
{
gpio_bit_reset(GPIOA,GPIO_PIN_5); // Write 1
delay_1us(2);
gpio_bit_set(GPIOA,GPIO_PIN_5);
delay_1us(60);
}
else
{
gpio_bit_reset(GPIOA,GPIO_PIN_5); // Write 0
delay_1us(60);
gpio_bit_set(GPIOA,GPIO_PIN_5);
delay_1us(2);
}
}
}
读取温度
//从ds18b20得到温度值
//精度:0.01C*100
//返回值:温度值 (-5500~12500)
short ds18b20_get_temp(void)
{
u8 temp;
u8 TL,TH;
short tem;
ds18b20_start (); // ds1820 start convert
ds18b20_rst();
ds18b20_check();
ds18b20_write_byte(0xcc); // skip rom
ds18b20_write_byte(0xbe); // convert
TL=ds18b20_read_byte(); // LSB
TH=ds18b20_read_byte(); // MSB
if(TH>7)
{
TH=~TH;
TL=~TL;
temp=0; //温度为负
}else temp=1; //温度为正
tem=TH; //获得高八位
tem<<=8;
tem+=TL; //获得底八位
tem=(float)(tem*6.25); //转换
if(temp)return tem; //返回温度值
else return -tem;
}
main函数
int main(void)
{
systick_config();
uart_init(115200);
while(ds18b20_init())
{
printf("ds18b20 error\r\n");
delay_1ms(500);
}
printf("初始化成功。\r\n");
while(1)
{
printf("temp=%d\r\n",ds18b20_get_temp());
delay_1ms(1000);
}
}