【理解ARM架構】操作寄存器實現UART | 段的概念 | IDE背后的命令

🐱作者:一只大喵咪1201
🐱專欄:《理解ARM架構》
🔥格言:你只管努力,剩下的交給時間!
圖

目錄

  • 🍠操作寄存器實現UART
    • 🍟UART原理
    • 🍟編程
  • 🍠段的概念
  • 🍠IDE背后的命令
  • 🍠總結

🍠操作寄存器實現UART

🍟UART原理

UART的全稱是Universal Asynchronous Receiver and Transmitter,即異步發送和接收。
串口在嵌入式中用途非常的廣泛,主要的用途有:

  • 打印調試信息;
  • 外接各種模塊:GPS、藍牙;

串口因為結構簡單、穩定可靠,廣受歡迎。

tu
如上圖所示,串口通信只需要三根線,發送(TXD)、接收(RXD)、地線(GND)。

  • 通信雙方的TXD與對方的RXD相連。

串口發送數據是以幀格式一幀一幀來發的,幀格式由1bit起始位,8或9bit數據位,1或1.5或2bit校驗位,1bit停止位組成。

  • 通常情況下都使用8bit數據位,不適用校驗位,這樣的一幀數據有10個bit。

校驗位又叫奇偶校驗位,如果8個數據位加校驗位中比特為位1的個數是奇數,校驗位就是1,否則就是0。

由于現在電子技術的逐漸成熟,串口通信很少出錯,所以校驗位使用的不多。

圖
如上圖所示是一幀數據傳送時的邏輯電平示意圖。

  • 發送方將自己的TXD線從高電平拉到低電平,保持一段時間,接收方讀取到自己的RXD線由高到底以后就知道要接收數據了。
  • 發送方按照自己發送的這個字節,從低位開始,改變TXD線的電平,每改變一次保持一段時間,如此反復8次完成一字節數據的發送。
  • 接收方在自己RXD線上的電平保持期間的中間時刻,根據電平狀態記錄該比特位的值,最后組合成一字節數據。
  • 發送方將一字節數據發送完畢后,將自己的TXD線拉高方便下次發送數據,接收方在接收到8bit數據以后,并且檢測到自己RXD線是高電平,就知道這一幀數據傳送完畢了。

上面描述數據發送過程中電平維持的時間,就是根據波特率來確定的,一般選波特率都會有9600,19200,115200等選項。

  • 波特率:可以簡單理解為,串口通信過程中1秒鐘能發送的比特位個數。
  • 波特率是通信雙方約定好的,一個按照這個速度發送數據,另一個按照這個速度接收數據。

邏輯電平:

圖

如上圖所示是本喵使用的ARM開發板串口發出的電平信號,在xV至5V之間,就認為是邏輯1,在0V至yV之間就為邏輯0,這叫做TTL/CMOS邏輯電平

圖
如上圖所示是RS-232邏輯電平,在-12V至-3V之間,就認為是邏輯1,在+3V至+12V之間就為邏輯0,RS-232的電平比TTL/CMOS高,能傳輸更遠的距離,在工業上用得比較多。

可以看到,RS-232與TTL/CMOS相同邏輯電平對應的真實電壓正負是相反的。


tu
如上圖所示,ARM芯片上的串口都是TTL電平的,通過板子上或者外接的電平轉換芯片,轉成RS232接口,連接到電腦的RS232串口上,實現兩者的數據傳輸。

圖
如上圖所示,現在的電腦越來越少有RS232串口的接口,但USB是幾乎都有的。因此使用USB串口芯片將ARM芯片上的TTL電平轉換成USB串口協議,即可通過USB與電腦數據傳輸。

  • 無論那種接口,板子上的芯片IO口輸出的都是TTL/CMOS電平,我們在寫程序時僅需要關心輸出的邏輯電平即可。

🍟編程

一款ARM芯片上會有多個USART串口,一般UART1用來輸出調試信息,這里本喵也使用USART1。

確定引腳:

圖
如上圖,本喵使用的STMF103ZET6芯片上,USART1的USART1_RX、USART1_TX,接到了PA10、PA9。

