STM32與Linux串口雙向通信

来源:https://www.cnblogs.com/muheandrabbit/p/18381596/STM32UartLinux
-Advertisement-
Play Games

STM32 與 linux 雙向串口通信實驗 本文記錄STM32 與 linux 雙向串口通信,包含stm32發送、Linux阻塞式接收;Linux發送,STM32阻塞式接收;本實驗的目的在於調通數據鏈路,為之後使用奠定基礎。 實驗平臺為: STM32方面用的是STM32H723ZGT6為核心的開發 ...


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端退出阻塞式接收,代碼如下:

  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方面:如果沒有開啟串口,需要在設備數中開啟串口,開啟過程可以見Luckfox的wiki:https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-UART#5修改設備樹
      Linux方面串口配置和接收邏輯直接由代碼配置,代碼邏輯為:首先以打開UART3,對其進行基本配置,配置完成後進入阻塞式接收程式,串口一直接收數據並列印,若一段時間未接收到數據則列印Timeout,開始下一輪接收;直到接收到"exit"數據,退出接收,關閉串口。程式如下:

#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[15];

    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[VTIME] = 1;    // inter-character timer unused
    tty.c_cc[VMIN] = 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[16] = {};
    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[bytes_read] = '\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端可以一直接收到數據,直到STM32端exit數據發送。

      可以看到最後一個數據為"exitreceiveTemp"這是為什麼呢?
從STM32端的代碼可以發現:

      這兩個發送間距很快,因此接收端認為其是一次發送;

Linux 向 STM32 串口發送數據

      發送完成後,接收就大同小異,STM32方面代碼較為簡單,邏輯為:阻塞式接收,通過判斷接收首位是否為0及字元'\0',判斷是否接收到數據,若接收到數據則printf出來,代碼如下:

  uint8_t ReceiveTemp[11] = {};
  while (1)
  {
    /* Receive data code */
    memset(ReceiveTemp, 0, sizeof(ReceiveTemp));
    HAL_UART_Receive(&huart2, ReceiveTemp, 11, 0xffff);
    if(ReceiveTemp[0] != 0)
    {
      printf("Receive data:%s\n", ReceiveTemp);
    }
    HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);
  }

      Linux方面,只需將接收部分換成發送即可,代碼邏輯為:定時發送。代碼如下:

   /* Transmit data in 1s intervals */
   char tx_buffer[] = {"0123456789"};
   while(1)
   {
       ssize_t bytes_written = write(serial_fd, tx_buffer, sizeof(tx_buffer));
       if(bytes_written != sizeof(tx_buffer))
       {
           fprintf(stderr, "Filed to send all data. Sent %zd out of %zu bytes.\n",
                   bytes_written, sizeof(tx_buffer));
       }else{
           printf("Data send successfully.Data len is:%d\n", bytes_written);
       }
       sleep(1);
   }

實驗現象為:
      Linux方面:每發送成功一次則列印一次;

STM32方面:每接收成功一次則將接收結果列印出來;

總結

      本文實現了STM32 與 Linux平臺的串口雙向阻塞式通訊,根據實驗效果驗證效果可行。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • liwen01 2024.09.01 前言 最近十幾年,通信技術發展迅猛,通信標準更新頻繁,有的設備還在使用 802.11/b/g/n 協議,有的已支持到 WiFi6、WiFi7。 而國內有關無線 WiFi 的書籍或資料卻很少,就算能找著的,大多也是比較老舊。本文試圖使用最新的數據來介紹 WiFi ...
  • 本章將和大家分享Docker中常用的命令。廢話不多說,下麵我們直接進入主題。 1、配置鏡像加速源 拉取鏡像慢,配置載入鏡像地址: 創建一個或修改 /etc/docker/daemon.json 文件(如果不存在則創建): vim /etc/docker/daemon.json 並添加或修改regis ...
  • Mac上HomeBrew安裝及換源教程 Mac的Mac OS系統來源於Unix系統,得益於此Mac系統的使用類似於Linux,因此Linux系統中的包管理概念也適用於Mac,而HomeBrew便是其中的一個優秀的包管理工具,而包管理工具是什麼呢?軟體包管理工具,擁有安裝、卸載、更新、查看、搜索等功能 ...
  • 在電腦電源管理中,S1, S2, S3, S4 代表不同的電源狀態或睡眠狀態。 瞭解這些狀態,對電腦設備理解功耗及工作狀態有很大幫助。最近公司開會,系統同事有講S3狀態功耗很低,我猜和電腦的睡眠、息屏有關。。。emmm,不懂就要學 查找資料,以下是這些狀態的詳細說明: S1 狀態(低電量等待狀態 ...
  • 32位配置寄存器:GPIOx_CRL,GPIOx_CRH 32位數據寄存器:GPIOx_IDR,GPIOx_ODR 32位置位/複位寄存器:GPIOx_BSRR 16位複位寄存器:GPIOx_BRR 32位鎖定寄存器:GPIOx_LCKR GPIO 寄存器詳解 CRL 32位埠配置低寄存器(GPI ...
  • 嵌入式STM32單片機開發環境配置教學Win/Mac · 本教程支持Windows和Mac · Windows可選的開發軟體為Keil、Clion、STM32CubeMX,可自由選擇開發方式 · Mac的開發環境為(Clion+OpenOCD+STM32CubeMX),僅支持HAL庫 · 本博客同步 ...
  • Multipass 虛擬機 ssh 登錄(密碼方式) [!NOTE] 以 Ubuntu 24,04 LTS 為例 準備工作 為了演示新建一個示例虛擬機。 multipass launch --name vm01 -c 4 -m 4G -d 100G --network bridged 操作步驟 進入 ...
  • 實踐環境 CentOS-7-x86_64-DVD-2009 簡介 Firewalld是一種簡單的、有狀態的、基於區域(zone-based)的防火牆。策略和區域用於組織防火牆規則。網路在邏輯上被劃分為多個區域,它們之間的流量可以通過策略進行管理。 查看防火牆狀態 # service firewall ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...