资讯详情

STM32的RT-Thread开发

1 硬件环境

stm32f103c8t6板及stm32f401ccu6板是目前性价比最高的stm32开发板,基本不到20元。由于rt-thread操作系统占用还是比较大的,所以stm32f103c8t64板,64K的内存已经十分局促了,因此stm32 rt-thread基于开发stm32f401ccu6.更合适。

ttl转usb板,我用的是ch340芯片

st-link.。

esp01s,目前性价比也很高wifi模块了。

几个数字传感器:单总线ds18b20温度传感器,IIC的dht20温湿度传感器和bmp280气压传感器等。

将stm32f103c8t6与st-link用swd连接,接入PC usb。

将ttl转usb接stm32f103c8t6 uart2(pa2和pa3)。

将esp01s接stm32f103c8t6 uart2(pa9和pa10)。

传感器通过杜邦线插入面包板stm32f103c8t6.。

2 开发环境

下载安装rt-thread studio。

创建一个rt-thread选择开发板、串口和项目st-link连接。

根据我们的硬件连接,选择串口连接UART二、修改连接针PA2和PA三、选择下载器ST-LINK,端口SWD。打开,基本就是这样。

编译和下载测试应该没有问题。

修改系统时钟。rt-thread缺乏配置的时钟是stm内部高速时钟,我们将其修改为外部时钟。driver/board.h修改文件。

/*-------------------------- CLOCK CONFIG BEGIN --------------------------*/  //#define BSP_CLOCK_SOURCE                  ("HSI") //#define BSP_CLOCK_SOURCE_FREQ_MHZ         ((int32_t)0) #define BSP_CLOCK_SOURCE                  ("HSE") #define BSP_CLOCK_SOURCE_FREQ_MHZ         ((int32_t)8) #define BSP_CLOCK_SYSTEM_FREQ_MHZ         ((int32_t)72) 

对于stm32f103c8t6,修改scripts/STM32F103C8/link.lds,将ROM大小修改为128.。原来64k对rt-thread太小了。由于stm32f103c8和stm32f103cB同一晶圆在同一生产线上生产,基本上stm32f103c8可以当是stm32f103cB对待。

修改项目配置,优化编译目标大小,选择交叉编译连接点newlib-nano。

3 添加Finsh shell

添加rt-thread内置命令调试终端。Rt-thread Settings,检查组件和服务Finsh Shell。

注释掉main.c调试打印文件,编译下载。打开终端,选择PC连接的Com端口,我的是Com10.。

4 Wifi连接并连接到阿里云

通过RT-Thread Settings添加AT_DEVICE->Espressif ESP8266和IoT Cloud->Ali-iotkit组件。填写你的Wifi接入的SSID、password,指定串口为uart1。

填写阿里云接入product key、product securet、device name、device securet等信息。

打开driver/board.h添加修改文件uart1宏定义。

#define BSP_USING_UART1 #define BSP_UART1_TX_PIN       "PA9" #define BSP_UART1_RX_PIN       "PA10"

保存修改,编译下载,打开调试终端。

5 时钟日历支持

打开driver/board.h按指示打开文件stm32内部时钟日历。

打开RT-Thread Settings,开启时钟日历支持。

在board.h取消#define BSP_USING_ONCHIP_RTC注释(我们取消了)。

打开drivers/stm32f1xx_hal_config.h,取下#define HAL_RTC_MODULE_ENABLED注释。

保存、编译、下载。

注意,激活Using RTC alarm和我们一起使用uart1有冲突。

6 通过AT命令获取NTP时间,同步rtc时钟。

修改GitHub RT-Thread_at_device/at_sample_client.c。

