cain · 2022年12月10日 · 广东

【GD32F427开发板试用】环境温湿度检测表项目

非常感谢极术社区和GigaDevice不定期的举行这种开发板试用的活动,使我们这种小白有机会进行学习,利用开发板做一些小的玩意,提高学习的兴趣。也感谢极术小姐姐,能够给我机会领取到开发板,而且物流邮寄的速度也很快。下面开始我们的兴趣之旅。
   我拿到的开发板主控使用的是GD32F427RKT6,LQFP64封装,32位Arm® Cortex®-M4,最高可达200MHz工作频率。6组UART口,3组I2C口,51组GPIO口,当然是可以功能复用的。开发板图片如下:
 title=
      拿到开发板后,计划用来做一个环境温湿度检测器,环境温湿度通过1.3”OLED显示出来。温湿度sensor采用AM2311,屏采用I2C接口的1.3”OLED屏模组。AM2311是采用单总线接口,接口简单,就三条线:电源/地/数据线。如下图所示:
 title=
单总线接口协议如下。
 title=
       1.3”OLED屏驱动芯片是SH1106,I2C接口。
1、 建立工程文件
    首先建立新的工程文件,导入GD32F427R的支持包,如下图所示,这部分都大同小异,度娘上很多介绍的,这里不做赘述。
 title=
2、 硬件映射
     硬件映射的目的是按目前的硬件连接建立.h文件,如下图所示:
 title=
        屏显示采用的是I2C1接口,PB10/PB11连接到I2C\\\_SCL和I2C\\\_SDA,温湿度总线连接到PC9。
3、 代码描述
 ①首先移植UART3接口及printf函数重定向,测试一下项目的建立正确与否。

#include <bsp_Uart3.h>

/** 配置调试串口(UART3) **/
void bsp_UART3_config(void)
{
    rcu_periph_clock_enable(RCU_GPIO_UART3);
    gpio_mode_set(DB_UART3_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,DB_UART3_TX_PIN|DB_UART3_RX_PIN);
    gpio_output_options_set(DB_UART3_PORT,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,DB_UART3_TX_PIN|DB_UART3_RX_PIN);
    gpio_af_set(DB_UART3_PORT,GPIO_AF_8,DB_UART3_TX_PIN|DB_UART3_RX_PIN);
    
//    usart_deinit(UART3);
    rcu_periph_clock_enable(RCU_DB_UART3);
    usart_baudrate_set(UART3,115200);
    usart_parity_config(UART3,USART_PM_NONE);
    usart_word_length_set(UART3,USART_WL_8BIT);
    usart_stop_bit_set(UART3,USART_STB_1BIT);
    usart_enable(UART3);
    usart_transmit_config(UART3,USART_TRANSMIT_ENABLE);
    usart_receive_config(UART3,USART_RECEIVE_ENABLE);
}

/** 重定向打印输入输出口 **/
int fputc(int ch,FILE *f)
{
    usart_data_transmit(UART3,(uint8_t) ch);
    while(usart_flag_get(UART3,USART_FLAG_TC) == 0);
    return (ch);
}
int fgetc(FILE *f)
{
    while(usart_flag_get(UART3,USART_FLAG_RBNE) == 0);
    return((int)(usart_data_receive(UART3)));
}

②I2C1接口初始化。

#include "bsp_i2c1.h"

/** I2C1初始化 **/
void bsp_I2C1_config(void)
{
    rcu_periph_clock_enable(RCU_I2C1_PORT);
    rcu_periph_clock_enable(RCU_I2C1);
    gpio_mode_set(I2C1_PORT,GPIO_MODE_AF,GPIO_PUPD_PULLUP,I2C1_SCL_PIN|I2C1_SDA_PIN);
    gpio_output_options_set(I2C1_PORT,GPIO_OTYPE_OD,GPIO_OSPEED_50MHZ,I2C1_SCL_PIN|I2C1_SDA_PIN);
    gpio_af_set(I2C1_PORT,GPIO_AF_4,I2C1_SCL_PIN|I2C1_SDA_PIN);
    
    i2c_clock_config(I2C1,I2C_Speed,I2C_DTCY_2);
    i2c_mode_addr_config(I2C1,I2C_I2CMODE_ENABLE,I2C_ADDFORMAT_7BITS,0x0A);
    i2c_ack_config(I2C1,I2C_ACK_ENABLE);
//    i2c_ackpos_config(I2C1,I2C_ACKPOS_CURRENT);
    i2c_enable(I2C1);    
}

③OLED屏的初始化。

