目录
概要
1、 操作系统----RTOS kernel
CMSIS-RTOS2
2、 程序API文档
3、 MQTT调试记录-2024年10月9日
4、 ML307_APP_DEMO_SDK使用指南
5、 MQTT登录onenet平台成功
6、 ML307R链接onenet平台成功-接收数据成功
7、 timer定时器调试
8、 操作系统--OS程序学习
1. 事件(Event)
2. 信号量(Semaphore)
3. 互斥锁(Mutex)
4. 消息队列(Message Queue)
总结
9、 UART调试
10、 CJSON调试
11、 file文件系统调试
12、 中移物联-oneos定位lbs
13、 获取模组运行状态信息
14、 gpio引脚配置及程序开发
概要
最近在升级以前用air724UG开发的如意控物联网demo开源项目,由于中移物联的openCPU采用C语言+RTOS实时操作系统开发,开发起来确实比较难,就在我的博客里做一个开发记录,为了日后再开发时查看,也分享给同样做ML307R--openCPU开发朋友们,希望对大家有所帮助。
前一个阶段的日记记录了我学习RTOS相关学习笔记,还有ML307R--openCPU开发环境搭建等笔记,这次笔记包含RTOS开发和硬件外围模块搭建和MQTT通讯等;由于没有时间发布博客,所以这些调试记录统一发出,具体内容详见目录,未来的预期是期望能够把如意控系统-Air724UG系统全面移植到这个平台上来,期望能够早日完工。
由于本篇博客为调试笔记,记录比较凌乱和无序,给大家造成的不便敬请谅解,有什么问题可以随时留言交流,我会尽快回复大家。
这是如意控air724UG老版本的博客、视频、微信小程序等的开源信息,未来小程序将兼容老版本的微信小程序;等硬件电路图搞完以后也会同步开源给大家。
未来开源资料(工程巨大,一个人搞确实难,期望能够早日完工,自己挖坑自己填 ̄□ ̄||):
a、硬件电路图--嘉立创开源
b、微信小程序原码开源---gitee
c、文档资料开源--csdn
我的博客《微信小程序+阿里物联平台+合宙Air724UG搭建无服务器物联系统(四)---微信小程序云开发(用于存储用户信息等)》, 一起来围观吧
https://blog.csdn.net/unforgettable2010/article/details/122993736?utm_source=app&app_version=5.4.0&code=app_1562916241&uLinkId=usr1mkqgl919blenhttps://blog.csdn.net/unforgettable2010/article/details/122993736?utm_source=app&app_version=5.4.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
我做的物联网开源项目,大家支持一下!一键三连,希望能对有相关开发应用的朋友有帮助。
打扰大家了
硬件电路开源地址:
https://oshwhub.com/codefarmer/ryk_open_20220212https://oshwhub.com/codefarmer/ryk_open_20220212
软件开源地址:
https://gitee.com/TR_studio/WXtodvchttps://gitee.com/TR_studio/WXtodvc
B站视频演示
https://www.bilibili.com/video/BV1em4y1Z71o/?spm_id_from=333.999.0.0&vd_source=800bd4bfe94152648b6e85bd265a9f0chttps://www.bilibili.com/video/BV1em4y1Z71o/?spm_id_from=333.999.0.0&vd_source=800bd4bfe94152648b6e85bd265a9f0c
1、 操作系统----RTOS kernel
CMSIS-RTOS2
CMSIS-RTOS2 定义了一组标准的 RTOS API,这些 API 可以由不同的 RTOS 实现。常见的支持 CMSIS-RTOS2 的 RTOS 包括:
- FreeRTOS: 一个流行的开源实时操作系统。
- Keil RTX5: ARM 自己提供的 RTOS。
- Micrium μC/OS-II 和 μC/OS-III: 商业 RTOS。
- Segger embOS: 商业 RTOS。
- 其他兼容的 RTOS。
2、 程序API文档
程序SDK应用API接口文档查询软件位置
ML307R_OpenCPU_Standard_1.1.0.24053111_release\docs\ML307R_OpenCPU_API手册.chm
该软件可以搜寻API接口文档,打开后为如下图所示:
3、 MQTT调试记录-2024年10月9日
local ProductId = "XXXXXXXX"
local ProductSecret = "XXXXXXXXXXXXXXXXXXX"
4、 ML307_APP_DEMO_SDK使用指南
5、 MQTT登录onenet平台成功
onenet平台设备三元素等信息修改
/*测试变量区,请修改以下参数*/#define APP_DEMO_MQTT_HOST "mqttstudio.heclouds.com" // MQTT测试服务器地址,支持域名,demo使用的是一个公有MQTT服务器,网址:https://www.emqx.com/zh/mqtt/public-mqtt5-broker#define APP_DEMO_MQTT_PORT 1883 // MQTT测试服务器端口#define APP_DEMO_MQTT_CLIENTID "RYK1" // MQTT测试客户端ID,对于同一服务器,clientid需要唯一,否则会互相挤下线#define APP_DEMO_MQTT_USERNAME "XXXXXXXXXX" // MQTT测试用户名#define APP_DEMO_MQTT_PASSWORD "version=2018-10-31&res=products%2FXXXXXXXXX%2Fdevices%2FRYK1&et=4763565690&method=sha1&sign=XXXXXXXXXXXXXXXXXX%3D" // MQTT测试用户密码#define APP_DEMO_MQTT_KEEPALIVE 120 // MQTT测试长连接KEEPALIVE心跳间隔#define APP_DEMO_MQTT_SUB_TOPIC "/thing/property/set" // MQTT接收订阅topic demo仅订阅一个 可自行修改代码 订阅多个#define APP_DEMO_MQTT_SUB_TOPIC2 "/thing/property/post/reply" // MQTT接收订阅topic demo仅订阅一个 可自行修改代码 订阅多个#define APP_DEMO_MQTT_PUB_TOPIC "/thing/property/post" // MQTT推送topic#define APP_DEMO_MQTT_PUB_TOPIC2 "/thing/property/post" // MQTT推送topic/*测试变量区,请修改以上参数*/
6、 ML307R链接onenet平台成功-接收数据成功
下面为接收onenet平台数据的ML307R调试log日志:
[ cmlog ][OPENCPU]:[CM_OC][INFO][MQTT]recv:topic:$sys/XXXXXXXXX/RYK6/thing/property/set,datalen:55
[ cmlog ][OPENCPU]:[APP_DEMO][INFO]qujztest66,payloadlen:{"id":"20","version":"1.0","params":{"ctrlpin":"0010"}}
[ cmlog ][OPENCPU]:[APP_DEMO][INFO]qujztest66,payloadlen:{"id":"22","version":"1.0","params":{"ctrlpin":"0011"}}
7、 timer定时器调试
timer定时器参考下面历程,用于如意控项目定时刷新信号强度,定时刷新IO口状态,定时刷新ADC值、定时刷新模组基站经纬度位置等信息。
注意:千万注意!!!
如下图,定时器中不能添加串口log打印,会报错。
8、 操作系统--OS程序学习
● osThreadId_t:线程ID,用于标识一个线程。
osThreadId_t 用于标识和引用 RTOS 中的一个线程。这个标识符可以在创建线程时获得,并且可以用于后续的操作,例如终止线程、获取线程状态等。
● osTimerId_t:定时器ID,用于标识一个定时器。
osTimerId_t 是实时操作系统(RTOS)中用于标识定时器的类型。sTimerId_t 用于标识和引用 RTOS 中的一个定时器。这个标识符可以在创建定时器时获得,并且可以用于后续的操作,例如启动、停止和删除定时器。
● osEventFlagsId_t:事件标志ID,用于标识一组事件标志。
osEventFlagsId_t 用于标识和引用 RTOS 中的一个事件标志组。这个标识符可以在创建事件标志组时获得,并且可以用于后续的操作,例如设置、清除、等待和读取事件标志。
● osMutexId_t:互斥锁ID,用于标识一个互斥锁。
osMutexId_t 用于标识和引用 RTOS 中的一个互斥锁。这个标识符可以在创建互斥锁时获得,并且可以用于后续的操作,例如获取、释放和删除互斥锁。
● osSemaphoreId_t:信号量ID,用于标识一个信号量。
osSemaphoreRelease 是实时操作系统(RTOS)中用于释放信号量的函数。信号量是一种同步机制,通常用于控制对共享资源的访问或协调多个线程/任务之间的操作。在许多 RTOS 中,例如 FreeRTOS 或者 CMSIS-RTOS,信号量可以用来实现互斥锁、计数信号量等功能。
● osMemoryPoolId_t:内存池ID,用于标识一个内存池。
● osMessageQueueId_t:消息队列ID,用于标识一个消息队列。
osMessageQueueId_t 用于标识和引用 RTOS 中的一个消息队列。这个标识符可以在创建消息队列时获得,并且可以用于后续的操作,例如发送、接收和删除消息队列。
● 实时操作系统(RTOS)中Event、 Semaphore、 Mutex 、 MessageQueue区别于用法?
在实时操作系统(RTOS)中,事件(Event)、互斥锁(Mutex)和消息队列(Message Queue)是常见的同步和通信机制。它们各自有不同的用途和特性,适用于不同的场景。下面是这三种机制的区别和用法:
1. 事件(Event)
定义:事件是一种简单的同步机制,用于通知任务某些条件已经满足或某个操作已经完成。
特点:
● 轻量级:事件通常占用较少的系统资源。
● 标志位:可以设置多个标志位,每个标志位代表一个特定的事件。
● 等待/触发:任务可以等待一个或多个事件的发生,而其他任务或中断可以触发这些事件。
用法:
● 状态通知:当某个条件发生变化时,可以通过事件来通知相关的任务。
● 超时处理:任务可以等待事件,并设置超时时间,以避免无限期等待。
2. 信号量(Semaphore)
定义:信号量是一种同步机制,用于控制对共享资源的访问。它可以是二值信号量(0 或 1)或计数信号量(非负整数)。
特点:
● 资源计数:信号量维护一个计数值,表示可用资源的数量。
● 阻塞/非阻塞:如果信号量计数值为 0,尝试获取信号量的任务会被阻塞,直到有其他任务释放信号量。
● 多任务协调:可以用于协调多个任务之间的操作。
用法:
● 资源管理:确保一次只有一个任务可以访问某个资源。
● 任务同步:用于同步多个任务的操作,例如生产者-消费者问题。
3. 互斥锁(Mutex)
定义:互斥锁是一种同步机制,用于保护共享资源,确保同一时间只有一个任务可以访问该资源。
特点:
● 独占性:互斥锁确保对共享资源的独占访问。
● 递归性:某些互斥锁支持递归锁定,即同一个任务可以多次获取同一个互斥锁。
● 优先级继承:互斥锁可以配置为支持优先级继承,以防止优先级反转问题。
用法:
● 保护共享资源:当多个任务需要访问同一个资源时,使用互斥锁来确保一次只有一个任务可以访问该资源。
● 避免竞争条件:通过互斥锁来避免多任务并发访问导致的数据不一致问题。
4. 消息队列(Message Queue)
定义:消息队列是一种通信机制,用于在任务之间传递数据块(消息)。
特点:
● 数据传递:任务可以通过消息队列传递结构化的数据。
● 缓冲区:消息队列通常有一个缓冲区,可以存储多个消息。
● 阻塞/非阻塞:发送和接收消息的操作可以是阻塞的或非阻塞的。
用法:
● 任务间通信:当任务需要交换数据时,使用消息队列来传递消息。
● 解耦合:通过消息队列,任务之间的耦合度降低,提高了系统的可维护性和扩展性。
总结
● 事件:用于简单地通知任务某个条件已经满足或某个操作已经完成。
● 信号量:用于控制对共享资源的访问,确保一次只有一个任务可以访问某个资源。
● 互斥锁:用于保护共享资源,确保同一时间只有一个任务可以访问该资源。
● 消息队列:用于在任务之间传递结构化的数据,实现任务间的通信。
选择哪种机制取决于你的具体需求。如果你只需要简单的状态通知,事件可能就足够了;如果你需要控制对共享资源的访问,信号量是一个很好的选择;如果你需要保护共享资源并避免竞争条件,互斥锁会更合适;如果你需要在任务之间传递数据,那么消息队列会更合适。
9、 UART调试
uart0测试成功!!采用uart0,用于接收和发送串口数据数据。
测试成功:
[20:35:19.721]发→◇{"name":"RYK1"}
□
[20:35:19.852]收←◆[ cmlog ][OPENCPU]:[APP_DEMO][INFO]qujztest
[ cmlog ][OPENCPU]:[APP_DEMO][INFO]qujztest-cjson--device_name:RYK1
[ cmlog ][OPENCPU]:[CM_OC][INFO]cm_mqtt_client_subscribe result:{"name":"RYK1"}
10、 CJSON调试
参考历程:
采用下面程序把CJSON转化为字符串,用于打印。
// 将 JSON 对象转换为字符串
char *jsonString = cJSON_Print(jsonArray);
测试成功:
uart_json=cJSON_Parse(data);uart_json = cJSON_GetObjectItem(uart_json, "token");strcpy(device_password,uart_json->valuestring);app_info_log("qujztest-cjson--device_password:%s",device_password);
11、 file文件系统调试
该文件系统用于存储设备的name和password等需要断电长期保存的设备信息等。
注意:每次文件中读取对应的KEY存储的字段,都是整体读出数据,然后再通过CJSON解析出相应的字段,因此每个文件尽量少存储不相关的数据,或者每个数据单独存储文件。
用一下程序文件存储成功
hal_configfile_set_str(RYKCONFIG_FILE_TEST,"token",device_password);app_info_log("qujztest-cjson--device_password:%s",device_password);
用一下程序文件读取成功
hal_configfile_get_str(RYKCONFIG_FILE_TEST,"name",device_name,sizeof(device_name));app_info_log("qujztest-cjson--device_name22:%s",device_name);hal_configfile_get_str(RYKCONFIG_FILE_TEST,"token",device_password,sizeof(device_password));app_info_log("qujztest-cjson--device_token22:%s",device_password);
12、 中移物联-oneos定位lbs
参照demo中的lbs定位程序,用oneos定位平台,实现模组基站等位功能。
参考demo中的程序调试成功:
//中移物联-oneos定位lbs
app_oneos_lbs_demo_func();
[ cmlog ]cm_lbs_http_callback:3,2114767144
[ cmlog ]cm_lbs_oneospos_callback event:0
[ cmlog ][OPENCPU]:[CM_OC][INFO]get oneos lbs data success22,longitude:126.502017,latitude:45.812373
13、 获取模组运行状态信息
注意:app_info_log,打印日志时,如果分多次打印时,模组重启,查看后发现为WDT,看门狗定时器超时,汇合到一个app_info_log 日志打印以后就不重启了。
// app_oneos_lbs_demo_func();app_info_log("qujztest-cjson--device_name:check:%d",timer_counter);app_info_log("qujztest-s_oneos_lbs_longitude:%s",s_oneos_lbs_longitude);app_info_log("qujztest-s_oneos_lbs_latitude:%s",s_oneos_lbs_latitude);ret = cm_sys_get_sn(SN);ret = cm_sys_get_imei(IMEI);ret = cm_sim_get_imsi(IMSI);ret = hal_modem_get_iccid(ICCID, sizeof(ICCID));/* 查询信号强度 */hal_modem_get_csq(&issi, &ber);ret = cm_adc_vbat_read(&voltage_vbat);app_info_log("Q#Z vbat:%ld(mv)!!timer:%d,longitude:%s,latitude:%s,SN:%s,IMEI:%s,IMSI:%s,ICCID:%s,issi:%ld\n",voltage_vbat,timer_counter,s_oneos_lbs_longitude,s_oneos_lbs_latitude,SN,IMEI,IMSI,ICCID,issi);
调试成功:
输出结果(以下设备信息我就不打马赛克了,希望朋友们手下留情!!)
[ cmlog ][OPENCPU]:[APP_DEMO][INFO]Q#Z vbat:3550(mv)!!timer:21,longitude:126.498037,latitude:45.815884,SN:20214M0001543L057943,IMEI:864979076391036,IMSI:460087436816288,ICCID:898604F4152391196288,issi:21
14、 gpio引脚配置及程序开发
引脚复用功能资料:
/*IOMUX FUNC definition */typedef enum{CM_IOMUX_FUNC_FUNCTION0 , /*!<不支持*/CM_IOMUX_FUNC_FUNCTION1, /*!<功能1*/CM_IOMUX_FUNC_FUNCTION2, /*!<功能2*/CM_IOMUX_FUNC_FUNCTION3, /*!<功能3*/CM_IOMUX_FUNC_FUNCTIONNUM_END,} cm_iomux_func_e;
void app_gpio_init(void){//引脚控制 CM_GPIO_NUM_0// CM_GPIO_NUM_0 // gpio 0// cm_gpio_set_level(UPDATER_LCD_BL_GPIO, CM_GPIO_LEVEL_HIGH);cm_gpio_cfg_t cfg = {.direction = CM_GPIO_DIRECTION_OUTPUT,.pull = CM_GPIO_PULL_UP};// /* 初始化gpio */// cm_gpio_init(UPDATER_LCD_BL_GPIO, &cfg);// cfg.direction = CM_GPIO_DIRECTION_INPUT;cm_iomux_set_pin_func(CM_IOMUX_PIN_0, CM_IOMUX_FUNC_FUNCTION1);cm_iomux_set_pin_func(CM_IOMUX_PIN_2, CM_IOMUX_FUNC_FUNCTION1);/* 初始化gpio */cm_gpio_init(CM_IOMUX_PIN_0, &cfg);cm_gpio_init(CM_IOMUX_PIN_2, &cfg);// cm_gpio_set_level(CM_IOMUX_PIN_0, CM_GPIO_LEVEL_HIGH);// cm_gpio_set_level(CM_IOMUX_PIN_2, CM_GPIO_LEVEL_HIGH);cm_gpio_set_level(CM_IOMUX_PIN_0, CM_GPIO_LEVEL_LOW);cm_gpio_set_level(CM_IOMUX_PIN_2, CM_GPIO_LEVEL_LOW);}
gpio初始化成功!!
程序中引脚置低,或者置高,用万用表测量引脚输出正常。