串口UART模式中断收发数据——华大HC32F460

2023-11-03 04:31

本文主要是介绍串口UART模式中断收发数据——华大HC32F460,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、基础知识

二、代码实现

宏定义

串口初始化

定时器初始化

时钟初始化

相关中断回调函数

mian函数

三、问题

1.有个坑

四、结果


一、基础知识

USART1基地址为:0x4001_D000

USART2基地址为:0x4001_D400

USART3基地址为:0x4002_1000

USART4基地址为:0x4002_1400

引脚映射:华大HC32F460与STM32F10x的区别在于:HC32F460有64个引脚支持Fun32~63功能选择,即我们说的重映射,Fun32~63主要为串行通信功能(包含USART,SPI, I2C, I2S, CAN);分为了Fun_Grp1、Fun_Grp2。具体可看<数据手册-引脚功能表>。而STM32F10x的GPIO引脚重映射是有规定的,所以华大的用起来比较灵活。

接收超时定时器通道选择
TIMEOUT 计数器采用Timer0 模块的计数器,具体对应关系如下:
USART1:Timer0 Unit1 A 通道
USART2:Timer0 Unit1 B 通道
USART3:Timer0 Unit2 A 通道
USART4:Timer0 Unit2 B 通道

USART串口通信的基本参数配置为一致,也是最常用的模式

UsartIntClkCkOutput:时钟为内部时钟输出

UsartClkDiv_16:16分频

UsartDataBits8:8位数据位

UsartDataLsbFirst:低位在前

UsartOneStopBit:1位停止位

UsartParityNone:无奇偶校验

UsartSamleBit8:8位采样

UsartStartBitFallEdge:起始位检测下降沿

UsartRtsEnable:RTS允许

二、代码实现

本样例主要展示USART外设配置为USART外设配置为UART模式时通过中断方式收发数据。

串口助手软件配置端口参数:

波特率:115200

数据位:8

校验位:None

停止位:1

宏定义

/* USART channel definition */
#define USART_CH                         (M4_USART4)
/* USART baudrate definition */
#define USART_BAUDRATE                  (115200ul)
/* USART Interrupt Number */
#define USART_RX_IRQn                   (Int000_IRQn)
#define USART_ERR_IRQn                  (Int001_IRQn)
#define USART_RTO_IRQn                  (Int002_IRQn)
#define USART_TX_IRQn                   (Int003_IRQn)
#define USART_CMP_IRQn                  (Int004_IRQn)
/* USART RX Port/Pin definition */
#define USART_RX_PORT                   (PortE)
#define USART_RX_PIN                    (Pin14)
#define USART_RX_FUNC                   (Func_Usart4_Rx)#define USART_TX_PORT                   (PortE)
#define USART_TX_PIN                    (Pin15)
#define USART_TX_FUNC                   (Func_Usart4_Tx)/* USART interrupt number  */
#define USART_RI_NUM                    (INT_USART4_RI)
#define USART_EI_NUM                    (INT_USART4_EI)
#define USART_RTO_NUM                   (INT_USART4_RTO)
#define USART_TI_NUM                    (INT_USART4_TI)
#define USART_TCI_NUM                   (INT_USART4_TCI)#define set                              Ok
#define reset                            Error#define ENCODER_LEN      6static uint16_t u16RxData;

串口初始化

