美丽的神话 发表于 2024-8-27 13:12:26

STM32与Linux串口双向通信

STM32 与 linux 双向串口通信实验

       本文记录STM32 与 linux 双向串口通信,包罗stm32发送、Linux阻塞式吸收;Linux发送,STM32阻塞式吸收;本实验的目的在于调通数据链路,为之后使用奠定底子。
实验平台为:
       STM32方面用的是STM32H723ZGT6为核心的开发板;开发环境为 VSCode + AC5编译器,调试器用的是STLINK-V2;
       Linux方面:用的是luckfox的RV1106-G3为核心的开发板;开发环境为window环境下的Clion+交叉编译器,linux为Ubuntu22.04虚拟机,使用ADB将编译后的步伐发送到linux开发板;
STM32 向 Linux 串口发送数据

       STM32方面代码使用CubuMx生成,串口基本参数为:
      1.波特率:115200;
      2.数据宽度为8bits;
      3.无停止位;
      4.无奇偶校验位;
      5.一个停止位;
      初始化方面代码比力简朴,故不放了,放一张CubeMx的配置截图:
https://img2024.cnblogs.com/blog/2973146/202408/2973146-20240827111520678-57684930.png
      发送代码在main的while循环中,代码逻辑为:每隔500ms发送一次数据,发送10次数据后发送"exit",使Linux端退出阻塞式吸收,代码如下:
uint8_t TransTemp[] = {"receiveTemp"};
while (1)
{
    /* Transmit data code*/
    for(int i=0; i<10; i++)
    {
      HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);   
      HAL_UART_Transmit(&huart2, TransTemp, sizeof(TransTemp), 0xffff);
      HAL_Delay(500);
    }
    HAL_UART_Transmit(&huart2, "exit", 4, 0xffff);
}      实验现象见图,在Linux端可以一直吸收到数据,直到STM32端exit数据发送。
https://img2024.cnblogs.com/blog/2973146/202408/2973146-20240827111530614-958261952.png
      可以看到最后一个数据为"exitreceiveTemp"这是为什么呢?
从STM32端的代码可以发现:
https://img2024.cnblogs.com/blog/2973146/202408/2973146-20240827111537018-976610089.png
      这两个发送间距很快,因此吸收端认为其是一次发送;
Linux 向 STM32 串口发送数据

      发送完成后,吸收就大同小异,STM32方面代码较为简朴,逻辑为:阻塞式吸收,通过判断吸收首位是否为0及字符'\0',判断是否吸收到数据,若吸收到数据则printf出来,代码如下:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
int main() {
    int serial_port_num=3;
    char serial_port;

    sprintf(serial_port,"/dev/ttyS%d",serial_port_num);
    int serial_fd;

    serial_fd = open(serial_port, O_RDWR | O_NOCTTY);
    if (serial_fd == -1) {
      perror("Failed to open serial port");
      return 1;
    }

    struct termios tty;
    memset(&tty, 0, sizeof(tty));

    if (tcgetattr(serial_fd, &tty) != 0) {
      perror("Error from tcgetattr");
      return 1;
    }

    cfsetospeed(&tty, B115200);
    cfsetispeed(&tty, B115200);

    tty.c_cflag &= ~PARENB; // NO parity bit
    tty.c_cflag &= ~CSTOPB; // 1 stop bit
    tty.c_cflag &= ~CSIZE;// clear transimit bit
    tty.c_cflag |= CS8;   // set data bits to 8 bits
    tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines

    // Set input mode (non-canonical, no echo,...)
    tty.c_lflag &= ~ICANON;
    tty.c_lflag &= ~ECHO;

    // Set output mode (no post-processing)
    tty.c_oflag &= ~OPOST;      // no post-processiing means that out row data

    // Set timeout to 1 second
    tty.c_cc = 1;    // inter-character timer unused
    tty.c_cc = 1;   // wait for up to 1 second for 1 byte

    if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {
      perror("Error from tcsetattr");
      return 1;
    }
    /* Receive data in block mode! */
    char rx_buffer = {};
    int bytes_read;
    // 主循环
    while (1) {
      memset(rx_buffer, 0, sizeof(rx_buffer)); // 清空缓冲区
      bytes_read = read(serial_fd, rx_buffer, sizeof(rx_buffer) - 1);
      if (bytes_read > 0) {
            rx_buffer = '\0'; // 添加字符串结束符
            printf("\rrx_buffer: %s\n", rx_buffer);
      } else if (bytes_read == 0) {
            printf("No data received.\n");
      } else {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                printf("Timeout occurred.\n");
            } else {
                perror("Error reading from serial port");
            }
      }

      // 检查是否接收到 "exit" 以退出循环
      if (strncmp(rx_buffer, "exit", 4) == 0) {
            break;
      }
    }
    close(serial_fd);

    return 0;
}      Linux方面,只需将吸收部分换成发送即可,代码逻辑为:定时发送。代码如下:
uint8_t ReceiveTemp = {};
while (1)
{
    /* Receive data code */
    memset(ReceiveTemp, 0, sizeof(ReceiveTemp));
    HAL_UART_Receive(&huart2, ReceiveTemp, 11, 0xffff);
    if(ReceiveTemp != 0)
    {
      printf("Receive data:%s\n", ReceiveTemp);
    }
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);
}实验现象为:
      Linux方面:每发送乐成一次则打印一次;
https://img2024.cnblogs.com/blog/2973146/202408/2973146-20240827111544864-510204482.png
STM32方面:每吸收乐成一次则将吸收结果打印出来;
https://img2024.cnblogs.com/blog/2973146/202408/2973146-20240827111551453-1336439510.png
总结

      本文实现了STM32 与 Linux平台的串口双向阻塞式通讯,根据实验结果验证结果可行。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: STM32与Linux串口双向通信