將引腳配置為UART功能:

  • 使能GPIOA/USART1模塊

圖
如上圖是,RCC_APB2ENR寄存器,GPIOA模塊、USART1模塊的使能都是在這一個寄存器里實現。

圖
如上圖,從芯片手冊中查看Reset and clock control RCC寄存器的基地址是0x40021000,再根據RCC_APB2ENR的偏移地址0x18得到該寄存器的絕對地址是0x40021000 + 0x18

將該寄存器的bit2和bit14寫一,此時就使能了GPIOA和USART1模塊。

圖

  • 配置引腳功能

從上面的芯片原理圖可以知道,PA9、PA10有三種功能:GPIO、USART1、TIMER1,所以這里要將其配置為USAT1功能。

tu
如上圖所示GPIOx_CRH寄存器,該寄存器的絕對地址是0x40010800 + 0x04,PA9配置為輸出,所以將MODE9代表的bit4和bit5配置成01,將CNF9代表的bit6和bit7配置為10

PA10配置為輸入,將MODE10代表的bit8和bit9配置為00,再將CNF10代表的bit10和bit11配置成01

圖

由于這里僅使能了USART1,沒有使能定時器,所以PA9和PA10的默認復用功能就是USART1,使用默認值即可。

設置串口參數:

  • 設置波特率

tu
如上圖所示是波特率的計算公式,USARTDIV由整數部分、小數部分組成,USARTDIV = DIV_Mantissa + (DIV_Fraction / 16) 。fck是內部時鐘頻率,這里就使用默認值,是8MHZ。

圖
如上圖USART_BRR寄存器,DIV_Mantissa表示整數部分,占用該寄存器的bit4~bit15,DIV_Fraction表示小數部分,占用該寄存器的bit0~bit3

以常用的波特率115200為例,來計算該寄存器的值:

設置波特率* 115200 = 8000000/16/USARTDIV* USARTDIV = 4.34* DIV_Mantissa = 4* DIV_Fraction / 16 = 0.34* DIV_Fraction = 16*0.34 = 5

所以給USART_BRR寄存器的bit4~bit15賦值4,bit0~bit3賦值5,根據這兩個值再來倒推一下真實的波特率:

真實波特率:* DIV_Fraction / 16 = 5/16=0.3125* USARTDIV = DIV_Mantissa + DIV_Fraction / 16 = 4.3125* baudrate = 8000000/16/4.3125 = 115942

可以看到,雖然和115200有點差距,但是并不影響。

  • 設置數據格式

圖
如上圖所示USART1_CR1寄存器,本喵將幀格式設置為1個起始位,8個數據位,無校驗位,1個停止位,所以將bit13設置1,bit12設置為0,bit10設置為0,bit3設置為1,bit2設置為1。

但是此時并沒有設置幾個停止位,還需要設置另一個寄存器:

tu
如上圖所示USART_CR2寄存器,將bit12~bit13設置為00,表示1個停止位。

根據狀態寄存器讀寫數據:

圖
如上圖所示串口模塊結構圖,發送有一個發送數據寄存器和發送移位寄存器,接收有一個接收數據寄存器和接收移位寄存器。

發送數據時,CPU將數據寫入到發送數據寄存器,然后由發送移位寄存器一位一位將數據通過TXD線發送出去。

接收數據時,RXD線上的數據一位一位放入接收移位寄存器,該寄存器接收完畢后將整個字節數據放入到接收數據寄存器,CPU從接收數據寄存器中可以直接讀取數據。

  • 狀態寄存器

圖
如上圖所示USART_SR狀態寄存器,TXE表示發送數據寄存器是否為空,該位并不能說明數據已經發送完了,因為真正發送數據的是移位寄存器,只能說發送數據寄存器將數據給了移位寄存器,CPU可以再向數據寄存器中寫數據了。

TC表示發送數據完成,即發送數據寄存器和移位寄存器中的數據都發送完畢了。RXNE表示接收數據寄存器中有數據了,說明已經接收到了數據,CPU可以來讀取了。

  • 數據寄存器

