环境:stm32f107、mdk
每个串口的DMA收发数据的通道都不一样:
串口配置:
u8 receive_data[1280]={0};
u8 RX_data[26] = {0};
void uart_init(u32 bound)
{
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; /*485收发控制线*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
USART_InitStruct.USART_BaudRate = bound;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(USART1, &USART_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; //串口4中断通道
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //响应优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
//中断向量控制器初始化
NVIC_Init(&NVIC_InitStruct);
//开启中断并且初始化 NVIC,使能中断(如果需要开启串口中断才需要这个步骤)。
//配置中断模式 有数据来即中断
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);
USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
USART_Cmd(USART1,ENABLE);//使能串口。
dma_init();
GPIO_ResetBits(GPIOA,GPIO_Pin_11); //DE 拉低485处于接收状态
}
void dma_init(void)
{
DMA_InitTypeDef DMA_Initstructure;
/开启DMA时钟/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
/*DMA配置*/
DMA_Initstructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
DMA_Initstructure.DMA_MemoryBaseAddr = (u32)receive_data;
DMA_Initstructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_Initstructure.DMA_BufferSize = 128;
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_High;
DMA_Initstructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel5,&DMA_Initstructure);
}
中断接收函数:
void USART1_IRQHandler(void) //上行485接收中断
{
unsigned char num=0;
if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)
{
num = USART1->SR;
num = USART1->DR; //清USART_IT_IDLE标志 不读的话会 一直进入中断
DMA_Cmd(DMA1_Channel5,DISABLE); //关闭DMA
num = 1280 - DMA_GetCurrDataCounter(DMA1_Channel5); //得到真正接收数据个数
//receive_data[num] = ‘\0’;
DMA1_Channel5->CNDTR=1280; //重新设置接收数据个数 DMA_Cmd(DMA1_Channel5,ENABLE); //开启DMA
DMA_Cmd(DMA1_Channel5,ENABLE); //开启DMA
printf("%s \r\n",receive_data );
RX_flg = 1;
}
}
发送26字节的报文效果如图:
解包主要程序:
void unpack_usart(void)
{
u16 i = 0;
u8 j = 0;
for(i=0;i<1280;i++)
{
if((receive_data[i]==0xAA) &&(receive_data[i+1]==0xBB))
{
for(j=0;j<26;j++)
{
RX_data[j] = receive_data[i];
i++;
}
return;
}
}
}
j<26 是因为我们需要的报文有效字节为26。
效果能截取有效、完整的一条报文