串口空闲中断+DMA接收一帧数据

环境: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。

效果能截取有效、完整的一条报文

在这里插入图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值