新手入门
- 积分
- 18
- 金钱
- 18
- 注册时间
- 2020-5-4
- 在线时间
- 7 小时
|
20金钱
本人使用STM32F103,串口2的DMA空闲中断,用来接收不定长的数据,初始化及处理代码如下,问题为:第一次进入中断正常处理,但是此后进入读取到的剩余传输字节一直是累加的,并不是接收一次处理完就复位,非常困惑。贴出代码如下:
USART2初始化如下:
void USART2_Init(u32 br_num)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_USART2, ENABLE); //使能USART2,GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
USART_DeInit(USART2); //复位串口2
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStructure.GPIO_Pin = USART2_Pin_TX; //PA2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //
GPIO_Init(GPIO_USART2, &GPIO_InitStructure); //
GPIO_InitStructure.GPIO_Pin = USART2_Pin_RX; //PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
GPIO_Init(GPIO_USART2, &GPIO_InitStructure); //
//USART2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_USART2_P; //抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_USART2_S; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART2 初始化设置
USART_InitStructure.USART_BaudRate = br_num; //串口波特率
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(USART2, &USART_InitStructure); //初始化串口2
#if USE_USART2_DMA_RX
/* 使能串口DMA */
USART2_DMA_Rx_Config();
// 开启 串口空闲IDEL 中断
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
// 开启串口DMA接收
USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);
#else
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
#endif
#if USE_USART2_DMA_TX
// 开启串口DMA发送
// USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE);
USART2_DMA_Tx_Config();
#endif
USART_Cmd(USART2, ENABLE); //使能串口2
}
DMA通道6初始化如下:
DMA_InitTypeDef DMA_InitStructure;
// 开启DMA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// 设置DMA源地址:串口数据寄存器地址*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART2_DR_ADDRESS;
// 内存地址(要传输的变量的指针)
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Usart2_Rx_Buf;
// 方向:从内存到外设
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
// 传输大小
DMA_InitStructure.DMA_BufferSize = USART2_RX_BUFF_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模式,一次或者循环模式
//DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
// 优先级:中
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
// 禁止内存到内存的传输
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
// 配置DMA通道
DMA_Init(USART2_RX_DMA_CHANNEL, &DMA_InitStructure);
// 清除DMA所有标志
DMA_ClearFlag(DMA1_FLAG_TC6);
DMA_ITConfig(USART2_RX_DMA_CHANNEL, DMA_IT_TE, ENABLE);
// 使能DMA
DMA_Cmd(USART2_RX_DMA_CHANNEL, ENABLE);
中断处理如下:
void USART2_IRQHandler(void)
{
if ((USART2->SR & (1 << 7)) && (USART2->CR1 & USART_CR1_TXEIE))
{
USART2->DR = TxBuffer2[TxCounter2++]; //写DR清除中断标志
if (TxCounter2 == count2)
{
USART2->CR1 &= ~USART_CR1_TXEIE; //关闭TXE中断
}
}
/*暂不使用DMA 必须要接收完才进空闲中断 CI1006发送家电控制时连续发了16帧*/
#if USE_USART2_DMA_RX
/* 使用串口DMA */
if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //串口空闲中断
{
/* 接收数据 */
REMAIN_count = USART2->SR; //读SR的作用是?
REMAIN_count = USART2->DR; //读DR的作用是?
USART_ClearITPendingBit(USART2, USART_IT_IDLE); //清掉空闲中断
/* 关闭DMA ,防止干扰 */
DMA_Cmd(USART2_RX_DMA_CHANNEL, DISABLE); /* 暂时关闭dma,数据尚未处理 */
/* 清DMA标志位 */
DMA_ClearFlag(DMA1_FLAG_TC6);
// DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);
REMAIN_count=DMA_GetCurrDataCounter(USART2_RX_DMA_CHANNEL);//获取剩余字节
memcpy(RxBuffer.DAT, Usart2_Rx_Buf, USART2_RX_BUFF_SIZE);
printf("%d|%d|%d|\r\n",USART2_RX_BUFF_SIZE-REMAIN_count,REMAIN_count,USART2_RX_BUFF_SIZE);
// printf("%s\r\n",Usart2_Rx_Buf);
memset(Usart2_Rx_Buf, 0x00, USART2_RX_BUFF_SIZE);
/* 重新赋值计数值,必须大于等于最大可能接收到的数据帧数目 */
USART2_RX_DMA_CHANNEL->CNDTR = USART2_RX_BUFF_SIZE;
/* 此处应该在处理完数据再打开*/
DMA_Cmd(USART2_RX_DMA_CHANNEL, ENABLE);
USART_Cmd(USART2, ENABLE); //使能串口2
// USART_ReceiveData(USART2);
}
#else
/* 接收中断 */
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
u8 com_data = USART2->DR;
SN_Reply_Get(com_data);
}
#endif
}
串口调试输出如下,每次发送接收数据都在累计,没被复位:
|
|