用的是STM32103RC ,UART4 DMA发送功能,初始化如下
void DigitalUartInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
GPIO_InitStructure.GPIO_Pin = DIGITAL_UART_TX_GPIO;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(DIGITAL_UART_GPIO_PTR, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = DIGITAL_UART_RX_GPIO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DIGITAL_UART_GPIO_PTR, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel4_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#if 1
DMA_DeInit(DMA2_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&DIGITAL_UART_PTR->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DigitalUartTxBuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
//DMA_InitStructure.DMA_BufferSize = 12;
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(DMA2_Channel5, &DMA_InitStructure);
//DMA_ITConfig(DMA2_Channel5, DMA_IT_TC, ENABLE);
//DMA_Cmd(DMA2_Channel5, ENABLE);
#endif
DMA_DeInit(DMA2_Channel3);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DIGITAL_UART_PTR+0x00000004;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)DigitalUartRxBuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = UART_RXBUF_SIZE;
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_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel3, &DMA_InitStructure);
DMA_ITConfig(DMA2_Channel3, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Channel3, ENABLE);
USART_InitStructure.USART_BaudRate = 9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
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_Tx | USART_Mode_Rx;
USART_Init(DIGITAL_UART_PTR, &USART_InitStructure);
//USART_DMACmd(ZJ_UART_PTR, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);
USART_DMACmd(DIGITAL_UART_PTR, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE);
USART_Cmd(DIGITAL_UART_PTR, ENABLE);
DititalMbox = OSMboxCreate((void*)NULL);
DititalUartSendSem = OSSemCreate(1);
}
我设想是每次发送的时候,更改buffer的地址和长度,发送请code如下
INT8U err;
DMA_InitTypeDef DMA_InitStructure;
OSSemPend(DititalUartSendSem,0,&err);
DMA_DeInit(DMA2_Channel5);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuf;
DMA_InitStructure.DMA_BufferSize = len;
DMA_Cmd(DMA2_Channel5, ENABLE);
这样的话我发现,只能进一次中断,中断code如下
void DMA2_Channel4_5_IRQHandler(void)
{
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL(); //保存全局中断标志,关总中断/* Tell uC/OS-II that we are starting an ISR*/
OSIntNesting++;
OS_EXIT_CRITICAL(); //恢复全局中断标志
if(DMA_GetITStatus(DMA2_IT_TC5)) //通道5传输完成中断TC 还有传输 过半中断HT 错误中断TE 全局中断GL
{
DMA_ClearITPendingBit(DMA2_IT_GL5); //清除全部中断标志
OSSemPost(DititalUartSendSem);
}
OSIntExit(); //在os_core.c文件里定义,如果有更高优先级的任务就绪了,则执行一次任务切换
}
如果把发送code改成
INT8U err;
DMA_InitTypeDef DMA_InitStructure;
OSSemPend(DititalUartSendSem,0,&err);
DMA_DeInit(DMA2_Channel5);
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&DIGITAL_UART_PTR->DR);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)pBuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 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_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel5, &DMA_InitStructure);
DMA_ITConfig(DMA2_Channel5, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Channel5, ENABLE);
也就是重新初始化DMA2_Channel5,中断就正常,哪位高手是否可以指点一下,谢谢 |