#include <stdlib.h> #include <string.h>  #include <rtthread.h> #include <at.h> #include <rtc.h> #include "main.h"  //#define LOG_TAG "at.ntp" //#include <at_log.h>  #define DBG_TAG "main" #define DBG_LVL DBG_LOG #include <rtdbg.h>  //#define AT_CLIENT_RECV_BUFF_LEN 512  date_time_t dt;  int main(void) {      //at_client_init("uart1", AT_CLIENT_RECV_BUFF_LEN);      if (!at_client_ntp())     {         set_date(dt.year,dt.month,dt.day);         set_time(dt.hour,dt.minus,dt.seconds);     }      time_t now;     /* 保存获得的当前时间值 */     /* 获取时间 */     now = time(RT_NULL);     /* 打印输出时间信息 */     rt_kprintf("%s\n", ctime(&now));      return RT_EOK; }   int at_client_ntp(void) {     at_response_t resp = RT_NULL;     int result = 0;      resp = at_create_resp(256, 0, rt_tick_from_millisecond(5000));     if (resp == RT_NULL)     {         LOG_E("No memory for response structure!");         return -2;     }      /* send AT */     at_exec_cmd(resp, "AT");     if (result != RT_EOK)     {         LOG_E("AT client send commands AT failed or return response error!");         goto __exit;     }     /* close echo */     at_exec_cmd(resp, "ATE0");     if (result != RT_EOK)     {         LOG_E("AT client send commands ATE0 failed or return response error!");         goto __exit;     }      result = at_exec_cmd(resp, "AT CIPSNTPCFG=1,8,\"ntp1.aliyun.com\",\"cn.pool.ntp.org\"");     if (result != RT_EOK)     {         LOG_E("AT client send commands AT CIPSNTPCFG failed or return response error!");         goto __exit;     }     rt_thread_mdelay(500);     at_exec_cmd(resp, "AT CIPSNTPTIME?");         goto __exit;     }     rt_thread_mdelay(500);     at_exec_cmd(resp, "AT CIPSNTPTIME?");     if (result != RT_EOK)     {         LOG_E("AT client send commands AT CIPSNTPTIME? failed or return response error!");         goto __exit;     }     /* Print response line buffer */     {         const char *line_buffer = RT_NULL;          LOG_D("Response buffer");          for(rt_size_t line_num = 1; line_num <= resp->line_counts; line_num  )         {             if((line_buffer = at_resp_get_line(resp, line_num)) != RT_NULL)             {                 LOG_D("line %d buffer : %s", line_num, lin_buffer);
            }
            else
            {
                LOG_E("Parse line buffer error!");
            }
        }
    }

    {
        char resp_arg[AT_CMD_MAX_LEN] = { 0 };
        const char * resp_expr = "+CIPSNTPTIME:%24[^\r\n]";

        LOG_D(" Parse arguments");
        if (at_resp_parse_line_args(resp, 1, resp_expr, resp_arg) == 1)
        {
            LOG_D("NTP Time: %s", resp_arg);

            char dt_s[4] = {0};
            memcpy(dt_s,resp_arg+4,3);
            for (int i=0;i<12;i++)
            {
                if (memcmp(month_s[i],dt_s,3) == 0)
                {
                    dt.month = i+1;
                }
            }
            memset(dt_s,0,4);
            memcpy(dt_s,resp_arg+8,2);
            dt.day = atoi(dt_s);
            memset(dt_s,0,4);
            memcpy(dt_s,resp_arg+11,2);
            dt.hour = atoi(dt_s);
            memset(dt_s,0,4);
            memcpy(dt_s,resp_arg+14,2);
            dt.minus = atoi(dt_s);
            memset(dt_s,0,4);
            memcpy(dt_s,resp_arg+17,2);
            dt.seconds = atoi(dt_s);
            memset(dt_s,0,4);
            memcpy(dt_s,resp_arg+20,4);
            dt.year = atoi(dt_s);

            rt_kprintf("ntp time is: %d-%d-%d %d:%d:%d\r\n",dt.year,dt.month,dt.day,dt.hour,dt.minus,dt.seconds);

            rt_memset(resp_arg, 0x00, AT_CMD_MAX_LEN);

            if (dt.year == 1970)
            {
                LOG_E("Error! Do not catch real time.");
                goto __exit;
            }
        }
        else
        {
            LOG_E("Parse error, current line buff : %s", at_resp_get_line(resp, 3));
            goto __exit;
        }
    }

__exit:
    if(resp)
    {
        at_delete_resp(resp);
    }

    return result;
}

7 接入DS18B20温度传感器

通过RT-Thread Settings,以此选择Packages->peripheral libraries and drivers->sensors drivers->DS18B20 sensor driver,保存。

修改ds18b20/ds18b20_sample.c at master · willianchanlovegithub/ds18b20 · GitHub

/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-05-08     RT-Thread    first version
 */

#include <rtthread.h>
#include <stdlib.h>
#include <rtthread.h>
#include "board.h"
#include "sensor.h"
#include "sensor_dallas_ds18b20.h"
#include "drv_common.h"

#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

/* Modify this pin according to the actual wiring situation */
#define DS18B20_DATA_PIN    GET_PIN(B, 10)

static int rt_hw_ds18b20_port(void);
static int ds18b20_read_temp_sample(void);
static void read_temp_entry(void *parameter);

int main(void)
{

    rt_hw_ds18b20_port();
    ds18b20_read_temp_sample();

    return RT_EOK;
}

