STM32CubeIDE 利用自带HAL库 串口收发

 

一、MX的配置

1.选择需要用的串口,模式Asynchronous,修改波特率为115200;其他值默认即可。

STM32CubeIDE 利用自带HAL库 串口收发_第1张图片

2.配置中断:2位抢占优先级,2位优先级;全局中断使能勾上。

STM32CubeIDE 利用自带HAL库 串口收发_第2张图片

另:最好设置一下不同外设单独C文件

STM32CubeIDE 利用自带HAL库 串口收发_第3张图片

 

二、案例1(以 0x0d 0x0a结尾的 开源原子的做法)

2.1 

uint8_t aRxBuffer[1];

uint8_t temp=0;
uint8_t USART_RX_BUF[USART_REC_LEN];   //接收缓冲
//接收状态位
//bit15接收完成标志
//bit14接收了0x0d
//bit13~0接收到的有效字节数目
uint16_t USART_RX_STA=0;//接收状态

另附实现printf的方法

#ifdef __GNUC__
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);

  return ch;
}

2.2

#define USART_REC_LEN  			200  		//定义最大接收字节数 200

extern uint8_t temp;

extern uint8_t  USART_RX_BUF[USART_REC_LEN]; 	//接收缓冲
extern uint16_t USART_RX_STA;         			//接收状态

extern uint8_t aRxBuffer[1];			//HAL库USART接收Buffer

2.3

HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);

while(1)
{
	if(USART_RX_STA&0x8000)
	{
	    len=USART_RX_STA&0x3fff;//计算长度
	    printf("\r\nsend:\r\n");
	    HAL_UART_Transmit(&huart1,(uint8_t*)USART_RX_BUF,len,1000);	//发送
	    while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);		//等待发送完成
	    USART_RX_STA=0;
	}
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{

  if(UartHandle == &huart1)//如果是串口1
  {
      //原子的协议 0d 0a结尾
    if((USART_RX_STA&0x8000)==0)//接收未完成
	{
		if(USART_RX_STA&0x4000)//接收到了0x0d
		{
			if(aRxBuffer[0]!=0x0a)USART_RX_STA=0;//接收错误,重新开始
			else USART_RX_STA|=0x8000;	//接收完成了
		}
		else //还没收到0X0D
		{
			if(aRxBuffer[0]==0x0d)USART_RX_STA|=0x4000;
			else
			{
				USART_RX_BUF[USART_RX_STA&0X3FFF]=aRxBuffer[0] ;
				USART_RX_STA++;
				if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收
			}
		}
	}
      

    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
  }
}

三、案例2 上位机发啥就回啥

//代码1中修改回调函数即可,while(1)内为空
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
    HAL_UART_Transmit(&huart1, (uint8_t *)aRxBuffer, 1,0xFFFF);
    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
}

四、案例3 消息头(0xfc 0xfe)+ 长度 + 消息内容

修改案例1的,其他文件可以一致

//变量定义
uint8_t flag; //接收结束标志
static uint8_t state; //消息接收状态
static uint8_t recv_cnt; //从消息头开始,消息已经接收的长度
static uint16_t header; //消息头
static uint8_t pkt_len; //消息长度

//开启接收中断
HAL_UART_Receive_IT(&huart1,(uint8_t *)aRxBuffer, 1);//HAL库中接收中断函数,内部开启了中断,并将数据存储在aRxBuffer,现在在aRxBuffer就缓存一个Byte,该函数只有接收完才会调用回调函数

while(1)
{
  if(flag==1)
	{
	    HAL_Delay(5);//不可删除  DO NOT DELET!!! 该延迟避免消息后的冗余数据导致中断响应错误
	    printf("\r\nsend:\r\n");
	    HAL_UART_Transmit(&huart1,(uint8_t*)USART_RX_BUF,pkt_len,1000);	//发送接收的数据
	    while(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TC)!=SET);		//等待发送完成
	    flag=0;
	}
}

//回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
  if(UartHandle == &huart1)//如果是串口1
  {
    if(flag!=1)//未按照长度接收结束
	{
	if(state==0)
	  {//未收到包头
	    if(aRxBuffer[0] ==0xfc)
	      header = 0x00fc;
	    else if(aRxBuffer[0] ==0xfe)
	      {
		    header=(header<<8)|aRxBuffer[0];
		    if(header==0xfcfe)
    	       {//收到包头
		          state=1;
		          USART_RX_BUF[0]=0xfc;
		          USART_RX_BUF[1]=0xfe;
		          recv_cnt=2;
		        }
	      }
	    else
	      header=0;
	  }
	else if(state==1)
	  {//收到包头未收到长�?
	    pkt_len=aRxBuffer[0];
	    USART_RX_BUF[recv_cnt++]=pkt_len;
	    state=2;
	  }
	else if(state==2)
	  {//收到包头且收到长�?
	    USART_RX_BUF[recv_cnt++]=aRxBuffer[0];
	    if(recv_cnt==pkt_len)
	      {//接收完毕,后面的数据都会丢弃直到收到新的头
		    flag=1;
		    state=0;
		    recv_cnt=0;
	      }
	  }

    }
    HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 1);
  }
}

 

 

你可能感兴趣的:(STM32,嵌入式)