加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專(zhuān)業(yè)用戶(hù)
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 一、配置底層引腳
    • 二、編寫(xiě)應(yīng)用層代碼
    • 三、進(jìn)階學(xué)習(xí)
    • 四、常見(jiàn)問(wèn)題解答
    • 五、結(jié)束語(yǔ)
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

RT-Thread零基礎(chǔ)快速入門(mén)第9講——串口(UART/RS485)

07/11 14:34
4259
閱讀需 19 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

串口是單片機(jī)最常用的通訊方式之一,關(guān)于串口的介紹在RT-thread官網(wǎng)上已經(jīng)有非常詳細(xì)的介紹了,我這里就不多講了,今天主要講一講官網(wǎng)上沒(méi)有的東西,讓你更加深入的了解RT-thread是如何配置和使用串口進(jìn)行數(shù)據(jù)收發(fā)的。

RT-thread官網(wǎng)上關(guān)于UART的資料:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/uart/uart_v1/uart

一、配置底層引腳

1、確定串口引腳

先從原理圖查看自己需要使用的串口號(hào)及對(duì)應(yīng)的引腳。比如我要使用串口3,引腳是PB10和PB11(USART3除了這一組引腳還有PC10、PC11)

在這里插入圖片描述

2、配置底層引腳

1)配置串口

打開(kāi)keil工程,使用STM32CubeMX配置底層接口(路徑一般在工程目錄下boardCubeMX_Config文件夾里面)

不懂的同學(xué)可以看下我之前的博客:RT-Thread零基礎(chǔ)快速入門(mén)第1講——新建工程

先打開(kāi)對(duì)應(yīng)的串口(Mode選擇Asynchronous即可),然后檢查GPIO是否和原理圖一致。

在這里插入圖片描述

如果不一致的話(huà)可以在右邊的芯片圖上面找到正確的引腳,然點(diǎn)擊引腳,修改該引腳為串口功能,最后再回到上一步,檢查一下串口是否已經(jīng)修改成正確的引腳了。

在這里插入圖片描述
在這里插入圖片描述

提示:使用STM32CubeMX配置串口只需要打開(kāi)串口和配置引腳,其他的像波特率、NVIC這些都需要管,因?yàn)檫@些都是在RTT應(yīng)用層初始化的時(shí)候配置的,即使在這里改了也是不起作用的。

2)生成新的工程

點(diǎn)擊右上角的GENERATE CODE,生成新工程即可。

注:如果生成工程時(shí)提示你是否需要下載新版本的固件庫(kù),可以下載也可以繼續(xù)使用舊的,一般都是沒(méi)問(wèn)題的。

在這里插入圖片描述

二、編寫(xiě)應(yīng)用層代碼

1、打開(kāi)串口使能

用env打開(kāi)工程,進(jìn)入menuconfig配置頁(yè)面,打開(kāi)串口使能。

提示:這里的使能和上面STM32CubeMX打開(kāi)串口是不一樣的,env配置使能之后實(shí)際上是打開(kāi)一個(gè)宏定義,打開(kāi)之后才能調(diào)用RTT串口相關(guān)的庫(kù)函數(shù),而STM32CubeMX使能則是把HAL庫(kù)串口相關(guān)的函數(shù)加進(jìn)來(lái)。

如果你不知道env怎么使用,可以在下面這個(gè)鏈接查看。

env使用方法:https://www.rt-thread.org/document/site/programming-manual/env/env/#bsp-menuconfig

在這里插入圖片描述

配置好之后,退出保存即可。

注意:如果menuconfig里面沒(méi)有你要使用的串口號(hào)怎么辦,這個(gè)問(wèn)題請(qǐng)?zhí)胶竺娌榭?“常見(jiàn)問(wèn)題解答”。

2、重新生成工程

在env輸入下面的命令,重新生成新的工程。

提示:會(huì)使用env的話(huà)應(yīng)該都知道這個(gè)操作。

scons --target=mdk5

3、編寫(xiě)串口收發(fā)代碼

