STM32 DMA定长发送+完成中断

这篇具有很好参考价值的文章主要介绍了STM32 DMA定长发送+完成中断。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代码测试完成,可以正常运行。

DMA发送需用到串口,故需配置串口。

串口配置

串口配置很简单,照抄就行,这里用的正点原子的源码。

串口配置主要分为定义句柄、开启时钟、配置IO并写入相关寄存器、配置串口模式、开启中断(本代码没有用到接收,所以无所谓)、

  • 定义相关句柄

GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
  • 开启时钟(USART1是APB2时钟,IO口是PA9 PA10,A组IO口时钟也是APB2,故一起设置)

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);    //使能USART1,GPIOA时钟
  • 配置IO

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
  • 配置串口模式

USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;    //收发模式
  • 根据上述配置,初始化串口

USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE);                    //使能串口1 

需使用DMA,故需在串口处使能DMA传输

  • 使能DMA传输

USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);

DMA配置

到此处,串口配置完毕,接下来配置DMA。

因为使用的是串口1,根据手册查询到对应的DMA为DMA1 4通道(TX)和DMA1 5通道(RX),只使用了TX串口,只需配置TX即可(即DMA1 4通道)。

dma传输完成中断,STM32 DMA,stm32,单片机,嵌入式硬件,Powered by 金山文档

根据结构体及成员相关解释,配置DMA1 4通道

dma传输完成中断,STM32 DMA,stm32,单片机,嵌入式硬件,Powered by 金山文档
dma传输完成中断,STM32 DMA,stm32,单片机,嵌入式硬件,Powered by 金山文档
dma传输完成中断,STM32 DMA,stm32,单片机,嵌入式硬件,Powered by 金山文档

先配置NVIC中断。

void DMA1_NVIC_Init(void)
{ 
    NVIC_InitTypeDef NVIC_InitStructure;
        //DMA1通道4 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel =  DMA1_Channel4_IRQn;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    
//        //DMA1通道5 NVIC 配置
//    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;                //NVIC通道设置
//    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ;                //抢占优先级
//    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                        //子优先级
//    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                            //IRQ通道使能

    NVIC_Init(&NVIC_InitStructure);    //根据指定的参数初始化VIC寄存器
}

配置DMA

  • 定义句柄

DMA_InitTypeDef DMA_InitStructure;
  • 开启DMA1时钟

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    //使能DMA传输
  • 调用NVIC中断函数,提前配置DMA1 4通道中断

DMA1_NVIC_Init();   //DMA通道配置中断
  • 根据DMA结构体 配置DMA1 4通道

先调用函数,清除DMA1 4通道配置,配置完成后调用函数

DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE); //DMA通道4传输完成中断

配置DMA1 4通道传输完成中断,使能DMA1 4通道。

DMA_DeInit(DMA1_Channel4);  //重置DMA1 4通道  USART1 TX
/********************************传输方向*****************************/    
    DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&USART1->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr=(u32) usart_txbuf;  //自定义数组
    DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;
    
/********************************数据大小及模式*****************************/        
    DMA_InitStructure.DMA_BufferSize=USART1_MAX_TX_LEN;   //数组大小
    DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
    
/********************************传输模式*****************************/    
    DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;
    
    DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;
    
    DMA_Init(DMA1_Channel4,&DMA_InitStructure);
    DMA_ITConfig(DMA1_Channel4, DMA_IT_TC, ENABLE);        //DMA通道4传输完成中断
    DMA_Cmd(DMA1_Channel4,ENABLE);
  • 配置4通道中断函数

//DMA1通道4中断,判断上次数据串口是否已经发送完成
void DMA1_Channel4_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC4)!= RESET)    //DMA接收完成标志
    {
        LED1=!LED1;
        DMA_ClearITPendingBit(DMA1_IT_TC4);     //清除中断标志 
    }
}

到此,DMA1 4通道配置完成。

主函数

u16 t;
 int main(void)
 { 
    u16 i=0;
    delay_init();             //延时函数初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
    uart_init(115200);         //串口初始化为9600
    LED_Init();                  //初始化与LED连接的硬件接口     
    DMA_init();
     for(i=0;i<USART1_MAX_RX_LEN;i++)
     {
     usart_txbuf[i]=i;
     }
     
    while(1)
    {    
        delay_ms(1000);
        t++;
        if(t%5==0){
        dma1_channel4();
        }
    }
}

注意事项

DMA发送完成一次后,需重新设置发送长度才可以再次使用。

/***********************设置DMA1 4缓存大小***********************/
void dma1_channel4(void)
{
     DMA_Cmd(DMA1_Channel4,DISABLE);   //关闭USART1 TX DMA1 所指示的通道  
     DMA_SetCurrDataCounter(DMA1_Channel4,USART1_MAX_RX_LEN);//DMA通道的DMA缓存的大小
     DMA_Cmd(DMA1_Channel4, ENABLE);     //使能USART1 TX DMA1 所指示的通道        
}

使用DMA中断,需提前使能,才可以进入中断。我把串口DMA使能放在串口的初始化函数里,所以串口初始化需在DMA初始化函数之前。