圖
如上圖所示USART_DR寄存器,寫、讀這個寄存器,就可以發送、讀取串口數據。


在配置完引腳和功能選擇以后,本喵在介紹USART_XXX寄存器的時候并沒有說它的地址,因為無論是設置波特率的USART_BRR,還是設置數據格式的USART_CR1,再或者狀態寄存器USART_SR,以及數據寄存器USART_DR這些都是以USART為基地址的。

圖
如上圖所示USART1的基地址是0x40013800,上面本喵提到的這些寄存器都是在這個基地址的基礎上進行偏移,也就是說它們都屬于USART1模塊中的寄存器。

typedef unsigned int uint32_t;
typedef struct
{volatile uint32_t SR;    /*!< USART Status register, Address offset: 0x00 */volatile uint32_t DR;    /*!< USART Data register,   Address offset: 0x04 */volatile uint32_t BRR;   /*!< USART Baud rate register, Address offset: 0x08 */volatile uint32_t CR1;   /*!< USART Control register 1, Address offset: 0x0C */volatile uint32_t CR2;   /*!< USART Control register 2, Address offset: 0x10 */volatile uint32_t CR3;   /*!< USART Control register 3, Address offset: 0x14 */volatile uint32_t GTPR;  /*!< USART Guard time and prescaler register, Address offset: 0x18 */
} USART_TypeDef;

如上面代碼所示,用一個結構體來表示USART模塊,里面的成員變量表示各個寄存器,讓它們在結構體中的偏移量和寄存器相對于USART模塊的偏移量相對應,此時就可以通過訪問這個結構體訪問到各個寄存器。

tu
如上圖所示是整個串口的初始化代碼,其中配置波特率等參數使用的是結構體訪問的寄存器,串口結構體是一個局部變量。

圖
如上圖所示,定義發送一個字符和接收一個字符的函數,通過判斷狀態寄存器的值,進而讀寫DR寄存器,也是通過結構體訪問的寄存器,結構體是一個局部變量。

圖
如上圖,此時將程序燒錄到開發板以后,會通過串口發送Hello字符串,在PC端發送一個字符,板子接收到以后返回該字符及下一個字符,此時我們的串口是配置好了。

問題:為什么每個函數中都得創建一個uart1結構體局部變量,而不是創建全局變量供這些函數使用呢?

🍠段的概念

圖
如上圖所示,增加三個函數,用來打印字符串及變量的地址。

圖
如上圖所示,創建四個全局變量,g_ConstChar被const修飾,然后在mymain中分別打印四個變量的地址及它們的值。

將程序編譯后燒錄到開發板中,通過串口工具來觀察輸出的內容。

圖
如上圖所示,來看這四個變量的地址,只有g_ConstChar這個被const修飾的變量地址是位于Flash中的,其他幾個變量都是位于RAM中。

圖
如上圖,keil中只能了Flash和RAM的起始地址,根據這兩個參數很容易判斷出這四個變量所處的位置。

圖
如上圖,再來看輸出的這四個變量的值,可以看到,只有const修飾的g_ConstChar變量輸出了B,其他幾個變量都沒有輸出對應的則,而是奇怪的東西。

  • 其他變量輸出的奇怪值表明,這幾個變量地址處的值是亂碼。

g_ConstChar變量位于Flash,也就是ROM,ROM是只讀的,不能寫,而其他三個變量位于RAM,RAM是可讀可寫的。

在編譯的時候,編譯器進行了判斷處理,g_ConstChar是只讀的,不會寫,所以把它放在Flash就可以。

  • Flash上存放這種只讀數據的區域叫做只讀數據段

其他三個變量會進行讀和寫的操作,所以編譯器給了它們一個鏈接地址,這個地址對應在RAM上,方便CPU進行讀寫。

  • RAM上存放這種可讀可寫全局變量的區域叫做可讀可寫數據段

