中移ML307A(4G Cat1,C-SDK,OpenCPU)模组学习开发-UART串口
<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ML307A_OPEN" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
测试
1,配置串口0为 115200波特率, 然后串口0收到什么就返回什么
初始化
串口接收和发送
#include "cm_sys.h" #include "cm_os.h" #include "cm_mem.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include <string.h> #include "cm_gpio.h" #include "cm_iomux.h" #include "cm_uart.h" #define URAT_ID 0 static void* g_uart_sem = NULL; #define uartRecvBuffLen 200 static char uartRecvBuff[uartRecvBuffLen] = {0};//缓存串口接收的数据 /* 串口接收*/ static void uartRecvTask(void *param) { int uartRecvLen=0; int len = 0; while (1) { uartRecvLen=0; if (g_uart_sem != NULL) { osSemaphoreAcquire(g_uart_sem, osWaitForever);//等待有串口信号量 } //读取串口数据 len = cm_uart_read(URAT_ID, (void*)&uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; while (len!=0)//直到读取完 { if (uartRecvLen < uartRecvBuffLen) { //读取串口数据 osDelay(1);//延时 len = cm_uart_read(URAT_ID, (void*)&uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; } else { break; } } //串口发送数据 cm_uart_write(URAT_ID, uartRecvBuff, uartRecvLen, 1000); } } //串口事件回调函数 static void uartEventCall(void *param, uint32_t type) { if (CM_UART_EVENT_TYPE_RX_ARRIVED & type)//收到新数据 { if (g_uart_sem != NULL) { osSemaphoreRelease(g_uart_sem);//发送一个信号量告知任务可以读取串口数据 } } if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type) { /* 收到溢出事件,触发其他线程处理溢出事件 */ } } int uartInit(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, 115200,//波特率 0 //配置为普通串口模式,若要配置为低功耗模式可改为1 }; /* 事件参数 */ cm_uart_event_t event = { CM_UART_EVENT_TYPE_RX_ARRIVED|CM_UART_EVENT_TYPE_RX_OVERFLOW, //注册需要上报的事件类型 NULL,//用户参数 uartEventCall //串口事件回调函数 }; /* 配置引脚复用 GPIO17,GPIO18设置为UART1功能*/ cm_iomux_set_pin_func(17,1); cm_iomux_set_pin_func(18,1); /* 注册事件和回调函数 */ ret = cm_uart_register_event(URAT_ID, &event); if (ret != 0){ return -1;} /* 开启串口 */ ret = cm_uart_open(URAT_ID, &config); if (ret != 0){ return -1;} /* 配置串口唤醒 ,只有UART0具有串口唤醒功能*/ if (URAT_ID == CM_UART_DEV_0) { /* 配置uart唤醒功能,使能边沿检测才具备唤醒功能,仅主串口具有唤醒功能,用于唤醒的数据并不能被uart接收,请在唤醒后再进行uart数传 */ cm_iomux_set_pin_cmd(CM_IOMUX_PIN_17, CM_IOMUX_PINCMD1_LPMEDEG, CM_IOMUX_PINCMD1_FUNC1_LPM_EDGE_RISE); } /*串口接收任务*/ osThreadAttr_t uart_task_attr = {0}; uart_task_attr.name = "uart_task"; uart_task_attr.stack_size = 4096 * 2; uart_task_attr.priority= osPriorityNormal; if (g_uart_sem == NULL) { g_uart_sem = osSemaphoreNew(1, 0, NULL);//创建一个信号量,初始化值为0 } osThreadNew(uartRecvTask, NULL, &uart_task_attr);//创建接收数据任务 return 0; } //相当于程序的main函数 int cm_opencpu_entry(char * param) { (void)param; uartInit(); return 0; }
连接上串口模块进行测试
标准方案
1,这边把串口封装了文件
这边把代码粘贴出来(大家注重使用就可以,使用出来有问题大家反馈给我)
#define uart_c_ #include "uart.h" #include "cm_sys.h" #include "cm_os.h" #include "cm_mem.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include <string.h> #include "cm_gpio.h" #include "cm_iomux.h" #include "cm_uart.h" //串口事件回调函数 static void uart0Event000000(void *param, uint32_t type) { uartStruct *uart = ( uartStruct *)param; if (CM_UART_EVENT_TYPE_RX_ARRIVED & type)//收到接收事件 { if (uart->osEventFlagsIdUart != NULL) { osEventFlagsSet(uart->osEventFlagsIdUart, UART_EVENT_RECV);//发送事件 } } if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type)//收到溢出事件 { if (uart->osEventFlagsIdUart != NULL) { osEventFlagsSet(uart->osEventFlagsIdUart, UART_EVENT_FULL);//发送事件 } } } //串口事件回调函数 static void uart1Event000000(void *param, uint32_t type) { uartStruct *uart = ( uartStruct *)param; if (CM_UART_EVENT_TYPE_RX_ARRIVED & type)//收到接收事件 { if (uart->osEventFlagsIdUart != NULL) { osEventFlagsSet(uart->osEventFlagsIdUart, UART_EVENT_RECV);//发送事件 } } if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type)//收到溢出事件 { if (uart->osEventFlagsIdUart != NULL) { osEventFlagsSet(uart->osEventFlagsIdUart, UART_EVENT_FULL);//发送事件 } } } //串口事件回调函数 static void uart2Event000000(void *param, uint32_t type) { uartStruct *uart = ( uartStruct *)param; if (CM_UART_EVENT_TYPE_RX_ARRIVED & type)//收到接收事件 { if (uart->osEventFlagsIdUart != NULL) { osEventFlagsSet(uart->osEventFlagsIdUart, UART_EVENT_RECV);//发送事件 } } if (CM_UART_EVENT_TYPE_RX_OVERFLOW & type)//收到溢出事件 { if (uart->osEventFlagsIdUart != NULL) { osEventFlagsSet(uart->osEventFlagsIdUart, UART_EVENT_FULL);//发送事件 } } } //串口发送数据任务 static void uart0SendTask000000(void *param) { uartStruct *uart = ( uartStruct *)param; osStatus_t status; uartSendStruct* uartSend; while(1) { status = osMessageQueueGet(uart->osMessageQueueIdUartSendData, &uartSend, NULL,osWaitForever); if (status == osOK) { cm_uart_write(uart->uartId, uartSend->data, uartSend->len, 1000); cm_free(uartSend->data); cm_free(uartSend); } } } //串口发送数据任务 static void uart1SendTask000000(void *param) { uartStruct *uart = ( uartStruct *)param; osStatus_t status; uartSendStruct* uartSend; while(1) { status = osMessageQueueGet(uart->osMessageQueueIdUartSendData, &uartSend, NULL,osWaitForever); if (status == osOK) { cm_uart_write(uart->uartId, uartSend->data, uartSend->len, 1000); cm_free(uartSend->data); cm_free(uartSend); } } } //串口发送数据任务 static void uart2SendTask000000(void *param) { uartStruct *uart = ( uartStruct *)param; osStatus_t status; uartSendStruct* uartSend; while(1) { status = osMessageQueueGet(uart->osMessageQueueIdUartSendData, &uartSend, NULL,osWaitForever); if (status == osOK) { cm_uart_write(uart->uartId, uartSend->data, uartSend->len, 1000); cm_free(uartSend->data); cm_free(uartSend); } } } /* 串口接收 */ static void uart0RecvTask000000(void *param) { uartStruct *uart = ( uartStruct *)param; int uartRecvLen=0; int len = 0; while (1) { uartRecvLen=0; //等待事件, uint32_t flag = osEventFlagsWait(uart->osEventFlagsIdUart, UART_EVENT_RECV | UART_EVENT_FULL, osFlagsWaitAll, osWaitForever); if (flag>0) { len = cm_uart_read(uart->uartId, (void*)&uart->uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; while (len!=0)//直到读取完 { if (uartRecvLen < uartRecvBuffLen) { osDelay(1);//延时 len = cm_uart_read(uart->uartId, (void*)&uart->uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; } else { break; } } if (uart->uartRecvCb) { uart->uartRecvCb(flag, uart->uartRecvBuff, uartRecvLen ); } } } } /* 串口接收 */ static void uart1RecvTask000000(void *param) { uartStruct *uart = ( uartStruct *)param; int uartRecvLen=0; int len = 0; while (1) { uartRecvLen=0; //等待事件, uint32_t flag = osEventFlagsWait(uart->osEventFlagsIdUart, UART_EVENT_RECV | UART_EVENT_FULL, osFlagsWaitAll, osWaitForever); if (flag>0) { len = cm_uart_read(uart->uartId, (void*)&uart->uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; while (len!=0)//直到读取完 { if (uartRecvLen < uartRecvBuffLen) { osDelay(1);//延时 len = cm_uart_read(uart->uartId, (void*)&uart->uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; } else { break; } } if (uart->uartRecvCb) { uart->uartRecvCb(flag, uart->uartRecvBuff, uartRecvLen ); } } } } /* 串口接收 */ static void uart2RecvTask000000(void *param) { uartStruct *uart = ( uartStruct *)param; int uartRecvLen=0; int len = 0; while (1) { uartRecvLen=0; //等待事件, uint32_t flag = osEventFlagsWait(uart->osEventFlagsIdUart, UART_EVENT_RECV | UART_EVENT_FULL, osFlagsWaitAll, osWaitForever); if (flag>0) { len = cm_uart_read(uart->uartId, (void*)&uart->uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; while (len!=0)//直到读取完 { if (uartRecvLen < uartRecvBuffLen) { osDelay(1);//延时 len = cm_uart_read(uart->uartId, (void*)&uart->uartRecvBuff[uartRecvLen], uartRecvBuffLen - uartRecvLen, 1000); uartRecvLen += len; } else { break; } } if (uart->uartRecvCb) { uart->uartRecvCb(flag, uart->uartRecvBuff, uartRecvLen ); } } } } int uart_init(uartStruct *uart) { int32_t ret = -1; /* 配置参数 */ cm_uart_cfg_t config = { uart->config.byte_size, uart->config.parity, uart->config.stop_bit, uart->config.flow_ctrl, uart->config.baudrate, uart->config.is_lpuart }; /* 事件参数 */ cm_uart_event_t event={0}; event.event_type = CM_UART_EVENT_TYPE_RX_ARRIVED|CM_UART_EVENT_TYPE_RX_OVERFLOW; //注册需要上报的事件类型 event.event_param = uart; if (uart->uartId==CM_UART_DEV_0) { event.event_entry = uart0Event000000; } else if (uart->uartId==CM_UART_DEV_1) { event.event_entry = uart1Event000000; } else if (uart->uartId==CM_UART_DEV_2) { event.event_entry = uart2Event000000; } //创建事件 uart->osEventFlagsIdUart = osEventFlagsNew(NULL); if (uart->osEventFlagsIdUart==NULL) { return -1; } //发送消息队列 uart->osMessageQueueIdUartSendData = osMessageQueueNew(50,sizeof(uartSendStruct *),NULL); if (uart->osMessageQueueIdUartSendData == NULL) { return -1; } osThreadAttr_t uart_send_task_attr = {0}; uart_send_task_attr.name = "UartSendTask"; uart_send_task_attr.stack_size = 4096 * 2; uart_send_task_attr.priority = osPriorityNormal; if (uart->uartId==CM_UART_DEV_0) { osThreadNew(uart0SendTask000000, (void *)uart, &uart_send_task_attr); } else if (uart->uartId==CM_UART_DEV_1) { osThreadNew(uart1SendTask000000, (void *)uart, &uart_send_task_attr); } else if (uart->uartId==CM_UART_DEV_2) { osThreadNew(uart2SendTask000000, (void *)uart, &uart_send_task_attr); } /* 配置引脚复用 */ if (uart->uartId==CM_UART_DEV_0) { cm_iomux_set_pin_func(17,1); cm_iomux_set_pin_func(18,1); } else if (uart->uartId==CM_UART_DEV_1) { cm_iomux_set_pin_func(28,1); cm_iomux_set_pin_func(29,1); } else if (uart->uartId==CM_UART_DEV_2) { cm_iomux_set_pin_func(50,3); cm_iomux_set_pin_func(51,3); } /* 注册事件和回调函数 */ ret = cm_uart_register_event(uart->uartId, &event); if (ret != 0) { cm_log_printf(0, "uart register event err,ret=%d\n", ret); return -1; } /* 开启串口 */ ret = cm_uart_open(uart->uartId, &config); if (ret != 0) { cm_log_printf(0, "uart init err,ret=%d\n", ret); return -1; } /* 配置串口唤醒 */ /* 只有UART0具有串口唤醒功能 */ if (uart->uartId == CM_UART_DEV_0) { /* 配置uart唤醒功能,使能边沿检测才具备唤醒功能,仅主串口具有唤醒功能,用于唤醒的数据并不能被uart接收,请在唤醒后再进行uart数传 */ cm_iomux_set_pin_cmd(CM_IOMUX_PIN_17, 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 = 4096 * 2; uart_task_attr.priority= osPriorityNormal; if (uart->osEventFlagsIdUart == NULL) { uart->osEventFlagsIdUart = osEventFlagsNew(NULL);//创建事件 if (uart->osEventFlagsIdUart==NULL) { return -1; } } if (uart->uartId==CM_UART_DEV_0) { osThreadNew(uart0RecvTask000000, (void *)uart, &uart_task_attr); } else if (uart->uartId==CM_UART_DEV_1) { osThreadNew(uart1RecvTask000000, (void *)uart, &uart_task_attr); } else if (uart->uartId==CM_UART_DEV_2) { osThreadNew(uart2RecvTask000000, (void *)uart, &uart_task_attr); } return 0; } void uartSendData(uartStruct *uart,char *data,uint16_t len) { uartSendStruct* uartSend = (uartSendStruct*)cm_malloc(sizeof(uartSendStruct)); if (uartSend!=NULL) { char *data1 = (char*)cm_malloc(len+1); if (data1!=NULL) { memcpy(data1,data,len); uartSend->data = data1; uartSend->len = len; if (osMessageQueuePut(uart->osMessageQueueIdUartSendData ,&uartSend,0U,0U)!=osOK) { cm_free(uartSend); } } else { cm_free(uartSend); } } }
#ifndef uart_c_ #define uart_c_ extern #else #define uart_c_ #endif #ifndef uart_h_ #define uart_h_ #include "cm_sys.h" #include "cm_os.h" #include "cm_mem.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include <string.h> #include "cm_gpio.h" #include "cm_iomux.h" #include "cm_uart.h" #define UART_EVENT_RECV 0x01 //串口接收到数据事件标志 #define UART_EVENT_FULL 0x02 //串口接收缓存区满事件标志 typedef struct{ char *data; uint32_t len; }uartSendStruct; #define uartRecvBuffLen 200//串口缓存数据长度 typedef struct{ cm_uart_cfg_t config; osEventFlagsId_t osEventFlagsIdUart;//事件句柄 osMessageQueueId_t osMessageQueueIdUartSendData;//发送数据队列 cm_uart_dev_e uartId;//串口号 char uartRecvBuff[uartRecvBuffLen];//缓存串口接收的数据 void (*uartRecvCb) (uint32_t flags, char *data, int len);//串口接收数据回调函数 }uartStruct; int uart_init(uartStruct *uart); void uartSendData(uartStruct *uart,char *data,uint16_t len); #endif
2,使用文件就把文件放到这个位置
然后在mk里面
#定义 CUSTOM_MAIN_DIR 代表 custom/custom_main 路径名称 CUSTOM_MAIN_DIR := custom/custom_main #追加源文件(.c文件) (custom/custom_main/src/custom_main.c) OC_FILES += $(CUSTOM_MAIN_DIR)/src/custom_main.c #追加lib文件(.a文件) (custom/custom_main/sys_package.a) OC_LIBS += $(CUSTOM_MAIN_DIR)/sys_package.a #追加 .h文件路径 (custom/custom_main/inc) INC += -I'$(CUSTOM_MAIN_DIR)/inc' #追加 .h文件路径 (custom/custom_main) INC += -I'$(CUSTOM_MAIN_DIR)' #追加 .h文件路径 (custom/custom_main/src) INC += -I'$(CUSTOM_MAIN_DIR)/src' #追加源文件(.c文件) OC_FILES += $(CUSTOM_MAIN_DIR)/src/uart.c
3,下面是串口0的使用
#include "cm_sys.h" #include "cm_os.h" #include "cm_mem.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include <string.h> #include "cm_gpio.h" #include "cm_iomux.h" #include "cm_uart.h" #include "uart.h" uartStruct uart0={0};//定义串口结构体变量 void uartRecvData(uint32_t flags, char *data, int len) { uartSendData(&uart0, data, len);//把接收的数据返回 } //相当于程序的main函数 int cm_opencpu_entry(char * param) { (void)param; //配置串口 uart0.uartId = 0;//配置串口号 uart0.uartRecvCb = uartRecvData;//设置接收数据函数 uart0.config.baudrate = 115200;//波特率 uart0.config.byte_size = CM_UART_BYTE_SIZE_8;//数据位数 uart0.config.flow_ctrl = CM_UART_FLOW_CTRL_NONE;//硬件流控 uart0.config.parity = CM_UART_PARITY_NONE;//奇偶校验 uart0.config.stop_bit = CM_UART_STOP_BIT_ONE;//停止位 uart0.config.is_lpuart = 0;//若要配置为低功耗模式可改为1 if (uart_init(&uart0) !=0)//初始化串口 { return -1; } return 0; }
3,再增加上串口1
#include "cm_sys.h" #include "cm_os.h" #include "cm_mem.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include <string.h> #include "cm_gpio.h" #include "cm_iomux.h" #include "cm_uart.h" #include "uart.h" uartStruct uart0={0};//定义串口结构体变量 uartStruct uart1={0};//定义串口结构体变量 void uartRecvData(uint32_t flags, char *data, int len) { uartSendData(&uart0, data, len);//把接收的数据返回 } void uart1RecvData(uint32_t flags, char *data, int len) { uartSendData(&uart1, data, len);//把接收的数据返回 } //相当于程序的main函数 int cm_opencpu_entry(char * param) { (void)param; //配置串口 uart0.uartId = 0;//配置串口号 uart0.uartRecvCb = uartRecvData;//设置接收数据函数 uart0.config.baudrate = 115200;//波特率 uart0.config.byte_size = CM_UART_BYTE_SIZE_8;//数据位数 uart0.config.flow_ctrl = CM_UART_FLOW_CTRL_NONE;//硬件流控 uart0.config.parity = CM_UART_PARITY_NONE;//奇偶校验 uart0.config.stop_bit = CM_UART_STOP_BIT_ONE;//停止位 uart0.config.is_lpuart = 0;//若要配置为低功耗模式可改为1 if (uart_init(&uart0) !=0)//初始化串口 { return -1; } //配置串口 uart1.uartId = 1;//配置串口号 uart1.uartRecvCb = uart1RecvData;//设置接收数据函数 uart1.config.baudrate = 115200;//波特率 uart1.config.byte_size = CM_UART_BYTE_SIZE_8;//数据位数 uart1.config.flow_ctrl = CM_UART_FLOW_CTRL_NONE;//硬件流控 uart1.config.parity = CM_UART_PARITY_NONE;//奇偶校验 uart1.config.stop_bit = CM_UART_STOP_BIT_ONE;//停止位 uart1.config.is_lpuart = 0;//若要配置为低功耗模式可改为1 if (uart_init(&uart1) !=0)//初始化串口 { return -1; } return 0; }
测试
4,再增加上串口2
#include "cm_sys.h" #include "cm_os.h" #include "cm_mem.h" #include "stdio.h" #include "stdlib.h" #include "stdarg.h" #include <string.h> #include "cm_gpio.h" #include "cm_iomux.h" #include "cm_uart.h" #include "uart.h" uartStruct uart0={0};//定义串口结构体变量 uartStruct uart1={0};//定义串口结构体变量 uartStruct uart2={0};//定义串口结构体变量 void uartRecvData(uint32_t flags, char *data, int len) { uartSendData(&uart0, data, len);//把接收的数据返回 } void uart1RecvData(uint32_t flags, char *data, int len) { uartSendData(&uart1, data, len);//把接收的数据返回 } void uart2RecvData(uint32_t flags, char *data, int len) { uartSendData(&uart2, data, len);//把接收的数据返回 } //相当于程序的main函数 int cm_opencpu_entry(char * param) { (void)param; //配置串口 uart0.uartId = 0;//配置串口号 uart0.uartRecvCb = uartRecvData;//设置接收数据函数 uart0.config.baudrate = 115200;//波特率 uart0.config.byte_size = CM_UART_BYTE_SIZE_8;//数据位数 uart0.config.flow_ctrl = CM_UART_FLOW_CTRL_NONE;//硬件流控 uart0.config.parity = CM_UART_PARITY_NONE;//奇偶校验 uart0.config.stop_bit = CM_UART_STOP_BIT_ONE;//停止位 uart0.config.is_lpuart = 0;//若要配置为低功耗模式可改为1 if (uart_init(&uart0) !=0)//初始化串口 { return -1; } //配置串口 uart1.uartId = 1;//配置串口号 uart1.uartRecvCb = uart1RecvData;//设置接收数据函数 uart1.config.baudrate = 115200;//波特率 uart1.config.byte_size = CM_UART_BYTE_SIZE_8;//数据位数 uart1.config.flow_ctrl = CM_UART_FLOW_CTRL_NONE;//硬件流控 uart1.config.parity = CM_UART_PARITY_NONE;//奇偶校验 uart1.config.stop_bit = CM_UART_STOP_BIT_ONE;//停止位 uart1.config.is_lpuart = 0;//若要配置为低功耗模式可改为1 if (uart_init(&uart1) !=0)//初始化串口 { return -1; } //配置串口 uart2.uartId = 2;//配置串口号 uart2.uartRecvCb = uart2RecvData;//设置接收数据函数 uart2.config.baudrate = 115200;//波特率 uart2.config.byte_size = CM_UART_BYTE_SIZE_8;//数据位数 uart2.config.flow_ctrl = CM_UART_FLOW_CTRL_NONE;//硬件流控 uart2.config.parity = CM_UART_PARITY_NONE;//奇偶校验 uart2.config.stop_bit = CM_UART_STOP_BIT_ONE;//停止位 uart2.config.is_lpuart = 0;//若要配置为低功耗模式可改为1 if (uart_init(&uart2) !=0)//初始化串口 { return -1; } return 0; }
测试
.