串口收發(fā)的示例代碼可以在RT-thread官網(wǎng)查看,有中斷接收的示例,也有DMA接收的示例,都是寫(xiě)的很詳細(xì)的了,拷貝過(guò)來(lái)改一下就可以用了。

你也可以在menuconfig里面打開(kāi)串口接收的示例。

在這里插入圖片描述

打開(kāi)示例之后要重新生成工程,也就是上面第2步的操作。

建議:如果只是測(cè)試串口功能的話(huà)可以直接添加示例文件,但是實(shí)際應(yīng)用中還是建議新建一個(gè)文件,然后編寫(xiě)串口的應(yīng)用代碼,再把這個(gè)文件加入到keil工程里面。

參考:RT-Thread零基礎(chǔ)快速入門(mén)第2講——添加新文件到工程

不管用哪種方法,示例代碼添加進(jìn)來(lái)之后還是要按照自己的需求修改配置,比如串口號(hào),波特率,串口接收的數(shù)據(jù)處理等。

我這里簡(jiǎn)單的舉個(gè)例子,具體怎么改還是要看你的功能需求。

以中斷接收的demo為例:

1)修改串口號(hào)

直接修改SAMPLE_UART_NAME這個(gè)宏即可,比如我這里用的是串口3,就改成"uart3"

#define SAMPLE_UART_NAME       "uart3"      /* 串口設(shè)備名稱(chēng) */

2)修改波特率

在查找串口(rt_device_find)之后,打開(kāi)串口(rt_device_open)之前添加下面這段代碼即可。

/* 修改串口配置參數(shù) */
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;  // 初始化配置參數(shù)
config.baud_rate = BAUD_RATE_9600;        //修改波特率為 9600
config.data_bits = DATA_BITS_8;           //數(shù)據(jù)位 8
config.stop_bits = STOP_BITS_1;           //停止位 1
config.bufsz     = 128;                   //修改緩沖區(qū) buff size 為 128
config.parity    = PARITY_NONE;           //無(wú)奇偶校驗(yàn)位
/* 控制串口設(shè)備。通過(guò)控制接口傳入命令控制字,與控制參數(shù) */
rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

如下圖所示:

在這里插入圖片描述

3)串口數(shù)據(jù)接收處理

如果數(shù)據(jù)不多處理不復(fù)雜,可以直接在接收數(shù)據(jù)的線(xiàn)程進(jìn)行數(shù)據(jù)處理,如下圖所示:

在這里插入圖片描述

如果數(shù)據(jù)比較多或者處理比較復(fù)雜需要消耗的時(shí)間比較長(zhǎng)的情況下,就不太建議在接收的線(xiàn)程進(jìn)行數(shù)據(jù)處理了,因?yàn)樵谶@里處理數(shù)據(jù)會(huì)影響后續(xù)的數(shù)據(jù)接收。

推薦幾種常用的解決方法:

1:使用消息隊(duì)列把接收到的數(shù)據(jù)傳輸到其他線(xiàn)程,在其他的線(xiàn)程做統(tǒng)一的數(shù)據(jù)處理。

2:如果接收是以中斷的方式,可以考慮在接收的時(shí)候就做先做簡(jiǎn)單的處理,比如用一個(gè)switch語(yǔ)句,每接收一個(gè)數(shù)據(jù)就處理一次,這樣就可以把每個(gè)字節(jié)接收的間隙時(shí)間利用起來(lái)。這個(gè)方法也可以用來(lái)判斷數(shù)據(jù)幀是否完整接收完成,是否有錯(cuò)誤的數(shù)據(jù)幀。

數(shù)據(jù)處理的方法有很多,各有優(yōu)劣,具體用哪種方式則要看實(shí)際的情況,適合的方法才是最好的。

利用switch語(yǔ)句處理接收數(shù)據(jù)的示例代碼:

switch(count)
{
    case 0:{
        if(ch == 0xFC){                  // 幀頭
            uart_rx_buffer[i++] = ch;
            count ++;
        }
        else{
            i = 0;
            count = 0;
        }
        break;
    }
    case 1:{                             // 地址
        if(ch == 1 || ch == 2){
            uart_rx_buffer[i++] = ch;
            count ++;
        }
        else{
            i = 0;
            count = 0;
        }
        break; 
    } 
    case 2:{                             // 命令
            if(ch == 0xD4){
            uart_rx_buffer[i++] = ch;
            count ++;
        }
        else{
            i = 0;
            count = 0;
        }
        break;
    }
    case 3:{
            uart_rx_buffer[i++] = ch;     // 數(shù)據(jù)高位
            count ++;
        break;
    }
    case 4:{
            uart_rx_buffer[i++] = ch;     // 數(shù)據(jù)高位
            count ++;
        break;
    }
    case 5:{
            uart_rx_buffer[i++] = ch;     // 校驗(yàn)
            i = 0;
            count = 0; 
            if(verify_check(uart_rx_buffer, 5) == uart_rx_buffer[5]) // 檢查校驗(yàn)
            {
                rt_sem_release(rs485_timeout_sem);
                uart_485_data_handle(uart_rx_buffer);
            }
        break; 
    }
    default: 
        i = 0;
        count = 0;
        break;
}

三、進(jìn)階學(xué)習(xí)

1、串口的硬件小知識(shí)

串口常用的電平有三種:TTL、RS232、RS485。

類(lèi)型 說(shuō)明
TTL 電壓范圍0V至+5V,高電平>2.4V,低電平<0.4V,一般MCU直接輸出的串口就是TTL電平
RS232 電壓范圍-15V至+15V,高電平為-3V至-15V,低電平為+3V至+15V
RS485 電壓范圍-7V至+12V,不同于TTL和RS232,RS485采用的差分信號(hào)負(fù)邏輯,高電平為兩線(xiàn)間的電壓差-2V至-6V,低電平為兩線(xiàn)間的電壓差+2V至+6V
USB 有單獨(dú)的協(xié)議,與TTL、RS232和RS485都不同

三種電平之間不能直接通信,需要通過(guò)轉(zhuǎn)換芯片轉(zhuǎn)換成相同的電平。除了這三種電平以外,我們常常還用到USB,USB有自己的協(xié)議(2.0、3.0、3.1等),USB和TTL、RS232和RS485這些電平之間也是不能直接通信的,也需要轉(zhuǎn)換。一般單片機(jī)或者其他MCU的串口電平都是TTL的,而PC端一般使用USB。

舉個(gè)例子:

如果MCU的串口需要連接到PC端,那么就需要實(shí)現(xiàn)TTL和USB直接的轉(zhuǎn)換,常用的方法如下:

1、通過(guò)一個(gè)USB轉(zhuǎn)TTL的芯片轉(zhuǎn)換,可以放在主板上,也可以用那種轉(zhuǎn)換小板,這個(gè)大家應(yīng)該比較熟悉了,某寶上面隨處可見(jiàn)。
2、通過(guò)一個(gè)TTL轉(zhuǎn)232的芯片轉(zhuǎn)換,然后再接一根USB轉(zhuǎn)232的連接線(xiàn),這個(gè)線(xiàn)常用DB9接口。
3、通過(guò)一個(gè)TTL轉(zhuǎn)485的芯片轉(zhuǎn)換,然后再接一根USB轉(zhuǎn)485的連接線(xiàn)。

TTL一般是板內(nèi)模塊間通訊用的比較多,因?yàn)榇诰€(xiàn)過(guò)長(zhǎng)會(huì)有線(xiàn)損,影響通訊,因此,外接的傳感器和MCU的通訊大多使用RS232和RS485這兩種,像RS485,串口線(xiàn)即使長(zhǎng)達(dá)一百米,也不影響正常通訊。

2、RS485的使用

上面簡(jiǎn)單介紹了三種電平硬件上的區(qū)別,那么在編程上又有什么區(qū)別呢?

