举报
【STM32G431】STM32使用STM32CubeMX配置串口接收中断并做简单的CRC校验
2026-01-13 00:31:45
93次阅读
0个评论
最后修改时间:2026-01-13 00:42:22

1.使用STM32CubeMX新建一个工程


2.设置系统主频,我这直接使用内部晶振,输入需要的主频回车会自动配置分频





3.配置串口


4.配置串口中断


5.导出代码

6.串口重定义printf

FILE *_stdout;       
 
void _sys_exit(int x) 
{ 
        x = x; 
} 

int fputc(int ch, FILE *f)
{         
        /* 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, 0x10);
        return ch;
}

7.简单写个接收和crc校验函数

// CRC 计算函数
uint8_t gh_crc8( uint8_t * p_buffer, uint16_t buf_size )
{
    uint8_t crc = 0;
    if(buf_size <= 0)
    {
        return crc;
    }
    while( buf_size-- )
    {
        for ( uint8_t i = 0x80; i != 0; i /= 2 )
        {
            if ( (crc & 0x80) != 0)
            {
                crc *= 2;
                crc ^= 0x07; // 多项式:X8 + X2 + X + 1
            }
            else
            {
                crc *= 2;
            }
            if ( (*p_buffer & i) != 0 ){
                crc ^= 0x07;
            }
        }
        p_buffer++;
    }
    return crc;
}


void handle_command(uint8_t command, uint8_t *data, uint8_t data_length) {
    // 处理具体命令和数据
    printf("Command: %d, Data Length: %d\r\n", command, data_length);
    // 在这里根据需要处理具体的命令和数据
}

void handle_crc_error(uint8_t crc) {
    // 处理CRC校验失败的情况
    printf("0x%02X,CRC Error: Data corrupted!\r\n",crc);
}

void process_received_data() {
    if (rx_index < 2) return; // 至少需要3个字节(命令 + 长度 + CRC)
		if (rx_index < rx_buffer[1]) return;
	
    uint8_t command = rx_buffer[0];
    uint8_t total_length = rx_buffer[1];

    // 检查是否接收到完整的数据
    if (rx_index >= total_length) { // 3个字节:命令、长度和CRC
        uint8_t data_length = total_length-1; // 数据长度
        uint8_t *data = &rx_buffer[2]; // 数据起始地址
        uint8_t crc_received = rx_buffer[data_length]; // 接收到的CRC

        // 计算CRC
        uint8_t crc_calculated = gh_crc8(rx_buffer, data_length); // 计算CRC(命令 + 长度 + 数据)

        // 校验CRC
        if (crc_calculated == crc_received) {
            // CRC 校验成功
            handle_command(command, data, data_length);
        } else {
            // CRC 校验失败,处理错误
            handle_crc_error(crc_calculated);
        }

        // 不论成功与否,重置接收索引,为下一个数据包准备
        rx_index = 0;
    }
}


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {  
    // 每次接收到一个字节
   

    if (rx_index < BUFFER_SIZE) {
        rx_buffer[rx_index++] = byte;

        // 根据协议处理接收到的数据
        process_received_data();
    } else {
        // 清理接收缓冲区以防止溢出
        rx_index = 0; // Reset or handle overflow
    }
		
		 HAL_UART_Receive_IT(&huart1, &byte, 1); // 继续接收下一个字节
}
8.实验现象,简单拼了一个协议:(命令(1B) + 总长度(1B) + 数据(变长) + CRC(1B))





收藏 0 0

登录 后评论。没有帐号? 注册 一个。

LTB

  • 0 回答
  • 0 粉丝
  • 0 关注