注意代码执行顺序及代码逻辑,无法进入中断的问题找了好久。文章来源地址https://www.toymoban.com/news/detail-617802.html

到了这里,关于STM32 DMA定长发送+完成中断的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • stm32 hal库uart使用 DMA中断只能发送一次的问题

    1.stm32 uart使用DMA,无论发送还是接收都各自有一个数据流中断。这个数据流中断是框架代码不必过多关心。 2.使用了DMA后,uart的global中断是否要使用?标准做法是在cubemx上要勾选的,不然,就会产生只能发送一次的问题。 问题的原因? 我相信这是hal库的问题,理论上讲有一

    2024年02月11日
    浏览(43)
  • stm32串口空闲中断+DMA传输接受不定长数据+letter shell 实现命令行

    空闲中断(IDLE),俗称帧中断,即第一帧数据接收完毕到第二帧数据开始接收期间存在一个空闲状态(每接收一帧数据后空闲标志位置1),检测到此空闲状态后即执行中断程序。 空闲中断的优点在于省去了帧头帧尾的检测 ,进入中断程序即意味着已经接收到一组完整数据,仅需

    2024年02月03日
    浏览(60)
  • STM32使用DMA传输UART空闲中断中接收的数据遇到的问题以及解决方法

    STM32使用DMA传输UART空闲中断中接收的数据遇到的问题以及解决方法 CubeMX配置 串口配置:使用默认配置(传输数据长度为8 Bit,奇偶检验无,停止位为1 Bit, 接收和发送都使能),因为我的是LIN项目所以使用的时串口的LIN模式,一般就是异步通信 打开DMA传输 打开串口接收中断

    2024年02月05日
    浏览(42)
  • 【STM32】IIC使用中DMA传输时 发送数据总少一个的问题

    在使用STM32 I2C数据发送过程中,发现每轮实际发送出去的数据总比在DMA配置中设定的传输数据个数要少一个。比方说:DMA配置里设定的传输数据个数是10个,结果发现在总线上只能发出9个,经过进一步发现是少了最后一个数据。当对I2C接收到的数据进行DMA传输时,没有异常。

    2024年02月10日
    浏览(32)
  • STM32_ADC————ADC+DMA多路数据传输,看门狗中断,传感器控制LED

    一:介绍ADC与DMA的基本情况与初始化 二:利用ADC+DMA+看门狗中断+传感器控制LED灯代码 三:总结实验过程中碰到的错误与问题 通过DMA转运ADC的数据,设置ADC的中断看门狗阈值,当光敏传感器的ADC采样值在看门狗高低阈值中间,不触发中断,如果超过看门狗的高低阈值就会触发

    2024年02月04日
    浏览(49)
  • STM32 TIMER_TRGO触发+ADC采集 + DMA传输 + 中断均方根处理 实现三相电压显示

    STM32 TIMER_TRGO触发+ADC采集 + DMA传输 实现三相电压采集 首先,是实际采集的三相电压值,用excel处理了下: 采集个电压,为什么这么复杂。 开始我也是直接用ADC采集,然后delay,再采集,然后delay,再采集……最后数据处理…… 问题是如果我们用单片机裸跑,每次delay都会卡死

    2024年02月16日
    浏览(41)
  • 关于STM32用DMA传输UART空闲中断中接收的数据时无法接收数据问题以及解决办法

             串口1相关的设置及printf函数的使用,这里没放,建议先实现串口打印功能 可以参考:使用STM32 CUBE IDE配置STM32F7 用DMA传输多通道ADC数据_stm32cubeide 配置adc_一只小白啊的博客-CSDN博客         普通模式和循环模式的区别在于,普通模式下,DMA只会接收一次数据,

    2024年02月05日
    浏览(62)
  • STM32F4_HAL库_串口阻塞/中断/DMA三种方式发送数据的配置

    串口阻塞发送的意思就是,发送一段数据,在没有发送完所有数据之前,一直停留在此发送函数(可设定阻塞时间),这个过程中会阻塞别的程序运行; HAL库的配置分为两个层次,一个是HAL库内部调用的、与MCU硬件相关的初始化xxx_MspInit,一个是我们外部调用的初始化xxx_In

    2023年04月25日
    浏览(54)
  • 【STM32】HAL库 STM32CubeMX——DMA (串口DMA发送接收)

    软件: STM32CubeMX KEIL5 mcuisp 串口通信助手 硬件: STM32F103C8Tx 杜邦线,面包板,USB转TTL DMA,全称Direct Memory Access,即直接存储器访问。 DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。 我们知道系统的运

    2024年02月12日
    浏览(66)
  • STM32 HAL DMA中断配置

    使用HAL库方式DMA中断时,在网上找了好多资料都没有怎么介绍。所以就自己研究了一下,并做个记录。我的芯片型号是STM32G030。下面我以I2C传数据为例介绍下HAL库是如何使用DMA中断的。 我使用的是I2C2,简单配置下参数,加上DMA通道。 DMA貌似默认开启了中断,蓝色的勾勾是我

    2024年04月23日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包