社区导航

 
查看: 591|回复: 2

[GD32F350作品提交] 《基于GD32的仓库温度报警系统》

[复制链接]

70

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2018-10-11 23:33:12 | 显示全部楼层 |阅读模式
一、方案名称:基于GD32F350的智能仓库温度报警器

二、方案概体介绍:
     该项目主要运用GD32F350作为主控MCU,通过一线式通讯接口,外接一个DS18B20进行温度采集。由于个人只是做项目的demo,没有购买多个DS18B20,一般仓库面积比较大,在实际监控中,建议外挂多个DS18B20模块在总线上,由于是单线式传输,因此对时序要求比较严苛,但它可以挂接许多个DS18B20模块,软硬件实现起来比较方便。本项目实现的功能比较简单,大概的执行流程就是通过DS18B20实时采集室内温度,并通过内部寄存器将模拟信号转换成数字信号,编写一线式通讯协议,使用GPIOB_12将完成数据的收发。当采集的温度值在10~33℃时为正常范围,显示内部LED灯为0.3秒亮灭间隔,外部7盏灯会依次以0.05秒的时间间隔亮灭。如果大于33℃或者小于10℃时,则内部LED灯以0.05秒的时间间隔依次两灭,同时外部LED的第8盏灯也会以0.3秒亮灭频率闪烁,并且外部蜂鸣器器会持续响起,用到的是GPIOC_6管脚。当然这温度的范围根据用户要求可以适时设定。

三、开发环境:
     本项目是在Keil uVision5上编译、链接、下载。在收到开发板后,首先当然是搭建好开发环境,在Keil uVision5上下载好针对GD32F350的动态库,这样方便后续的程序编译下载。由于此次项目没有采用OLED显示模组,而八段数码管的点亮驱动要求GPIO的资源较多,因此没有去点亮数码管显示实时温度值了,用到的是串口实时打印。

四、总体结构框图及主模块图:

五、项目心得体会:
    由于该项目是采用DS18B20的外部温度采集模块,其通讯方式是单线式,因此要求的时序比较精准。下面是在demo包下改成的配置。库函数system_gd32f3x0.c原始系统配置的是__SYSTEM_CLOCK_108M_PLL_HXTAL外部晶振,但是拿到的板子外部晶振没有给我们用户焊接,因此系统会切换为__SYSTEM_CLOCK_8M_IRC8M内部RC 8Mhz的系统时钟频率。GD32F350是支持内部RC 8Mhz晶振倍频到108Mhz的,需要修改如下宏定义。如果这个没有设置好,那拿到DS18B20datasheet后,看时序图就知道这是至关重要的。之前没有发现这点漏洞,老是发现DS18B20初始化失败,采集数据都是为0℃。
#if defined (GD32F350)
//#define __SYSTEM_CLOCK_8M_HXTAL              (__HXTAL)
//#define __SYSTEM_CLOCK_8M_IRC8M              (__IRC8M)
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL         (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M_DIV2    (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_84M_PLL_HXTAL         (uint32_t)(84000000)
//#define __SYSTEM_CLOCK_84M_PLL_IRC8M_DIV2    (uint32_t)(84000000)
//#define __SYSTEM_CLOCK_96M_PLL_HXTAL         (uint32_t)(96000000)
//#define __SYSTEM_CLOCK_96M_PLL_IRC8M_DIV2    (uint32_t)(96000000)
//#define __SYSTEM_CLOCK_96M_PLL_IRC48M_DIV2   (uint32_t)(96000000)
//#define __SYSTEM_CLOCK_108M_PLL_HXTAL        (uint32_t)(108000000)
#define __SYSTEM_CLOCK_108M_PLL_IRC8M_DIV2     (uint32_t)(108000000)
#endif /* GD32F350 */

    项目功能很简单,内容也比较少,但是走了很多弯路,导致浪费了很多时间。由于项目是用之前做51单片机的系统开发板,该板是由本人手动画PCB,然后用FeCl3蚀刻,钻孔,手动焊接,此次派上用场了。但这次项目也是只用到LED发光二极管和蜂鸣器部分电路,由于LED8与蜂鸣器是串联在一起的,调试的时候一上电,如果在初始化配置GPIOC_6口为输出时,外部电路老是有1.5V左右的电平输出,因此蜂鸣器总是响起。后面量测才知道是硬件电路所致,因为串联了LED8,将电压拉低,三极管被驱动。因此这能在初始化GPIOC_6口时将配置改成输入,当要让蜂鸣器启动时再将改口改成输出。
本来计划采用外部按键来中断蜂鸣器报警,然后可以通过外部按键调节设定温度范围告警值,但由于没有显示部分,操作起来也没有那么方便,因此该部分待后续慢慢完善吧。总的来说此项目的功能是达到了,DS18B20采集的温度值也比较精准。此次项目让我收获许多,同时在微信群里认识了众多有识之士,通过网友的发帖,也认识到自己的差距。时不待我,只有不断的进行实际项目的开发,才能让自己独当一面。

六、视频演示:
七、项目前期帖子回顾:
       GD32F350RB终于收到了,开箱测试一下!
http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=918279&fromuid=736480
    基于GD32的仓库温度报警系统---串口调试
http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=977265&fromuid=736480
    基于GD32的仓库温度报警系统---DS18B20资料细读
http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=1006098&fromuid=736480
    基于GD32的仓库温度报警系统---GPIO口点灯
http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=1006113&fromuid=736480
    基于GD32的仓库温度报警系统---GPIO口驱动蜂鸣器
http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=1006114&fromuid=736480
    基于GD32的仓库温度报警系统---GPIO初始化与延时设定
http://bbs.eeworld.com.cn/forum.php?mod=viewthread&tid=1029153&fromuid=736480

八、项目代码:








此帖出自GD32 MCU论坛
结构概况框图.png
DS18B20硬件连接图示.png
DS18B20原理图.png

智能仓库温度报警器.zip

4.62 MB, 阅读权限: 1, 下载次数: 31

工程代码



回复

使用道具 举报

70

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

 楼主| 发表于 2018-10-13 10:01:15 | 显示全部楼层
主要代码附上:
static void ds18b20_write8(unsigned char data)   //数据线从高电平拉至低电平,产生写起始信号。15us之内将所需写的位送到数据线上,
{                                                                 //在15~60us之间对数据线进行采样,如果是高电平就写1,低电平写0。
        int i;
          //unsigned long flags;
         gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_12);
       for (i = 0; i < 8; i++) {
                if ((data & 0x1) == 1) {
                        gpio_bit_reset(GPIOB, GPIO_PIN_12);
                        delayus(3);
                        gpio_bit_set(GPIOB, GPIO_PIN_12);
                        delayus(80);
                } else {
                        gpio_bit_reset(GPIOB, GPIO_PIN_12);
                        delayus(80);
                        gpio_bit_set(GPIOB, GPIO_PIN_12);
                        delayus(3);
                }
                data >>= 1;
       }
}

static unsigned char ds18b20_read8(void)     //主机数据线先从高拉至低电平1us以上,再使数据线升为高电平,从而产生读信号
{                                                           //每个读周期最短的持续时间为60us,各个读周期之间必须有1us以上的高电平恢复期
        int i;
        unsigned char bit;
        unsigned char data = 0;
        
        for (i = 0; i < 8; i++) {                   //一个字节有8位
                    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_12);
                gpio_bit_reset(GPIOB, GPIO_PIN_12);
                delayus(2);
                    gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_12);
                bit = gpio_input_bit_get(GPIOB, GPIO_PIN_12);
                data |= (bit << i);
                delayus(60);
        }
        return data;
}

