cubemx hal 串口中断回调函数

文章讲述了如何在Cubemx中正确配置端口,使用HAL_UART_Receive_IT进行串口中断接收,并在回调函数中处理接收到的数据,如解析速度和角度信息。涉及到的关键词包括数据类型转换和超时处理。
摘要由CSDN通过智能技术生成

先将cubemx配置好端口
千万不要马虎,特别是对自己不熟悉的板子 一定要检查tx rx接口是否和板子外接的串口对应上了
在使用H723VGT6时
在这里插入图片描述
开启串口 并开启中断后
cube上默认的是PB14 PB15 端口
而与板子相连的是PA9 PA19 口
***********************************************************************************************接下来就是编写函数了

main.c

uint8_t		Res,buf,flag=0;
HAL_UART_Receive_IT(&huart1, &Res, 1); 用于开启中断


//重写回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart1)
    {
				buf=Res;
				HAL_UART_Transmit(&huart1,(uint8_t*)&buf,1, 1000);
		   
				if(buf == '1')
				{
					flag = 1;
				}
				else if(buf == '2')
				{
					flag = 2;
				}
        // 等待下一次接收中断
        HAL_UART_Receive_IT(&huart1, &Res, 1);
    }
}

问题:HAL_UART_Transmit(&huart1,&Res,1, 1000);
传参错误
指针变成了野指针
程序死机
把一级指针当作二级指针使用

需要在回调里面用buf就行转存
Res会被冲掉

接下来在由上位机传过来的参数是{300|500}
需要给中间两个数字取出来
传到另外的函数中

还有需要注意 这两个数字的大小是在 -1000~1000
uint8_t 是0~255
int8_t 是 -128 到 127
uint16_t 是 C/C++ 中的无符号 16 位整数类型,范围是从 0 到 65535( 2 16 − 1 2^{16} - 1 2161)。这意味着它可以表示的整数范围是从 0 到 65535,包括这两个端点值。

int16_t 是 C/C++ 中的有符号 16 位整数类型,范围是从 -32768 到 32767。

control.h

#ifndef __CINTROL_H
#define __CINTROL_H

#include "main.h"
#include "usart.h"
#include "stdlib.h"



#endif



control.c

#include "control.h"


uint8_t buf[256];
uint8_t idx=0,start=0,end=0;


extern uint8_t		Res; 
extern int16_t		speed,angula;  
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart1)
    {
			if(Res=='{')
				start=1;
			else if(Res=='}')
			{
				start=0;
				end=1;
			}
			if(start==1)
			{
				buf[idx++]=Res;
			}
			if(end==1)
			{
					char *p;
					p=(char *)&buf[0];
					p=p+1;
					angula = atoi((char*)p);
					p=strchr((char*)buf,'|');
					speed=atoi(p+1);
					idx=0;
					end=0;	
					printf("angula:%d\n",angula);
					printf("speed:%d\n",speed);
					memset(buf,0,256);
			
			}
		

        // 等待下一次接收中断
        HAL_UART_Receive_IT(&huart1, &Res, 1);
    }
}




当串口未接收到数据时候 需要将flag置为0 但是串口在未接收到消息时候不进入 串口中断回调函数 不能直接在串口回调函数里面判断

#include "control.h"

char str[10];
uint8_t buf[256];
uint8_t idx=0,start=0,end=0;
extern int a;

extern uint32_t last_receive_time,no_data_timeout;




extern uint8_t		Res,flag; 
extern int16_t		speed,angula;  

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{ 
	

    if(huart == &huart1)
    {

			if(Res=='{')
			{
				start=1;
				a=3;
			}
				
			else if(Res=='}')
			{
				start=0;
				end=1;    
			}
			if(start==1)
			{
				buf[idx++]=Res;
			}
			if(end==1)
			{
					char *p;
					p=(char *)&buf[0];
					p=p+1;
					flag = atoi((char*)p);
					p=strchr((char*)buf,'|');
					speed=atoi(p+1);
					idx=0;
					end=0;	
//					printf("flag:%d\n",flag);
//					printf("speed:%d\n",speed);
					memset(buf,0,256);
				 
					last_receive_time = HAL_GetTick(); // 更新最后接收时间
			}
		

        // 等待下一次接收中断
        HAL_UART_Receive_IT(&huart1, &Res, 1);
    }
}



main.c