//初始化SH1106                        
void OLEDConfiguration(void)
{           
    OLED_WR_Byte(0xAE, OLED_CMD);//--display off
    OLED_WR_Byte(0x02, OLED_CMD);//---set low column address
    OLED_WR_Byte(0x10, OLED_CMD);//---set high column address
    OLED_WR_Byte(0x40, OLED_CMD);//--set start line address  
    OLED_WR_Byte(0xB0, OLED_CMD);//--set page address
    OLED_WR_Byte(0x81, OLED_CMD); // contract control
    OLED_WR_Byte(0xCF, OLED_CMD);//--128   
    OLED_WR_Byte(0xA1, OLED_CMD);//set segment remap 
    OLED_WR_Byte(0xA6, OLED_CMD);//--normal / reverse
    OLED_WR_Byte(0xA8, OLED_CMD);//--set multiplex ratio(1 to 64)
    OLED_WR_Byte(0x3F, OLED_CMD);//--1/64 duty
    OLED_WR_Byte(0xAD, OLED_CMD);//set charge pump enable
    OLED_WR_Byte(0x8B, OLED_CMD);//-0x8B 内供 VCC
    OLED_WR_Byte(0x33, OLED_CMD);//-0X30---0X33 set VPP 9V
    OLED_WR_Byte(0xC8, OLED_CMD);//Com scan direction
    OLED_WR_Byte(0xD3, OLED_CMD);//-set display offset
    OLED_WR_Byte(0x00, OLED_CMD);//
    
    OLED_WR_Byte(0xD5, OLED_CMD);//set osc division
    OLED_WR_Byte(0x80, OLED_CMD);//
    
    OLED_WR_Byte(0xD9, OLED_CMD);//set area color mode off
    OLED_WR_Byte(0x05, OLED_CMD);//
    
    OLED_WR_Byte(0xD9, OLED_CMD);//Set Pre-Charge Period
    OLED_WR_Byte(0x1F, OLED_CMD);//
    
    OLED_WR_Byte(0xDA, OLED_CMD);//set com pin configuartion
    OLED_WR_Byte(0x12, OLED_CMD);//
    
    OLED_WR_Byte(0xDB, OLED_CMD);//set Vcomh
    OLED_WR_Byte(0x40, OLED_CMD);//
    
    
    OLED_WR_Byte(0xAF,OLED_CMD);//--turn on oled panel
    
    OLED_Display_Status(Display_Clear);
    OLED_Set_Pos(0, 0); 
}

④建立字符串及数字显示函数,以方便后续温湿度的显示。

//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示                 
//size:选择字体 16/12 
void OLED_ShowChar(uint8_t x, uint8_t y, uint8_t chr)
{          
    uint8_t c = 0, i = 0;    
    c = chr - ' ';//得到偏移后的值            
    if(x > Max_Column - 1)
    {
        x = 0;
        y += 2;
    }
    if(SIZE == 16)
    {
        OLED_Set_Pos(x, y);    
        for(i = 0; i < 8; i ++)
        {
            OLED_WR_Byte(F8X16[c * 16 + i], OLED_DATA);
        }
        OLED_Set_Pos(x, y + 1);
        for(i = 0; i < 8; i ++)
        {
            OLED_WR_Byte(F8X16[c * 16 + i + 8], OLED_DATA);
        }
    }
    else 
    {    
        OLED_Set_Pos(x, y + 1);
        for(i = 0; i < 6; i ++)
        {
            OLED_WR_Byte(F6x8[c][i],OLED_DATA);
        }
    }
}
//m^n函数
uint32_t oled_pow(uint8_t m,uint8_t n)
{
    uint32_t result = 1;     
    while(n --)
    {
        result *= m;
    }    
    return result;
}    

//显示2个数字
//x,y :起点坐标     
//len :数字的位数
//size:字体大小
//mode:模式    0,填充模式;1,叠加模式
//num:数值(0~4294967295);               
void OLED_ShowNum(uint8_t x, uint8_t y, uint32_t num, uint8_t len, uint8_t size)
{             
    uint8_t t,temp;
    uint8_t enshow = 0;                           
    for(t = 0; t < len; t ++)
    {
        temp = (num / oled_pow(10, len - t - 1)) % 10;
        if(enshow == 0 && t < (len - 1))
        {
            if(temp == 0)
            {
                OLED_ShowChar(x + (size / 2) * t, y, ' ');
                continue;
            }else enshow = 1; 
        }
         OLED_ShowChar(x + (size / 2) * t, y, temp + '0'); 
    }
}

//显示一个字符号串
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *chr)
{
    uint8_t j = 0;
    while (chr[j] != '\0')
    {        
        OLED_ShowChar(x, y, chr[j]);
        x += 8;
        if(x > 120)
        {
            x = 0; 
            y += 2;
        }
        j++;
    }
}

////显示汉字
void OLED_ShowCHinese(uint8_t x, uint8_t y, uint8_t no)
{                      
    uint8_t t, adder = 0;
    OLED_Set_Pos(x, y);    
    for(t = 0; t < 16; t ++)
    {
        OLED_WR_Byte(Hzk[2 * no][t], OLED_DATA);
        adder += 1;
    }    
    OLED_Set_Pos(x, y + 1);    
    for(t = 0; t < 16; t ++)
    {    
        OLED_WR_Byte(Hzk[2 * no + 1][t], OLED_DATA);
        adder += 1;
    }                    
}

