GD32VW553-IOT 利用DS18B20读取温度,利用74HC595级联驱动数码管显示温度

分享作者:TKST
评测品牌:萤火工场
评测型号:GD32VW553-IOT
发布时间:2025-02-20 14:04:31
0
概要
硬件函数采用宏定义针脚,代码可快速移植
开源口碑分享内容

感谢iceasy与火萤工厂提供的GD32VW553-IOT开发板

结合现有的51开发板的中硬件做一个温度计,如下图所示:


main.c文件内容

#include "gd32vw55x.h"

#include "systick.h"

#include <stdio.h>

#include "main.h"

#include "DS18B20.h"

#include "74HC595.h"



extern uint8_t seg_position[8];

extern uint8_t seg_code[17];


//从DS18B20读取的是float格式温度,而74HC595下发的是uint8_t格式数据

//因此需要将float数据转换为uint8_t数据

//定义一个数组用来重构数码管的显示字符

uint8_t seg_temp_code[8];

void datapross(float dat)

{

//定义一个整形数据作为缓存变量

int a;

//判断温度的正负

if(dat<0)

{

seg_temp_code[0]=0x40;

dat=-dat;

}else{

seg_temp_code[0]=0x00;

}

//保留两位小数,并+0.5对原始数据的第三位小数进行四舍五入

a=dat*100+0.5;

seg_temp_code[1] = seg_code[a / 10000];

seg_temp_code[2] = seg_code[a % 10000 / 1000];

seg_temp_code[3] = seg_code[a % 1000 / 100] | 0X80;

seg_temp_code[4] = seg_code[a % 100 / 10];

seg_temp_code[5] = seg_code[a % 10];

seg_temp_code[6] = 0x00;

seg_temp_code[7] = 0x00;

}


/*

* 主函数

*/


int main(void)

{

//配置延迟时钟

   systick_config();

uint8_t i;

//初始化

DS18B20_Init();

HC595_Init();

//消影

HC595_Write_data(0x00,0x00);


//检测DS18B20,(ds18b20调试成功)

while(DS18B20_Init())

{

//-轮流滚动说明器件通讯错误。

HC595_ALL(0x40);

}


   while(1)

   {

    i=0;

    datapross(DS18B20_GetTemperture());

    for(i=0;i<8;i++)

    {

    HC595_Write_data(seg_temp_code[i],seg_position[i]);

    }

    //测试不消影也可用

    //delay_1us(500);

    //消影

    //HC595_Write_data(0x00,0x00);

   }

}

systick.c文件

#include "gd32vw55x.h"

#include "systick.h"


volatile static uint32_t delay;


void systick_config(void)

{

   SysTimer_SetControlValue(SysTimer_MTIMECTL_CMPCLREN_Msk);

   SysTimer_SetCompareValue(SystemCoreClock / 4000000);

   __ECLIC_SetTrigIRQ(CLIC_INT_TMR, ECLIC_POSTIVE_EDGE_TRIGGER);

   eclic_irq_enable(CLIC_INT_TMR, 0, 0);

}



void delay_1ms(uint32_t count)

{

   delay = count * 1000;

   while(0U != delay) {

   }

}


//定义微秒函数

void delay_1us(uint32_t count)

{

   delay = count;

   while(0U != delay) {

   }

}


void delay_decrement(void)

{

   if(0U != delay) {

       delay--;

   }

}

systick.h文件

#ifndef SYSTICK_H

#define SYSTICK_H


#include <stdint.h>



void systick_config(void);


void delay_1ms(uint32_t count);

//us延迟函数

void delay_1us(uint32_t count);


void delay_decrement(void);


#endif


74HC595.c文件:

#include "gd32vw55x.h"

#include "74HC595.h"

#include "systick.h"


//两个74HC595级联,靠近单片的74HC595用于数码管段选,次级74HC595用于未选,

//即十六位数据中低8位用于显示数字,高8位用于选择数码管位置

//动态数码管采用共阴极结构方式,


//定义数码管显示数组

uint8_t seg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};


//定义数码管显示位,共阴极,取反码

uint8_t seg_position[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};


//初始化数据引脚为输出模式

uint8_t HC595_Init()

