当前位置: 首页 > news >正文

北京房产网站建设如何开发自己的小程序

北京房产网站建设,如何开发自己的小程序,app开发公司q1654534794下拉推广,柳州网站建设11[MSPM0开发]之七 MSPM0G3507 UART串口收发、printf重定向,解析自定义协议等 一、 MSPM0G3507 UART概述二、 MSPM0G3507 UART结构及收发工作过程三、 MSPM0G3507 UART例程概述四、MSPM0G3507 配置五、 MSPM0G3507 UART 串口发送及printf重定向5.1 MSPM0G3507 UART 串…

[MSPM0开发]之七 MSPM0G3507 UART串口收发、printf重定向,解析自定义协议等

  • 一、 MSPM0G3507 UART概述
  • 二、 MSPM0G3507 UART结构及收发工作过程
  • 三、 MSPM0G3507 UART例程概述
  • 四、MSPM0G3507 配置
  • 五、 MSPM0G3507 UART 串口发送及printf重定向
    • 5.1 MSPM0G3507 UART 串口发送
    • 5.2 MSPM0G3507 UART 串口中断接收测试
    • 5.3 MSPM0G3507 printf重定向
  • 六 MSPM0G3507 UART中断接收及循环缓冲实现自定义协议数据解析
  • 七、 遗留问题----fputc重定义
  • 八 续上了

一、 MSPM0G3507 UART概述

UART 控制器包含以下特性:
• 完全可编程串行接口
– 5、 6、 7 或== 8 个数据位==
– 偶校验、奇校验、固定校验或无奇偶校验位生成与检测
– 可产生 1 或 2 个停止位
– 最低有效位或最高有效位数据最先传送和接收
断线检测
– 输入信号上的干扰滤波器
– 可编程波特率生成, 过采样率为 16、 8 或 3 倍
独立的发送和接收 4 深度 FIFO 可减少 CPU 中断服务负载
• 支持 DMA 数据传输
• 提供标准的基于 FIFO 深度的中断以及发送结束中断
• 在包括停止和待机模式在内的所有低功耗模式下均有效
• 在低功耗模式下运行时, 支持通过异步快速时钟请求在检测到起始位时唤醒 SYSOSC( 在 FCL 模式下使用
SYSOSC 时, 支持高达 19200B 的速率)( 精度 1%)
• 支持环回模式运行
• 支持硬件流控
• 支持 9 位多点配置
• 支持的协议:
– 本地互连网络 (LIN) 支持
– DALI
IrDA
– ISO7816 Smart Card
RS485
– 曼彻斯特编码
空闲线多处理器
MSPM0G350x 包含四个 UART 接口;一个支持 LIN、IrDA、DALI、Smart Card、Manchester,三个支持待机模式下的低功耗运行
特性

二、 MSPM0G3507 UART结构及收发工作过程

结构
发送数据:
当需要进行发送时, 先将数据写入发送 FIFO。
如果启用 UART, 则会根据 UARTx.LCRH 寄存器中指示的参数开始发送数据帧。
UART 模块会持续发送数据, 直到发送 FIFO 中没有可发数据为止
数据一经写入发送 FIFO( 即, 如果 FIFO 不为空), UARTx.STAT 寄存器中的 BUSY 位即会生效, 并在数据发送期间一直保持有效。
仅当发送 FIFO 为空, 且最后一个字符( 包括停止位) 已发送到移位寄存器时, BUSY 位才为负。即使无法再启用UART, UART 也可以指示它正忙。生成 BREAK 信号期间, 也会设置 BUSY。

接收数据:
当接收器空闲( RX 信号持续为 1) 且数据输入变为低电平( 已接收到开始位) 时, 接收计数器开始运行, 并根据UARTx.CTL0 寄存器中 HSE 位的过采样设置, 在不同的周期对数据进行采样。
如果 RX 信号在基于过采样设置的特定数量的周期后仍为低电平, 则开始位有效并被识别。
检测到有效的开始位后, 将根据数据字符的编程长度对连续的数据位进行采样。之后将捕获并校验奇偶校验位( 如果使能了奇偶校验) 。
数据长度和奇偶校验都在UART.LCRH 寄存器中定义。
如果 RXD 信号为高电平, 则确认有效停止位, 否则发生成帧错误。
若成功接收到一帧数据, 则数据和与之相关的错误标志都将保存到接收 FIFO 中。

