首页 > 解决方案 > 串行通信期间读取的未知字节

问题描述

我正在编写代码以使用串行端口和 MCU 的 UART 与 stm32 设备(stm32l412kb)进行通信。代码的目的是 MCU 将向主机发送指令/请求字节。主机将根据该指令进行操作。例如,发送的第一条指令是 ACK(确认)字节 = 0x79。当计算机收到此信息时,会发回一个 ACK​​。

这第一个字节完美地工作。但是,要发送的第二个字节是 VERSION_REQUEST 字节 = 0x01。当 stm32 代码循环等待响应时,stm32 继续发送这个字节并且只发送这个字节。问题出在主机端,无论延迟如何,计算机都在读取字节模式:1B、08、D4、9F、79(作为= ACK)。计算机会循环读取这些,没有出现 01。

由于stm32和主机端都有代码,我不确定问题出在哪里。主机端的代码(宏和 main())是:

    #include <windows.h>
    #include <cstdio>
    #include <stdint.h>

    HANDLE hSerial;

    /*Macros*/
    #define ACK 0x79    //Acknowledge byte used in UART communication
    #define NACK 0x1F   //Not acknowledged byte used in UART communication

    //Manually change the version number of the latest update
    #define VERSION_NUMBER 0x0001

    /*Instruction Macros*/
    #define VERSION_REQUEST 0x01
    #define DOWNLOAD_REQUEST 0x02

    /*Function Prototypes*/
    char receiveInstruction();
    int sendACK();
    int sendVersionNumber();

    void initialiseSerialPort();
    void readData(char Rx_Buffer[], int numberOfBytes);
    void writeData(char Tx_Buffer[], int numberOfBytes);


    int main(){

        /*Error Handling*/
        char lastError[1024];

        initialiseSerialPort();

        while (1) {
            uint8_t instruction = 0;
            printf("Searching for incoming instruction...\n");

        //This odd while requirements were to try and enclose the problem
        //Wait until familiar instruction is read
            while ((instruction != ACK) && (instruction != VERSION_REQUEST)) {
                instruction = receiveInstruction();
                printf("Received Instruction: %X \n", instruction);
            }
            printf("Received Instruction: %X \n", instruction);
            if (instruction == ACK) {
                sendACK();
            }
            else if (instruction == VERSION_REQUEST) {
                sendVersionNumber();
            }
            else {
                printf("Unknown request received.\n");
            }
            Sleep(100);

        }

        /*Close Down*/
        CloseHandle(hSerial); //Without closing - may not be able to access the port until reboot


        FormatMessage(
            FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL,
            GetLastError(),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            lastError,
            1024,
            NULL);
        return 0 ;
    }

readData 和 readInstruction 函数是:

    void readData(char Rx_Buffer[], int numberOfBytes)
    {
        /*Clear Buffer*/
        for (int i = 0; i < numberOfBytes; i++) {
            Rx_Buffer[i] = 0 ;
        }

        DWORD dwBytesRead = 0;

        /*Read Bytes*/
        if (!ReadFile(hSerial, Rx_Buffer, numberOfBytes, &dwBytesRead, NULL)) {
            //error occurred. Report to user.
        }
    }


    char receiveInstruction()
    {
        //Initialise reading buffer, this decides which mode of transmission to use.
        char Rx_Buffer[1];
        Rx_Buffer[0] = 0;

        //While the buffer is empty, read for an instruction

        while (Rx_Buffer[0] == 0) {
            readData(Rx_Buffer, 1);
            Sleep(100);
        }

        return Rx_Buffer[0];
    }

如果 stm32 端需要代码,我可以提供,但它看起来只是循环发送版本号请求(主机未收到)。

对不起,这是一个相当模糊的问题,我真的不知道在哪里看。如果需要任何进一步的细节,我可以提供。

非常感谢一如既往的帮助,非常感谢。

标签: c++serial-portstm32uartserial-communication

解决方案


  • 您可以尝试从主机发送具有特定位模式的 STM 字节,每次发送之间至少等待 500 毫秒以避免合并字节。

0x01, 0x55,0xFF

注意你从 STM 中读到的内容。

  • 然后从STM到主机尝试同样的事情。

记下您从主持人那里读到的内容

  • 然后你可以从差异中推断出一些东西:

如果你确定你总是从一侧发送一个字节,而你从另一侧得到不同的读数(比如你的模式),那么它看起来很像一个同步问题。含义:波特率,而不是奇偶校验位或停止位,因为在这种情况下,模式将始终与 0x01 转换为 0x10 相同。

但是使用逻辑分析仪会容易得多:)

我也可能是噪音。当您查看模式字节时,它与 0x01 非常不同:

0x01 : 0b00000001
0x1B : 0b00011011
0x08 : 0b00001000
0xD4 : 0b11010100
0x9F : 0b10011111
0x79 : 0b01111001

推荐阅读