翼度科技»论坛 云主机 LINUX 查看内容

STM32与Linux串口双向通信

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
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的配置截图:

      发送代码在main的while循环中,代码逻辑为:每隔500ms发送一次数据,发送10次数据后发送"exit",使Linux端退出阻塞式接收,代码如下:
  1.   uint8_t TransTemp[] = {"receiveTemp"};
  2.   while (1)
  3.   {
  4.     /* Transmit data code*/
  5.     for(int i=0; i<10; i++)
  6.     {
  7.       HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);   
  8.       HAL_UART_Transmit(&huart2, TransTemp, sizeof(TransTemp), 0xffff);
  9.       HAL_Delay(500);
  10.     }
  11.     HAL_UART_Transmit(&huart2, "exit", 4, 0xffff);
  12.   }
复制代码
      实验现象见图,在Linux端可以一直接收到数据,直到STM32端exit数据发送。

      可以看到最后一个数据为"exitreceiveTemp"这是为什么呢?
从STM32端的代码可以发现:

      这两个发送间距很快,因此接收端认为其是一次发送;
Linux 向 STM32 串口发送数据

      发送完成后,接收就大同小异,STM32方面代码较为简单,逻辑为:阻塞式接收,通过判断接收首位是否为0及字符'\0',判断是否接收到数据,若接收到数据则printf出来,代码如下:
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <fcntl.h>
  4. #include <termios.h>
  5. #include <unistd.h>
  6. int main() {
  7.     int serial_port_num=3;
  8.     char serial_port[15];
  9.     sprintf(serial_port,"/dev/ttyS%d",serial_port_num);
  10.     int serial_fd;
  11.     serial_fd = open(serial_port, O_RDWR | O_NOCTTY);
  12.     if (serial_fd == -1) {
  13.         perror("Failed to open serial port");
  14.         return 1;
  15.     }
  16.     struct termios tty;
  17.     memset(&tty, 0, sizeof(tty));
  18.     if (tcgetattr(serial_fd, &tty) != 0) {
  19.         perror("Error from tcgetattr");
  20.         return 1;
  21.     }
  22.     cfsetospeed(&tty, B115200);
  23.     cfsetispeed(&tty, B115200);
  24.     tty.c_cflag &= ~PARENB; // NO parity bit
  25.     tty.c_cflag &= ~CSTOPB; // 1 stop bit
  26.     tty.c_cflag &= ~CSIZE;  // clear transimit bit
  27.     tty.c_cflag |= CS8;     // set data bits to 8 bits
  28.     tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines
  29.     // Set input mode (non-canonical, no echo,...)
  30.     tty.c_lflag &= ~ICANON;
  31.     tty.c_lflag &= ~ECHO;
  32.     // Set output mode (no post-processing)
  33.     tty.c_oflag &= ~OPOST;      // no post-processiing means that out row data
  34.     // Set timeout to 1 second
  35.     tty.c_cc[VTIME] = 1;    // inter-character timer unused
  36.     tty.c_cc[VMIN] = 1;     // wait for up to 1 second for 1 byte
  37.     if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {
  38.         perror("Error from tcsetattr");
  39.         return 1;
  40.     }
  41.     /* Receive data in block mode! */
  42.     char rx_buffer[16] = {};
  43.     int bytes_read;
  44.     // 主循环
  45.     while (1) {
  46.         memset(rx_buffer, 0, sizeof(rx_buffer)); // 清空缓冲区
  47.         bytes_read = read(serial_fd, rx_buffer, sizeof(rx_buffer) - 1);
  48.         if (bytes_read > 0) {
  49.             rx_buffer[bytes_read] = '\0'; // 添加字符串结束符
  50.             printf("\rrx_buffer: %s\n", rx_buffer);
  51.         } else if (bytes_read == 0) {
  52.             printf("No data received.\n");
  53.         } else {
  54.             if (errno == EAGAIN || errno == EWOULDBLOCK) {
  55.                 printf("Timeout occurred.\n");
  56.             } else {
  57.                 perror("Error reading from serial port");
  58.             }
  59.         }
  60.         // 检查是否接收到 "exit" 以退出循环
  61.         if (strncmp(rx_buffer, "exit", 4) == 0) {
  62.             break;
  63.         }
  64.     }
  65.     close(serial_fd);
  66.     return 0;
  67. }
复制代码
      Linux方面,只需将接收部分换成发送即可,代码逻辑为:定时发送。代码如下:
  1.   uint8_t ReceiveTemp[11] = {};
  2.   while (1)
  3.   {
  4.     /* Receive data code */
  5.     memset(ReceiveTemp, 0, sizeof(ReceiveTemp));
  6.     HAL_UART_Receive(&huart2, ReceiveTemp, 11, 0xffff);
  7.     if(ReceiveTemp[0] != 0)
  8.     {
  9.       printf("Receive data:%s\n", ReceiveTemp);
  10.     }
  11.     HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);
  12.   }
复制代码
实验现象为:
      Linux方面:每发送成功一次则打印一次;

STM32方面:每接收成功一次则将接收结果打印出来;

总结

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

来源:https://www.cnblogs.com/muheandrabbit/p/18381596/STM32UartLinux
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具