無論有沒有被const修飾的變量,它們都有初始值A或者B,這個兩個數值是不會變的,只是用來使用的,所以編譯器將這兩個值放在這兩個變量位于Flash上的地址處(加載地址)。

  • 有幾個有初始值的全局變量,Flash中就會保存幾個初始值。
  • Flash以及內存中并沒有變量名,只會在變量的地址處直接存放數值。

char g_A = 0這種初始值為0的全局變量,以及char g_B這種沒有初始值的全局變量,Flash上就沒有必要存放它們的初始值。

假設初始值為0的變量有一萬個,Flash中難道要存放1萬個0嗎?肯定不會的,這樣浪費內存不說,還沒有任何意義。對于沒有初始值的全局變量Flash中更不會存放它的初始值了。

所以編譯器在編譯的時候,直接給這種初始值為0或者沒有初始值的全局變量分配一個鏈接地址,位于RAM中,CPU直接去鏈接地址讀寫就可以了。

  • 這種存放初始值為0或者沒有初始值所在的RAM區域被叫做BSS段或者ZI段

我們寫的代碼經過編譯鏈接以后,會生成一個二進制可執行文件,里面全部都是機器碼,這部分代碼并不會改變,所以也存放到Flash上。

  • 存放代碼的Flash區域被叫做代碼段

至于棧以及堆本喵在前面的文章中就詳細講解過,這里就不再說了,有興趣的小伙伴可以移步單片機中的C語言。

所以,程序分為這幾個段:

  • 代碼段(RO-CODE):就是程序本身,不會被修改
  • 可讀可寫的數據段(RW-DATA):有初始值的全局變量、靜態變量,需要從ROM上復制到內存
  • 只讀的數據段(RO-DATA):可以放在ROM上,不需要復制到內存
  • BSS段或ZI段:
    • 初始值為0的全局變量或靜態變量,沒必要放在ROM上,使用之前清零就可以
    • 未初始化的全局變量或靜態變量,沒必要放在ROM上,使用之前清零就可以
  • 局部變量:保存在棧中,運行時生成
  • 堆:一塊空閑空間,使用malloc函數來管理它,malloc函數可以自己寫

🍠IDE背后的命令

IDE指集成開發環境(Integrated Development Environment)。我們開發STM32F103等單片機程序時使用是keil5就是一種IDE。

使用IDE,很容易操作,點點鼠標就可完成,添加文件,指定文件路徑(頭文件路徑、庫文件路徑),指定鏈接庫,編譯、鏈接,下載、調試等功能。

其實在我們點下某一個按鈕以后,IDE的背后會執行一系列指令:

tu
如上圖,在keil5的Output選擇中勾選Create Batch File,然后重新全部編譯。

圖
如上圖,此時在當前工程的Objects目錄下會多出上面紅色框中的四個文件。

圖
如上圖所示分別是這幾個文件中的內容,都是一系列的命令行指令,用來編譯和鏈接文件的指令,具體怎么用不用管,只需要知道有這些東西。

  • start._ia中的命令行就是在讓start.s匯編文件編譯成start.o目標文件。
  • main._i中的命令行就是在讓main,c源文件編譯成main.o目標文件。
  • uart._i中的命令行就是在讓uart.c源文件編譯成uart.o目標文件。
  • led.linp中的命令行就是把這幾個.o目標文件鏈接在一起形成一個二進制可執行文件led.axf,我們燒錄的就是這個文件。

當我們點下IDE上的編譯選項時,IDE會自動執行上面四個文件中的內容,最后生成我們需要的東西。

🍠總結

雖然配置串口已經是一個老生常談的問題了,但是相信大家很少直接使用寄存器地址來配置吧,這個過程中可以加深對ARM架構的理解。

串口配好后通過打印數據過程中出現的問題介紹了段的概念,編譯器不同類型的變量放在內存中不同的位置。

要意識到,編譯一個工程的背后沒有那么簡單。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/167363.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/167363.shtml
英文地址,請注明出處:http://en.pswp.cn/news/167363.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python——第十二天

內置模塊或者其他模塊學習方式&#xff1a; dir help os模塊負責程序與操作系統的交互&#xff0c;提供了訪問操作系統底層的接口&#xff1b;即os模塊提供了非常豐富的方法用來處理文件和目錄。 os&#xff1a; os.path 遍歷C盤代碼 import os from os import path def …