uint32_t last_receive_time = 0;
uint32_t no_data_timeout = 2000; // 设置没有接收到数据的超时时间,单位为毫秒
  while (1)
  {
		if ((HAL_GetTick() - last_receive_time) > no_data_timeout)
        {
            flag = 0; // 如果超时没有接收到数据,将 flag 置为 0
        }

数据处理这块给我干蒙了
还有个方法
给定时器定为100ms 然后 100ms 到了 检测标志量是否为1 标志量置为0
但是只要串口中断在接收 标志量就会被置为1 就可以避免 标志量一直为1 然后只要标志量为0 就停

将发送给串口3的数据存储在数组中

#define MAX_RX_BUFFER_SIZE 100  // 定义最大接收缓冲区大小,根据实际需要调整

uint8_t rxBuffer[MAX_RX_BUFFER_SIZE];  // 定义接收数据的数组
uint32_t rxBufferIdx = 0;  // 定义接收数据的索引


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  if (huart == &huart3)  // 假设是串口3的接收中断
  {
    rxBuffer[rxBufferIdx++] = huart->Instance->DR;  // 将接收到的数据存入数组,并更新索引

    if (rxBufferIdx >= MAX_RX_BUFFER_SIZE)
    {
      rxBufferIdx = 0;  // 如果超过了数组大小,可以选择重置索引或者其他处理方式
    }
    HAL_UART_Transmit(&huart3, &rxBuffer[rxBufferIdx - 1], 1, 1000);  // 发送刚接收到的单个字节
    HAL_UART_Receive_IT(&huart3, &rxBuffer[rxBufferIdx], 1);  // 重新启动接收
  }
}


问题分析和解决方案:
发送数据问题:

在 HAL_UART_Transmit(&huart3, (uint8_t*)&rxBuffer, 1, 1000); 这行代码中,你发送了 rxBuffer 数组的内容,而不是实际接收到的数据。
rxBuffer 是一个数组,你发送的是数组的地址,而不是单个接收到的字节。这会导致上位机接收到的数据可能不是你预期的内容。
解决方案:

如果你想要发送刚接收到的单个字节,应该发送 rxBuffer[rxBufferIdx - 1],因为 rxBufferIdx 在存储完数据后已经自增了。
修改为 HAL_UART_Transmit(&huart3, &rxBuffer[rxBufferIdx - 1], 1, 1000); 这样可以发送刚接收到的单个字节。

我发送数据的格式改为{X20,Y-30}

#include "uart_control.h"


uint8_t buf[256];
uint8_t idx=0,start=0,end=0;


extern uint8_t		Res; 
extern int16_t		x_speed,y_speed;  
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart == &huart3)
    {
			if(Res=='{')
				start=1;
			else if(Res=='}')
			{
				start=0;
				end=1;
			}
			if(start==1)
			{
				buf[idx++]=Res;
			}
			else if (end == 1)
        {
            buf[idx] = '\0';  // Null-terminate the string
            char *p = strstr((char*)buf, "X");
            if (p != NULL)
            {
                p += 1;  // Skip 'X'
                char *endptr;
                x_speed = (int16_t)strtol(p, &endptr, 10);
                
                p = strstr((char*)buf, "Y");
                if (p != NULL)
                {
                    p += 1;  // Skip 'Y'
                    y_speed = (int16_t)strtol(p, &endptr, 10);
                }
            }

            idx = 0;
            end = 0;
            memset(buf, 0, sizeof(buf));
        }
		
        // 等待下一次接收中断
        HAL_UART_Receive_IT(&huart3, &Res, 1);
    }
}



#ifndef UART__CONTROL_H
#define UART__CONTROL_H

#include "main.h"
#include "usart.h"
#include "stdlib.h"
#include "string.h"


#endif


  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HAL库中,中断回调函数是用来处理硬件中断事件的函数。当一个中断事件发生时,系统会调用预先注册的中断回调函数来处理该事件。 通常,你需要完成以下步骤来使用中断回调函数: 1. 注册中断回调函数:通过调用相应的HAL库函数,将你编写的中断回调函数与特定的中断线路或外设相关联。 2. 编写中断回调函数:根据你的需求和硬件的特性,编写中断回调函数的代码。这个函数将在中断事件发生时被调用。 3. 中断处理:当中断事件发生时,系统会自动调用已注册的中断回调函数。在中断回调函数中,你可以执行一些特定的操作,如读取/写入数据、更新状态等。 以下是一个简单的示例,演示如何使用HAL库来注册和处理中断回调函数: ```c #include "stm32f4xx_hal.h" // 中断回调函数 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_0) { // 处理GPIO_Pin为GPIO_PIN_0的中断事件 // 在这里执行你的操作 } } int main(void) { // 初始化HALHAL_Init(); // 配置GPIO引脚和中断触发条件 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // 上升沿触发 GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 注册中断回调函数 HAL_GPIO_RegisterCallback(GPIO_PIN_0, HAL_GPIO_EXTI_Callback); // 使能中断 HAL_NVIC_EnableIRQ(EXTI0_IRQn); while(1) { // 主循环代码 } } ``` 在上面的例子中,我们使用了STM32F4系列的HAL库来配置GPIO引脚和中断触发条件,并注册了名为"HAL_GPIO_EXTI_Callback"的中断回调函数。当GPIO_PIN_0引脚上升沿触发中断时,该函数将被调用。 请注意,具体的HAL库函数和回调函数命名可能会根据你使用的硬件平台和库版本而有所不同。因此,在实际开发中,你需要参考相关的文档和示例代码来正确使用中断回调函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值