UART状态标志:
![状态标志](https://i-blog.csdnimg.cn/direct/15e5553a5c6d470c9dc3e3f6c944b560.png组态标志
天猛星电路原理图:
图中使用了UART0,映射在了PA10、PA11两个引脚上。并且通过调试下载处的排针和USB typeC接口引出。
原理图

三、 MSPM0G3507 UART例程概述

例程概述

四、MSPM0G3507 配置

配置基于uart_echo_interrupts_standby例程修改
时钟配置波特率等参数
高级参数配置

五、 MSPM0G3507 UART 串口发送及printf重定向

5.1 MSPM0G3507 UART 串口发送

uart初始化:

//GPIO重映射部分 void SYSCFG_DL_GPIO_init(void) 中:DL_GPIO_initPeripheralOutputFunction(GPIO_UART_0_IOMUX_TX, GPIO_UART_0_IOMUX_TX_FUNC);DL_GPIO_initPeripheralInputFunction(GPIO_UART_0_IOMUX_RX, GPIO_UART_0_IOMUX_RX_FUNC);// UART硬件初始化
static const DL_UART_Main_ClockConfig gUART_0ClockConfig = {.clockSel    = DL_UART_MAIN_CLOCK_BUSCLK,.divideRatio = DL_UART_MAIN_CLOCK_DIVIDE_RATIO_1
};static const DL_UART_Main_Config gUART_0Config = {.mode        = DL_UART_MAIN_MODE_NORMAL,.direction   = DL_UART_MAIN_DIRECTION_TX_RX,.flowControl = DL_UART_MAIN_FLOW_CONTROL_NONE,.parity      = DL_UART_MAIN_PARITY_NONE,.wordLength  = DL_UART_MAIN_WORD_LENGTH_8_BITS,.stopBits    = DL_UART_MAIN_STOP_BITS_ONE
};/*** @brief 初始化UART_0模块* * 该函数负责配置和初始化UART_0模块,包括设置时钟配置、初始化配置、* 过采样率、波特率除数以及中断和FIFO的相关配置。通过这些配置,可以* 使UART_0模块以特定的波特率进行通信,并具备基本的中断和数据处理能力。*/
SYSCONFIG_WEAK void SYSCFG_DL_UART_0_init(void)
{// 设置UART_0的时钟配置DL_UART_Main_setClockConfig(UART_0_INST, (DL_UART_Main_ClockConfig *) &gUART_0ClockConfig);// 初始化UART_0配置DL_UART_Main_init(UART_0_INST, (DL_UART_Main_Config *) &gUART_0Config);// 设置UART_0的过采样率为16倍DL_UART_Main_setOversampling(UART_0_INST, DL_UART_OVERSAMPLING_RATE_16X);// 设置UART_0的波特率除数,以达到9600的波特率DL_UART_Main_setBaudRateDivisor(UART_0_INST, UART_0_IBRD_32_MHZ_9600_BAUD, UART_0_FBRD_32_MHZ_9600_BAUD);/* 中断配置 */// 使能UART_0的接收中断DL_UART_Main_enableInterrupt(UART_0_INST, DL_UART_MAIN_INTERRUPT_RX);/* FIFO配置 */// 使能UART_0的FIFO功能DL_UART_Main_enableFIFOs(UART_0_INST);// 设置UART_0接收FIFO的触发阈值为半满DL_UART_Main_setRXFIFOThreshold(UART_0_INST, DL_UART_RX_FIFO_LEVEL_1_2_FULL);// 设置UART_0发送FIFO的触发阈值为四分之一空DL_UART_Main_setTXFIFOThreshold(UART_0_INST, DL_UART_TX_FIFO_LEVEL_1_4_EMPTY);// 使能UART_0模块DL_UART_Main_enable(UART_0_INST);
}     

main.c初始化调用及串口发送字符串:

int main(void) {SYSCFG_DL_init();NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN);NVIC_EnableIRQ(UART_0_INST_INT_IRQN);UART_printf("helloWorld\r\n");while (1) {delay_cycles(32000000);UART_printf("helloWorld\r\n");}
}

其中 UART_printf函数定义如下:

void UART_printf(const char *format, ...) {uint32_t length;va_list args;uint32_t i;char TxBuffer[128] = {0};va_start(args, format);length = vsnprintf((char *)TxBuffer, sizeof(TxBuffer), (char *)format, args);va_end(args);for (i = 0; i < length; i++) {DL_UART_Main_transmitDataBlocking(UART_0_INST, TxBuffer[i]);}
}

提供另一个仅支持发送字符串函数:

void sendString(const char *str) {while (*str != '\0') {DL_UART_Main_transmitDataBlocking(UART_0_INST, (uint8_t)*str);str++;}
}

5.2 MSPM0G3507 UART 串口中断接收测试

