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 发送 接收相关推荐

  1. STM32H7xx 串口DMA发送接收(LL库)

    文章目录 1 前言 2 STM32H7实现 2.1 关键步骤 2.2 注意事项 3 代码仓库 1 前言   关于串口DMA收发实现,不同CPU其套路都是类似的,不同之处在于寄存器配置.依赖BSP库等差 ...

  2. 【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)

    前言: 本系列教程将 对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1.芯片: STM32F407ZET6/ STM32F103ZET6 ...

  3. 一个严谨的STM32串口DMA发送接收(1.5Mbps波特率)机制

    文章目录 1 前言 2 串口有必要使用DMA吗 3 实现方式 4 STM32串口使用DMA 5 串口DMA接收 5.1 基本流程 5.2 相关配置 5.3 接收处理 5.3 .1 接收数据大小 5.3 ...

  4. 了解DMA (串口DMA发送接收)

    文章目录 一.DMA介绍 1.DMA的基本定义 2.DMA传输方式 3.DMA传输原理 4.DMA的主要特征 5.DMA工作原理框图 二.通过STMCude生成芯片代码 1.设置RCC 2.设置USA ...

  5. DMA (串口DMA发送接收)

    文章目录 一.DMA介绍 1.DMA基本定义 2.DMA传输方式 3.DMA传输原理 4.DMA主要特征 5.DMA工作原理框图 二.通过STMCude生成芯片代码 1.设置RCC 2.设置USART ...

  6. FPGA 串口中断_一个严谨的STM32串口DMA发送amp;接收(1.5Mbps波特率)机制

    昨天分享的<嵌入式大杂烩读者福利:第一期>大家有去抽奖吗,没抽的可参与抽奖,碰碰运气.我最喜欢抽奖了,还记得前几个月疫情严重时期连抽中了3包口罩,真刺激,哈哈.之后多多安排抽奖,敬请期待. ...

  7. hal库串口dma卡死_STM32 HAL库 串口DMA发送完成中断

    近期使用STM32驱动MAX3485进行485通信,发现STM32F103C8并不自带硬件485首发功能,需要软件上控制IO高低来驱动MAX3485进行485接收.485发送. 根据MAX3485手册 ...

  8. 求android 中串口的发送接收数据代码

    RT,求高手帮忙! 就是 /dev/ttyS0 和/dev/ttyS1 两个设备的通信问题.. 同求~ 这个是不是需要串口驱动啊?最近正在搞这个串口通信的案子,头疼 同样也没有搞出来,老是报:不能扫描 ...

  9. stm32 usart 单线半双工串口 DMA发送 最后一个字节发不出来问题

    最近遇到一个小问题,感觉很有意思便记下来分享一下 ,顺便也为日后类似的问题提供点思路: 使用stm32串口发送数据 ,串口是单线半双工模式,要求数据发送前串口变成发送模式,发送完后立即变回接收模式,发 ...

最新文章

  1. eclipse下tomcat添加部署Module,Web名称与项目名称不一致的解决方法
  2. elastic-job的原理简介和使用
  3. S5PV210开发 -- I2C 你知道多少?(三)
  4. matlab空格会消失了,如何在Matlab中自动删除保存的尾随空格?
  5. Oracle adviser,Oracle10g SQL tune adviser
  6. 记一次培训机构“面试”过程
  7. 创意美食海报,悬浮跳动食材,视觉刺激大脑(PSD分层模板)
  8. html中input描述,input的type值类型和描述-HTML
  9. Delphi Sql语句中值的引用
  10. 点击场景中的物件无法定位到Hierarchy
  11. LeetCode - Remove Duplicates from Sorted List
  12. ios 音频录音、上传至7牛、播放及其与android兼容的问题
  13. ImportREC输入表重建工具
  14. 泛微Ecology8.0移动端模板必填字段JS代码
  15. 斯坦福大学自然语言处理第一课“引言(Introduction)”
  16. OpenHarmony更新编译问题及解决办法
  17. ps怎么加底部阴影_PS三分钟之如何在PS中给物体添加阴影
  18. 移动通信的主要测量指标及注意事项(转)
  19. Android 高级混淆和代码保护技术
  20. 成功时间管理软件推荐-DesktopCal和GTD

热门文章

  1. 华为设备上配置链路聚合和OSPF、RIP
  2. 浅谈LCA问题(最近公共祖先)(三种做法)
  3. wordpress代码插件_您可能想尝试的20个WordPress短代码和插件
  4. 教小学生学英语系统(一次课设项目)
  5. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十六)通用型角色头像面板...
  6. 《饮酒·其五》古诗鉴赏
  7. (转新浪)深锐观察:科比OMG 一个只想赢的强迫症患者的故事
  8. vue使用elemtui + xlsx实现excel导入,上传到koa后端
  9. QQ链接防拦截方法(非官方页面、停止访问该页面等)
  10. 玩转微博之如何增加粉丝