ROS stm32F4串口+DMA通信

介绍

本博文基于stm32F407,利用uart3发送数据,并由uart3接收ROS通过串口发送的数据后由uart1发送回ROS。以下,主要针对于调试过程中的问题的总结

发送数据错位

发送协议:

012 …11
0xaa0xaDATA

初始化:

MYDMA_Config_Inter(DMA1_Stream3,DMA_Channel_4,
				  (u32)&USART3->DR,(u32)TxBuffer,
				  TxBufferSize,DMA1_Stream3_IRQn, DMA_DIR_MemoryToPeripheral);

主函数使能uart3发送

USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
MYDMA_Enable(DMA1_Stream3, TxBufferSize);    

在代码中要注意初始化发送的大小应该和在主函数使能发送的大小应该一致,如果不一致会出现数据错位,导致ROS在解析数据的过程中会把后续接收的数据过程中,直接认为数据不对而直接丢弃数据。

uart接收

在调试过程中,一开始只开启了空闲中断,但是一直出现ROS第一次发送的数据无法接收,而后续的数据可以接收到。后面才发现空闲中断无法接收第一次发送的数据。
解决方法:
初始化时开启接收中断,进入接收中断后在开启空闲中断并关闭接收中断

void USART3_IRQHandler(void) {
	// 空闲中断
	if(USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) {
		
		DMA_Cmd(DMA1_Stream1, DISABLE);

		DMA_ClearFlag(DMA1_Stream1, DMA_FLAG_TCIF1|DMA_FLAG_FEIF1|DMA_FLAG_DMEIF1
					 |DMA_FLAG_TEIF1|DMA_FLAG_HTIF1);
		DMA_SetCurrDataCounter(DMA1_Stream1, USART_REC_LEN);
    	DMA_Cmd(DMA1_Stream1, ENABLE);
  }
	// 接收中断
	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) {
		
		DMA_Cmd(DMA1_Stream1, DISABLE);
		
		DMA_ClearFlag(DMA1_Stream1, DMA_FLAG_TCIF1|DMA_FLAG_FEIF1
					 |DMA_FLAG_DMEIF1|DMA_FLAG_TEIF1|DMA_FLAG_HTIF1);
		DMA_SetCurrDataCounter(DMA1_Stream1, USART_REC_LEN);
   	    DMA_Cmd(DMA1_Stream1, ENABLE);
		USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); 
		USART_ITConfig(USART3, USART_IT_RXNE, DISABLE);
	}
} 

以下是接收数据后直接开启UART1,并通过UART1发送,并通过长度判断来实现对不定长的数据的接收

void DMA1_Stream1_IRQHandler() {
	// clear flag, and waiting for finishing receiving
	if (DMA_GetFlagStatus(DMA1_Stream1, DMA_FLAG_TCIF1) != RESET) {
		DMA_Cmd(DMA1_Stream1, DISABLE); // close DMA, forbidden having other data flow in 
		UART3_ReceiveSize = USART_REC_LEN - DMA_GetCurrDataCounter(DMA1_Stream1);
		if (UART3_ReceiveSize != 0) {
			USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
			MYDMA_Enable(DMA2_Stream7, UART3_ReceiveSize);
		}
		
		DMA_ClearFlag(DMA1_Stream1, DMA_FLAG_TCIF1|DMA_FLAG_FEIF1|DMA_FLAG_TEIF1|DMA_FLAG_HTIF1|DMA_FLAG_DMEIF1);
		DMA_SetCurrDataCounter(DMA1_Stream1, USART_REC_LEN);
		DMA_Cmd(DMA1_Stream1, ENABLE);
	}
}

ROS端部分程序

while (ros::ok()) {
	if (ser.available()) {
		ser.read(r_buffer, rBUFFERSIZE);
		if (data_analyse(r_buffer) != 0) {
			for (int i = 0; i < 4; ++i){
				posx.cvalue[i] = r_buffer[2+i];
				posy.cvalue[i] = r_buffer[6+i];
				vx.cvalue[i] = r_buffer[10+i];
				vy.cvalue[i] = r_buffer[14+i];
				angular_v.cvalue[i] = r_buffer[18+i];
				pose_angular.cvalude[i] = r_buffer[22+i];
			}
			ROS_INFO("posx: [%f],posy: [%f],vx: [%f],vy.: [%f],angular_v: [%f],pose_angular: [%f]", posx.fvalue,posy.fvalue,vx.fvalue,vy.fvalue,angular_v.fvalue,pose_angular.fvalue);
		}
		ros::spinOnce();
	}
}

后续会公开代码,请期待我的代码分享,谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值