ML307R OpenCPU UART使用

一、串口使用流程图

二、串口相关函数介绍

三、实现串口收发

一、串口使用流程图

OneMO ML307R模组提供了2路UART给开发者用于通讯开发,以及1路DBG UART用于log的打印。UART Demo示例可以在SDK:examples\uart\src\cm_demo_uart.c中查看。

串口使用流程图

二、串口相关函数介绍

可以在UART Demo示例可以在SDK:examples\uart\src\cm_demo_uart.h中查看

从这里可以看到ML307R 是用户可用只有2个串口

/****************************************************************************//***  @brief 打开串口*  *  @param [in] dev 串口设备ID*  @param [in] cfg 串口配置*  *  @return  *    = 0  - 成功 \n*    < 0  - 失败, 返回值为错误码*  *  @details open之前必须先对引脚复用功能进行设置。\n*           串口支持的波特率及模式见cm_uart_cfg_t结构体注释说明,请详细查看波特率宏定义处的注意事项*/
int32_t cm_uart_open(cm_uart_dev_e dev, cm_uart_cfg_t *cfg);/***  @brief 注册串口事件*  *  @param [in] dev 串口设备ID*  @param [in] event 串口事件*  *  @return  *    = 0  - 成功 \n*    < 0  - 失败, 返回值为错误码*  *  @details 事件包括串口数据可读/溢出等。需在open之前注册。\n*           内置4K缓存区保存未读出的数据,若注册了溢出事件,缓存区满后将上报溢出,缓存区溢出状态下将丢弃新接收的数据。\n*           回调函数中不可输出LOG、串口打印、执行复杂任务或消耗过多资源。*/
int32_t cm_uart_register_event(cm_uart_dev_e dev, void *event);/***  @brief 关闭串口*  *  @param [in] dev 串口设备ID*  *  @return*    = 0  - 成功 \n*    < 0  - 失败, 返回值为错误码*  *  @details */
int32_t cm_uart_close(cm_uart_dev_e dev);/***  @brief 串口写数据*  *  @param [in] dev 串口设备ID*  @param [in] data 待写入数据*  @param [in] len 长度*  @param [in] timeout 超时时间(ms)(无效参数)*  *  @return *    = 实际写入长度 - 成功 \n*    < 0 - 失败, 返回值为错误码*  *  @details */
int32_t cm_uart_write(cm_uart_dev_e dev, const void *data, int32_t len, int32_t timeout);/***  @brief 串口读数据*  *  @param [in] dev 串口设备ID*  @param [out] data 待读数据*  @param [in] len 长度*  @param [in] timeout 超时时间(ms)(无效参数)*  *  @return *    = 实际读出长度 - 成功 \n*    < 0 - 失败, 返回值为错误码*  *  @details */
int32_t cm_uart_read(cm_uart_dev_e dev, void* data, int32_t len, int32_t timeout);

三、实现串口收发

