1. 开发环境
- 开发某项目,硬件资源是20K RAM+ 128K ROM
应用场景是将传感器数据和云平台和手机交互
软件系统可选项有
- RT_thread
- freeRTOS
- cola os
选用的软件操作系统是RT_thread
使用RT_thread可选用的开发环境有
- RT thread studio
- ENV+KEIL
- ENV+VC code
-
第一种方案
RT thread studio + STM32cubeMX +HAL库
此种方案,软件环境搭建高效,稳定,
可在RT thread settings直观裁剪操作系统初始配置
直接进入用户代码的编写 -
第二种方案
ENV+KEIL+STM32cubeMX
此种方案,在于ENV工具使用的熟练度
虽然ENV对于芯片扩展具有优势,配置的灵活性更大
但是考虑到项目后期的试错成本平衡
但是有时间还是要使用 -
回头看:从后面某个时间节点来看: 简单有效的工具就是合适
-
选用工具就是编译,调试一下,至于代码编写阅读工具,因人而异,没有最好
-
source insight + vs code + 等等
2. 软件基础环境了解
- 进入链接,安装完成
https://www.rt-thread.org/document/site/#/development-tools/rtthread-studio/um/studio-user-begin

- 按照教程新建项目(可忽略)
- 创建好项目的路径(可忽略)

(workspace 为项目的工作空间路径) - 导入现有的项目

- 编译完成表示环境搭建完成

- 进入RT_thread 进行系统初始配置,裁剪功能,合理分配资源

- 进入cubemx setting进行MCU基础硬件初始化

- 详见文章下章
每次使用CubeMX修改基础的硬件配置后请小心的检查此文件

- 下面就进行用户代码的添加了
3. 项目文件夹
- 项目分类如下

- app 文件夹下为用户的应用层代码。涉及到软件每一个功能的逻辑
- applications文件夹下为用户集中控制的逻辑
- bsp文件夹为各外设模组的底层驱动,可以理解为模组的初始化,数据读写
- cubemx为软件cubeMX自动生成的代码,此文件无需添加用户代码
- Debug为编译调试生成文件,只需关注后期生产烧录的HEX文件,升级需要的BIN文件
- drivers为操作系统自带的板级库函数,大多数已屏蔽,未使用
- libraries为HAL库函数
- lwrb为数据环形缓冲
- RTT为SEGGER RTT文件,软件版本788
- rt-thread为操作系统源文件. 版本403
4. 硬件初始化配置
- 详细的使用
RT-Thread Studio与CubeMX联合编程
推荐链接
https://blog.youkuaiyun.com/qq_40824852/article/details/123067421
链接1 - CubeMX 使用
推荐链接
https://www.waveshare.net/study/portal.php?mod=list&catid=40
链接2

3. 配置概览



- 备注项

- 备注项
在HAL库中有一个stm32f1xx_hal_msp.c的文件,这个文件的作用就是根据用户所提供的具体的MCU型号以及硬件配置,对HAL库进行初始化设置操作。所以这个文件是就HAL库与MCU结合的纽带
虽然 STM32CubeMX 生成了多个文件用来初始化外设,但 RT-Thread 只使用了 STM32CubeMX 生成的 stm32fxx_hal_msp.c 文件和 stm32fxx_hal_conf.h 文件。
5. 基础配置完成
目前已经使用cubeMX和rt thread setting完成基础配置
开始进入软件的开发阶段
6. 主函数初始化
- 外设模组初始化在main.c文件中,
- 第一步初始化所有外设
- 进入主控线程
- 设备使用模型