上面的初始化代码中,包含串口的发送和接收,以及开启了串口中断。
在5.1基础上增加串口接收中断服务函数即可
下面的中断服务函数中实现 当串口接收到数据后,翻转LED并将接收到的通过串口发送

void UART_0_INST_IRQHandler(void) {switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {/*! UART interrupt index for UART receive */case DL_UART_MAIN_IIDX_RX: DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);gEchoData = DL_UART_Main_receiveData(UART_0_INST);DL_UART_Main_transmitData(UART_0_INST, gEchoData);break;default:break;}
}

测试结果

5.3 MSPM0G3507 printf重定向

在5.2基础上,引用头文件

#include <stdarg.h>
#include <stdio.h>
#include <string.h>

重定向实现3个发送函数

int fputc(int _c, FILE *_fp) {DL_UART_Main_transmitDataBlocking(UART_0_INST, _c);return _c;
}int fputs(const char *restrict s, FILE *restrict stream) {uint16_t i, len;len = strlen(s);for (i = 0; i < len; i++) {DL_UART_Main_transmitDataBlocking(UART_0_INST, s[i]);}return len;
}int puts(const char *_ptr) {int cnt = fputs(_ptr, stdout);cnt += fputs("\n", stdout);return cnt;
}

运行结果:
运行结果

六 MSPM0G3507 UART中断接收及循环缓冲实现自定义协议数据解析

要求:定义一个全局数组做串口接收缓存,接收中断将接收到的压入缓存,在main.c的while()循环中,读取缓存数据并进行帧数据解析,支持自定义帧头内容和长度,一帧数据的长度,读取一帧数据长度。
使用通义灵码生成。
cmd_queue.h

/*!* \file cmd_queue.h* \brief 串口指令队列(支持多队列、多帧头、可配置帧长)* \version 1.3* \date 2024.10* \copyright wo4fisher*/#ifndef _CMD_QUEUE
#define _CMD_QUEUE
#include "ti_msp_dl_config.h"// 队列配置参数
#define QUEUE_MAX_SIZE 100typedef uint8_t qdata;
typedef uint16_t qsize;// 接收状态结构体
typedef struct {uint8_t pos;        // 当前接收位置const qdata *pHead; // 帧头指针uint8_t head_len;   // 帧头长度uint8_t frame_len;  // 总帧长(含帧头)
} CmdState;// 队列句柄结构体定义
typedef struct {qsize _head;                 // 写指针qsize _tail;                 // 读指针qdata _data[QUEUE_MAX_SIZE]; // 数据缓冲区
} QueueHandle;/*!* \brief 初始化一个新的队列* \param[out] q 指向队列句柄的指针*/
void queue_init(QueueHandle *q);/*!* \brief 清空指定队列* \param[in] q 队列句柄*/
void queue_reset(QueueHandle *q);/*!* \brief 将字节加入队列* \param[in] q 队列句柄* \param[in] _data 要入队的数据*/
void queue_push(QueueHandle *q, qdata _data);/*!* \brief 从队列中取出一个字节* \param[in] q 队列句柄* \param[out] _data 数据输出指针* \return 成功返回 true,队列为空返回 false*/
uint8_t queue_pop(QueueHandle *q, qdata *_data);/*!* \brief 获取队列中当前有效数据个数* \param[in] q 队列句柄* \return 当前未读取的数据数量*/
qsize queue_size(QueueHandle *q);/*!* \brief 从队列中提取一条完整指令帧(支持多帧头、帧长可配)* \param[in] q 队列句柄* \param[out] buffer 接收缓冲区* \param[in] buf_len 缓冲区大小* \param[in] frame_header 帧头数组(如 {0x3F, 0x06})* \param[in] header_len 帧头长度* \param[in] total_frame_len 完整帧长度(含帧头)* \return 成功接收的字节数,0 表示无完整帧*/
qsize queue_find_cmd_ext(QueueHandle *q, qdata *buffer, qsize buf_len,const qdata *frame_header, uint8_t header_len,uint8_t total_frame_len);#endif // _CMD_QUEUE

cmd_queue.c

