我正在尝试使用 FreeRTOS(互斥体和流缓冲区)、DMA 和 USART3 实现 stm32f103 和 SIM900A 之间的通信。
我已启用 USART_IT_IDLE USART3 中断,以便能够检测 SIM900 传输结束并强制触发 DMA 传输完成中断以将数据从内存复制到 FreeRtos 的流缓冲区。
这篇文章说这是可能的。
/**
* \brief Global interrupt handler for USART2
*/
void USART2_IRQHandler(void) {
/* Check for IDLE flag */
if (USART2->SR & USART_FLAG_IDLE) { /* We want IDLE flag only */
/* This part is important */
/* Clear IDLE flag by reading status register first */
/* And follow by reading data register */
volatile uint32_t tmp; /* Must be volatile to prevent optimizations */
tmp = USART2->SR; /* Read status register */
tmp = USART2->DR; /* Read data register */
(void)tmp; /* Prevent compiler warnings */
DMA1_Stream5->CR &= ~DMA_SxCR_EN; /* Disabling DMA will force transfer complete interrupt if enabled */
}
}
但我的调试器说:不
这是我的代码:
#define BUFF_SIZE 16
uint8_t RX_BUFFER[BUFF_SIZE] = {"\0"};
uint8_t TX_BUFFER[BUFF_SIZE] = {"\0"};
....
// USART TX channel
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(USART3->DR);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&TX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStruct.DMA_BufferSize = sizeof(TX_BUFFER);
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStruct);
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = sizeof(RX_BUFFER);
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// USART RX channel
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)&RX_BUFFER[0];
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = sizeof(RX_BUFFER);
DMA_Init(DMA1_Channel3, &DMA_InitStruct);
// Interrupts
USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
USART_DMACmd(USART3, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
USART_Cmd(USART3, ENABLE);
DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel3, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY + 10;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&NVIC_InitStructure);
....
void USART3_IRQHandler() {
if (USART_GetITStatus(USART3, USART_IT_IDLE) == SET) {
volatile uint32_t tmp = USART3->SR;
tmp = USART3->DR;
(void) tmp;
// HERE interrupt should be fired!
DMA1_Channel3->CCR &= (uint16_t)(~DMA_CCR1_EN);
USART_ClearITPendingBit(USART3, USART_IT_IDLE);
}
}
void DMA1_Channel3_IRQHandler(void) {
if (DMA_GetITStatus(DMA1_IT_TC3) == SET) {
uint8_t len = BUFF_SIZE - DMA1_Channel3->CNDTR;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xStreamBufferSendFromISR(xUSART3ReceiveStreamBuffer, &RX_BUFFER, len, &xHigherPriorityTaskWoken);
for (uint8_t i = 0; i < len; i++) {
RX_BUFFER[i] = '\0';
}
DMA1_Channel3->CNDTR = BUFF_SIZE;
DMA_Cmd(DMA1_Channel3, ENABLE);
DMA_ClearITPendingBit(DMA1_IT_TC3);
}
}
为什么我不能强制 DMA1_IT_TC3 中断?还是可以强制在STM32F103上?