{

//开启时钟

rcu_periph_clock_enable(HC595_PORT_RCC);

//设置端口模式

   gpio_mode_set(HC595_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,HC595_PIN_SRCLK | HC595_PIN_RCLK |HC595_PIN_SER); //浮空输出

   gpio_output_options_set(HC595_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,HC595_PIN_SRCLK | HC595_PIN_RCLK |HC595_PIN_SER); //设置输出模式


   //初始化为低电平输出,提高稳定性

   HC595_PIN_SER_Low();

   HC595_PIN_SRCLK_Low();

   HC595_PIN_RCLK_Low();


}




//写数据,HCHdata存储数码管位置信息,HCLdata显示数字信息

void HC595_Write_data(uint8_t HCLdata,uint8_t HCHdata)

{

//合并数据

uint16_t HCdata;

HCdata=((HCHdata<<8)|HCLdata);

//写高16位

uint8_t a=0;

for(a=0;a<16;a++)//循环8次即可将一个字节写入寄存器中

{

//优先传输数据中的高位

if(HCdata & 0x8000)

{

HC595_PIN_SER_High();

}else

{

HC595_PIN_SER_Low();

}

HCdata<<=1;//将低位移动到高位

HC595_PIN_SRCLK_Low();

delay_1us(10);

HC595_PIN_SRCLK_High();

delay_1us(10);//移位寄存器时钟上升沿将端口数据送入寄存器中

}

HC595_PIN_RCLK_Low();

delay_1us(10);

HC595_PIN_RCLK_High();//存储寄存器时钟上升沿将前面写入到寄存器的数据输出

delay_1us(500);

//数据针脚低电平输出,提高稳定性

HC595_PIN_SER_Low();

HC595_PIN_SRCLK_Low();

HC595_PIN_RCLK_Low();


}



//轮动显示某个数据

void HC595_ALL(uint8_t dat)

{

uint8_t Ldat;

uint8_t i;

Ldat=0x01;

for(i=0;i<8;i++)

{

HC595_Write_data(dat,~Ldat);

Ldat<<=1;

delay_1ms(200);

if(Ldat==0x00)

{

Ldat=0x01;

}

}

}


74HC595.h文件:

#ifndef __74HC595_h

#define __74HC595_h


extern uint8_t seg_code[17];



//定74HC595通讯引脚与时钟

#define HC595_PORT GPIOA

#define HC595_PIN_SRCLK GPIO_PIN_1

#define HC595_PIN_RCLK GPIO_PIN_2

#define HC595_PIN_SER GPIO_PIN_3

#define HC595_PORT_RCC RCU_GPIOA


#define HC595_PIN_SRCLK_High() gpio_bit_set(HC595_PORT,HC595_PIN_SRCLK)

#define HC595_PIN_SRCLK_Low() gpio_bit_reset(HC595_PORT,HC595_PIN_SRCLK)

#define HC595_PIN_RCLK_High() gpio_bit_set(HC595_PORT,HC595_PIN_RCLK)

#define HC595_PIN_RCLK_Low() gpio_bit_reset(HC595_PORT,HC595_PIN_RCLK)

#define HC595_PIN_SER_High() gpio_bit_set(HC595_PORT,HC595_PIN_SER)

#define HC595_PIN_SER_Low() gpio_bit_reset(HC595_PORT,HC595_PIN_SER)




uint8_t HC595_Init(void);

void HC595_Write_data(uint8_t HCLdata,uint8_t HCHdata);

void HC595_ALL(uint8_t dat);



#endif

DS18B20.c文件:

#include "gd32vw55x.h"

#include "systick.h"

#include "DS18B20.h"




//设置DS18B20输入输出模式

void DS18B20_IO_OUT()

{

//设置端口模式

gpio_mode_set(DS18B20_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,DS18B20_PIN); //浮空输出

gpio_output_options_set(DS18B20_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX,DS18B20_PIN); //设置输出模式


}




void DS18B20_IO_IN()

{

//设置端口输入模式

gpio_mode_set(DS18B20_PORT, GPIO_MODE_INPUT,GPIO_PUPD_NONE,DS18B20_PIN); //浮空输入

}


//复位DS18B20

void DS18B20_Rest()

{

DS18B20_IO_OUT();

gpio_bit_reset(DS18B20_PORT,DS18B20_PIN);

delay_1us(750);

gpio_bit_set(DS18B20_PORT,DS18B20_PIN);

delay_1us(15);

}


