ROS stm32F4串列埠+DMA通訊
阿新 • • 發佈:2021-01-02
ROS stm32F4串列埠+DMA通訊
介紹
本博文基於stm32F407,利用uart3傳送資料,並由uart3接收ROS通過串列埠傳送的資料後由uart1傳送回ROS。以下,主要針對於除錯過程中的問題的總結
傳送資料錯位
傳送協議:
0 | 1 | 2 …11 |
---|---|---|
0xaa | 0xa | DATA |
初始化:
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();
}
}
後續會公開程式碼,請期待我的程式碼分享,謝謝!