简介
1、使用到的软件 STM32CubeMX 6.1.0 和keil 5.33
2、芯片 STM32L071CBT6
3、实现功能,按帧接收串口数据,数据存入接收buff,帧长存入全局变量
实现原理
当一帧数据传输结束之后,总线IDLE会维持高电平状态,此时就可以触发MCU的IDLE中断。因此利用IDLE中断进行串口不定长数据的接收。省去了用于检测传输是否完成的判断动作。
然而在HAL库中并未集成IDLE中断的处理,所以,我们可以在串口的中断处理中添加对IDLE总线状态的判断,以检测当前帧是否传输完成。
工程实现
1、CubeMX工程配制
(使能两个串口,串口1发送,串口2接收)
串口DMA设置
中断使能 2、代码编辑
main.c全局变量定义
/* USER CODE BEGIN 0 */
uint8_t gcRXDBuffer[50], gcRXDPointer; //接收的缓冲区、接收指针
uint16_t gcRXDLength; //接收的帧长度
uint8_t gcTXDBuffer[50], gcTXDPointer, gcTXDLength; //发送的缓冲区,发送指针,发送的长度
uint8_t recv_end_flag; //接收完成标识
/* USER CODE END 0 */
函数 MX_USART2_UART_Init(void) 中添加
/* USER CODE BEGIN USART2_Init 2 */
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); //使能idle中断
HAL_UART_Receive_DMA(&huart2,gcRXDBuffer,sizeof(gcRXDBuffer)); //打开DMA串口接收
/* USER CODE END USART2_Init 2 */
串口中断处理函数中modify
extern uint8_t gcRXDBuffer[50], gcRXDPointer ; //接收的缓冲区、接收指针、接收的帧长度
extern uint16_t gcRXDLength;
extern uint8_t recv_end_flag;
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除标志位
HAL_UART_DMAStop(&huart2); //
temp = __HAL_DMA_GET_COUNTER(huart2.hdmarx);// 获取DMA中未传输的数据个数
gcRXDLength = sizeof(gcRXDBuffer) - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = 1; // 接受完成标志位置1
HAL_UART_Receive_DMA(&huart2,gcRXDBuffer,sizeof(gcRXDBuffer));//重新打开DMA接收
}
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
主函数main中
/* USER CODE BEGIN 2 */
strcpy((char*)gcTXDBuffer,"this is test message!"); //include
uint8_t sendBuff[] = {"123456789"};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
int i=0;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(500);
i++;
if(i%2)
HAL_UART_Transmit(&huart1, gcTXDBuffer,10,0XFFFF);
else
HAL_UART_Transmit(&huart1, sendBuff,8,0XFFFF);
HAL_Delay(100);
if(recv_end_flag ==1)
{
//add code to deal UART message
gcRXDLength=0;//清除计数
recv_end_flag=0;//清除接收结束标志位
}
HAL_Delay(500);
}
/* USER CODE END 3 */

CNDTR寄存器设置说明
HAL_UART_Receive_DMA(&huart2,gcRXDBuffer,sizeof(gcRXDBuffer)); ====》》
UART_Start_Receive_DMA(huart, pData, Size) ====》》
HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, (uint32_t)huart->pRxBuffPtr, Size) ====》》
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength)====》》
/* Configure DMA Channel data length */
hdma->Instance->CNDTR = DataLength;
通过以上调用,最终在DMA_SetConfig函数中,对CNDTR寄存器进行了设置。
简介
1、使用到的软件 STM32CubeMX 6.1.0 和keil 5.33
2、芯片 STM32L071CBT6
3、实现功能,按帧接收串口数据,数据存入接收buff,帧长存入全局变量
实现原理
当一帧数据传输结束之后,总线IDLE会维持高电平状态,此时就可以触发MCU的IDLE中断。因此利用IDLE中断进行串口不定长数据的接收。省去了用于检测传输是否完成的判断动作。
然而在HAL库中并未集成IDLE中断的处理,所以,我们可以在串口的中断处理中添加对IDLE总线状态的判断,以检测当前帧是否传输完成。
工程实现
1、CubeMX工程配制
(使能两个串口,串口1发送,串口2接收)
串口DMA设置
中断使能 2、代码编辑
main.c全局变量定义
/* USER CODE BEGIN 0 */
uint8_t gcRXDBuffer[50], gcRXDPointer; //接收的缓冲区、接收指针
uint16_t gcRXDLength; //接收的帧长度
uint8_t gcTXDBuffer[50], gcTXDPointer, gcTXDLength; //发送的缓冲区,发送指针,发送的长度
uint8_t recv_end_flag; //接收完成标识
/* USER CODE END 0 */
函数 MX_USART2_UART_Init(void) 中添加
/* USER CODE BEGIN USART2_Init 2 */
__HAL_UART_ENABLE_IT(&huart2,UART_IT_IDLE); //使能idle中断
HAL_UART_Receive_DMA(&huart2,gcRXDBuffer,sizeof(gcRXDBuffer)); //打开DMA串口接收
/* USER CODE END USART2_Init 2 */
串口中断处理函数中modify
extern uint8_t gcRXDBuffer[50], gcRXDPointer ; //接收的缓冲区、接收指针、接收的帧长度
extern uint16_t gcRXDLength;
extern uint8_t recv_end_flag;
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
uint32_t tmp_flag = 0;
uint32_t temp;
tmp_flag =__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE); //获取IDLE标志位
if((tmp_flag != RESET))//idle标志被置位
{
__HAL_UART_CLEAR_IDLEFLAG(&huart2);//清除标志位
HAL_UART_DMAStop(&huart2); //
temp = __HAL_DMA_GET_COUNTER(huart2.hdmarx);// 获取DMA中未传输的数据个数
gcRXDLength = sizeof(gcRXDBuffer) - temp; //总计数减去未传输的数据个数,得到已经接收的数据个数
recv_end_flag = 1; // 接受完成标志位置1
HAL_UART_Receive_DMA(&huart2,gcRXDBuffer,sizeof(gcRXDBuffer));//重新打开DMA接收
}
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
主函数main中
/* USER CODE BEGIN 2 */
strcpy((char*)gcTXDBuffer,"this is test message!"); //include
uint8_t sendBuff[] = {"123456789"};
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
int i=0;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(500);
i++;
if(i%2)
HAL_UART_Transmit(&huart1, gcTXDBuffer,10,0XFFFF);
else
HAL_UART_Transmit(&huart1, sendBuff,8,0XFFFF);
HAL_Delay(100);
if(recv_end_flag ==1)
{
//add code to deal UART message
gcRXDLength=0;//清除计数
recv_end_flag=0;//清除接收结束标志位
}
HAL_Delay(500);
}
/* USER CODE END 3 */

CNDTR寄存器设置说明
HAL_UART_Receive_DMA(&huart2,gcRXDBuffer,sizeof(gcRXDBuffer)); ====》》
UART_Start_Receive_DMA(huart, pData, Size) ====》》
HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, (uint32_t)huart->pRxBuffPtr, Size) ====》》
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength)====》》
/* Configure DMA Channel data length */
hdma->Instance->CNDTR = DataLength;
通过以上调用,最终在DMA_SetConfig函数中,对CNDTR寄存器进行了设置。
举报