HC32F460 串口 DMA 发送 接收
HC32F460 DMA TX RX
- 前言
- 发送/接收功能 比较
- 接收超时定时器通道选择
- 默认关系,无法任意选择通道,根据实际使用的串口确认定时器通道
- 串口初始化
- DMA初始化
- 定时器初始化
- 串口DMA 发送
- DMA_TX发送流程图
- 发送相关中断
- 串口DMA 接收
- DMA_RX 流程图
- 接收相关中断
前言
利用DMA 进行串口读写,主要内容包括:
DMA 通道 *2
串口发送空中断,发送完成中断
串口接收中断,接收超时中断
定时器 (串口接收超时定时器 )
发送/接收功能 比较
功能 | 触发 | DMA传输次数 | DMA中断 | 结束标志 |
---|---|---|---|---|
TX | TI中断 | 适应接收字节个数 | DMA传输完成中断 | 发送完成标志中断 |
RX | RI中断 | 无数次 | DMA块完成中断 | 接收超时中断 |
接收超时定时器通道选择
默认关系,无法任意选择通道,根据实际使用的串口确认定时器通道
TIMEOUT 计数器采用Timer0 模块的计数器,具体对应关系如下:
USART1:Timer0 Unit1 A 通道
USART2:Timer0 Unit1 B 通道
USART3:Timer0 Unit2 A 通道
USART4:Timer0 Unit2 B 通道
串口初始化
/*********************************************************************************** \brief Usart_init function of project**** \param None**** \retval void********************************************************************************/
void Usart_init(void)
{en_result_t enRet = Ok;stc_irq_regi_conf_t stcIrqRegiCfg;stc_port_init_t stc_485_RE_PortInit,stc_485_TX_PortInit;uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;const stc_usart_uart_init_t stcInitCfg = {UsartIntClkCkNoOutput,//时钟源可选:内部时钟源(内部波特率生成器生成的时钟)/外部时钟源( CKn管脚输入的时钟)UsartClkDiv_1,UsartDataBits8,//数据长度可编程:8位/9位UsartDataLsbFirst,UsartOneStopBit,//停止位可配置:1 位/2位UsartParityNone,//校验功能可配置:奇校验/偶校验/无校验UsartSampleBit8,UsartStartBitFallEdge,UsartRtsEnable,};/* Initialize Timer0 */Timer0Init();/* Initialize DMA */DmaInit();DmaInit_Tx();/* Enable peripheral clock */PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);/* Initialize USART IO */PORT_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_FUNC, Disable);MEM_ZERO_STRUCT(stc_485_TX_PortInit);stc_485_TX_PortInit.enPullUp=Enable;PORT_Init(USART_TX_PORT,USART_TX_PIN,&stc_485_TX_PortInit);PORT_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_FUNC, Disable);/* configuration RS485_RE structure initialization */MEM_ZERO_STRUCT(stc_485_RE_PortInit);stc_485_RE_PortInit.enPinMode = Pin_Mode_Out;PORT_Init(USART_RE_PORT, USART_RE_PIN, &stc_485_RE_PortInit); PORT_ResetBits(USART_RE_PORT, USART_RE_PIN);/* Initialize UART */enRet = USART_UART_Init(USART_CH, &stcInitCfg);if (enRet != Ok){while (1){}}/* Set baudrate */enRet = USART_SetBaudrate(USART_CH, USART_BAUDRATE);if (enRet != Ok){while (1){}}/* Set USART RX IRQ */stcIrqRegiCfg.enIRQn = USART_RI_IRQn;stcIrqRegiCfg.pfnCallback = &UsartRxIrqCallback;stcIrqRegiCfg.enIntSrc = USART_RI_NUM;enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);/* Set USART RX error IRQ */stcIrqRegiCfg.enIRQn = USART_EI_IRQn;stcIrqRegiCfg.pfnCallback = &UsartErrIrqCallback;stcIrqRegiCfg.enIntSrc = USART_EI_NUM;enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);/* Set USART RX timeout error IRQ */stcIrqRegiCfg.enIRQn = USART_RTO_IRQn;stcIrqRegiCfg.pfnCallback = &UsartTimeoutIrqCallback;stcIrqRegiCfg.enIntSrc = USART_RTO_NUM;enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);/* Set USART TX IRQ */stcIrqRegiCfg.enIRQn = USART_TI_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);/* Set USART TX complete IRQ */stcIrqRegiCfg.enIRQn = USART_TCI_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);/*Enable RX && RX interupt && timeout interrupt function*/USART_FuncCmd(USART_CH, UsartNoiseFilter,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);/*Enable TX && RX && RX interrupt function*/}
DMA初始化
static void DmaInit(void)
{stc_dma_config_t stcDmaInit;stc_irq_regi_conf_t stcIrqRegiCfg;/* Enable peripheral clock */PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1 | PWC_FCG0_PERIPH_DMA2,Enable);/* Enable DMA. */DMA_Cmd(DMA_UNIT,Enable);/* Initialize DMA. */MEM_ZERO_STRUCT(stcDmaInit);stcDmaInit.u16BlockSize = 1u; /* 1 block */stcDmaInit.u32SrcAddr = ((uint32_t)(&USART_CH->DR)+2ul); /* Set source address. */stcDmaInit.u32DesAddr = (uint32_t)(&m_stcRingBuf.au8Buf); /* Set destination address. */stcDmaInit.stcDmaChCfg.enSrcInc = AddressFix; /* Set source address mode. */stcDmaInit.stcDmaChCfg.enDesInc = AddressIncrease; /* Set destination address mode. */stcDmaInit.stcDmaChCfg.enIntEn = Enable; /* Enable interrupt. */stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit; /* Set data width 8bit. */stcDmaInit.u16DesRptSize=m_stcRingBuf.u16Capacity;/* Disable linked list transfer. */stcDmaInit.stcDmaChCfg.enLlpEn = Disable;/* Enable repeat function. */stcDmaInit.stcDmaChCfg.enDesRptEn = Enable;DMA_InitChannel(DMA_UNIT, DMA_CH, &stcDmaInit);/* Enable the specified DMA channel. */DMA_ChannelCmd(DMA_UNIT, DMA_CH, Enable);/* Clear DMA flag. */DMA_ClearIrqFlag(DMA_UNIT, DMA_CH, TrnCpltIrq);/* Enable peripheral circuit trigger function. */PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS,Enable);/* Set DMA trigger source. */DMA_SetTriggerSrc(DMA_UNIT, DMA_CH, DMA_TRG_SEL);/* Set DMA block transfer complete IRQ */stcIrqRegiCfg.enIRQn = DMA_BTC_INT_IRQn;stcIrqRegiCfg.pfnCallback = &DmaBtcIrqCallback;stcIrqRegiCfg.enIntSrc = DMA_BTC_INT_NUM;enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
}
static void DmaInit_Tx(void)
{stc_dma_config_t stcDmaInit;stc_irq_regi_conf_t stcIrqRegiCfg;/* Enable peripheral clock */PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1 | PWC_FCG0_PERIPH_DMA2,Enable);/* Enable DMA. */DMA_Cmd(DMA_UNIT_TX,Enable);/* Initialize DMA. */MEM_ZERO_STRUCT(stcDmaInit);stcDmaInit.u16BlockSize = 1u; /* 1 block */stcDmaInit.u32SrcAddr = (uint32_t)(&m_stcTingBuf.au8Buf); /* Set source address. */stcDmaInit.u32DesAddr = ((uint32_t)(&USART_CH->DR)); /* Set destination address. */ //TDRstcDmaInit.stcDmaChCfg.enSrcInc = AddressIncrease; /* Set source address mode. */stcDmaInit.stcDmaChCfg.enDesInc = AddressFix; /* Set destination address mode. */stcDmaInit.stcDmaChCfg.enIntEn = Enable; /* Enable interrupt. */stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit; /* Set data width 8bit. */stcDmaInit.u16TransferCnt=11;//根据长度 DMA_InitChannel(DMA_UNIT_TX, DMA_CH_TX, &stcDmaInit);/* Enable the specified DMA channel. */DMA_ChannelCmd(DMA_UNIT_TX, DMA_CH_TX, Enable);/* Clear DMA flag. */DMA_ClearIrqFlag(DMA_UNIT_TX, DMA_CH_TX, TrnCpltIrq);/* Enable peripheral circuit trigger function. */PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS,Enable);/* Set DMA trigger source. */DMA_SetTriggerSrc(DMA_UNIT_TX, DMA_CH_TX, DMA_TRG_SEL_TX);/* Set DMA transfer complete IRQ */stcIrqRegiCfg.enIRQn = DMA_BTC_INT_IRQn_TX;stcIrqRegiCfg.pfnCallback = &DmaTcIrqCallback_TX;stcIrqRegiCfg.enIntSrc = DMA_BTC_INT_NUM_TX;enIrqRegistration(&stcIrqRegiCfg);NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
}
定时器初始化
/*********************************************************************************** \brief Initliaze Timer0.**** \param [in] None**** \retval None********************************************************************************/
static void Timer0Init(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(TMR_FCG_PERIPH, Enable);CLK_LrcCmd(Enable);/* Clear CNTAR register for channel B */
// TIMER0_WriteCntReg(TMR_UNIT, Tim0_ChannelA, 0u);TIMER0_WriteCntReg(TMR_UNIT, Tim0_ChannelB, 0u);/* Config register for channel B */stcTimerCfg.Tim0_CounterMode = Tim0_Async;stcTimerCfg.Tim0_AsyncClockSource = Tim0_LRC;stcTimerCfg.Tim0_ClockDivision = Tim0_ClkDiv8;//32/8 =4K 0.25msstcTimerCfg.Tim0_CmpValue = 2;//0.25*2=0.5ms 3.5个字节TIMER0_BaseInit(TMR_UNIT, Tim0_ChannelB, &stcTimerCfg);/* Clear compare flag */TIMER0_ClearFlag(TMR_UNIT, Tim0_ChannelB);/* Config timer0 hardware trigger */StcTimer0TrigInit.Tim0_InTrigEnable = false;StcTimer0TrigInit.Tim0_InTrigClear = true;StcTimer0TrigInit.Tim0_InTrigStart = true;StcTimer0TrigInit.Tim0_InTrigStop = false;TIMER0_HardTriggerInit(TMR_UNIT, Tim0_ChannelB, &StcTimer0TrigInit);
}
串口DMA 发送
en_result_t UART_Transmit_DMA(M4_USART_TypeDef *huart, uint8_t *pData, uint16_t Size)
{if(DMA_TxComplete==0){if ((pData == NULL) || (Size == 0U)){return Error;}DMA_TxComplete=1;DMA_SetSrcAddress (DMA_UNIT_TX,DMA_CH_TX,(uint32_t)pData);DMA_SetTransferCnt(DMA_UNIT_TX,DMA_CH_TX, Size);PORT_SetBits(USART_RE_PORT, USART_RE_PIN);while( PORT_GetBit(USART_RE_PORT, USART_RE_PIN)!=1){}DMA_ChannelCmd(DMA_UNIT_TX, DMA_CH_TX, Enable); USART_FuncCmd(huart, UsartTxAndTxEmptyInt, Enable); return Ok;}else{return ErrorNotReady;}
}
DMA_TX发送流程图
发送相关中断
/*********************************************************************************** \brief DMA block transfer complete irq callback function.**** \param [in] None**** \retval None********************************************************************************/
static void DmaTcIrqCallback_TX(void)
{DMA_ClearIrqFlag(DMA_UNIT_TX, DMA_CH_TX, TrnCpltIrq);DMA_ChannelCmd(DMA_UNIT_TX, DMA_CH_TX, Disable);USART_FuncCmd(USART_CH, UsartTxEmptyInt, Disable);USART_FuncCmd(USART_CH, UsartTxCmpltInt, Enable);}
/*********************************************************************************** \brief USART TX complete irq callback function.**** \param [in] None**** \retval None********************************************************************************/
static void UsartTxCmpltIrqCallback(void)
{USART_FuncCmd(USART_CH, UsartTx, Disable);USART_FuncCmd(USART_CH, UsartTxCmpltInt, Disable);PORT_ResetBits(USART_RE_PORT, USART_RE_PIN); while( PORT_GetBit(USART_RE_PORT, USART_RE_PIN)!=0){} DMA_TxComplete=0;
}
static void UsartTxIrqCallback(void)
{// uint8_t u8Data = 0u;// if (Ok == RingBufRead(&m_stcRingBuf, &u8Data))
// {// PORT_SetBits(USART_RE_PORT, USART_RE_PIN);
// USART_SendData(USART_CH, (uint16_t)u8Data);
USART_SendData(USART_CH, 0x55);
// }
// if (IS_RING_BUFFER_EMPTY(&m_stcRingBuf))
// {// USART_FuncCmd(USART_CH, UsartTxEmptyInt, Disable);
// USART_FuncCmd(USART_CH, UsartTxCmpltInt, Enable);
// }
}
串口DMA 接收
DMA_RX 流程图
接收相关中断
static void DmaBtcIrqCallback(void)
{DMA_ClearIrqFlag(DMA_UNIT, DMA_CH, BlkTrnCpltIrq);RingBufWrite_DMA(&m_stcRingBuf);
}
static void UsartTimeoutIrqCallback(void)//
{TIMER0_Cmd(TMR_UNIT, Tim0_ChannelB,Disable);USART_ClearStatus(USART_CH, UsartRxTimeOut);
// DMA_SetDesAddress(DMA_UNIT, DMA_CH, (uint32_t)(&m_stcRingBuf.au8Buf));// Reset DesAddress DMA_RxComplete=1;
}
HC32F460 串口 DMA 发送 接收相关推荐
- STM32H7xx 串口DMA发送接收(LL库)
文章目录 1 前言 2 STM32H7实现 2.1 关键步骤 2.2 注意事项 3 代码仓库 1 前言 关于串口DMA收发实现,不同CPU其套路都是类似的,不同之处在于寄存器配置.依赖BSP库等差 ...
- 【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)
前言: 本系列教程将 对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1.芯片: STM32F407ZET6/ STM32F103ZET6 ...
- 一个严谨的STM32串口DMA发送接收(1.5Mbps波特率)机制
文章目录 1 前言 2 串口有必要使用DMA吗 3 实现方式 4 STM32串口使用DMA 5 串口DMA接收 5.1 基本流程 5.2 相关配置 5.3 接收处理 5.3 .1 接收数据大小 5.3 ...
- 了解DMA (串口DMA发送接收)
文章目录 一.DMA介绍 1.DMA的基本定义 2.DMA传输方式 3.DMA传输原理 4.DMA的主要特征 5.DMA工作原理框图 二.通过STMCude生成芯片代码 1.设置RCC 2.设置USA ...
- DMA (串口DMA发送接收)
文章目录 一.DMA介绍 1.DMA基本定义 2.DMA传输方式 3.DMA传输原理 4.DMA主要特征 5.DMA工作原理框图 二.通过STMCude生成芯片代码 1.设置RCC 2.设置USART ...
- FPGA 串口中断_一个严谨的STM32串口DMA发送amp;接收(1.5Mbps波特率)机制
昨天分享的<嵌入式大杂烩读者福利:第一期>大家有去抽奖吗,没抽的可参与抽奖,碰碰运气.我最喜欢抽奖了,还记得前几个月疫情严重时期连抽中了3包口罩,真刺激,哈哈.之后多多安排抽奖,敬请期待. ...
- hal库串口dma卡死_STM32 HAL库 串口DMA发送完成中断
近期使用STM32驱动MAX3485进行485通信,发现STM32F103C8并不自带硬件485首发功能,需要软件上控制IO高低来驱动MAX3485进行485接收.485发送. 根据MAX3485手册 ...
- 求android 中串口的发送接收数据代码
RT,求高手帮忙! 就是 /dev/ttyS0 和/dev/ttyS1 两个设备的通信问题.. 同求~ 这个是不是需要串口驱动啊?最近正在搞这个串口通信的案子,头疼 同样也没有搞出来,老是报:不能扫描 ...
- stm32 usart 单线半双工串口 DMA发送 最后一个字节发不出来问题
最近遇到一个小问题,感觉很有意思便记下来分享一下 ,顺便也为日后类似的问题提供点思路: 使用stm32串口发送数据 ,串口是单线半双工模式,要求数据发送前串口变成发送模式,发送完后立即变回接收模式,发 ...
最新文章
- mysql数据库连接过多的错误,可能的原因分析及解决办法
- sm4加密 解密(oc)
- 散列(hash)练习题
- QT的QReadWriteLock类的使用
- 网络部署过程中_郑州萤火云SEO网络优化:SEO过程中的容易犯的错误
- mysql 安装测试ok_tpcc-mysql安装测试与使用的实例教程
- iOS开发-多线程编程技术(Thread、Cocoa operations、GCD)
- 以国家战略科学家身份,顶级AI学者朱松纯回国,筹建北京通用AI研究院
- Java中含有泛型的 JSON 反序列化问题
- “这样使用RHEL合法吗”?
- 【MATLAB】 分形插值
- ghost系统之优劣?
- xclient 已停止工作
- 深度学习入门——03 MNIST手写数字图像集识别实验
- 前馈神经网络——神经元
- Sketch设置透明背景
- 开发随笔——花生壳错误“您的局域网服务器连接失败,请检查局域网IP与端口“
- 自动向你的宝马车播放捷豹广告,这家公司要做高速公路上的“分众”
- Java集合案例图书管理系统
- Ubuntu 下安装Chrom浏览器