TencentOS tiny危险气体探测仪产品级开发
项目展示效果:
项目开源仓库:
https://gitee.com/morixinguan/tencent-os-tiny-hazardous-gas-detector.git
欢迎大家clone。
前面我们分享了几篇文章:
基于事件型表驱动法菜单框架之小熊派简易气体探测器实战项目开发(上)
基于事件型表驱动法菜单框架之小熊派简易气体探测器实战项目开发(中)
这几篇文章都跟最终要达到的效果关联很大,但是功能并没有完善,今天分享的这个总算是有点像产品的样子了,但无奈硬件资源有限,无法完成太多功能,但我还是希望有朝一日,我能利用我身边的资源把它做成一个公模开源的手持式危险气体探测仪,并继续完善优化软件逻辑以及产品功能,甚至会加入一些标准化的东西(国标、行标、企标),让它看起来真正的像一个产品,并且希望有机会能够量产,帮助更多的工程师入门。
1、软件组成
1.1、软件架构图
1.2、软件框架图
1.2.1 整体框架图
1.2.2 核心软件框架
菜单部分以及传感器部分都是基于表驱动+状态机的方式实现:
1.3、相对于之前发布文章的功能差异
优化UI界面 TencentOS tiny加持 完成记录及记录逻辑 完成阈值设置逻辑 完成报警设置逻辑 完成调试模式逻辑 完成仪器信息查看
1.3.1 优化UI界面
1.3.2 TencentOS tiny加持
由于有TecentOS tiny RTOS的加持,使得我们编程的行为习惯不能像裸机那么随便了,所以,在多个任务并行的过程中,在一些临界区资源的地方必须要加上调度锁,以防止线程切换的过程中产生一些乱象,比如LCD显示接口,但凡是需要显示的地方,都要做好保护,如果没有做好保护,那你可能会看到类似如下的现象:
明明我的软件代码编写的逻辑就没有在这个地方做显示,为啥突然有个莫名其妙的色块产生??这就是因为任务发生切换导致显示的错乱现象;简单的可能是这样的现象,严重的话产品直接就死机了。那么如何加调度锁呢?
例如,给显示一个ASCII码字符串的地方加上调度锁:
/**
* @brief 显示一个ASCII码字符串
* @param x,y 显示起始坐标
* @param str 需要显示的字符串
* @param size 字体大小(支持16/24/32号字体)
* @return none
* @note 1. 需要font.h字库文件的支持
* 2. 超过指定width不显示超过的字符
*/
void LCD_ShowCharStr(uint16_t x, uint16_t y, uint8_t max_width, char* str, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{
//锁定系统调度
tos_knl_sched_lock();
max_width += x;
while((*str <= '~') && (*str >= ' ')) //判断是否非法字符
{
if(x >= max_width)
{
//x方向越界,结束
break;
}
LCD_ShowChar(x,y,*str,back_color, font_color,font_size);
x += font_size / 2;
str++;
}
//解锁系统调度
tos_knl_sched_unlock();
}
加调度锁的方法,即是在函数入口处加上tos_knl_sched_lock
,在函数出口的地方tos_knl_sched_unlock
解除调度锁,这样就完成了一个显示过程的保护,当然,在对SD卡文件系统读写参数的过程中,我们也需要做好保护,比如:
/*用户参数保存处理*/
void User_Para_Save_Process(void)
{
//锁定系统调度
tos_knl_sched_lock();
/*write config.ini parse*/
retUSER_SYS_CONFIG = f_open(&USER_SYS_CONFIG_File, SETTING_PARA, FA_OPEN_EXISTING | FA_WRITE);
if(FR_OK != retUSER_SYS_CONFIG)
{
printf("iniparser: cannot open %s\n", SETTING_PARA);
return ;
}
printf("参数设置保存成功\n");
iniparser_dump_ini(Config_ini, &USER_SYS_CONFIG_File);
f_close(&USER_SYS_CONFIG_File);
iniparser_freedict(Config_ini);
Load_Config_ini_File();
//解锁系统调度
tos_knl_sched_unlock();
}
如果没有做好保护,当你在写入参数到文件系统的时候,此时任务发送了切换,那么很容易就会导致写入错乱进而跳转到:
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
系统有时候就莫名其妙的卡死了;以上这些都是我个人对于RTOS的学习和使用经验,如有说得不合理的地方,欢迎大佬指点迷津。
1.3.3 记录及记录逻辑
记录存储相关数据结构如下:
/*文件名大小限制*/
#define FILE_NAME_LEN 20
/*检测数据大小限制*/
#define DETECT_DATA_LEN 50
/*一个文件存储检测记录的条数*/
#define DETECT_DATA_INDEX 100
typedef struct
{
int serial_number ; //序号
int year ; //2019-
uint8_t month ; //0-12
uint8_t day ; //0-31
uint8_t hour ; //0-24
uint8_t minute ; //0-59
uint8_t detect_result ; //检测结果
/*当前位于文件的哪一行*/
int Current_Line;
/*当前文件编号查询索引*/
int file_number_index ;
/*当前流水号,每次记录初始化的时候会赋值一次*/
int Current_Serial_Number ;
} Record_Data;
extern Record_Data csv_file_record ;
记录逻辑采用分文件csv存储,将csv文件序号存放在ini文件中,然后通过文件序号快速定位到具体是哪个csv文件的哪一行,该策略支持10000条数据实时查询并能保证流程不卡顿,已在相关产品中量产应用。
1.3.4 完成阈值设置逻辑
该设置逻辑分为三档,分别是低、中、高灵敏度,分别对应1000、300、200三档阈值设定,该灵敏度对应的阈值与检测逻辑相关联,对应逻辑关系如下:
阈值设置是系统配置参数的其中一项,数据结构如下:
当SD卡中如果没有配置文件,它有一个默认的结果,用于表示它开机的状态,这个状态是存储在INI文件里的:
1.3.5 完成报警设置逻辑
它是系统配置参数的其中一项,数据结构如下:
当SD卡中如果没有配置文件,它有一个默认的结果,用于表示它开机的状态,这个状态是存储在INI文件里的:
该设置逻辑分为开关,当打开报警,则检测逻辑跳转到危险时,蜂鸣器会发出响声,否则不会发出响声,它的过程是通过一个标志volume进行控制的。
1.3.6 完成调试模式逻辑
它是系统配置参数的其中一项,数据结构如下:
当SD卡中如果没有配置文件,它有一个默认的结果,用于表示它开机的状态,这个状态是存储在INI文件里的:
该设置逻辑分为开关,当打开调试,则检测逻辑中显示烟感值,否则不会显示烟感值,它的过程是通过一个标志debug_flag进行控制的。
1.3.7 完成仪器信息查看
这个功能在上一篇文章其实已经提及了,这里就不再重复说了,详细请看上一篇推文:
2、其它
另外要注意的地方,SD卡内存放的UI为显示界面一些图标存放的地方,其它的文件由软件自动生成:
Para.ini(配置文件)
BearPi_Log0.csv(检测记录存储文件)
本节代码已同步到码云的代码仓库中,获取方法如下:
1、新建一个文件夹
2、使用git clone远程获取文初的代码仓库
项目开源仓库:
https://gitee.com/morixinguan/tencent-os-tiny-hazardous-gas-detector.git
我还将之前做的一些项目以及练习例程在近期内全部上传完毕,与大家一起分享交流:
公众号粉丝福利时刻
这里我给大家申请到了福利,本公众号读者购买小熊派开发板可享受9折优惠,有需要购买小熊派以及腾讯物联网开发板的朋友,淘宝搜索即可,跟客服说你是公众号:嵌入式云IOT技术圈 的粉丝,立享9折优惠!
往期精彩
移植uc/OS-III最新版到小熊派开发板(STM32L431)
觉得本次分享的文章对您有帮助,随手点[在看]
并转发分享,也是对我的支持。