3.1   配置串口设置信息

    /* 配置参数 */cm_uart_cfg_t config = {CM_UART_BYTE_SIZE_8, CM_UART_PARITY_NONE,CM_UART_STOP_BIT_ONE, CM_UART_FLOW_CTRL_NONE, CM_UART_BAUDRATE_115200,0   //配置为普通串口模式,若要配置为低功耗模式可改为1};

3.2 设置串口事件信息     事件里面添加了 接收到新的数据事件和 接收FIFO缓存溢出事件,这个在之后接收回调中处理。

    /* 事件参数 */cm_uart_event_t event = {CM_UART_EVENT_TYPE_RX_ARRIVED|CM_UART_EVENT_TYPE_RX_OVERFLOW,   //注册需要上报的事件类型"uart0",                                                        //用户参数cm_serial_uart_callback                                         //上报事件的回调函数};

3.3 设置串口功能复用
 

    /* 配置引脚复用 */cm_iomux_set_pin_func(OPENCPU_TEST_UARTTX_IOMUX);cm_iomux_set_pin_func(OPENCPU_TEST_UARTRX_IOMUX);

3.4 注册串口事件  主要是串口接收

    /* 注册事件和回调函数 */ret = cm_uart_register_event(OPENCPU_MAIN_URAT, &event);if (ret != RET_SUCCESS){cm_log_printf(0, "uart register event err,ret=%d\n", ret);return;}

3.5 打开串口

    /* 开启串口 */ret = cm_uart_open(OPENCPU_MAIN_URAT, &config);if (ret != RET_SUCCESS){cm_log_printf(0, "uart init err,ret=%d\n", ret);return;}

3.6  设置启用串口接收线程。

    /* 以下为串口接收示例,不影响串口配置,用户可酌情参考 */osThreadAttr_t uart_task_attr = {0};uart_task_attr.name = "uart_task";uart_task_attr.stack_size = 2048;uart_task_attr.priority= UART_TASK_PRIORITY;gstUartCmdRecv.cmd_execute = 0;if (g_uart_sem == NULL){g_uart_sem = osSemaphoreNew(1, 0, NULL);}OC_Uart_TaskHandle = osThreadNew(cm_uart_recv_task, 0, &uart_task_attr);

串口事件

/* 回调函数中不可输出LOG、串口打印、执行复杂任务或消耗过多资源,建议以信号量或消息队列形式控制其他线程执行任务 */
static void cm_serial_uart_callback(void *param, uint32_t type)
{uart_event_msg_t msg = {0};if (CM_UART_EVENT_TYPE_RX_ARRIVED & type){/* 收到接收事件,触发其他线程执行读取数据 */osSemaphoreRelease(g_uart_sem);}if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type){/* 收到溢出事件,触发其他线程处理溢出事件 */msg.msg_type = type;if (uart_event_queue != NULL)//向队列发送数据{osMessageQueuePut(uart_event_queue, &msg, 0, 0);}}
}
/* 串口接收示例,平时使用信号量挂起,当收到接收事件后,释放信号量以触发读取任务 */
static void cm_uart_recv_task(void *param)
{int temp_len = 0;while (1){if (g_uart_sem != NULL){osSemaphoreAcquire(g_uart_sem, osWaitForever);//阻塞}if (rx_rev_len < UART_BUF_LEN){temp_len = cm_uart_read(OPENCPU_MAIN_URAT, (void*)&rx_rev_data[rx_rev_len], UART_BUF_LEN - rx_rev_len, 1000);rx_rev_len += temp_len;cm_uart_write(OPENCPU_MAIN_URAT, rx_rev_data, rx_rev_len, 1000);rx_rev_len = 0;}}
}

以上就是把接收到的数据再发送出来

以下是完整的串口代码

#define UART_BUF_LEN            1024/***************************************************************************** Private Types****************************************************************************/typedef struct{int msg_type;
} uart_event_msg_t;/***************************************************************************** Private Function Prototypes****************************************************************************/void cm_demo_printf(char *str, ...);
static void cm_uart_recv_task(void *param);/***************************************************************************** Private Data****************************************************************************/static int rx_rev_len = 0;
static char rx_rev_data[UART_BUF_LEN] = {0};
static osThreadId_t OC_Uart_TaskHandle = NULL; //串口数据接收、解析任务Handle
static void* g_uart_sem = NULL;
static osMessageQueueId_t uart_event_queue = NULL;
static osThreadId_t uart_event_thread = NULL;cm_uart_cmd_recv_t gstUartCmdRecv = {0}; //串口命令缓冲区/***************************************************************************** Private Functions****************************************************************************//* 用于测试串口事件,用户可参考 */
static void uart_event_task(void *arg)
{uart_event_msg_t msg = {0};while (1){if (osMessageQueueGet(uart_event_queue, &msg, NULL, osWaitForever) == osOK){//cm_log_printf(0, "uart event msg type = %d\n", msg.msg_type);if (CM_UART_EVENT_TYPE_RX_OVERFLOW & msg.msg_type){cm_log_printf(0, "CM_UART_EVENT_TYPE_RX_OVERFLOW... ...");}}}
}/* 用于测试串口事件,用户可参考 */
static int uart_event_task_create(void)
{if (uart_event_queue == NULL){uart_event_queue = osMessageQueueNew(10, sizeof(uart_event_msg_t), NULL);}if (uart_event_thread == NULL){osThreadAttr_t attr1 = {.name = "uart_event",.priority = UART_TASK_PRIORITY,.stack_size = 1024,};uart_event_thread = osThreadNew(uart_event_task, NULL, (const osThreadAttr_t*)&attr1);}return 0;
}/* 回调函数中不可输出LOG、串口打印、执行复杂任务或消耗过多资源,建议以信号量或消息队列形式控制其他线程执行任务 */
static void cm_serial_uart_callback(void *param, uint32_t type)
{uart_event_msg_t msg = {0};if (CM_UART_EVENT_TYPE_RX_ARRIVED & type){/* 收到接收事件,触发其他线程执行读取数据 */osSemaphoreRelease(g_uart_sem);}if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type){/* 收到溢出事件,触发其他线程处理溢出事件 */msg.msg_type = type;if (uart_event_queue != NULL)//向队列发送数据{osMessageQueuePut(uart_event_queue, &msg, 0, 0);}}
}/* 串口接收示例,平时使用信号量挂起,当收到接收事件后,释放信号量以触发读取任务 */
static void cm_uart_recv_task(void *param)
{int temp_len = 0;while (1){if (g_uart_sem != NULL){osSemaphoreAcquire(g_uart_sem, osWaitForever);//阻塞}if (rx_rev_len < UART_BUF_LEN){temp_len = cm_uart_read(OPENCPU_MAIN_URAT, (void*)&rx_rev_data[rx_rev_len], UART_BUF_LEN - rx_rev_len, 1000);rx_rev_len += temp_len;cm_uart_write(OPENCPU_MAIN_URAT, rx_rev_data, rx_rev_len, 1000);rx_rev_len = 0;}}
}/***************************************************************************** Public Functions****************************************************************************//* 从测试串口打印字符串 */
void cm_demo_printf(char *str, ...)
{static char s[600]; //This needs to be large enough to store the string TODO Change magic numberva_list args;int len;if ((str == NULL) || (strlen(str) == 0)){return;}va_start(args, str);len = vsnprintf((char*)s, 600, str, args);va_end(args);cm_uart_write(OPENCPU_MAIN_URAT, s, len, 1000);
}void my_printf(const char *str, ...)
{static char s[1000]; //This needs to be large enough to store the string TODO Change magic numberva_list args;int len;if ((str == NULL) || (strlen(str) == 0)){return;}va_start(args, str);len = vsnprintf((char*)s, 1000, str, args);va_end(args);cm_uart_write(OPENCPU_MAIN_URAT, s, len, 1000);//uart_write_bytes(UART_NUM_1, (const char *) p_buf, len);
}/* 若要修改测试串口可在cm_common.h中修改宏定义 */
void cm_demo_uart(void)
{int32_t ret = -1;/* 配置参数 */cm_uart_cfg_t config = {CM_UART_BYTE_SIZE_8, CM_UART_PARITY_NONE,CM_UART_STOP_BIT_ONE, CM_UART_FLOW_CTRL_NONE, CM_UART_BAUDRATE_115200,0   //配置为普通串口模式,若要配置为低功耗模式可改为1};/* 事件参数 */cm_uart_event_t event = {CM_UART_EVENT_TYPE_RX_ARRIVED|CM_UART_EVENT_TYPE_RX_OVERFLOW,   //注册需要上报的事件类型"uart0",                                                        //用户参数cm_serial_uart_callback                                         //上报事件的回调函数};cm_log_printf(0, "uart NUM = %d demo start... ...", OPENCPU_MAIN_URAT);/* 配置引脚复用 */cm_iomux_set_pin_func(OPENCPU_TEST_UARTTX_IOMUX);cm_iomux_set_pin_func(OPENCPU_TEST_UARTRX_IOMUX);/* 注册事件和回调函数 */ret = cm_uart_register_event(OPENCPU_MAIN_URAT, &event);if (ret != RET_SUCCESS){cm_log_printf(0, "uart register event err,ret=%d\n", ret);return;}/* 开启串口 */ret = cm_uart_open(OPENCPU_MAIN_URAT, &config);if (ret != RET_SUCCESS){cm_log_printf(0, "uart init err,ret=%d\n", ret);return;}/* 配置串口唤醒 *//* 只有UART0具有串口唤醒功能 */if (OPENCPU_MAIN_URAT == CM_UART_DEV_0){/* 配置uart唤醒功能,使能边沿检测才具备唤醒功能,仅主串口具有唤醒功能,用于唤醒的数据并不能被uart接收,请在唤醒后再进行uart数传 */cm_iomux_set_pin_cmd(OPENCPU_UART_WEKEUP_PIN, CM_IOMUX_PINCMD1_LPMEDEG, CM_IOMUX_PINCMD1_FUNC1_LPM_EDGE_RISE);}cm_log_printf(0, "cm_uart_register_event start... ...\n");/* 以下为串口接收示例,不影响串口配置,用户可酌情参考 */osThreadAttr_t uart_task_attr = {0};uart_task_attr.name = "uart_task";uart_task_attr.stack_size = 2048;uart_task_attr.priority= UART_TASK_PRIORITY;gstUartCmdRecv.cmd_execute = 0;if (g_uart_sem == NULL){g_uart_sem = osSemaphoreNew(1, 0, NULL);}OC_Uart_TaskHandle = osThreadNew(cm_uart_recv_task, 0, &uart_task_attr);uart_event_task_create();
}/* 关闭串口 */
void cm_test_uart_close(char **cmd, int len)
{cm_uart_dev_e dev = atoi(cmd[2]);if (0 == cm_uart_close(dev)){cm_demo_printf("uart%d close is ok\n", dev);}else{cm_demo_printf("uart%d close is error\n", dev);}
}
void bsp_uart_init(void)
{cm_demo_uart();cm_demo_printf("\r\nuart_init\r\n");
}

串口接收程序逻辑:1、初始化信号量>2、触发接收事件>3、callback函数中释放信号量>4、接收处理线程接收处理数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/840649.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3实战笔记(42)—Vue + ECharts:流量数据可视化的强大组合

文章目录 前言vue3使用echarts标准demo&#xff1a;总结 前言 在前端开发中&#xff0c;数据可视化已经成为了一个不可或缺的部分。Vue.js作为一个轻量级且易于上手的渐进式JavaScript框架&#xff0c;与ECharts这个强大的数据可视化库的结合&#xff0c;使得在Vue应用中构建交…

java继承(构造器)使用细节3

那么我们怎么来选择用父类的 有参构造器 和无参构造器泥&#xff1f; 就可以不写 或只写super() 并且如像爸爸的爸爸还有爸爸&#xff0c;还有构造。所以会一直调用到爷爷的构造。 细节2 直接继承指的是儿子和爸爸&#xff0c;爸爸和爷爷

Python 渗透测试:Redis 数据库 弱密码测试.(6379端口)

什么是 Redis 数据库 Redis (Remote Dictionary Server) 是一个开源的、内存中的数据结构存储系统&#xff0c;它可以用作数据库、缓存和消息中间件。它支持多种类型的数据结构,如字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等&#xff0…

View function mapping is overwriting an existing endpoint function: home_page

这个错误是因为在你的 Flask 应用中,你定义了两个或多个视图函数,它们使用了相同的 endpoint 名称。Flask 不允许多个视图函数使用相同的 endpoint 名称,因为这会导致冲突。 通常,这个错误会出现在以下几种情况下: 你在不同的路由装饰器中使用了相同的 endpoint 名称。你…

Xilinx(AMD) FPGA通过ICAP原语读取芯片IDCODE实现方法

1 概述 Xilinx每种型号的FPGA芯片都有一个唯一的IDCODE与之对应&#xff0c;同一型号不同封装的IDCODE是相同的。IDCODE的获取方法包括JTAG、ICAP原语、AXI_HWICAP IP核等。获取IDCODE常用于根据芯片型号改变代码的功能&#xff0c;或者对代码进行授权保护&#xff0c;只能在指…

Java使用apache.poi生成excel插入word中

加油&#xff0c;新时代打工人&#xff01; 工作需求&#xff0c;上个文章我们生成好的word&#xff0c;这次将生成好的excel表格数据&#xff0c;插入word中。需要准备好excle数据&#xff0c;然后插入到word中。 最后个需要&#xff0c;就是把这些生成好的word文档转成pdf进行…

EyeMock下载与使用教程

视频眼神修复直视镜头的AI具有极高的灵活性和适应性。它可以根据不同的拍摄环境和主播需求进行个性化设置&#xff0c;确保最佳的视觉呈现效果。在直播互动中&#xff0c;主播可能因为分神或疲劳而失去与观众的直视&#xff0c;这款工具能够迅速识别并修复这一问题&#xff0c;…

机器学习(七) ----------聚类(K-means)

目录 1 核心思想 2 K-means算法 2.1 算法概述 2.2 算法步骤 2.3 数学原理 2.4 ‘肘’方法确定K值 2.4.1 原理 2.4.2 步骤 2.4.3 代码实现 2.5 聚类评估方法 2.5.1 SC轮廓系数&#xff08;Silhouette Coefficient&#xff09; 计算方法 解读 注意事项 2.5.2 Cal…

刷代码随想录有感(77):回溯算法——含有重复元素的全排列

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<int> tmp;vector<vector<int>> res;void backtracking(vector<int> nums, vector<int> used){if(tmp.size() nums.size()){res.push_back(tmp);return;}sort(nums.begin(),…

对安卓手机上损坏的 SD 卡进行故障排除:恢复提示和修复

概括 如果您总是在旅途中&#xff0c;那么您很可能每天都在使用 SD 卡。这些微小但功能强大的闪存已经变得和手机的内部存储一样有用。它们可以存储数据并移动您想要的任何数据类型&#xff0c;因为它们在 Android 设备上添加了额外的存储空间。不幸的是&#xff0c;他们可能会…

四天学会JS高阶(学好vue的关键)——深入面向对象(理论+实战)(第三天)

***本章面试使用居多* 理论篇**一、编程思想 1.1 面向过程 JS 前端居多 按照步骤 性能高 适合跟硬件关系很紧密 没有面向对象易维护易复用易扩展 1.2 面向对象 java典型 按照功能&#xff0c;把事务分别成一个个对象&#xff0c;对象之间分工合作 比较灵活 适合多人合作的…

python绘制多级饼图(分层饼图)

python绘制多级饼图&#xff08;分层饼图&#xff09; 介绍效果代码 介绍 多级饼图展示了数据的层次结构&#xff0c;其中每个级别表示数据的一个层次。我们可以使用matplotlib绘制多级饼图。 效果 代码 import matplotlib.pyplot as plt# 示例数据 outer_labels [Category…

css卡片横线100%宽度

所需样式: 横线不用border, 用单独一个div, 这样就不会影响父组件的padding <div class"pumpDetailView"><div class"pump_title_name"><span>{{ pumpInfo.pointname }}</span><divclass"point_state":style"…

html 字体设置 (web端字体设置)

windows自带的字体是有版权的&#xff0c;包括微软雅黑&#xff08;方正&#xff09;、宋体&#xff08;中易&#xff09;、黑体&#xff08;中易&#xff09;等 版权算是个大坑&#xff0c;所谓为了避免版权问题&#xff0c;全部使用开源字体即可 我这里选择的是思源宋体&…

nodejs 与 npm 版本对应关系

官方地址&#xff1a;https://nodejs.org/en/about/previous-releases

C++容器之无序多集(std::unordered_multiset)

目录 1 概述2 使用实例3 接口使用3.1 construct3.2 assigns3.3 iterators3.4 capacity3.5 find3.6 count3.7 equal_range3.8 emplace3.9 emplace_hint3.10 insert3.11 erase3.12 clear3.13 swap3.14 bucket_count3.15 max_bucket_count3.16 bucket_size3.17 bucket3.18 load_fa…

全栈式数据统计:SqlAlchemy怎样连接MsSql Server获取视图列表

1.源代码 #-----------获取数据库视图列表----------------------------- # -------密码含特殊字符使用 from urllib.parse import quote_plus as urlquotefrom sqlalchemy import create_engine, MetaData, inspect# 替换为你的数据库连接字符串 DRIVER "ODBC Driver 1…

【新】snapd申请Let‘s Encrypt免费SSL证书、自动化续签证书

简介 之前写过一篇certbot申请SSL证书的文章&#xff1a;SSL证书申请&#xff0c;写得比较详细&#xff0c;但是最近发现使用snapd会更方便。 使用机器&#xff1a;Ubuntu 20.04 简单步骤 1、首先安装必要软件 sudo apt install snapd sudo apt install certbot sudo apt …

可视化在医疗健康领域的巨大价值,该如何设计呢。

可视化设计在医疗健康领域具有以下价值&#xff1a; 数据展示与分析&#xff1a;可视化设计可以将医疗健康领域的大量数据以图表、图形等形式进行展示和分析&#xff0c;帮助医生、研究人员和决策者更直观地理解和解读数据&#xff0c;发现规律和趋势&#xff0c;从而做出科学决…

C++高效死锁检测——实现原理与应用(基于强连通分量)

背景 在项目使用多进程、多线程过程中&#xff0c;因争夺资源而造成一种资源竞态&#xff0c;所以需加锁处理。如下图所示&#xff0c;线程 A 想获取线程 B 的锁&#xff0c;线程 B 想获取线程 C 的锁&#xff0c;线程 C 想获取线程 D 的锁&#xff0c; 线程 D 想获取线程 A 的…