://
***注意***
//TIM3时钟和SPI1时钟不能同时打开,否则TIM3的CH1、CH2不能输出PWM,但CH3、CH4能输出
//APB1ENR最好全部打开,否则TIM1在极偶尔情况下会不工作
另外,STM32中很多的IO都是复用,对于具备多个复用功能的IO要尤其小心
具体这个问题,我没有遇到过,不过能从你的描述来看,可能是你自己的程序问题:
1、用官方例程来测试没有问题,至少说明硬件和软件出现问题的几率比较小
2、加中断后,出现问题。这就很可能是中断处理的问题。
3、如果你没有加操作系统的话,就是你采用前后台的系统结构。
(1)把定时器的中断处理时间尽量减少(就是在中断响应函数执行时间缩短)
(2)把中断过程处理的for循环移到中断外面来处理,比如main函数里面,在中断函数只要做一个标记就可以了。
从你描述的过程中,应该是中断执行时间太久的原因(for循环越长出现这种卡死的概率越大),这个很可能是系统错过了某个事件。
不知道你的中断的优先级是怎么配置的。也有可能是让DMA中断不能及时响应。
STM32的DMA有多路!例如F103zet6有DMA1
7路
DMA2
5路,共计12路DMA通道。
使用三个不同外设分别配置三个通道即可!要注意每个外设对应的通道是手册中固定的,不能自己定义。同时避开冲突的外设即可。
举例:ADC1,TIM2_CH3,TIM4_CH1三个外设通道可配置为DMA1_CH1
。使用此三个外设时必须配置为此通道,且此三个外设不可同时使能配置使用!
stm32 DMA错误无法恢复问题
stm32f446,程序中需要ADC1、ADC3和DAC同时工作。
首先,在此工程的STM32G474版中,使用TIM8同时触发2个AD、一个DA工作,所以在STM32F446版中也使用此策略,结果无法实现。
所以使用了TIM8-trog触发ADC1,TIM8-ch1触发ADC3,TIM6触发DAC输出波形。
在长时间运行后,或者反复进出jlink调试,会导致ADC的DMA过程受阻,ADC的OVERRUN位置位,一般清除此位后即可恢复运行
后来DMA数据进一步增加,即使清除OVERRUN位,也不会恢复工作了。
由于此时设备已经发到客户手中,即使能够复现,也无法调试。所以费了很大的劲,通过反复进出调试器的方式复现了错误,然后在调试器中对ADC、DMA等寄存器进行操作。发现此时连续扫描型的ADC并未受影响,仍然通过DMA传出数据。只是定时器触发的ADC阻塞,并且,DMA寄存器不受控了,写入值也不发生变化。
通过复位DMA时钟的方式,才改变了DMA寄存器的值。然后给DMA重新初始化,程序又开始工作了:
1 RCC-AHB1RSTR |= RCC_AHB1Periph_DMA2;2 RCC-AHB1RSTR = ~RCC_AHB1Periph_DMA2;3 RCC-AHB1ENR = ~RCC_AHB1Periph_DMA2;4 RCC-AHB1RSTR |= RCC_AHB1Periph_DMA2;5 RCC-AHB1RSTR = ~RCC_AHB1Periph_DMA2;
也不知道这个RSTR是在ENR之前还是之后,所以反复写了两遍
但是这个AD用的DMA2,在ADC2上也使用了,所以ADC2也需要重新初始化。结果ADC2通过重启时钟的方式,寄存器不会归零,必须人工归零后才能使用。
如果只是无法进中断,你检查下NVIC的中断映射是否配置,我用的是DMA发送,给你参考下。
相关定义:
#define USART1_Tx_DMA_Channel DMA1_Channel4
#define USART1_Tx_DMA_STREAM DMA2_Stream7
#define USART1_Tx_DMA_TCIF DMA1_FLAG_TC4
#define USART1_Rx_DMA_Channel DMA1_Channel5
#define USART1_Rx_DMA_FLAG DMA1_FLAG_TC5
#define USART1_DR_Base ((uint32_t)USART1-DR)
代码:
#ifdef USART1_USE_DMA_MODE
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA1时钟
#ifdef USART1_DMA_TX
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; //设置中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //主优先级设置
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //设置优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //打开中断
NVIC_Init(NVIC_InitStructure);
DMA_DeInit(USART1_Tx_DMA_Channel);
DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)m_UartDCB.pSendBuff;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
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_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(USART1_Tx_DMA_Channel, DMA_InitStructure); //配置DMA1
DMA_ITConfig(USART1_Tx_DMA_Channel, DMA_IT_TC, ENABLE); //使能DMA发送中断
#endif //_USART_DMA_TX__
#endif //USE_DMA_MODE
本文标签:stm32dma不好使