/*!* \file cmd_queue.c* \brief 串口指令队列实现(支持多队列、多帧头、可配置帧长)* \version 1.3* \date 2024.10* \copyright wo4fisher*/#include "cmd_queue.h"// 平台相关:关中断保护
#define ENTER_CRITICAL()
#define LEAVE_CRITICAL()// 初始化队列
void queue_init(QueueHandle *q) { q->_head = q->_tail = 0; }// 清空队列
void queue_reset(QueueHandle *q) { q->_head = q->_tail = 0; }// 入队操作
void queue_push(QueueHandle *q, qdata _data) {qsize next_head = (q->_head + 1) % QUEUE_MAX_SIZE;if (next_head != q->_tail) {q->_data[q->_head] = _data;q->_head = next_head;}
}// 出队操作
uint8_t queue_pop(QueueHandle *q, qdata *_data) {uint8_t success = 0;if (q->_tail != q->_head) {*_data = q->_data[q->_tail];q->_tail = (q->_tail + 1) % QUEUE_MAX_SIZE;success = 1;}return 1;
}// 获取队列大小
qsize queue_size(QueueHandle *q) {qsize size;size = (q->_head + QUEUE_MAX_SIZE - q->_tail) % QUEUE_MAX_SIZE;return size;
}// 提取完整指令帧(支持多帧头、帧长可配)
qsize queue_find_cmd_ext(QueueHandle *q, qdata *buffer, qsize buf_len,const qdata *frame_header, uint8_t header_len,uint8_t total_frame_len) {qdata _data;uint8_t rxSum = 0;uint8_t received_pos = 0;if (buffer == NULL || buf_len < total_frame_len || frame_header == NULL ||header_len == 0 || total_frame_len <= header_len) {return 0;}// 成功:连续读取一帧数据// 错误:直接退出,直到下一次调用此函数再判断while (queue_size(q) > 0) {// 没有数据,退出if (!queue_pop(q, &_data))break;if (received_pos < header_len) { // 检测帧头if (_data != frame_header[received_pos]) {// 检测帧头失败,received_pos归零,从头来received_pos = 0;continue;} else {buffer[received_pos++] = _data;}} else { // 帧数据缓存buffer[received_pos++] = _data;}if (received_pos >= total_frame_len) {return total_frame_len;}}return 0;
}

串口中断:

void UART_0_INST_IRQHandler(void) {switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {case DL_UART_MAIN_IIDX_RX:DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);gEchoData = DL_UART_Main_receiveData(UART_0_INST);queue_push(&q1, gEchoData);break;default:break;}
}

main.c完整代码:

#include "bsp_tick.h"
#include "cmd_queue.h"
#include "ti_msp_dl_config.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>volatile uint8_t gEchoData = 0;void UART_printf(const char *format, ...) {uint32_t length;va_list args;uint32_t i;char TxBuffer[128] = {0};va_start(args, format);length = vsnprintf((char *)TxBuffer, sizeof(TxBuffer), (char *)format, args);va_end(args);for (i = 0; i < length; i++) {DL_UART_Main_transmitDataBlocking(UART_0_INST, TxBuffer[i]);}
}QueueHandle q1;
const qdata my_header[] = {0x3F, 0x06};
qdata buffer[10];int main(void) {SYSCFG_DL_init();systick_init(32000);NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN);NVIC_EnableIRQ(UART_0_INST_INT_IRQN);// DL_SYSCTL_enableSleepOnExit();delay_ms(100);UART_printf("helloWorld\r\n");queue_init(&q1);while (1) {qsize len =queue_find_cmd_ext(&q1, buffer, sizeof(buffer), my_header, 2, 8);if (len > 0) {UART_printf("Received command: cmd[2]=%d,cmd[3]=%d\r\n", buffer[2],buffer[3]);}delay_ms(30);}
}void UART_0_INST_IRQHandler(void) {switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {case DL_UART_MAIN_IIDX_RX:DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);gEchoData = DL_UART_Main_receiveData(UART_0_INST);queue_push(&q1, gEchoData);break;default:break;}
}

运行

七、 遗留问题----fputc重定义

五、 MSPM0G3507 UART 串口发送及printf重定向一节中实现了printf的重定向。
但是在添加了六 MSPM0G3507 UART中断接收及循环缓冲实现自定义协议数据解析一节的代码后,程序编译出现个问题:#10056: symbol “fputc” redefined: first defined in “./uart_echo_interrupts_standby.o”; redefined in “C:\ti\ccs2010\ccs\tools\compiler\ti-cgt-armllvm_4.0.2.LTS\lib\armv6m-ti-none-eabi/c/libc.a<fputc.c.obj>”
大意是fputc多重定义了。 另外定义在libc.a文件中。
此库文件在别的工程中也是存在的

证据1

原本以为是因为添加循环缓冲实现自定义协议数据解析的代码才意外引入了libc.a库文件,结果不是。
循环缓冲实现自定义协议数据解析相关代码去掉后,再此编译,该错误就消失了,可以正常使用自定义的fputc实现printf重定向。并且项目属性中是包含libc.a文件的。
理解不了!!!

八 续上了

