当前位置:   article > 正文

STM32入门笔记(02):USART串口通信注意事项笔记(SPL库函数版)

STM32入门笔记(02):USART串口通信注意事项笔记(SPL库函数版)

在这里插入图片描述

这是通过串口通信发送过来的数据,里面包括了故障码,电压,电流,频率等信息,请你用STM32f103系列单片机的串口1读取该数据并解析出电压和电流是多少?

要用STM32F103系列单片机的串口1读取并解析发电机上的逆变器发送的数据,你需要编写代码来完成以下步骤:

  1. 初始化串口:配置STM32的USART1以正确的波特率和参数读取数据。
  2. 读取数据:从串口缓冲区读取完整的数据包。
  3. 解析数据:从数据包中提取电压和电流信息。

假设数据格式如下(每个字节的数据如图所示):

  • 起始位:字节0
  • 数据长度:字节1
  • 故障码、电压、电流、频率等信息从字节2开始

根据图片中的数据:

  • 电压信息在字节2和字节3
  • 电流信息在字节4和字节5

以下是一个示例代码,用于在STM32F103系列单片机上实现上述步骤:

#include "stm32f10x.h"
#include "usart.h"  // 包含USART初始化配置文件

#define DATA_LENGTH 31  // 假设总共要读取31个字节的数据

uint8_t received_data[DATA_LENGTH];  // 接收数据的缓冲区

void USART1_IRQHandler(void) {
    static uint8_t i = 0;
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        received_data[i++] = USART_ReceiveData(USART1);
        if (i >= DATA_LENGTH) {
            i = 0;  // 重置接收计数器
        }
    }
}

void init_USART1(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置USART1 Tx (PA.09) 作为推挽复用功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART1 Rx (PA.10) 作为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // USART参数配置
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能USART接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    // 配置USART1中断
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能USART
    USART_Cmd(USART1, ENABLE);
}

