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. mysql数据库连接过多的错误,可能的原因分析及解决办法
  2. sm4加密 解密(oc)
  3. 散列(hash)练习题
  4. QT的QReadWriteLock类的使用
  5. 网络部署过程中_郑州萤火云SEO网络优化:SEO过程中的容易犯的错误
  6. mysql 安装测试ok_tpcc-mysql安装测试与使用的实例教程
  7. iOS开发-多线程编程技术(Thread、Cocoa operations、GCD)
  8. 以国家战略科学家身份,顶级AI学者朱松纯回国,筹建北京通用AI研究院
  9. Java中含有泛型的 JSON 反序列化问题
  10. “这样使用RHEL合法吗”?
  11. 【MATLAB】 分形插值
  12. ghost系统之优劣?
  13. xclient 已停止工作
  14. 深度学习入门——03 MNIST手写数字图像集识别实验
  15. 前馈神经网络——神经元
  16. Sketch设置透明背景
  17. 开发随笔——花生壳错误“您的局域网服务器连接失败,请检查局域网IP与端口“
  18. 自动向你的宝马车播放捷豹广告,这家公司要做高速公路上的“分众”
  19. Java集合案例图书管理系统
  20. Ubuntu 下安装Chrom浏览器

热门文章

  1. Python-解决使用 plt.savefig 保存图片时一片空白
  2. android mimi 病毒如何,迷你脑将揭开人类朊病毒的神秘面纱
  3. 计算机产品多久更新一代,产品迭代更新快 PC买新不买旧真的对吗?
  4. Don’t Shave Yaks,别给耗牛剪毛_kiteseas_新浪博客
  5. macbook中的一些快捷功能
  6. 网络编程:套接字 socket
  7. 可以上网,微信发不出文件
  8. 成就最强机甲战神|Cocos精品《星战风暴》
  9. JQuery案例-QQ表情案例
  10. 在庫転送オーダーでのプラント間返品および店舗返品(メモ)