static void ds18b20_reset(void)
{
        unsigned char ret;
          gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_12);  //DQ先置高
          delayus(3);                                                 //稍延时
        gpio_bit_reset(GPIOB, GPIO_PIN_12);             //发送复位脉冲
        delayus(500);                                    //延时(>480us)
        gpio_bit_set(GPIOB, GPIO_PIN_12);               //拉高数据线  
        delayus(30);                                                //等待(15~60us)
          gpio_bit_write(GPIOB, GPIO_PIN_12,RESET);                                            
          gpio_mode_set(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_12);  
          
        ret = (gpio_input_bit_get(GPIOB, GPIO_PIN_12));
        delayus(500);                                                  
        if (ret == 0) {
                EvbUart1Printf("reset ok.\n");
        } else {
                EvbUart1Printf("reset failed.\n");
        }
}

static float ds18b20_read()
{
        int temp = 0;
          int minus;
        char temp1,temp2;
        ds18b20_reset();                          //初始化
        ds18b20_write8(DS18B20_SKIP_ROM);   //跳过读序列号的操作
        ds18b20_write8(DS18B20_COVERTT);    //启动温度转换
          delayus(125);                                  //转换需要一点时间,延时
        ds18b20_reset();                          //初始化
        ds18b20_write8(DS18B20_SKIP_ROM);   //跳过读序列号的操作
        ds18b20_write8(DS18B20_READ_MEM);   //读温度寄存器(头两个值分别为温度的低位和高位)
        
        temp1 = ds18b20_read8();
        temp2 = ds18b20_read8();

        if(temp2&0xfc)
        {
                minus=1;
                temp=((temp2<<8)|temp1);
                temp=((~temp)+1);
        }
        else
        {
                minus=0;
                temp=((temp2<<8)|temp1);
        }
        temp=(float)temp*0.0625;
        if(minus==1)
        {
                temp=-temp;
        }
        return temp;
}


如有不妥之处,请网友提出,谢谢!


回复

使用道具 举报

3426

TA的帖子

171

TA的资源

管理员

Rank: 13Rank: 13Rank: 13Rank: 13

发表于 2018-10-25 09:09:34 | 显示全部楼层


附给评委补充材料:
yin_wu_qing
基于GD32的仓库温度报警系统---串口调试
yin_wu_qing
请教怎样使用GPIO口点亮八段数码管
yin_wu_qing
基于GD32的仓库温度报警系统---DS18B20资料细读
yin_wu_qing
基于GD32的仓库温度报警系统---GPIO口点灯
yin_wu_qing
基于GD32的仓库温度报警系统---GPIO口驱动蜂鸣器
yin_wu_qing
基于GD32的仓库温度报警系统---GPIO初始化与延时设定




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2018-12-12 06:31 , Processed in 0.120290 second(s), 15 queries , Gzip On, MemCache On.

快速回复 返回顶部 返回列表