移植标准库串口循迹到HAL库

0.前言

由于使用数字循迹,占用的IO口太多,我这里使用串口接收循迹反馈的数据,只需要四根线就可以了。

1.STM32Cubemx配置

我这里使用的是USART3

 

 配置的异步通信,波特率9600,注意配置不要出错,错了会导致异常

 这里我开启了全局中断,目的是当循迹接收到数据的时候,可以进入中断进行处理数据。

主函数部分

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
// 使能 USART3 接收中断
__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  track_zhixian2();
	   HAL_Delay(10); // 添加延时,单位为毫秒,根据实际情况调整
  }
  /* USER CODE END 3 */
}

这里还配置了usart1用来在电脑查看数据,自己配置的话需要重定向

 HAL_Delay(10); // 添加延时,单位为毫秒,根据实际情况调整

记住要加延时函数,以便持续接收数据,太快的话接收不到数据。

usart.c

/* USER CODE BEGIN 1 */
uint8_t USART_RX_STA[3] = {0};//用来存储数据的数组

uint8_t Num = 0;//1.用于数组存储 2.用来延时的计数器

void Read_Data(uint16_t *Data)//定义了一个名为 Read_Data 的函数,该函数接收一个指向 uint16_t 类型变量的指针作为参数,并返回空值。	

{	
uint8_t y = 0;//循环的值,用来延时的计数器


while(HAL_UART_GetState(&huart3) != HAL_UART_STATE_READY);//这是一个循环语句,它会一直等待,直到串口3 (&huart3) 的状态变为 READY(就绪)为止。HAL_UART_GetState() 是一个函数,用于获取指定串口的当前状态。在这里,通过检查串口3的状态是否为 READY 来确保之前的串口操作已经完成,以免发生冲突或数据丢失。
//是一个用于获取指定串口当前状态的函数。在这里,通过检查串口3的状态是否为 READY,确保之前的串口操作已经完成。这样可以避免冲突或数据丢失。
HAL_UART_Transmit(&huart3, (uint8_t *)"\x57", 1, HAL_MAX_DELAY);//将数据通过串口三发送,以用来激活对应的循迹模块
/* HAL_UART_Transmit() 来通过串口三发送数据。该函数的参数如下:

第一个参数是串口句柄 &huart3,表示使用 USART3。
第二个参数是待发送数据的指针,这里是一个长度为 1 的 uint8_t 类型的数组 "\x57",即发送一个字节的数据 0x57。
第三个参数是待发送数据的长度,这里是 1。
第四个参数是发送超时时间,使用 HAL_MAX_DELAY 表示无限等待,直到发送完成。*/


	while(Num != 1)//当 Num 不等于 1 时执行循环体内的代码。
	{
		
		HAL_Delay(1);
		if(y>5)
		{
			y=0;
			break;
		}
		y++;
	}
	*Data = USART_RX_STA[0];//接收到的数据存储到指针所指向的位置



}
void track_zhixian2()
{
uint16_t Temp[2] = {0};
//Temp是一个指向uint16_t类型的数组。通过调用函数Read_Data(Temp),接收到的数据将存储在Temp数组中。
Read_Data(Temp);
switch(Temp[0])//对数组的第一个元素进行判断
{

case 0xFE:		printf("1");	break;
case 0xFC:		printf("2");	break;
case 0xFD:		printf("3");	break;
case 0xF9:		printf("4"); 	break;
case 0xFB:		printf("5"); 	break;
case 0xF3:		printf("6"); 	break;
case 0xF7:		printf("7"); 	break;
case 0xE7:		printf("8");    break;
case 0xEF:		printf("9"); 	break;
case 0xCF:		printf("10"); 	break;
case 0xDF:		printf("11");  	break;
case 0x9F:		printf("12");   break;
case 0xBF:		printf("13");	break;
case 0x3F:		printf("14");	break;
case 0x7F:		printf("15");	break;
default:		printf("0");	break;
}
}

并且在usart.h中定义这两个函数

/* USER CODE BEGIN Prototypes */
void track_zhixian2();
void Read_Data(uint16_t *Data);
/* USER CODE END Prototypes */

stm32f1xx_it.c

/**
  * @brief This function handles USART3 global interrupt.
  */
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */

  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
/*********************************************************************
 *  函数名称:void USART3_IRQHandler
 *  函数功能:串口3中断服务函数
 *  形    参:无
 *  输    出:无
 *  备    注:
	// 使能 USART3 接收中断
__HAL_UART_ENABLE_IT(&huart3, UART_IT_RXNE);
使用中断函数必须先对他使能
 ********************************************************************/
if (__HAL_UART_GET_IT_SOURCE(&huart3, UART_IT_RXNE) != RESET)//判断是否使能中断
{
if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != RESET)//判断是否有数据可读
{
USART_RX_STA[Num] = (uint8_t)(huart3.Instance->DR & 0x00FF);//将数据从DR中取出,并且与运算取出低八位,高八位用于校验
//再将数据存储到STA函数里面
Num++;
if (Num >= 3) {
  Num = 0;
}
__HAL_UART_CLEAR_FLAG(&huart3, UART_FLAG_RXNE);//清除标志位,用来重新接收数据
}
}

  /* USER CODE END USART3_IRQn 1 */
}

这里的Num需要加上进行溢出判断,笔者在移植代码的时候遇见了只有上电时,代码才有用,过一会串口就不发数据了,串口助手的R显示64,每次上电都64的加,最后发现是对Num没有进行溢出判断,Num是一个数组的索引,加到3后就接收不了其他数据了,串口中断就没用了

如果数组接收数据的索引没有被清零,并且继续接收新的数据,可能会导致一些问题和后果。

  1. 数据覆盖:当数组接收数据的索引超过了数组的边界(比如数组长度为8,但索引达到了9),新接收到的数据将会覆盖数组中已有的数据。这会导致数据的丢失和混乱。

  2. 内存溢出:如果数组接收数据的索引一直增加,而没有被清零或重置,数组可能会溢出到其他内存区域。这可能会破坏其他变量或数据结构的内容,导致程序崩溃或产生不可预测的结果。

  3. 串口错误:如果索引没有被清零,而且继续向数组中写入数据,串口可能无法正确地处理和解析数据。这可能导致通信错误、数据错误或其他串口相关问题。

为了避免上述问题,建议在使用数组接收数据之前,始终将索引清零或重置为适当的初始值。这可以通过在合适的时机显式地将索引设置为0来实现,以确保接收新数据时能正确地存储和处理数据。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值