先初始化串口,开启串口时钟,DMA时钟,这里用的是DMA1 然后开启串口的读取中断。
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 开启DMA时钟 // 开启DMA时钟
RCC_APB2PeriphClockCmd(DEBUGx_USART_RX_GPIO_CLK, ENABLE);
/* 使能 UART 时钟 */
RCC_APB1PeriphClockCmd(DEBUGx_USART_CLK, ENABLE);
/* 配置Tx引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = DEBUGx_USART_TX_PIN; //PA.3
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(DEBUGx_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// PA.2
GPIO_InitStructure.GPIO_Pin = DEBUGx_USART_RX_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(DEBUGx_USART_RX_GPIO_PORT, &GPIO_InitStructure);
/* 配置串DEBUG_USART 模式 */
USART_InitStructure.USART_BaudRate = DEBUGx_USART_BAUDRATE;
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_Rx | USART_Mode_Tx;
USART_Init(DEBUGx_USART, &USART_InitStructure);
DMA_DeInit(DMA1_Channel6);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR; //DMA外设地址
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)USART2_data.USART_BUFF; //DMA 存储器0地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //外设到存储器模式
DMA_InitStructure.DMA_BufferSize = USART2_TEMP_LEN; //数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //存储器数据长度:8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //使用普通模式
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //高等优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel6, &DMA_InitStructure); //初始化DMA Stream
USART_ITConfig(DEBUGx_USART, USART_IT_RXNE, ENABLE);//开启相关中断
USART_DMACmd(DEBUGx_USART,USART_DMAReq_Rx,ENABLE);
USART_Cmd(DEBUGx_USART, ENABLE);
USART_ClearFlag(DEBUGx_USART, USART_FLAG_TC);
DMA的串口数据流映射表 DMA1和DMA2
串口中断里面开启空闲中断
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_IDLE)!=RESET) //空闲中断触发
{
//接收数据
usart2_receive(); //取出接收数据包并处理函数
USART_ReceiveData(USART2); //清除空闲中断标志位(接收函数有清标志位的作用)
USART_ITConfig(USART2, USART_IT_IDLE, DISABLE); //关闭空闲中断
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启读取中断
}
else if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET) //空闲中断触发
{
usart2_receive();
USART_ReceiveData(USART2); //清空标志
}else
{
USART_ReceiveData(USART2); //清除空闲中断标志位(接收函数有清标志位的作用)
USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); //开启空闲中断
USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
}
}
接收串口数据函数
void usart2_receive(void)
{
uint16_t buff_length;
buff_length=DMA_GetCurrDataCounter(DMA1_Channel6);/* 获取接收到的数据长度 单位为字节*/
DMA_Cmd(DMA1_Channel6, DISABLE); /* 暂时关闭dma,数据尚未处理 */
USART2_data.USART_LEN = USART2_TEMP_LEN -(u16)buff_length; /* 获取数据长度 */
DMA_ClearFlag(DMA1_FLAG_TC6); /* 清DMA标志位 */
DMA_SetCurrDataCounter(DMA1_Channel6,USART2_TEMP_LEN);/* 重新赋值计数值,必须大于等于最大可能接收到的数据帧数目 */
// usart2_RX_data[RX2]=USART2_data;
USART2_task(&USART2_data);
DMA_Cmd(DMA1_Channel6, ENABLE); /*打开DMA*/
}
第一次激活DMA
DMA_Cmd(DMA1_Channel6, DISABLE);
DMA_SetCurrDataCounter(DMA1_Channel6,USART3_TEMP_LEN);
DMA_Cmd(DMA1_Channel6, ENABLE);