static void read_temp_entry(void *parameter)
{
    rt_device_t dev = RT_NULL;
    struct rt_sensor_data sensor_data;
    rt_size_t res;

    dev = rt_device_find(parameter);
    if (dev == RT_NULL)
    {
        rt_kprintf("Can't find device:%s\n", parameter);
        return;
    }

    if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK)
    {
        rt_kprintf("open device failed!\n");
        return;
    }
    rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100);

    while (1)
    {
        res = rt_device_read(dev, 0, &sensor_data, 1);
        if (res != 1)
        {
            rt_kprintf("read data failed!size is %d\n", res);
            rt_device_close(dev);
            return;
        }
        else
        {
            if (sensor_data.data.temp >= 0)
            {
                rt_kprintf("temp:%3d.%dC, timestamp:%5d\n",
                           sensor_data.data.temp / 10,
                           sensor_data.data.temp % 10,
                           sensor_data.timestamp);
            }
            else
            {
                rt_kprintf("temp:-%2d.%dC, timestamp:%5d\n",
                           abs(sensor_data.data.temp / 10),
                           abs(sensor_data.data.temp % 10),
                           sensor_data.timestamp);
            }
        }
        rt_thread_mdelay(5000);
    }
}

static int ds18b20_read_temp_sample(void)
{
    rt_thread_t ds18b20_thread;

    ds18b20_thread = rt_thread_create("18b20tem",
                                      read_temp_entry,
                                      "temp_ds18b20",
                                      1024,
                                      RT_THREAD_PRIORITY_MAX / 2,
                                      20);
    if (ds18b20_thread != RT_NULL)
    {
        rt_thread_startup(ds18b20_thread);
    }

    return RT_EOK;
}
//INIT_APP_EXPORT(ds18b20_read_temp_sample);

static int rt_hw_ds18b20_port(void)
{
    struct rt_sensor_config cfg;

    cfg.intf.user_data = (void *)DS18B20_DATA_PIN;
    rt_hw_ds18b20_init("ds18b20", &cfg);

    return RT_EOK;
}
//INIT_COMPONENT_EXPORT(rt_hw_ds18b20_port);

 8 IIC传感器接入

通过RT-Thread Settings使能i2c driver支持。

 在board.h取消#define BSP_USING_I2C1注释,针对硬件连接修改针脚,比如SCL->PB6,SDA->PB7。

BMP280气压传感器 

通过RT-Thread Settings打开BMP280气压传感器的支持。

 主程序添加传感器初始化。

#include "sensor_bs_bmp280.h"

#define BMP280_I2CBUS_NAME "i2c1"


int rt_hw_bmp280_port(void)
{
    struct rt_sensor_config cfg;

//    cfg.intf.dev_name = BMP280_I2CBUS_NAME;
    cfg.intf.dev_name = "i2c1";
    cfg.intf.user_data = (void *)BMP280_ADDR_DEFAULT;
    rt_hw_bmp280_init("bmp280", &cfg);

    return RT_EOK;
}
INIT_APP_EXPORT(rt_hw_bmp280_port);

 修改C:\RT-ThreadStudio\workspace\stm32f103-sensor\packages\bmp280-latest\sensor_bs_bmp280.h

#ifndef SENSOR_BS_BMP280_H__
#define SENSOR_BS_BMP280_H__

#include "sensor.h"
#include "bmp280.h"
//#define BMP280_ADDR_DEFAULT BMP280_I2C_ADDR_SEC
//#define BMP280_I2CBUS_NAME "i2c2"
#define BMP280_ADDR_DEFAULT BMP280_I2C_ADDR_PRIM
int rt_hw_bmp280_init(const char *name, struct rt_sensor_config *cfg);
#endif

注意宏定义#define BMP280_ADDR_DEFAULT BMP280_I2C_ADDR_PRIM,即BMP2800 I2C地址为0x76,这时需要将BMP280 SDO管脚接GND。

调试终端输入sensor_polling temp_bmp和sensor_polling baro_bmp,可以看到数据。

DHT20温湿度传感器

直接用现有AHT10传感器模块。

 主程序添加传感器初始化。

#include "sensor_asair_aht10.h"
#define AHT10_I2C_BUS "i2c1"

int rt_hw_aht10_port(void)
{
    struct rt_sensor_config cfg;

    cfg.intf.dev_name = AHT10_I2C_BUS;
    cfg.intf.user_data = (void *)AHT10_I2C_ADDR;
    rt_hw_aht10_init("aht10", &cfg);

    return RT_EOK;
}
INIT_ENV_EXPORT(rt_hw_aht10_port);

调试终端输入sensor_polling temp_aht和sensor_polling humi_aht,可以看到数据。

9 使用STM32F401CCU6开发板

修改编译器Linker,选择do not use syscalls (--specs=nosys-specs)。

 修改linkscritps/STM32F401CC/link.lds,SECTIONS添加。

    .heap :
    {
        __end__ = .;
        PROVIDE(end = .);
        *(.heap*)
        __HeapLimit = .;
    } > RAM

标签: 300pa2pa传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台