//检测DS18B20是否存在

uint8_t DS18B20_Check(void)

{

uint8_t retry=0;

DS18B20_IO_IN();

while(gpio_input_bit_get(DS18B20_PORT,DS18B20_PIN) && retry<200) //引脚变为低电平则为响应存在

{

retry++;

delay_1us(1);

}

if(retry>=200)return 1;

else retry=0;

while(!gpio_input_bit_get(DS18B20_PORT,DS18B20_PIN) && retry<240)

{

retry++;

delay_1us(1);

}

if(retry>=240)return 1;

return 0;

}


//初始化DS18B20,检测DS18B20是否存在,0存在,1不存在

uint8_t DS18B20_Init(void)

{


//开启时钟

rcu_periph_clock_enable(DS18B20_PORT_RCC);

DS18B20_IO_OUT();

delay_1us(10);

DS18B20_Rest();

return DS18B20_Check();

}



//写字节,先写低位再写高位

void DS18B20_Write_Byte(uint8_t dat)

{

uint8_t i;

uint8_t Write_Byte=0;

DS18B20_IO_OUT();

for(i=0;i<8;i++)

{

Write_Byte = dat & 0x01; //取低位数据

dat>>=1;

if(Write_Byte)

{

//写1,先拉低2微秒,再拉高60微秒

gpio_bit_reset(DS18B20_PORT,DS18B20_PIN); //输出低电平

delay_1us(2);

gpio_bit_set(DS18B20_PORT,DS18B20_PIN); //输出高电平

delay_1us(60);

}else{

//写0,先拉低60微秒,再拉高2微秒

gpio_bit_reset(DS18B20_PORT,DS18B20_PIN); //输出低电平

delay_1us(60);

gpio_bit_set(DS18B20_PORT,DS18B20_PIN); //输出高电平

delay_1us(2);

}

}

}



//读一位数据

uint8_t DS18B20_Read_Bit(void)

{

uint8_t data=0;

DS18B20_IO_OUT();

gpio_bit_reset(DS18B20_PORT,DS18B20_PIN); //输出低电平,总线拉低两个微秒

delay_1us(2);

gpio_bit_set(DS18B20_PORT,DS18B20_PIN);

DS18B20_IO_IN();

delay_1us(12); //15us内读取数据

if(gpio_input_bit_get(DS18B20_PORT,DS18B20_PIN))data=1; //输入高电平则将data置1

else data=0;

delay_1us(50);

return data;

}


//读一个字节,先读低位后读高位

uint8_t DS18B20_Read_Byte(void)

{

uint8_t i=0;

uint8_t data;

uint8_t Read_Byte;

for(i=0;i<8;i++)

{

data=DS18B20_Read_Bit();

Read_Byte=(data<<7)|(Read_Byte>>1);

}

return Read_Byte;

}



//读取温度

float DS18B20_GetTemperture(void)

{

uint8_t a,b; //a用来保存低字节,b用来保存高字节

uint16_t temp;

float value;

DS18B20_Init();

DS18B20_Write_Byte(0xcc);

DS18B20_Write_Byte(0x44);

DS18B20_Init();

DS18B20_Write_Byte(0xcc);

DS18B20_Write_Byte(0xbe);

a=DS18B20_Read_Byte(); //读取低位

b=DS18B20_Read_Byte(); //读取高位

temp=(b<<8|a);

//判断高5位,正温度还是负温度?

if((temp & 0xf800)== 0xf800)

{

temp=(~temp)+1; //负温度为数据取反加1

value=temp*(-0.0625);

}else

{

value=temp*0.0625;

}

return value;

}

DS18B20.h文件:

#ifndef __DS18B20_h

#define __DS18B20_h


#include "gd32vw55x.h"


//定义DS18B20通讯引脚与时钟

#define DS18B20_PORT GPIOA

#define DS18B20_PIN GPIO_PIN_0

#define DS18B20_PORT_RCC RCU_GPIOA


//初始化,初始化成功则返回0,失败返回1

uint8_t DS18B20_Init();



//写字节,先写低位再写高位

void DS18B20_Write_Byte(uint8_t dat);


//读一个字节

uint8_t DS18B20_Read_Byte(void);



//读取温度

float DS18B20_GetTemperture(void);



#endif


全部评论
暂无评论
0/144