⑤AM2311初始化,建立协议接口。

void am2311_in_init(void)        //IO设置为输入
{
    rcu_periph_clock_enable(RCU_TandH_port);
    gpio_mode_set(TandH_port,GPIO_MODE_INPUT,GPIO_PUPD_NONE,TandH_pin);
    gpio_output_options_set(TandH_port,GPIO_OTYPE_OD,GPIO_OSPEED_50MHZ,TandH_pin);
}

void am2311_out_init(void)        //IO设置为输出
{
    rcu_periph_clock_enable(RCU_TandH_port);
    gpio_mode_set(TandH_port,GPIO_MODE_OUTPUT,GPIO_PUPD_PULLUP,TandH_pin);
    gpio_output_options_set(TandH_port,GPIO_OTYPE_PP,GPIO_OSPEED_50MHZ,TandH_pin);
}

void am2311_reset(void)            //向AM2311发送读取信号,拉低至少1ms
{
    am2311_out_init();
    AM2311_OUT(0);                
    delay_1ms(2);                //拉低2ms
    AM2311_OUT(1);
    am2311_in_init();            //设置为输入,释放总线
    delay_10us(2);                //20us后AM2311响应
}

⑥读取温湿度函数。

uint16_t am2311_read_data(int16_t *cache)
{
    uint16_t timeout = 0;
    uint8_t  i,data_buf[5];
    uint8_t  check_data = 0;
    am2311_reset();
    if(AM2311_CHECK == 0)            //接收到响应信号 = 80us的低电平 + 80us的高电平
    {            
        while(AM2311_CHECK == 0)    //80us的低电平信号是否完毕
        {
            timeout++;
            if(timeout > 1000)        //防止进入死循环
                return 0;            
        }
        timeout = 0;
        while(AM2311_CHECK == 1)    //80us高电平信号是否完毕
        {
            timeout++;
            if(timeout > 1000)        //防止进入死循环
                return 0;
        }
        for(i = 0; i < 5; i++)
        {
            data_buf[i] = am2311_read_byte();
        }
        check_data = data_buf[0]+data_buf[1]+data_buf[2]+data_buf[3];
        if(check_data == data_buf[4])//数据校验
        {
            printf("SENSOR Read successful! \r\n");
            cache[0] = data_buf[0]*256 + data_buf[1];
            if(data_buf[2] & 0x80)     //零下
            {
                cache[1] = (data_buf[2]&0x7F)*256 + data_buf[3];
                cache[1] = 0 - cache[1];
            }
            else                     //零上
            {
                cache[1] = data_buf[2]*256 + data_buf[3];
            }
            return 1;
        }
    }
    printf("SENSOR Read Failure! \r\n");
    return 0;
}

⑦main主函数中将温湿度读取函数及屏显示函数连接起来,以实现设计意图。

int main(void)
{
        int16_t humi=0,temp=0;
        int16_t buffer[2];
    
        systick_config();
        bsp_UART3_config();
        bsp_I2C1_config();
        OLEDConfiguration();
        OLED_ShowString(0,3,"GD32F427R study");
        delay_1ms(1500);            
        delay_1ms(1500);            
        OLED_Display_Status(Display_Clear);
        OLED_Display_Status(Display_ON);
        OLED_ShowCHinese(0,1,0);                              //温
        OLED_ShowCHinese(16,1,2);                                //度
        OLED_ShowCHinese(32,1,3);                                //:
        OLED_ShowCHinese(0,3,1);                              //湿
        OLED_ShowCHinese(16,3,2);                                //度
        OLED_ShowCHinese(32,3,3);                                //:
        OLED_ShowString(0,6,"Design by cain");
        printf("system start ... \r\n");
    while(1) 
        {
                am2311_read_data(buffer);                        //连续两次采集时间间隔要大于2S    
                humi = buffer[0]/10;
                temp = buffer[1]/10;
                OLED_ShowNum(48,1,temp,2,16);
                OLED_ShowNum(48,3,humi,2,16);
                delay_1ms(500);                                            //AM2311上电后要等待2S以越过不稳定状态
                delay_1ms(500);            
                delay_1ms(500);
                delay_1ms(500);
                delay_1ms(500);
                printf("Humidity = %d Temperature = %d \r\n",humi,  temp);
    }
}

4、 编译下载
Build 项目文件:
 title=
编译没有错误,下载到开发板中,显示效果如下:
 title=

5、 试用总结
 通过本次试用,深切的感觉到GD32F427RKT6功能相当强大,适用于多种场合,外设资源丰富,速度能满足大部分消费类电子的要求,应用前景广阔。
视频显示结果

对本项目有兴趣的伙伴可以通过百度网盘下载相关源码:
链接:https://pan.baidu.com/s/19YNXC-xAAfHfApy5m1VO9w?pwd=9miy
提取码:9miy

文件名 大小 下载次数 操作
T_H_Detector.zip 583.83KB 0 下载
推荐阅读
关注数
10708
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息