修改YOLOv5的模型結構第三彈

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 | 接輔導、項目定制&#x1f680; 文章來源&#xff1a;K同學的學習圈子 文章目錄 任務任務拆解 開始修改C2模塊修改yolo.py修改模型配置文件 模型訓練 上次已…

【工具使用】Keil工具的使用——常用配置介紹

Keil調試具體教程學習 目錄 ???????Keil調試具體教程學習 常用功能總結 &#xff08;2&#xff09;目標設置&#xff08;Target&#xff09; ①設置晶振頻率 ②跨模塊優化選項 ③微庫選項 &#xff08;3&#xff09;輸出設置&#xff08;Output&#xff09; ①…

插入排序(形象類比)

最近在看riscv手冊的時候&#xff0c;里面有一段代碼是插入排序&#xff0c;但是單看代碼的時候有點迷&#xff0c;沒看懂咋操作的&#xff0c;后來又查資料復習了一下&#xff0c;最終才把代碼看明白&#xff0c;所以寫篇博客記錄一下。 插入排序像打撲克牌 這是我聽到過比較形…

list的總結

目錄 1.什么是list 1.1list 的優勢和劣勢 優勢&#xff1a; 劣勢&#xff1a; 2.構造函數 2.1 default (1) 2.2 fill (2) 2.3 range (3) 2.4 copy (4) 3.list iterator的使用 3.1. begin() 3.2. end() 3.3迭代器遍歷 4. list容量函數 4.1. empty() 4.2. siz…

語音合成綜述Speech Synthesis

一、語音合成概述 語音信號的產生分為兩個階段&#xff0c;信息編碼和生理控制。首先在大腦中出現某種想要表達的想法&#xff0c;然后由大腦將其編碼為具體的語言文字序列&#xff0c;及語音中可能存在的強調、重讀等韻律信息。經過語言的組織&#xff0c;大腦通過控制發音器…

正整數分解

題目編號&#xff1a;Exp08-Basic01&#xff0c;GJBook3-12-05 題目名稱&#xff1a;正整數分解 題目描述&#xff1a;正整數n&#xff0c;按第一項遞減的順序依次輸出其和等于n的所有不增的正整數和式。 輸入&#xff1a;一個正整數n&#xff08;0<n≤15&#xff09;。 …

qRT-PCR相對定量計算詳解qPCR相對定量計算方式——2^-(??Ct) deta t

做完轉錄組分析之后&#xff0c;一般都要求做qRT-PCR來驗證二代測序得到的轉錄本表達是否可靠。熒光定量PCR是一種相對表達定量的方法&#xff0c;他的計算方法有很多&#xff0c;常用的相對定量數據分析方法有雙標曲線法&#xff0c;ΔCt法&#xff0c;2^-ΔΔCt法(Livak法)&a…

順序表基本操作全面解析

文章目錄 1.線性表2.順序表分類2.1 靜態順序表2.2 動態順序表 3. 順序表各接口實現1. 定義結構體(Seqlist)2. 結構體初始化(SLInit)3.檢查容量 (SLCheckCapacity)4.打印數據 (SLPrintf)5.插入操作5.1 從數據頭部插入(SLPushFront)5.2 從數據尾部插入(SLPushBack)5.3 從任意下標…

100天精通Python(可視化篇)——第106天:Pyecharts繪制多種炫酷桑基圖參數說明+代碼實戰

文章目錄 專欄導讀一、桑基圖介紹1. 桑基圖是什么?2. 桑基圖應用場景?二、桑基圖配置選項1. 導包2. add函數3. 分層設置三、桑基圖基礎1. 普通桑基圖2. 修改標簽位置3. 修改節點布局方向4、月度開支桑基圖書籍推薦專欄導讀 ????本文已收錄于《100天精通Python從入門到就…

線性表之順序表