對(duì)于TTL和RS232來(lái)說(shuō),編程都是一樣的,只要配置好UART的收發(fā)即可,電平的轉(zhuǎn)換都是通過(guò)轉(zhuǎn)換芯片來(lái)完成的,與代碼無(wú)關(guān)。RS485也是類(lèi)似的,電平的轉(zhuǎn)換也是通過(guò)轉(zhuǎn)換芯片來(lái)完成,但不同的是RS232是可以同時(shí)收發(fā)的,而RS485在同一時(shí)間只能發(fā)送或者接收,因此,RS485的轉(zhuǎn)換芯片多了一個(gè)使能引腳,這個(gè)使能腳是用來(lái)切換發(fā)送模式和接收模式的,一般是由MCU來(lái)控制。

在這里插入圖片描述

我們?cè)趯?xiě)代碼的時(shí)候只要把RS485這個(gè)使能腳的控制加進(jìn)去就可以了。

1)先定義485的使能引腳,以及加入GPIO配置要用到的頭文件。

#include <rtdevice.h>
#include <board.h>
#define RS485_RE  GET_PIN(G, 8)

提示:引腳號(hào)用宏定義,這樣的話(huà)如果以后要修改引腳,就不需要把每個(gè)函數(shù)都改一遍。

2)在串口初始化的時(shí)候把485使能引腳的初始化也加進(jìn)去,默認(rèn)設(shè)置為接收模式。

rt_pin_mode(RS485_RE, PIN_MODE_OUTPUT);   // 配置RS485使能引腳為輸出
rt_pin_write(RS485_RE, PIN_LOW);          // 配置RS485為接收模式(一般低電平是接收模式,高電平是發(fā)送模式,當(dāng)然,也有相反的,主要還是看485用什么芯片)

3)在串口發(fā)送數(shù)據(jù)前切換485為發(fā)送模式,發(fā)送完成后再切回接收模式。

rt_pin_write(RS485_RE, PIN_HIGH);         // 發(fā)送模式 
rt_device_write(serial, 0, &ch, 1);       // 發(fā)送數(shù)據(jù)
rt_pin_write(RS485_RE, PIN_LOW);          // 接收模式

四、常見(jiàn)問(wèn)題解答

1、ENV配置里面沒(méi)有我要用的串口號(hào)

問(wèn)題分析:這是因?yàn)槟氵@個(gè)工程menuconfig頁(yè)面的配置文件并沒(méi)有把所有串口和配置都添加進(jìn)來(lái)。

解決辦法:在工程目錄下board文件夾里面有一個(gè)Kconfig文件,這個(gè)就是menuconfig頁(yè)面的配置文件,在里面找到串口的配置,可以把原有的配置修改成你想要的串口號(hào),也可以照貓畫(huà)虎的抄一遍原有的配置,然后再修改成你想要的串口號(hào)。修改完之后重新打開(kāi)menuconfig即可,如果報(bào)錯(cuò)打不開(kāi)了,說(shuō)明的改的有問(wèn)題,有語(yǔ)法錯(cuò)誤。

在這里插入圖片描述

還有一個(gè)辦法就是直接在工程文件里面的rtconfig.h添加串口使能的宏定義,實(shí)際上使用env配置修改的也是這個(gè)文件的宏,但是這樣做有一個(gè)問(wèn)題就是每次你使用env配置好參數(shù)之后,你都要再手動(dòng)添加一遍串口使能的宏,因?yàn)槊看问褂胑nv配置參數(shù)的時(shí)候都會(huì)按照Kconfig文件覆蓋一遍,而Kconfig又沒(méi)有你手動(dòng)添加的這個(gè)宏,所以,最好還是用上面的方法,在根本上解決問(wèn)題。

在這里插入圖片描述

2、ENV配置的串口配置沒(méi)有DMA模式

問(wèn)題分析:這個(gè)問(wèn)題和上面那個(gè)問(wèn)題其實(shí)是一樣的,修改Kconfig即可

3、ENV配置沒(méi)錯(cuò),硬件電路也是對(duì)的,但是串口就是收不到數(shù)據(jù)

