中移物联ML307C模组OPENCPU笔记3
2.custom_main.c 里面的int cm_opencpu_entry(char * param)函数是程序的main函数, 程序从这个函数里面开始执行。存放 SDK 提供的公共头文件,例如 cm_i2c.h, cm_os.h, cm_uart.h 等。这个文件就是您需要烧录到模组中的程序。CM_USB_DEMO_QUEUE_HANDLE:用于存储消息队列的句柄,用于接收USB数据。CM_
*本次的笔记将详细介绍 ML307C-DC-CN 模组 所使用的 OpenCPU SDK 开发包,包括其目录结构、核心组件。在此基础上,我们将重点讲解如何基于该 SDK 创建一个全新的项目工程,从 函数入口开始,逐步编写和集成您的业务逻辑代码,最终实现一个完整的、可烧录运行的嵌入式应用程序。*
1、SDK包

注意:解压时尽量不要加中文,如果名字太长,也可以适当缩短
本相关文件均存放在SDK文件夹中,文件包含:
-
项目根目录:ML307C-DC-CN_OPENCPU_SDK
这是整个SDK项目的顶层文件夹,包含了所有源代码、配置文件和构建脚本。 -
核心开发区域
custom 文件夹
这是您进行二次开发的核心区域。所有您自己编写的业务逻辑代码都应放在此处。
custom_main: 这是官方为您预设的一个“空工程”模板,供您参考和修改。inc: 存放您自定义的头文件(.h),例如 my_app.h。
src: 存放您自定义的源文件(.c),例如 my_app.c。custom_main.c: 这是程序的入口点。
int cm_opencpu_entry(void *param) 函数是模组启动后首先执行的函数。您需 要在这里编写您的主循环或初始化代码。 -
辅助与参考资源
docs 文件夹
包含项目的 API 文档 和说明文件。可以在这里查阅各个函数的用法和参数说明。examples 文件夹
这是 官方提供的示例程序。它展示了如何使用 SDK 中的各种功能,如:
使用 UART 串口
通过 MQTT 协议连接云平台
配置和使用 LwM2M 协议
进行 HTTP 请求
读写文件系统
等等💡 建议:在开始开发前,务必先阅读 examples 中的代码,了解基本的编程模式和 API 调用方法。
include 文件夹
存放 SDK 提供的公共头文件,例如 cm_i2c.h, cm_os.h, cm_uart.h 等。这些头文件定义了模组提供的各种外设接口和操作系统服务。kernel 文件夹
存放操作系统的内核代码和底层驱动。普通开发者通常不需要修改此部分。 -
构建与输出
out 文件夹
这是 固件输出文件夹。当您成功编译项目后,生成的最终固件文件会存放在此目录下。这个文件就是您需要烧录到模组中的程序。prebuild 文件夹
可能存放预编译的库文件或中间文件,由构建系统自动生成。test 文件夹
这是为 ML307C-DC 模组专门准备的测试 Demo。third-party 文件夹
存放第三方开源库,如 libcurl、mbedtls 等。tools 文件夹
存放各种辅助工具,如烧录工具、打包脚本等。 -
项目管理文件
README.md: 项目的说明文档,通常包含项目简介、快速入门指南、依赖项等。
SConstruct / scons: 构建脚本,用于自动化编译整个项目。
二、创建自己的工程
基于custom创建用户工程
1.可见custom是一个空的工程,通过上节的 编译下载和运行第一个程序 咱知道咱是在custom里面写自己的程序;
sys_package是这边自己增加的文件,后期将会把封装的功能放到里面,然后提供接口使用文档供用户使用;
咱后面写自己的程序的时候需要把.c文件放到src文件夹里面(这是硬性规定); .h文件可以随意。
2.custom_main.c 里面的 int cm_opencpu_entry(char * param) 函数是程序的main函数, 程序从这个函数里面开始执行
3.在src文件夹新建自己需要的.c和.h文件
三、USB例程
USB功能是将USB例化成串口使用,连接电脑设备管理器会出现2个ASR Modem Device 其中一个为USB例化串口,可进行本demo中的回显测试
注意该USB存在一特性:需先以某波特率发任意字节给模组,进行波特率适配,模组才能通过USB往外输出数据
static osThreadId_t CM_USB_DEMO_MAIN_TASKHANDLE = NULL; // USB DEMO测试线程
static osMessageQueueId_t CM_USB_DEMO_QUEUE_HANDLE = NULL; // USB 队列用于接收USB数据
作用:
CM_USB_DEMO_MAIN_TASKHANDLE:用于存储USB主任务的线程ID。
CM_USB_DEMO_QUEUE_HANDLE:用于存储消息队列的句柄,用于接收USB数据。
USB接收数据回调函数
static void cm_usb_demo_recv_callback(void *data, int32_t len)
{
if (len <= 0) // 如果无数据 则返回
{
return;
}
cm_usb_demo_data_t *usb_recv_data = cm_malloc(sizeof(cm_usb_demo_data_t));
if (usb_recv_data == NULL)
{
return;
}
usb_recv_data->event = CM_USB_DEMO_EVENT_RECV;
memcpy(usb_recv_data->data, data, len);
usb_recv_data->datalen = len;
if (osOK != osMessageQueuePut(CM_USB_DEMO_QUEUE_HANDLE, &usb_recv_data, 0, 0)) //timeout一定要为0 不能在回调中做阻塞操作
{
cm_free(usb_recv_data);
return;
}
}
作用:当USB接收到数据时被调用,将数据封装后放入消息队列。
使用方法:
通过 cm_usb2com_register_recv_cb() 注册此回调函数。
回调中分配内存保存数据,然后通过 osMessageQueuePut() 将数据放入队列。
USB插拔事件回调函数
static void cm_usb_demo_event_callback(int32_t event)
{
cm_usb_demo_data_t *usb_recv_data = cm_malloc(sizeof(cm_usb_demo_data_t));
if (usb_recv_data == NULL)
{
return;
}
usb_recv_data->event = event;
if (osOK != osMessageQueuePut(CM_USB_DEMO_QUEUE_HANDLE, &usb_recv_data, 0, 0))
{
cm_free(usb_recv_data);
return;
}
return;
}
作用:当USB设备插入或拔出时被调用,将事件放入消息队列。
使用方法:
通过 cm_usb2com_register_status_cb() 注册此回调函数。
USB主线程
static void cm_usb_demo_main(void)
{
while (1)
{
cm_usb_demo_data_t *usb_data = {0};
if (osOK == osMessageQueueGet(CM_USB_DEMO_QUEUE_HANDLE, &usb_data, NULL, osWaitForever))
{
switch (usb_data->event)
{
case CM_USB_DEMO_EVENT_RECV:
//注意该打印函数只能打印最多108字节 超过字节不打印 而非数据接收有问题
cm_log_printf(0,"CM_USB_DEMO_EVENT_RECV:%s,%d", usb_data->data, usb_data->datalen);
cm_usb2com_send_data(usb_data->data,usb_data->datalen); //实现回显
break;
case CM_USB_DEMO_EVENT_INSERT:
cm_log_printf(0,"CM_USB_DEMO_EVENT_INSERT");
break;
case CM_USB_DEMO_EVENT_REMOVE:
cm_log_printf(0,"CM_USB_DEMO_EVENT_REMOVE");
break;
default:
break;
}
cm_free(usb_data);
usb_data = NULL;
}
}
}
作用:处理来自消息队列的数据,包括回显接收的数据和打印插拔事件。
使用方法:
在 cm_opencpu_entry() 中创建此线程。
通过 osMessageQueueGet() 从队列中获取数据并处理。
USB接口测试启动函数
int cm_opencpu_entry(void *arg)
{
(void)arg;
cm_usb2com_register_recv_cb(cm_usb_demo_recv_callback); //数据接收回调
cm_usb2com_register_status_cb(cm_usb_demo_event_callback); //USB插拔检测事件回调
/*创建USB数据接收队列*/
if (CM_USB_DEMO_MAIN_TASKHANDLE == NULL)
{
CM_USB_DEMO_QUEUE_HANDLE = osMessageQueueNew(20, sizeof(cm_usb_demo_data_t *), NULL); // 创建消息队列 用于接收USB回调中的数据
if (CM_USB_DEMO_QUEUE_HANDLE == NULL)
{
cm_log_printf(0,"CM_DEMO_USB_QUEUE_HANDLE is NULL");
}
}
/*创建USB数据接收/发送处理线程*/
osThreadAttr_t usb_demo_main_task_attr = {0};
usb_demo_main_task_attr.name = "usb_demo_main_task";
usb_demo_main_task_attr.stack_size = 4 * 1024;
usb_demo_main_task_attr.priority = osPriorityNormal;
if (CM_USB_DEMO_MAIN_TASKHANDLE == NULL)
{
CM_USB_DEMO_MAIN_TASKHANDLE = osThreadNew((osThreadFunc_t)cm_usb_demo_main, 0, &usb_demo_main_task_attr);
if (CM_USB_DEMO_MAIN_TASKHANDLE == NULL)
{
cm_log_printf(0,"CM_USB_DEMO_MAIN_TASKHANDLE is NULL");
}
}
return 0;
}
作用:初始化USB功能,注册回调函数,创建消息队列和处理线程。
使用方法:
作为程序入口点,在系统启动时被调用。
注册USB数据接收和状态回调函数。
创建消息队列和主线程来处理USB事件。
更多推荐



所有评论(0)