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后就接收不了其他数据了,串口中断就没用了
如果数组接收数据的索引没有被清零,并且继续接收新的数据,可能会导致一些问题和后果。
-
数据覆盖:当数组接收数据的索引超过了数组的边界(比如数组长度为8,但索引达到了9),新接收到的数据将会覆盖数组中已有的数据。这会导致数据的丢失和混乱。
-
内存溢出:如果数组接收数据的索引一直增加,而没有被清零或重置,数组可能会溢出到其他内存区域。这可能会破坏其他变量或数据结构的内容,导致程序崩溃或产生不可预测的结果。
-
串口错误:如果索引没有被清零,而且继续向数组中写入数据,串口可能无法正确地处理和解析数据。这可能导致通信错误、数据错误或其他串口相关问题。
为了避免上述问题,建议在使用数组接收数据之前,始终将索引清零或重置为适当的初始值。这可以通过在合适的时机显式地将索引设置为0来实现,以确保接收新数据时能正确地存储和处理数据。