- 简述:第一步注册设备,添加设备对应接口
- 第二步应用层调用接口,先查找设备,然后初始化打开,后面可以正常使用设备接口读写控制等
- 备注:注册打开设备一定要有返回值,否则使用异常(。。。)
rt_err_t gps_init(rt_device_t dev)
{
LOG_OUT("gps_init\r\n");
return RT_EOK;
}
- 在设备扫描函数完成设备的查找,初始状态配置
7.软件框架设计
- 项目软件的设计思想是
主函数main为主控函数
控制着其他线程的状态和整机设备的运行模式,
休眠模式或工作模式
NB的线程为两个
一个为与NB模组交互的AT指令控制线程
使用的是基于状态机编写的交互逻辑,用户自定义灵活度最高,占用资源小
有一款开源组件AT COMMAND
https://gitee.com/moluo-tech/AT-Command
此组件的问题是占用资源大,基础配置5K左右,编写逻辑不灵活、
选用的是基于状态机和二维数组编写的【表驱动】【查表】
推荐链接
https://blog.youkuaiyun.com/weixin_42192405/article/details/115765164
对逻辑编写,扩展很友好,不占用资源
一个为NB与云端交互的控制线程
控制着的事件有
typedef enum
{
I_EVT_IDLE = 1 << 0,//空闲
I_EVT_POWERON = 1 << 1,//电源上电事件
I_EVT_RET_SUCC = 1 << 2,//返回成功事件
I_EVT_RET_FAIL = 1 << 3,//返回失败事件
I_EVT_UPDATA_SUCC = 1 << 4,//上传成功事件
I_EVT_UPDATA_FAIL = 1 << 5,//上传失败事件
I_EVT_RTC_UPDATA = 1 << 6,//RTC触发事件
I_EVT_SENSOR_REC = 1 << 7,//传感器反馈结果事件
I_EVT_SENSOR_SEND = 1 << 8,//传感器控制参数事件
}IOT_EVT_EVENT_T;
每种事件对应执行一种任务,
蓝牙与NB类似
也是两个线程
一个是与模组交互AT控制的线程
一个是控制与APP交互的事件的线程
//EVT任务事件
typedef enum
{
B_EVT_IDLE = 1 << 0,//空闲
B_EVT_POWERON = 1 << 1,//电源上电事件
B_EVT_RET_SUCC = 1 << 2,//返回成功事件
B_EVT_RET_FAIL = 1 << 3,//返回失败事件
B_EVT_UPDATA_SUCC = 1 << 4,//上传成功事件
B_EVT_UPDATA_FAIL = 1 << 5,//上传失败事件
B_EVT_RTC_UPDATA = 1 << 6,//RTC触发事件(可忽略)
}BLE_EVT_EVENT_T;
传感器采集为一个线程
线程目前设计的是等待采集的事件触发,然后顺序采集数据,
采集完成数据后反馈给控制线程
然后挂起等待下一次采集事件
/*
* 步骤
*/
typedef enum
{
idle_step = 0,//空闲
methane_step,//甲烷
triaxial_step,//三轴
temperature_step,//温度
distance_step,//距离
gps_step,//gps
water_step,//水浸
rtc_step,//rtc
battery_step,//电量
finish_step,//结束
}SENSOR_SCAN_STEP_T;
/*
* 传感器数据
*/
typedef struct
{
uint16_t methane; //甲烷
uint16_t temperature;//温度
uint16_t air;//气压
uint8_t err;//错误状态
uint8_t direction_x;//x轴偏角
uint8_t direction_y;//y轴偏角
uint8_t direction_z;//z轴偏角
uint16_t temper;//温度
uint16_t humidity;//湿度
uint16_t distance;//距离
uint32_t latitude;//纬度
uint32_t longitude;//经度
uint8_t water;//水浸
uint32_t timestamp;//时间戳
uint16_t battery;//电量
}sensor_data_t;
上面为传感器的类别与对应的数据
case methane_step:
{
if(app_gas_data_read(&sensor_data.methane, &sensor_data.temperature, &sensor_data.air, &sensor_data.err) == true)
{
LOG_OUT("methane_step ok\r\n");
LOG_OUT("methane=%d ", sensor_data.methane);
LOG_OUT("temperature=%d ", sensor_data.temperature);
LOG_OUT("air=%d ", sensor_data.air);
LOG_OUT("err=%d\r\n", sensor_data.err);
}
else
{
LOG_OUT("methane_step err\r\n");
}
sensor_ctl.step++;
}
break;
bool app_gas_data_read(uint16_t *ch4, uint16_t *temper, uint16_t *air, uint8_t *err)
{
uint8_t temp_buff[8] = {0};
if(rt_device_read(app_gas_dev, RT_NULL, temp_buff, RT_NULL) > 0)
{
// for(uint8_t t=0; t<6; t++)
// {
// LOG_OUT("[%x]",temp_buff[t]);
// }
*ch4 = temp_buff[0]<<8 | temp_buff[1];
*temper = temp_buff[2]<<8 | temp_buff[3];
*air = temp_buff[4]<<8 | temp_buff[5];
*err = temp_buff[7];
return true;
}
return false;
}
8. 软件框架简述
- RTC驱动着设备的唤醒工作
- 设备工作先 采集数据 然后 上传 云端
- 共 6个 线程
- NB 2个, 一个和模组AT交互,一个控制着业务数据流
- BLE 2个, 一个和模组AT交互, 一个控制着业务数据流
- 传感器 1个, 被动开启工作,工作完挂起等待
- 主控 1个, 控制着设备的休眠和其他线程
- 蓝牙是随时可能连接插入
- 核心点是 数据本地保存+数据上云
- 难点是 0%数据丢失
- 复盘点是 如果要做一款极致性价比的产品 ,差距有多少, 当然考虑因素有很多
9. 备注点
- 上电初始化 - 蓝牙休眠 - 设备工作一轮 (传感器+NB)表明设备已上线
- 蓝牙是微信小程序随时可以连接, IO中断唤醒, 接收指令后, 开始采集
- NB与云端通讯是 先发送数据 再等待接收
- 硬件资源 RAM 20K 大概已使用 18K
- 固件大小 已 108K 左右
- BOOTloader 设计 16K 大小
- 总计 128K FLASH 没有剩余多少
- 芯片自带的6K EEPROM 使用了 2K 空间

1019

被折叠的 条评论
为什么被折叠?



