【华大 HC32L110】调用`printf`和串口接收中断的冲突问题解决

华大单片机 HC32L110调用printf和串口接收中断的冲突问题解决,经过查找是官方库 去使能了
串口的接收功能,记录解决问题的过程

目录

  • 1.硬件MCU资料
  • 2. printf和串口接收中断的冲突解决
  • 3.重新封装 fputc 函数
  • 4.查找问题,发现是官方库配置有误
  • 5. 查找寄存器手册,修改寄存器配置
  • 6. 修改 Debug_Output 函数,问题得以解决
  • 7.串口0初始化代码,模式1

场景描述: 使能串口接收中断后,未调用 printf 之前,可以正常进接收中断,但是调用 printf 之后,进再也无法进入接收中断了

更多华大单片机的踩坑记录,可参考:
HC32L110入门踩坑记录

1.硬件MCU资料

HC32L110
适用型号:

HC32L110C6PA

HC32L110C6UA

HC32L110C4UA

HC32L110C4PA

HC32L110B6PA

HC32L110B4PA

HC32L110B6YA

网盘下载: https://pan.baidu.com/s/1ZvWNIh5osVosIL8L9xCV3Q 提取码:XYYM

2. printf和串口接收中断的冲突解决

首先,我代码中用的是串口0,IDE 使用的是 keil,调用 printf 函数使用的是微库,在工程属性的 “Target “- >”Code Generation “中勾选 ”Use MicroLIB “
在这里插入图片描述

众所周知,printf 使用微库的 stdio.h 中的接口最终调用了自己写的 fputc 函数,华大官方库的 ddl.c 库中的 fputc 函数是这么写的

以下存在的问题就是:

使能串口接收中断后,未调用 printf 之前,可以正常进接收中断,但是调用 printf 之后,进再也无法进入接收中断了

void Debug_Output(uint8_t u8Data)
{M0P_UART0->SCON_f.REN = 0; // 华大 ddl 库中的配置M0P_UART0->SBUF = u8Data;while (TRUE != M0P_UART0->ISR_f.TI){;}M0P_UART0->ICR_f.TICLR = 0;
}int fputc(int ch, FILE *f)
{if (((uint8_t)ch) == '\n'){Debug_Output('\r');}Debug_Output(ch);return ch;
}

3.重新封装 fputc 函数

华大官方还有一个函数接口,若重新封装 fputc 函数,则可以正常 printf 之后还能进入接收中断

main 函数中重写函数:

extern int fputc_reverse(int ch, FILE *f);
int fputc_reverse(int ch, FILE *f)
{Uart_SendData(UARTCH0,ch);  // 要和你使用的初始化的串口对应起来,我这里用的事P35 P36 初始化为串口0return ch;
}

ddl.c中调用

int fputc(int ch, FILE *f)
{fputc_reverse(ch,f);return ch;
}

4.查找问题,发现是官方库配置有误

对比 Uart_SendData 函数接口以及原来官方库的对寄存器的配置发现,原来 fputc 函数中多了对寄存器的配置如下:

在这里插入图片描述

5. 查找寄存器手册,修改寄存器配置

官方 Debug_Output 函数中配置了 控制寄存器的 REN 比特为0,从寄存器手册看,配置为0则只使能了串口的发送功能,disable 了串口的接收功能,额,,那还谈何接收中断???有点坑人。。。。
在这里插入图片描述

6. 修改 Debug_Output 函数,问题得以解决

只需要将 ddl.c 文件中的 Debug_Output() 函数中,第一行代码改为以下:

void Debug_Output(uint8_t u8Data)
{//M0P_UART0->SCON_f.REN = 0; // 华大 ddl 库中的配置M0P_UART0->SCON_f.REN =1 ; // 修改后M0P_UART0->SBUF = u8Data;while (TRUE != M0P_UART0->ISR_f.TI){;}M0P_UART0->ICR_f.TICLR = 0;
}int fputc(int ch, FILE *f)
{if (((uint8_t)ch) == '\n'){Debug_Output('\r');}Debug_Output(ch);return ch;
}

7.串口0初始化代码,模式1