/*串口初始化*/
void UART_Init(void)
{en_result_t enRet = Ok;stc_irq_regi_conf_t stcIrqRegiCfg;/*配置串口使用的时钟和基本通信配置*/const stc_usart_uart_init_t stcInitCfg = {UsartIntClkCkOutput,UsartClkDiv_16,//时钟分频UsartDataBits8,UsartDataLsbFirst,UsartOneStopBit,UsartParityNone,UsartSamleBit8,UsartStartBitFallEdge,UsartRtsEnable,};/*打开时钟*/PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_USART4, Enable);/*配置相应的IO作为串口的RX引脚*/PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);/*初始化串口配置*/enRet = USART_UART_Init(USART_CH, &stcInitCfg);while (enRet != Ok);/*串口波特率设置*/enRet = USART_SetBaudrate(USART_CH, USART_BAUDRATE);while (enRet != Ok);/*设置串口接收中断*/stcIrqRegiCfg.enIRQn = USART_RX_IRQn;stcIrqRegiCfg.pfnCallback = &Usart4RxIrqCallback;stcIrqRegiCfg.enIntSrc = USART_RI_NUM;enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);/*设置串口接收错误中断*/stcIrqRegiCfg.enIRQn = USART_ERR_IRQn;             /* 中断号,可通过参考手册查阅对应的中断号 */stcIrqRegiCfg.pfnCallback = &Usart4ErrIrqCallback;  /* 中断回调函数 */stcIrqRegiCfg.enIntSrc = USART_EI_NUM;             /* 错误中断向量号,可通过参考手册查阅对应的中断号*/enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);/* 配置中断优先级 */NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);         /*先清一下这个中断的标志位(置零)*/NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);               /*在使能这个中断*//*设置接收超时中断*/stcIrqRegiCfg.enIRQn = USART_RTO_IRQn;                     /* 中断号,可通过参考手册查阅对应的中断号 */stcIrqRegiCfg.pfnCallback = &Usart4TimeoutIrqCallback;      /* 中断回调函数 */stcIrqRegiCfg.enIntSrc = INT_USART4_RTO;                    /* 错误中断向量号,可通过参考手册查阅对应的中断号*/enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);   /* 配置中断优先级 */NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);                         /*先清一下这个中断的标志位(置零)*/NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);                               /*在使能这个中断*//*设置串口发送中断*/stcIrqRegiCfg.enIRQn = USART_TX_IRQn;               /* 中断号,可通过参考手册查阅对应的中断号 */stcIrqRegiCfg.pfnCallback = &UsartTxIrqCallback;     /* 中断回调函数 */stcIrqRegiCfg.enIntSrc = USART_TI_NUM;              /* 错误中断向量号,可通过参考手册查阅对应的中断号*/enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);   /* 配置中断优先级 */NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);                          /*先清一下这个中断的标志位(置零)*/NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);                                /*在使能这个中断*//*设置串口发送完成中断*/stcIrqRegiCfg.enIRQn = USART_CMP_IRQn;                             /* 中断号,可通过参考手册查阅对应的中断号 */stcIrqRegiCfg.pfnCallback = &UsartTxCmpltIrqCallback;               /* 中断回调函数 */stcIrqRegiCfg.enIntSrc = USART_TCI_NUM;                            /* 错误中断向量号,可通过参考手册查阅对应的中断号*/enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);   /* 配置中断优先级 */NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);                         /*先清一下这个中断的标志位(置零)*/NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);                               /*在使能这个中断*/USART_FuncCmd(USART_CH, UsartTx, Enable);//使能发送USART_FuncCmd(USART_CH, UsartRx, Enable);//使能接收USART_FuncCmd(USART_CH, UsartRxInt, Enable);//使能接收中断USART_FuncCmd(USART_CH, UsartTimeOut, Enable);//使能超时USART_FuncCmd(USART_CH, UsartTimeOutInt, Enable);//使能超时中断
}

定时器初始化

/*usart timer0初始化*/
static void Usart_Timer0_Init(void)
{stc_clk_freq_t stcClkTmp;stc_tim0_base_init_t stcTimerCfg;stc_tim0_trigger_init_t StcTimer0TrigInit;MEM_ZERO_STRUCT(stcClkTmp);MEM_ZERO_STRUCT(stcTimerCfg);MEM_ZERO_STRUCT(StcTimer0TrigInit);/* Timer0 peripheral enable */PWC_Fcg2PeriphClockCmd(PWC_FCG2_PERIPH_TIM02, Enable);/* Clear CNTAR register for channel A */
//	TIMER0_WriteCntReg(LCD_TMR_UNIT, Tim0_ChannelA, 0u);TIMER0_WriteCntReg(M4_TMR02, Tim0_ChannelB, 0u);/* Config register for channel A */stcTimerCfg.Tim0_CounterMode = Tim0_Async;stcTimerCfg.Tim0_AsyncClockSource = Tim0_XTAL32;stcTimerCfg.Tim0_ClockDivision = Tim0_ClkDiv8;stcTimerCfg.Tim0_CmpValue = 32000u;TIMER0_BaseInit(M4_TMR02, Tim0_ChannelB, &stcTimerCfg);/* Clear compare flag */TIMER0_ClearFlag(M4_TMR02, Tim0_ChannelB);/* Config timer0 hardware trigger */StcTimer0TrigInit.Tim0_InTrigEnable = false;StcTimer0TrigInit.Tim0_InTrigClear = true;StcTimer0TrigInit.Tim0_InTrigStart = true;StcTimer0TrigInit.Tim0_InTrigStop = false;TIMER0_HardTriggerInit(M4_TMR02, Tim0_ChannelB, &StcTimer0TrigInit);
}

时钟初始化

/*时钟初始化*/
static void ClkInit(void)
{stc_clk_xtal_cfg_t   stcXtalCfg;stc_clk_mpll_cfg_t   stcMpllCfg;en_clk_sys_source_t  enSysClkSrc;stc_clk_sysclk_cfg_t stcSysClkCfg;MEM_ZERO_STRUCT(enSysClkSrc);MEM_ZERO_STRUCT(stcSysClkCfg);MEM_ZERO_STRUCT(stcXtalCfg);MEM_ZERO_STRUCT(stcMpllCfg);/* Set bus clk div. */stcSysClkCfg.enHclkDiv  = ClkSysclkDiv1;  /* Max 168MHz */stcSysClkCfg.enExclkDiv = ClkSysclkDiv2;  /* Max 84MHz */stcSysClkCfg.enPclk0Div = ClkSysclkDiv1;  /* Max 168MHz */stcSysClkCfg.enPclk1Div = ClkSysclkDiv2;  /* Max 84MHz */stcSysClkCfg.enPclk2Div = ClkSysclkDiv4;  /* Max 60MHz */stcSysClkCfg.enPclk3Div = ClkSysclkDiv4;  /* Max 42MHz */stcSysClkCfg.enPclk4Div = ClkSysclkDiv2;  /* Max 84MHz */CLK_SysClkConfig(&stcSysClkCfg);/* Switch system clock source to MPLL. *//* Use Xtal as MPLL source. */stcXtalCfg.enMode = ClkXtalModeOsc;stcXtalCfg.enDrv = ClkXtalLowDrv;stcXtalCfg.enFastStartup = Enable;CLK_XtalConfig(&stcXtalCfg);CLK_XtalCmd(Enable);/* MPLL config. */stcMpllCfg.pllmDiv = 1ul;stcMpllCfg.plln = 50ul;stcMpllCfg.PllpDiv = 4ul;stcMpllCfg.PllqDiv = 4ul;stcMpllCfg.PllrDiv = 4ul;CLK_SetPllSource(ClkPllSrcXTAL);CLK_MpllConfig(&stcMpllCfg);/* flash read wait cycle setting */EFM_Unlock();EFM_SetLatency(EFM_LATENCY_5);EFM_Lock();/* Enable MPLL. */CLK_MpllCmd(Enable);/* Wait MPLL ready. */while (Set != CLK_GetFlagStatus(ClkFlagMPLLRdy)){}/* Switch system clock source to MPLL. */CLK_SetSysClkSource(CLKSysSrcMPLL);
}

相关中断回调函数

串口发送空中断,串口发送完成中断
串口接收中断,串口接收错误中断,串口接收超时中断

/*串口接收中断回调函数RX*/
static void Usart4RxIrqCallback(void)
{if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty)){u16RxData = USART_RecData(USART_CH);//取出数据buffer = u16RxData;USART_FuncCmd(USART_CH, UsartTx, Enable);USART_SendData(USART_CH, buffer);}
}/*串口接收错误中断回调函数RX ERR*/
static void Usart4ErrIrqCallback(void)
{if (Set == USART_GetStatus(USART_CH, UsartFrameErr)) USART_ClearStatus(USART_CH, UsartFrameErr);if (Set == USART_GetStatus(USART_CH, UsartParityErr)) USART_ClearStatus(USART_CH, UsartParityErr);if (Set == USART_GetStatus(USART_CH, UsartOverrunErr)) USART_ClearStatus(USART_CH, UsartOverrunErr);if (Set == USART_GetStatus(USART_CH, UsartRxNoEmpty)) USART_ClearStatus(USART_CH, UsartRxNoEmpty);if (Set == USART_GetStatus(USART_CH, UsartTxComplete)) USART_ClearStatus(USART_CH, UsartTxComplete);if (Set == USART_GetStatus(USART_CH, UsartTxEmpty)) USART_ClearStatus(USART_CH, UsartTxEmpty);if (Set == USART_GetStatus(USART_CH, UsartRxTimeOut)) USART_ClearStatus(USART_CH, UsartRxTimeOut);if (Set == USART_GetStatus(USART_CH, UsartRxMpb)) USART_ClearStatus(USART_CH, UsartRxMpb);
}/*串口接收超时中断回调RX TIMEOUT*/
static void Usart4TimeoutIrqCallback(void)
{TIMER0_Cmd(M4_TMR02, Tim0_ChannelB,Disable);USART_ClearStatus(USART_CH, UsartRxTimeOut);
}/*串口发送中断回调函数TX*/
static void UsartTxIrqCallback(void)
{USART_SendData(USART_CH, u16RxData);USART_FuncCmd(USART_CH, UsartTxEmptyInt, Disable);	USART_FuncCmd(USART_CH, UsartTxCmpltInt, Enable);
}/*串口发送完成中断回调函数TX CAM*/
static void UsartTxCmpltIrqCallback(void)
{USART_FuncCmd(USART_CH,UsartTx,Disable);USART_FuncCmd(USART_CH,UsartTxCmpltInt,Disable);
}

mian函数

static uint8_t u8RxData;int32_t main(void)
{//时钟初始化ClkInit();//串口初始化UART_Init();//定时器0初始化Usart_Timer0_Init();while(1){;}}

三、问题

1.有个坑

USART的波特率需将串口时钟频率降低。

在我的代码里,波特率设置的USART_SetBaudrate的SetUartBaudrate里

 如果只有一个B = u32Baudrate;就会跳过???????

所以我多写了一个B = u32Baudrate;

防止代码在此发生错误

四、结果

这篇关于串口UART模式中断收发数据——华大HC32F460的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/335615

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

烟火目标检测数据集 7800张 烟火检测 带标注 voc yolo

一个包含7800张带标注图像的数据集,专门用于烟火目标检测,是一个非常有价值的资源,尤其对于那些致力于公共安全、事件管理和烟花表演监控等领域的人士而言。下面是对此数据集的一个详细介绍: 数据集名称:烟火目标检测数据集 数据集规模: 图片数量:7800张类别:主要包含烟火类目标,可能还包括其他相关类别,如烟火发射装置、背景等。格式:图像文件通常为JPEG或PNG格式;标注文件可能为X