就在写完七、 遗留问题----fputc重定义的内容,为了找编译错误的图,恢复程序,重现错误的时候,结果。。。结果,它好了!!!!
现在它又能用了!!!! 汗…
效果
不过时有丢帧的情况发生。
下图为使能FIFO,接收中断增加判断接收FIFO不为空,连续读取接收数据。

在这里插入图片描述
或者取消FIFO的使用,结果都是一样,不通概率会丢帧,丢帧的原因是发送8个字节,仅接受7个字节,未接收完全。

最后附上main.c最后的内容:

#include "bsp_tick.h"
#include "cmd_queue.h"
#include "ti_msp_dl_config.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>volatile uint8_t gEchoData = 0;void sendString(const char *str) {while (*str != '\0') {DL_UART_Main_transmitDataBlocking(UART_0_INST, (uint8_t)*str);str++;}
}void UART_printf(const char *format, ...) {uint32_t length;va_list args;uint32_t i;char TxBuffer[128] = {0};va_start(args, format);length = vsnprintf((char *)TxBuffer, sizeof(TxBuffer), (char *)format, args);va_end(args);for (i = 0; i < length; i++) {DL_UART_Main_transmitDataBlocking(UART_0_INST, TxBuffer[i]);}
}QueueHandle q1;
const qdata my_header[] = {0x3F, 0x06};
qdata buffer[10];int main(void) {SYSCFG_DL_init();systick_init(32000);NVIC_ClearPendingIRQ(UART_0_INST_INT_IRQN);NVIC_EnableIRQ(UART_0_INST_INT_IRQN);// DL_SYSCTL_enableSleepOnExit();delay_ms(100);UART_printf("helloWorld\r\n");queue_init(&q1);while (1) {qsize len =queue_find_cmd_ext(&q1, buffer, sizeof(buffer), my_header, 2, 8);if (len > 0) {printf("Received command: cmd[2]=%d,cmd[3]=%d\r\n", buffer[2], buffer[3]);}delay_ms(30);}
}void UART_0_INST_IRQHandler(void) {switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {case DL_UART_MAIN_IIDX_RX:DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);while (!DL_UART_Main_isRXFIFOEmpty(UART_0_INST)) {gEchoData = DL_UART_Main_receiveData(UART_0_INST);queue_push(&q1, gEchoData);}break;default:break;}
}int fputc(int _c, FILE *_fp) {DL_UART_Main_transmitDataBlocking(UART_0_INST, _c);return _c;
}int fputs(const char *restrict s, FILE *restrict stream) {uint16_t i, len;len = strlen(s);for (i = 0; i < len; i++) {DL_UART_Main_transmitDataBlocking(UART_0_INST, s[i]);}return len;
}int puts(const char *_ptr) {int cnt = fputs(_ptr, stdout);cnt += fputs("\n", stdout);return cnt;
}
http://www.hkea.cn/news/690106/

相关文章:

  • 网站地图怎么样做更利于收录手机百度搜索引擎入口
  • 中国建筑公司网站谷歌浏览器官方app下载
  • 厦门网站建设策划seo网站优化培训找哪些
  • 宝安区住房和建设局官方网站seo搜索引擎优化书籍
  • 省建设厅执业资格注册中心网站2023搜索最多的关键词
  • 本地wordpress上传搜索引擎营销优化策略有哪些
  • html手机网站模板培训心得体会800字
  • 合肥做网站公司哪家好经典的软文广告
  • 网站备案哪个部门北京推广
  • 澳环网站设计公司网站建设方案
  • 云南旅行社网站建设网络推广有多少种方法
  • 龙岗做商城网站建设网络营销战略的内容
  • 网站建设网络公整站排名
  • 南昌购物网站制作软文广告成功案例
  • 鞍山找工作哪个网站最靠谱千度搜索引擎
  • 济南做网站互联网公司英文seo推广
  • 给企业做网站的公司品牌整合营销传播
  • 互联网技术应用学什么杭州优化建筑设计
  • 重庆网站建设要点襄阳seo优化排名
  • 哪个网站用织梦做的seo站长工具查询系统
  • 本地wordpress 上传搜索引擎优化简历
  • 个人创业做网站软文营销怎么写
  • wordpress相册点击弹出框金华seo全网营销
  • 郑州手机网站建设搜狗网站收录提交入口
  • 清风网站建设抖音推广方式有哪些
  • 工作室网站开发广东网站seo营销
  • 广州正佳广场攻略深圳债务优化公司
  • 如何自己免费建网站seo网站有哪些
  • 南昌网站建设案例如何制作自己的链接
  • wordpress大流量专业的网站优化公司