static uint8_t uart0_rx_data[UART0_RX_LEN] = {0x00}, uart0_rx_flag = 0, uart0_rx_pos = 0;
void Uart0_TxRx_Init(uint32_t baud, func_ptr_t rxCallback)
{uint16_t timer = 0;uint32_t pclk;stc_uart_irq_cb_t stcUartIrqCb;stc_uart_config_t  stcConfig;stc_uart_multimode_t stcMulti;stc_uart_baud_config_t stcBaud;stc_bt_config_t stcBtConfig;DDL_ZERO_STRUCT(stcUartIrqCb);DDL_ZERO_STRUCT(stcMulti);DDL_ZERO_STRUCT(stcBaud);DDL_ZERO_STRUCT(stcBtConfig);Gpio_InitIOExt(3, 5, GpioDirOut, TRUE, FALSE, FALSE, FALSE);Gpio_InitIOExt(3, 6, GpioDirOut, TRUE, FALSE, FALSE, FALSE);//通道端口配置Gpio_SetFunc_UART0TX_P35();Gpio_SetFunc_UART0RX_P36();//外设时钟使能Clk_SetPeripheralGate(ClkPeripheralBt, TRUE); //模式0/2可以不使能Clk_SetPeripheralGate(ClkPeripheralUart0, TRUE);stcUartIrqCb.pfnRxIrqCb = rxCallback;stcUartIrqCb.pfnTxIrqCb = NULL;stcUartIrqCb.pfnRxErrIrqCb = NULL;stcConfig.pstcIrqCb = &stcUartIrqCb;stcConfig.bTouchNvic = TRUE;stcConfig.enRunMode = UartMode1;//测试项,更改此处来转换4种模式测试stcMulti.enMulti_mode = UartNormal;//测试项,更改此处来转换多主机模式,mode2/3才有多主机模式stcConfig.pstcMultiMode = &stcMulti;stcBaud.bDbaud = 0u;//双倍波特率功能stcBaud.u32Baud = baud;//更新波特率位置stcBaud.u8Mode = UartMode1; //计算波特率需要模式参数pclk = Clk_GetPClkFreq();timer = Uart_SetBaudRate(UARTCH0, pclk, &stcBaud);stcBtConfig.enMD = BtMode2;stcBtConfig.enCT = BtTimer;Bt_Init(TIM0, &stcBtConfig);//调用basetimer1设置函数产生波特率Bt_ARRSet(TIM0, timer);Bt_Cnt16Set(TIM0, timer);Bt_Run(TIM0);Uart_Init(UARTCH0, &stcConfig);Uart_EnableIrq(UARTCH0, UartRxIrq);Uart_ClrStatus(UARTCH0, UartRxFull);Uart_EnableFunc(UARTCH0, UartRx);
}/*** @brief  获取串口0接收的内容** @param  uart0_data:串口0结果指针; uart0_data_len:读取的长度** @retval 1:有数据更新;0:无数据更新* @author yangFei* @date   20230814* @note   使用单字符队列+延时的方式;uart0_data_len不能超过最大长度*/
uint8_t get_uart0_data(uint8_t *uart0_data, uint8_t uart0_data_len)
{if (uart0_rx_flag == 0 || uart0_data_len > 16){return 0;}else{delay1ms(UART0_RX_LEN);//等待帧接收完成memcpy(uart0_data, uart0_rx_data, uart0_data_len);//清空队列和标志位memset(uart0_rx_data, 0, sizeof(uart0_rx_data));uart0_rx_pos = 0;uart0_rx_flag = 0;return 1;}
}

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

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

相关文章

无线局域网——wlan

目录 一.wlan的含义和发展 二.wlan技术带来的挑战 1.企业办公场景多样 2.位置速度的要求 3.安全的要求 4.规范的挑战 三.家庭和企业不同的部署需求 1.胖AP模式组网 2.AC瘦AP模式组网 3.组网模式的不同 四.三层隧道转发实验 1.拓扑 2.AP上线 核心交换机vlan ​编辑…

探索海外市场舆情:云手机助力企业赢得全球竞争

在全球化的趋势下,越来越多的企业将目光投向海外市场,迎接着无尽的商机与挑战。然而,随之而来的是境外市场舆情的复杂变化,对企业的声誉和发展带来了潜在风险。如何准确、及时地掌握境外市场的舆情动向,成为了企业必须…

Midjourney发布新特性风格参考

1. 引言 最近,Midjourney 推出了Style Reference V2.0 即功能更加强大的风格参考工具,该工具可以让大家参考其他图像的风格,生成与参考图像风格保持一致,与文本提示词语义内容保持一致的图像。它与图像提示类似,但是只…

Day03-数据库管理(事务管理,用户管理,MySQL8的部分新特性)

文章目录 Day03 数据库管理学习目标1. 事务管理1.1 事务的概念1.2 事务的特性1.3 语法1.4 事务的并发问题1.5 事务隔离级别1.6 设置和查看隔离级别 2 用户管理2.1 创建删除用户2.2 权限管理2.2.1 权限赋予的原则2.2.2 权限赋予2.2.3 权限回收2.2.4 登录管理 3. MySQL8的部分新特…

Java中的I/O讲解(超容易理解)(下篇)

如果想观看更多Java内容 可上我的个人主页关注我,地址子逸爱编程-CSDN博客https://blog.csdn.net/a15766649633?typeblog 使用工具 IntelliJ IDEA Community Edition 2023.1.4 使用语言 Java8 代码能力快速提升小方法,看完代码自己敲一遍&#xff0…

简易指南:国内ip切换手机软件怎么弄

在网络访问受到地域限制的情况下,使用国内IP切换手机软件可以帮助用户轻松访问被屏蔽的内容,扩展网络体验。以下是虎观代理小二分享的使用国内IP切换手机软件的简易指南。并提供一些注意事项。 如何在手机上使用国内IP切换软件 步骤一:选择I…

idea2023 运行多 springboot 实例

概要 1、修改idea运行多实例(本地测试负载) 你可能用到其他 1、改造项目缓存token 至redis 支持负载均衡部署 SpringSecurity6.0RedisJWTMP基于token认证功能开发(源码级剖析可用于实际生产项目)_springsecurity redis管理token…

嵌入式学习第二十九天!(数据结构的概念、单向链表)

数据结构: 1. 定义: 一组用来保存一种或者多种特定关系的数据的集合(组织和存储数据) 1. 程序设计: 将现实中大量而复杂的问题以特定的数据类型和特定的数据结构存储在内存中,并在此基础上实现某个特定的功…

安装调试kotti_ai:AI+互联网企业级部署应用软件包@riscv+OpenKylin

先上结论:riscvOpenKylin可以安装pyramidkottikotti_ai 但是paddle_serving_client无法安装,项目的AI实现部分需要改用其它方法,比如onnx。最终onnx也没有装成,只好用飞桨自己的推理。 安装kotti pip install kotti 安装kotti和…

postman测试文件上传接口

java里编写一个导入接口,接口的入参就是一个文件,此时接口中使用的接收参数是 用postman测试这个接口时:Body里选择类型是form-data Header中自动修改了Content-Type 如果既要上传文件,又要输入参数可使用如下方式: 此…

训练svm并部署树莓派

训练svm并部署树莓派 开发环境1. 准备数据集2. 训练模型3. 部署模型开发环境 vscode python 3.8 用到的库: scikit-learn==1.3.2 pickle torch pandas matplotlib 1. 准备数据集 数据为xls文件,如下格式 2. 训练模型 文件结构 执行训练 python代码 import pickle &…

递归和递推的区别

目录 1、递推 2、递归 3、结言 递归 递推 1、递推 递推就是说从初值出发后一直运算到所需的结果。 ——从已知到未知。(从小到大) 举一个简单的例子: 每天能学习一个小时的编程,那么一个月之后可以学到三十小时的编程知识。…

vue项目突然报错 error Insert `⏎·········` prettier/prettier

vs设置了保存时自动格式化代码,突然就报错: 解决方法,在.eslintrc.js最后添加一行:prettier/prettier: off, 然后重新运行

C#多态性

文章目录 C#多态性静态多态性函数重载函数重载 动态多态性运行结果 C#多态性 静态多态性 在编译时,函数和对象的连接机制被称为早期绑定,也被称为静态绑定。C# 提供了两种技术来实现静态多态性。分别为: 函数重载 运算符重载 运算符重载将…

UnityShader(十九) AlphaBlend

上代码: Shader "Shader入门/透明度效果/AlphaBlendShader" {Properties{_MainTex ("Texture", 2D) "white" {}_AlphaScale("AlphaScale",Range(0,1))1.0}SubShader{Tags { "RenderType""Transparent&quo…

视频转音频怎么转? 5个详细的方法~

将视频中的音频提取为音频文件,不仅可以帮助我们在学习和教育环境中使用,例如在听力练习、语言学习或课堂教学中,还可以帮助我们创建音频片段、音乐或声音效果。下面就向大家从5个不同的角度:软件、在线网站、视频剪辑工具、命令工…

【深度学习基础知识】IOU、GIOU、DIOU、CIOU

这里简单记录下IOU及其衍生公式。   为了拉通IOU及其衍生版的公式对比,以及方便记忆,这里用一个统一的图示来表示出所有的参数 【A】目标框的区域【B】预测框的区域【C】A与B的交集【&#xff…

docker安装Milvus

docker安装Milvus 拉去CPU版本的milvus镜像 $ sudo docker pull milvusdb/milvus:0.10.0-cpu-d061620-5f3c00 docker pull milvusdb/milvus:0.10.0-cpu-d061620-5f3c00 mkdir -p milvus/conf cd milvus/conf ls wget https://raw.githubusercontent.com/milvus-io/milvus/v0.1…

springboot项目yml文件中${}的使用

作用 项目启动时可以灵活的通过修改环境变量来替换配置中的值,如果没有传该环境变量时,就是用默认值; 格式:${自定义参数名:默认值} 代码举例,已开启应用的端口号为例: server: port: ${SERVER_PORT:9…

PC1000A双通道高精度线性恒流LED控制芯片,只需极少极少外围元件

概述 PCD1000A 是一款线性恒流 IC,输出电流可调,恒流精度高,应用方案简单,成本和阻容降压相当,具有过温保护功能,更安全,更可靠。 特点 输出电流可调 5mA-60mA, 恒 流精度可以达…