文章目錄 主要內容一.順序表1.插入操作&#xff1a;代碼如下&#xff08;示例&#xff09;: 2.刪除操作&#xff1a;代碼如下&#xff08;示例&#xff09;: 3.按值查找&#xff1a;代碼如下&#xff08;示例&#xff09;: 總結 主要內容 順序表 預備知識 定義&#xff1a; 線…

GEE:基于 Landst 遙感數據計算的 kNDVI 下載 APP

作者&#xff1a;CSDN _養樂多_ 本文記錄了在Google Earth Engine&#xff08;GEE&#xff09;平臺中&#xff0c;使用 Landsat 遙感數據計算并且下載 kNDVI 的應用 APP 鏈接&#xff0c;并介紹該 APP 的使用方法和步驟。該APP可以為用戶展示 NDVI 和 kNDVI 的遙感影像&#…

抽象類, 接口, Object類 ---java

目錄 一. 抽象類 1.1 抽象類概念 1.2 抽象類語法 1.3 抽象類特性 1.4 抽象類的作用 二. 接口 2.1 接口的概念 2.2 語法規則 2.3 接口的使用 2.4 接口間的繼承 2.5 抽象類和接口的區別 三. Object類 3.1 toString() 方法 3.2 對象比較equals()方法 3.3 hash…

免費獲取GPT-4的五種工具

不可否認&#xff0c;由OpenAI帶來的GPT-4已是全球最受歡迎的、功能最強大的大語言模型&#xff08;LLM&#xff09;之一。大多數人都需要使用ChatGPT Plus的訂閱服務去訪問GPT-4。為此&#xff0c;他們通常需要每月支付20美元。那么問題來了&#xff0c;如果您不想每月有這筆支…

基于JavaWeb+SpringBoot+Vue醫院管理系統小程序的設計和實現

基于JavaWebSpringBootVue醫院管理系統小程序的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄[Java 源碼獲取 源碼獲取入口 Lun文目錄 目錄 1系統概述 1 1.1 研究背景 1 1.2研究目的 1 1.3系統設計思想 1 2相關技術 2 2.1微信小程序 2 2.2 …

井蓋位移傳感器廠家批發,守護井蓋安全

窨井蓋廣泛分布于城市街道&#xff0c;其管理效果直接反映了城市治理的現代化程度。根據住房和城鄉建設部發布的《關于進一步加強城市窨井蓋安全管理的通知》&#xff0c;全國各地需加強窨井蓋的安全管理。作為市政基礎設施的一個重要的組成部分&#xff0c;井蓋的管理工作不僅…

去水印網站哪個好?試試這個去水印軟件!

在工作中&#xff0c;我們都曾遇到過圖片水印的困擾。在眾多的在線水印去除工具中&#xff0c;雖然選擇看似豐富&#xff0c;但往往很難找到完全滿足我們需求的那一個。有些工具操作過程繁復&#xff0c;有些工具在處理復雜水印時力不從心&#xff0c;還有些工具在去水印的過程…

【Spring日志】

一.日志作用 1.定位和發現問題 這是日志的主要用途,通過查看日志,我們可以定位問題發生的位置,從而快速的發現問題,分析問題. 2.系統監控 監控幾乎是一個成熟系統的標配,我們可以通過日志記錄這個系統的運行狀態,比如記錄方法的響應時間,響應狀態,通過設置不同的規則,超過閾值就…

【MyBatis <if> <where>標簽介紹】

文章目錄 <if>標簽<where>標簽<foreach>標簽 <if>標簽 <if>標簽允許我們在SQL語句中添加條件判斷。 <if test"condition"><!-- 當條件滿足時執行的SQL語句 --> </if>其中&#xff0c;test屬性是一個表達式&#x…

葡萄酒按酒體如何分類,都有什么特點?

葡萄酒的酒體是指酒液在口腔中的飽滿度和分量感&#xff0c;品酒者常用“輕盈”“厚重”“適中”等詞匯來形容。所以&#xff0c;云倉酒莊的品牌雷盛紅酒分享在葡萄酒分類中還有一個類型&#xff0c;就是按照酒體進行分類。一般分為輕盈型、中等型、飽滿型。 輕盈型&#xff1…