問(wèn)題分析:假如你ENV的配置是沒(méi)錯(cuò)的,硬件電路也確認(rèn)過(guò)是正常的,使用list_device也能查找到uart設(shè)備,但是就是收不到數(shù)據(jù),有可能是底層串口沒(méi)有配置好,比如底層的引腳號(hào)配置的不對(duì)或者串口根本就沒(méi)有打開(kāi),這種情況在修改了電路圖或者工程的時(shí)候很容易出現(xiàn),也很容易忽視,因?yàn)檫@個(gè)問(wèn)題編譯的時(shí)候并不會(huì)報(bào)錯(cuò),你不仔細(xì)核對(duì)原理圖是發(fā)現(xiàn)不了的。

解決辦法:使用STM32CubeMX配置好串口的參數(shù),具體的操作上面已經(jīng)介紹過(guò),就不多說(shuō)了。

4、STM32CubeMX、ENV及串口初始化等軟件部分都確認(rèn)是對(duì)的,但就是沒(méi)有數(shù)據(jù)

問(wèn)題分析:這種情況就要結(jié)合硬件一起排查了,最快的排查方法就是直接上示波器或者邏輯分析儀,可以單獨(dú)寫(xiě)一個(gè)測(cè)試線(xiàn)程,讓單片機(jī)定時(shí)發(fā)數(shù)據(jù)(發(fā)什么數(shù)據(jù)不重要),然后用示波器查看MCU串口的TX引腳的波形,正常的波形是很規(guī)律的,每一幀的數(shù)據(jù)間隔也會(huì)跟你定時(shí)的時(shí)間一致,并且數(shù)據(jù)幀的波形都是比較漂亮的方波。如果沒(méi)有波形,排除MCU損壞的情況的話(huà),肯定還是軟件沒(méi)有配置好。接收的測(cè)試也是一樣的,可以通過(guò)PC端的串口助手定時(shí)發(fā)送數(shù)據(jù),然后測(cè)試MCU串口的RX引腳,看看波形是否正常,如果波形正常,但是單片機(jī)就是沒(méi)有收到數(shù)據(jù),那肯定還是軟件沒(méi)有配置好。

5、串口每次都只能通過(guò)輸入命令啟動(dòng)嗎

命令行輸入只是為了方便我們測(cè)試,實(shí)際使用的話(huà)可以使用INIT_APP_EXPORT自動(dòng)加載函數(shù),或者在其他函數(shù)、線(xiàn)程里面調(diào)用。
例如:

INIT_APP_EXPORT(uart_sample);

五、結(jié)束語(yǔ)

串口的使用其實(shí)非常簡(jiǎn)單,但是實(shí)際使用的時(shí)候往往會(huì)因?yàn)橐恍┬?wèn)題折騰了半天,這個(gè)時(shí)候一定要冷靜的分析問(wèn)題,先檢查一遍硬件電路,再按流程檢查一遍配置和代碼,最后實(shí)在沒(méi)辦法了就上示波器吧。

好了,關(guān)于RT-thread串口的介紹就到這里,如果還有什么問(wèn)題,歡迎在評(píng)論區(qū)留言。如果這篇文章能夠幫到你,就給我點(diǎn)個(gè)贊吧,如果想了解更多RT-thread和單片機(jī)的內(nèi)容,可以關(guān)注一下博主,后續(xù)我還會(huì)繼續(xù)分享更多的經(jīng)驗(yàn)給大家。

推薦器件

更多器件
器件型號(hào) 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊(cè) ECAD模型 風(fēng)險(xiǎn)等級(jí) 參考價(jià)格 更多信息
ASEM1-16.000MHZ-LC-T 1 Abracon Corporation MEMS OSC XO 16.0000MHZ CMOS SMD
$1.63 查看
CAT24C04WI-GT3 1 Rochester Electronics LLC 512X8 I2C/2-WIRE SERIAL EEPROM, PDSO8, 0.150 INCH, GREEN, MS-012, SOIC-8
$0.21 查看
LTST-C190CKT 1 Lite-On Semiconductor Corporation Single Color LED, Red, Water Clear, 1.1mm,

ECAD模型

下載ECAD模型
$0.21 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