int main(void) {
    uint16_t voltage = 0;
    uint16_t current = 0;

    // 初始化USART1,波特率设置为9600(根据实际情况调整)
    init_USART1(9600);

    while (1) {
        // 检查数据包是否完整接收
        if (received_data[1] == 28) {  // 确保接收的数据长度正确
            // 解析电压和电流数据
            voltage = (received_data[2] << 8) | received_data[3];
            current = (received_data[4] << 8) | received_data[5];
            
            // 在这里可以对解析出的电压和电流进行处理,例如显示或记录
            // 注意:电压和电流的单位以及是否需要转换取决于发送方的数据格式定义
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

注意事项:

  1. 波特率设置:根据实际设备的波特率设置USART_InitStructure.USART_BaudRate
  2. 数据长度检查:确保接收的数据长度正确。
  3. 电压和电流解析:根据具体协议,确定数据的字节顺序和单位。

进一步优化:

  1. 数据验证:增加数据包头和校验码的验证,以确保数据的准确性。
  2. 错误处理:处理接收过程中可能出现的错误,如丢包或数据损坏。

为了增加数据包头和校验码的验证,以确保数据的准确性,你可以对接收到的数据包进行更严格的检查和处理。以下是增加数据包头和校验码验证的详细步骤和示例代码。

数据包结构假设

假设你的数据包结构如下:

  • 起始位:字节0(例如,固定为0xAA)
  • 数据长度:字节1(例如,固定为28)
  • 数据内容:字节2到字节29
  • 校验码:字节30(例如,使用简单的累加和校验)

校验码计算方法

假设校验码是所有数据字节(包括起始位和数据长度)的累加和的低8位。

示例代码

以下代码展示了如何在STM32F103单片机上实现数据包头和校验码的验证:

#include "stm32f10x.h"
#include "usart.h"

#define DATA_LENGTH 31  // 数据包总长度

uint8_t received_data[DATA_LENGTH];  // 接收数据的缓冲区

// 计算校验码
uint8_t calculate_checksum(uint8_t *data, uint8_t length) {
    uint8_t checksum = 0;
    for (uint8_t i = 0; i < length; i++) {
        checksum += data[i];
    }
    return checksum;
}

// USART1中断服务程序
void USART1_IRQHandler(void) {
    static uint8_t i = 0;
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        received_data[i++] = USART_ReceiveData(USART1);
        if (i >= DATA_LENGTH) {
            i = 0;  // 重置接收计数器
        }
    }
}

void init_USART1(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置USART1 Tx (PA.09) 作为推挽复用功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART1 Rx (PA.10) 作为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // USART参数配置
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能USART接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    // 配置USART1中断
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能USART
    USART_Cmd(USART1, ENABLE);
}

int main(void) {
    uint16_t voltage = 0;
    uint16_t current = 0;

    // 初始化USART1,波特率设置为9600(根据实际情况调整)
    init_USART1(9600);

    while (1) {
        // 检查数据包是否完整接收
        if (received_data[1] == 28) {  // 确保接收的数据长度正确
            // 验证数据包头和校验码
            if (received_data[0] == 0xAA) {  // 验证起始位
                uint8_t checksum = calculate_checksum(received_data, DATA_LENGTH - 1);
                if (checksum == received_data[30]) {  // 验证校验码
                    // 解析电压和电流数据
                    voltage = (received_data[2] << 8) | received_data[3];
                    current = (received_data[4] << 8) | received_data[5];
                    
                    // 在这里可以对解析出的电压和电流进行处理,例如显示或记录
                    // 注意:电压和电流的单位以及是否需要转换取决于发送方的数据格式定义
                }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

代码解释

  1. 校验码计算

    • 函数calculate_checksum用于计算接收到的数据包的校验码。
  2. USART1中断服务程序

    • USART1_IRQHandler中,当接收到新字节时,将其存入接收缓冲区received_data中。
  3. 主循环

    • 检查接收的数据长度是否正确。
    • 验证起始位(假设为0xAA)。
    • 计算并验证校验码。
    • 解析并处理电压和电流数据。

注意事项

  • 波特率设置:根据实际设备的波特率调整USART_InitStructure.USART_BaudRate
  • 校验和验证:根据实际应用选择合适的校验算法,如CRC校验等。
  • 数据解析:根据实际数据格式调整解析代码。

为了处理接收过程中可能出现的错误,如丢包或数据损坏,你可以增加一些错误处理机制,包括超时处理、错误计数、数据重发请求等。以下是具体的步骤和代码示例。

增加错误处理机制

  1. 超时处理:设置接收数据的超时机制,如果在预定时间内没有接收到完整的数据包,则认为接收超时。
  2. 错误计数:记录接收错误的次数,当错误次数超过一定阈值时,采取相应的措施。
  3. 数据包头和校验码验证:在接收数据时,严格验证数据包头和校验码,确保数据完整性。
  4. 丢包重发机制:如果检测到数据包错误,可以请求发送方重新发送数据。

示例代码

以下是一个包含错误处理机制的示例代码:

#include "stm32f10x.h"
#include "usart.h"
#include <stdbool.h>
#include <string.h>

#define DATA_LENGTH 31  // 数据包总长度
#define TIMEOUT_THRESHOLD 1000  // 超时时间阈值
#define ERROR_THRESHOLD 5  // 最大允许错误次数

uint8_t received_data[DATA_LENGTH];  // 接收数据的缓冲区
uint8_t data_index = 0;  // 当前接收数据的索引
uint32_t timeout_counter = 0;  // 超时计数器
uint8_t error_count = 0;  // 错误计数器

// 计算校验码
uint8_t calculate_checksum(uint8_t *data, uint8_t length) {
    uint8_t checksum = 0;
    for (uint8_t i = 0; i < length; i++) {
        checksum += data[i];
    }
    return checksum;
}

// USART1中断服务程序
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t received_byte = USART_ReceiveData(USART1);
        received_data[data_index++] = received_byte;
        timeout_counter = 0;  // 重置超时计数器

        if (data_index >= DATA_LENGTH) {
            data_index = 0;  // 重置接收计数器
        }
    }
}

void init_USART1(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置USART1 Tx (PA.09) 作为推挽复用功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART1 Rx (PA.10) 作为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // USART参数配置
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能USART接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    // 配置USART1中断
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能USART
    USART_Cmd(USART1, ENABLE);
}

int main(void) {
    uint16_t voltage = 0;
    uint16_t current = 0;

    // 初始化USART1,波特率设置为9600(根据实际情况调整)
    init_USART1(9600);

    while (1) {
        // 超时处理
        if (timeout_counter++ > TIMEOUT_THRESHOLD) {
            timeout_counter = 0;
            data_index = 0;  // 重置接收索引
            error_count++;
            if (error_count >= ERROR_THRESHOLD) {
                // 错误处理逻辑,例如重启或告警
                // 这里简单地重置错误计数器
                error_count = 0;
            }
        }

        // 检查数据包是否完整接收
        if (data_index == DATA_LENGTH) {
            // 验证数据包头和校验码
            if (received_data[0] == 0xAA && received_data[1] == 28) {  // 验证起始位和长度
                uint8_t checksum = calculate_checksum(received_data, DATA_LENGTH - 1);
                if (checksum == received_data[30]) {  // 验证校验码
                    // 解析电压和电流数据
                    voltage = (received_data[2] << 8) | received_data[3];
                    current = (received_data[4] << 8) | received_data[5];
                    
                    // 在这里可以对解析出的电压和电流进行处理,例如显示或记录
                    // 注意:电压和电流的单位以及是否需要转换取决于发送方的数据格式定义
                    
                    // 数据处理成功,重置错误计数器
                    error_count = 0;
                } else {
                    // 校验码错误
                    error_count++;
                }
            } else {
                // 数据包头错误
                error_count++;
            }
            // 重置接收索引
            data_index = 0;
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126

代码解释

  1. 超时处理

    • 通过timeout_counter计数器记录接收数据的超时时间。
    • 如果在预定时间内(TIMEOUT_THRESHOLD)没有接收到完整的数据包,则认为接收超时,重置接收索引并增加错误计数器。
  2. 错误计数

    • 通过error_count记录接收错误的次数,当错误次数超过ERROR_THRESHOLD时,可以采取相应的措施,比如重启或告警。
    • 在本示例中,错误计数器简单地重置。
  3. 数据包头和校验码验证

    • 检查接收到的数据包长度是否正确。
    • 验证起始位和数据长度。
    • 计算校验码并与接收到的校验码比较。
    • 如果数据包头或校验码错误,增加错误计数器。
  4. 丢包重发机制

    • 这个示例中没有具体实现丢包重发机制,但可以通过串口发送请求重新发送数据包的命令来实现。
    • 如果检测到数据包错误,可以发送请求给发电机上的逆变器,要求重新发送数据。

注意事项

  • 实际应用中,错误处理策略需要根据具体需求进行调整,例如记录错误日志、发送告警信息或重新初始化串口等。
  • 校验码计算方法可以根据实际应用进行调整,如使用CRC校验等。
  • 丢包重发机制可以通过串口发送指令来实现,需要和逆变器的通信协议相匹配。

为了提高通信的可靠性可以增加握手协议,确保双方在传输数据之前已经准备好,并且可以用于初始化一些必要的参数。

以下是一个简单的握手协议示例:

  1. 发送握手请求:STM32单片机发送握手请求到发电机上的逆变器。
  2. 等待握手响应:STM32单片机等待逆变器的握手响应。
  3. 验证握手响应:STM32单片机验证握手响应是否正确。如果正确,则继续进行数据传输;否则,重新发送握手请求或进行错误处理。

示例代码

以下是一个示例代码,展示了如何在STM32F103单片机上实现握手协议:

#include "stm32f10x.h"
#include "usart.h"
#include <stdbool.h>
#include <string.h>

#define DATA_LENGTH 31  // 数据包总长度
#define TIMEOUT_THRESHOLD 1000  // 超时时间阈值
#define ERROR_THRESHOLD 5  // 最大允许错误次数
#define HANDSHAKE_REQUEST 0x55  // 握手请求命令
#define HANDSHAKE_RESPONSE 0xAA  // 握手响应命令

uint8_t received_data[DATA_LENGTH];  // 接收数据的缓冲区
uint8_t data_index = 0;  // 当前接收数据的索引
uint32_t timeout_counter = 0;  // 超时计数器
uint8_t error_count = 0;  // 错误计数器

// 计算校验码
uint8_t calculate_checksum(uint8_t *data, uint8_t length) {
    uint8_t checksum = 0;
    for (uint8_t i = 0; i < length; i++) {
        checksum += data[i];
    }
    return checksum;
}

// USART1中断服务程序
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        uint8_t received_byte = USART_ReceiveData(USART1);
        received_data[data_index++] = received_byte;
        timeout_counter = 0;  // 重置超时计数器

        if (data_index >= DATA_LENGTH) {
            data_index = 0;  // 重置接收计数器
        }
    }
}

void init_USART1(uint32_t baudrate) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 开启时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    // 配置USART1 Tx (PA.09) 作为推挽复用功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置USART1 Rx (PA.10) 作为浮空输入
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // USART参数配置
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 使能USART接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    // 配置USART1中断
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 使能USART
    USART_Cmd(USART1, ENABLE);
}

bool handshake(void) {
    uint32_t handshake_timeout = 0;

    // 发送握手请求
    USART_SendData(USART1, HANDSHAKE_REQUEST);

    // 等待握手响应
    while (handshake_timeout++ < TIMEOUT_THRESHOLD) {
        if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
            uint8_t response = USART_ReceiveData(USART1);
            if (response == HANDSHAKE_RESPONSE) {
                return true;  // 握手成功
            }
        }
    }
    return false;  // 握手失败
}

int main(void) {
    uint16_t voltage = 0;
    uint16_t current = 0;

    // 初始化USART1,波特率设置为9600(根据实际情况调整)
    init_USART1(9600);

    // 进行握手
    while (!handshake()) {
        // 握手失败,重新尝试
    }

    while (1) {
        // 超时处理
        if (timeout_counter++ > TIMEOUT_THRESHOLD) {
            timeout_counter = 0;
            data_index = 0;  // 重置接收索引
            error_count++;
            if (error_count >= ERROR_THRESHOLD) {
                // 错误处理逻辑,例如重启或告警
                // 这里简单地重置错误计数器
                error_count = 0;
            }
        }

        // 检查数据包是否完整接收
        if (data_index == DATA_LENGTH) {
            // 验证数据包头和校验码
            if (received_data[0] == 0xAA
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/623412
推荐阅读
相关标签
  

闽ICP备14008679号