女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

第3章_UART 開發基礎

嵌入式Linux那些事 ? 來源:嵌入式Linux那些事 ? 作者:嵌入式Linux那些事 ? 2024-06-29 14:27 ? 次閱讀

第3章 UART 開發基礎

3.1 同步傳輸與異步傳輸

3.1.1 概念與示例

使用生活例子來說明什么是同步、異步:

  • 同步:朋友打電話說到我家吃飯,我在家里等他們
  • 異步:朋友沒有提前打招呼,突然就到我家來了

它們的差別在于:有沒有使用一種方法“實現約好時間”。

在電子產品中, 使用同步傳輸時, 一般涉及兩個信號

  • 時鐘信號:用來通知對方要讀取數據了
  • 數據信號:用來傳輸數據

同步傳輸示例如下:

  • 時鐘信號:打電話,起約定作用
  • 數據信號:傳輸數據

img

異步傳輸示例如下:

img

使用異步信號傳輸數據時,雙方遵守相同的約定:

  • 起始信號:發送方可以通知接收方"注意了,我要開始傳輸數據了"
  • 數據的表示: 怎么表示邏輯 1,怎么表示邏輯 0。

紅外遙控器解碼器為例,它向單片機發出的數據格式如下:

  • 起始信號:解碼器發出一個 9ms 的低電平、 4.5ms 的高電平, 用來同時對方說"開始了"

img

  • 表示一位數據
    • 邏輯 1:0.56ms 的低電平+1.69ms 的高電平
    • 邏輯 0:0.56ms 的低電平+0.56ms 的高電平

img

  • 接收方、發送方都遵守這樣的約定, 就可以使用一條線傳輸數據

3.1.2 差別

同步傳輸異步傳輸
信號線多:時鐘信號、數據信號少:只需要數據信號
速率可變, 提高時鐘信號頻率即可雙方提前約定
抗干擾能力

3.2 UART 協議與操作方法

3.2.1 UART 協議

通用異步收發器簡稱 UART,即“Universal Asynchronous Receiver Transmitter”, 它用來傳輸串行數據:發送數據時,CPU 將并行數據寫入 UART,UART 按照一定的格式在一 根電線上串行發出;接收數據時, UART 檢測另一根電線上的信號,將串行數據收集放在緩 沖區中,CPU 即可讀取 UART 獲得這些數據。 UART 之間以全雙工方式傳輸數據,最精簡的連 線方法只有三根電線:TxD 用于發送數據, RxD 用于接收數據,GND 用于給雙方提供參考電 平,連線如圖所示:

img

UART 使用標準的 TTL/CMOS 邏輯電平(0~5V、0~3.3V、0~2.5V 或 0~1.8V 四種)來表 示數據,高電平表示 1,低電平表示 0。進行長距離傳輸時,為了增強數據的抗干擾能力、 提高傳輸長度, 通常將 TTL/CMOS 邏輯電平轉換為 RS-232 邏輯電平, 3~12V 表示 0,-3~- 12V 表示 1。

TxD、RxD 數據線以“位”為最小單位傳輸數據。幀(frame)由具有完整意義的、不可 分割的若干位組成,它包含開始位、數據位、較驗位(需要的話)和停止位。發送數據之前,

UART 之間要約定好數據的傳輸速率(即每位所占據的時間,其倒數稱為波特率)、數據的傳

輸格式(即有多少個數據位、是否使用較驗位、是奇較驗還是偶較驗、有多少個停止位)。 數據傳輸流程如下:

  • 平時數據線處于“空閉”狀態(1 狀態)。
  • 當要發送數據時,UART 改變 TxD 數據線的狀態(變為 0 狀態)并維持 1 位的時間──這 樣接收方檢測到開始位后,再等待 1.5 位的時間就開始一位一位地檢測數據線的狀態 得到所傳輸的數據。
  • UART 一幀中可以有 5、6、7 或 8 位的數據,發送方一位一位地改變數據線的狀態將它 們發送出去,首先發送最低位。
  • 如果使用較驗功能, UART 在發送完數據位后,還要發送 1 個較驗位。有兩種較驗方法: 奇較驗、偶較驗──數據位連同較驗位中, “1”的數目等于奇數或偶數。
  • 最后, 發送停止位, 數據線恢復到“空閉”狀態(1 狀態)。停止位的長度有 3 種: 1 位、 1.5 位、 2 位。

下圖演示了 UART 使用 7 個數據位、偶較驗、2 個停止位的格式傳輸字符“A ”(二進制 值為 0b01000001)時, TTL/CMOS 邏輯電平、 RS-232 邏輯電平對應的波形。

img

雙方約定了“傳輸一 bit 數據的時間”, 就可以算出 1 秒內能傳輸多少 bit 數據, 這 被稱為“比特率”, 又經常被稱為“波特率”。兩者有什么關系?

假設發送方 A 能精確控制信號的電壓, 接收方 B 也能精確識別電壓, 雙方如此約定:

電壓范圍表示的兩 bit 數據
0~0.7V0b00
~0.8 1.5V0b01
1.6~2.3V0b10
~2.4 3.3V0b11

那么要傳輸一個字節的數據, 比如 0x78,它的二進制數為 0b01,11,10,00,只需要傳 輸 4 次(假設 1ms 改變一次電壓, 假設先傳輸低位):

  • 第 1ms,A 設置電壓為 0V,B 識別出電壓后,認為收到了 bit1 為 0、bit0 為 0
  • 第 2ms,A 設置電壓為 1.6V,B 識別出電壓后, 認為收到了 bit3 為 1、bit2 為 0
  • 第 3ms,A 設置電壓為 2.4V,B 識別出電壓后, 認為收到了 bit5 為 1、bit4 為 1
  • 第 4ms,A 設置電壓為 0.8V,B 識別出電壓后, 認為收到了 bit7 為 0、bit6 為 1

只需要 4ms,就傳輸了 4 個狀態,但是傳輸了 8bit 數據:波特率*2=比特率。

假設發送方 A 精確控制信號電壓的能力比較差,只能保證 00.7V、1.83.3V 的電壓比 較穩定;接收方 B 識別電壓的能力也不夠精確,只能保證可以識別出 0~0.7V、1.8 3.3V 的 電壓, 于是雙方約定:

電壓范圍表示的 1 bit 數據
0~0.7V0
1.8~3.3V1

那么要傳輸一個字節的數據, 比如 0x78,它的二進制數為 0b01111000,需要傳輸 8 次 (假設 1ms 改變一次電壓,假設先傳輸低位):

  • 第 1ms,A 設置電壓為 0V,B 識別出電壓后,認為收到了 bit0 為 0
  • 第 2ms,A 設置電壓為 0V,B 識別出電壓后,認為收到了 bit1 為 0
  • 第 3ms,A 設置電壓為 0V,B 識別出電壓后,認為收到了 bit2 為 0
  • 第 4ms,A 設置電壓為 3.3V,B 識別出電壓后, 認為收到了 bit3 為 1
  • 第 5ms,A 設置電壓為 3.3V,B 識別出電壓后, 認為收到了 bit4 為 1
  • 第 6ms,A 設置電壓為 3.3V,B 識別出電壓后, 認為收到了 bit5 為 1
  • 第 7ms,A 設置電壓為 3.3V,B 識別出電壓后, 認為收到了 bit6 為 1
  • 第 8ms,A 設置電壓為 0V,B 識別出電壓后,認為收到了 bit7 為 0

需要 8ms,傳輸 8 個狀態, 傳輸了 8bit 數據:波特率=比特率。

所以,波特率: 1 秒內傳輸信號的狀態數(波形數)。比特率: 1 秒內傳輸數據的 bit 數。如果一個波形, 能表示 N 個 bit,那么:波特率 * N = 比特率。

3.2.2 STM32H5 UART 硬件結構

img

3.2.3 RS485 協議

使用 RS485 協議傳輸數據時, 電路圖如下:

img

RS485 協議里,使用 A、B 差分信號線傳輸數據: 兩線間的電壓差為+(2 至 6)V 表示 邏輯 1,電壓差為-(2 至 6)V 時表示邏輯 0。它是半雙工的傳輸方式:MCU1 要發送數據 時,從 TxD 引腳把數據發送給電平轉換芯片 MAX13487EESA,它把 TxD 的信號轉換為差分信 號傳遞給另一個電平轉換芯片 MAX13487EESA,進而轉換為 TTL 電平通過 RO 發送到 MCU2 的 RxD 引腳。MCU2 要給 MCU1 發送數據的話,必須等待差分信號線處于空閑狀態。

對于軟件而言, 使用 RS485 跟普通的 UART 沒有區別。

3.3 UART 編程

3.3.1 硬件連接

按照下圖連線: 調試、供電、兩個 485 互連。

img

3.3.2 三種編程方式

結合 UART 硬件結構, 有 3 種編程方法:

  • 查詢方式:
    • 要發送數據時, 先把數據寫入 TDR 寄存器, 然后判斷 TDR 為空再返回。當然也可以先 判斷 TDR 為空, 再寫入。
    • 要讀取數據時, 先判斷 RDR 非空, 再讀取 RDR 得到數據。
  • 中斷方式:
    • 使用中斷方式, 效率更高,并且可以在接收數據時避免數據丟失。
    • 要發送數據時, 使能“TXE”中斷(發送寄存器空中斷)。在 TXE 中斷處理函數里, 從 程序的發送 buffer 里取出一個數據, 寫入 TDR。等再次發生 TXE 中斷時, 再從程序的發送 buffer 里取出下一個數據寫入 TDR。
    • 對于接收數據,在一開始就使能“RXNE”中斷(接收寄存器非空) 。這樣,UART 接收 到一個數據就會觸發中斷,在中斷程序里讀取 RDR 得到數據, 存入程序的接收 buffer。當 程序向讀取串口數據時, 它直接讀取接收 buffer 即可。
    • 這里涉及的“發送 buffer”、“接收 buffer”,特別適合使用“環形 buffer ”。
  • DMA 方式:
    • 使用中斷方式時, 在傳輸、接收數據時,會發生中斷, 還需要 CPU 執行中斷處理函數。 有另外一種方法:DMA(Direct Memory Access), 它可以直接在 2 個設備之間傳遞數據,無需 CPU 參與。

框圖如下:

img

設置好 DMA(源、目的、地址增減方向、每次讀取數據的長度、讀取次數)后,DMA 就 會自動地在 SRAM 和 UART 之間傳遞數據:

  • 發送時: DMA 從 SRAM 得到數據, 寫入 UART 的 TDR 寄存器
  • 接收時: DMA 從 UART 的 RDR 寄存器得到數據, 寫到 SRAM 去
  • 指定的數據傳輸完畢后,觸發 DMA 中斷;在數據傳輸過程中,沒有中斷, CPU 無需處理。

函數如下:

查詢方式中斷方式DMA 方式
發送HAL_UART_TransmitHAL_UART_Transmit_ITHAL_UART_TxCpltCallbackHAL_UART_Transmit_DMAHAL_UART_TxHalfCpltCallback HAL_UART_TxCpltCallback
接 收HAL_UART_ReceiveHAL_UART_Receive_ITHAL_UART_RxCpltCallbackHAL_UART_Receive_DMAHAL_UART_RxHalfCpltCallback HAL_UART_RxCpltCallback
錯誤HAL_UART_ErrorCallbackHAL_UART_ErrorCallback

3.3.3 查詢方式

本 節 程 序 源 碼 為 “ 3_ 程 序 源 碼 ?1_ 視 頻 配 套 的 源 碼 3-4_UART 編程 ( 查 詢 方 式)uart_poll.7z”。
缺點: 發送數據時要死等發送完畢,接收數據時容易丟失。

3.3.4 中斷方式

本 節 程 序 源 碼 為 “ 3_ 程 序 源 碼 ?1_ 視 頻 配 套 的 源 碼 3-5_UART 編程 ( 中 斷 方 式)uart_int.7z”。
缺點: 需要是事先調用接收函數, 才能通過中斷接收數據, 易丟失。

3.3.5 DMA 方式

本 節 程 序 源 碼 為 “ 3_ 程序源碼 ?1_ 視 頻 配 套 的 源 碼 3-6_UART 編程 (DMA 方 式)uart_dma.7z”。
本節講的是傳統 DMA 方式,不涉及“idle 中斷”, 它會在后面講解。 缺點: 需要是事先調用接收函數, 才能通過中斷接收數據, 易丟失。

3.4 效率最高的 UART 編程方法

3.4.1 IDLE 中斷

IDLE,空閑的定義是:總線上在一個字節的時間內沒有再接收到數據。

UART 的 IDLE 中斷何時發生? RxD 引腳一開始就是空閑的啊, 難道 IDLE 中斷一直產生? 不是的。當我們使能 IDLE 中斷后,它并不會立刻產生,而是: 至少收到 1 個數據后, 發現 在一個字節的時間里,都沒有接收到新數據,才會產生 IDLE 中斷。

我們使用 DMA 接收數據時,確實可以提高 CPU 的效率, 但是“無法預知要接收多少數 據”, 而我們想盡快處理接收到的數據。怎么辦? 比如我想讀取 100 字節的數據, 但是接 收到 60 字節后對方就不再發送數據了, 怎么辦? 我們怎么判斷數據傳輸中止了? 可以使用 IDLE 中斷。在這種情況下,DMA 傳輸結束的條件有 3:

  • 接收完指定數量的數據了, 比如收到了 100 字節的數據了,HAL_UART_RxCpltCallback 被調用
  • 總線空閑了: HAL_UARTEx_RxEventCallback 被調用
  • 發生了錯誤: HAL_UART_ErrorCallback 被調用

使用 IDLE 狀態來接收的函數有:

函數回調函數
查詢方式HAL_UARTEx_ReceiveToIdle根據返回參數 RxLen 判斷是否接收 完畢, 還是因為空閑而返回
中斷方式HAL_UARTEx_ReceiveToIdle_IT完畢: HAL_UART_RxCpltCallback 因為空閑而中止:HAL_UARTEx_RxEventCallback
DMA 方式HAL_UARTEx_ReceiveToIdle_DMA傳輸一半:HAL_UART_RxHalfCpltCallback 完畢:HAL_UART_RxCpltCallback因為空閑而中止:HAL_UARTEx_RxEventCallback
錯誤HAL_UART_ErrorCallback

3.4.2 DMA 發送/DMA+IDLE 接收

要點有 3:

  • 對于發送:使用“HAL_UART_Transmit_DMA”函數
  • 對于接收:一開始就調用“HAL_UARTEx_ReceiveToIdle_DMA”啟動接收
  • 在回調函數“HAL_UART_RxCpltCallback”或“HAL_UARTEx_RxEventCallback”里讀取、 存儲數據后,再次調用“HAL_UARTEx_ReceiveToIdle_DMA”啟動接收

3.5 在 RTOS 里使用 UART

3.5.1 程序框架

本程序的重點在于如何高效地接收數據:

  • 使用 DMA+IDLE 中斷的方式接收數據,它會把數據存入臨時緩沖區;
  • 在回調函數里:把臨時緩沖器的數據寫入隊列,然后再次使能 DMA
  • AP 讀取隊列: 如果隊列里沒有數據則阻塞。

框架如下:

img

3.5.2 編寫程序

本 節 程 序 源 碼 為 “ 3_ 程 序 源 碼 ?1_ 視 頻 配 套 的 源 碼 3-8_ 在 RTOS 里 使 用 UARTuart_rtos.7z”。

3.5.3 面向對象封裝 UART

我們使用多個 UART:UART2、UART4,以初始化為例,有如下函數:

void UART2_Rx_Start(void);
void UART4_Rx_Start(void) ;

對于使用者而言,非常不友好:當 UART 數量增多,他需要記住、使用多個函數名;當 更換某個 UART,他需要修改多處代碼。 比如對于如下代碼, 當需要更換為 UART4 時, 需要 修改第 1、3 行代碼為 UART4 的函數:

uart2_init(115200, 'N', 8, 1);
 char *str = “www.100ask.net”;
 uart2_sendp(str, strlen(str), 100);

把 UART 的操作封裝為結構體, 可以解決這個問題。 UART 的操作主要有 3 個函數: 初始 化、發送數據、接收數據。那么可以抽象出如下結構體:

struct UART_Device {
    char *name;
    int (*Init)( struct UART_Device *pDev, int baud, char parity, int data_bit, int stop_bit);
    int (*Send)( struct UART_Device *pDev, uint8_t *datas, uint32_t len, int timeout); 
    int (*RecvByte)( struct UART_Device *pDev, uint8_t *data, int timeout);
};

本節為 UART2、UART4 分別構造一個“struct UART_Device”結構體,比如:

strcut UART_Device g_uart2_dev = {“uart2”, uart2_init, uart2_send, uart2_recvbyte};
strcut UART_Device g_uart4_dev = {“uart4”, uart4_init, uart4_send, uart4_recvbyte};

使用時,示例代碼如下:

struct UART_Device *pDev = &g_uart2_dev;
pDev- >Init(pDev, 115200, 'N', 8, 1);
char *str = “www.100ask.net”;
pDev- >Send(pDev, str, strlen(str), 100);

如果要更換串口,只需要修改第 1 行代碼, 讓它指向 g_uart4_dev 即可:這就是面向 對象編程的優點。

本節代碼為: 本節程序源碼為“3_程序源碼?1_視頻配套的源碼3-9_面向對象封裝 UARTuart_rtos_all_ok.7z ”

先使用 STM32CubeMX 配置 UART2、UART4,把它們的發送、接收都使用 DMA。如下圖配 置:

img

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5140

    文章

    19524

    瀏覽量

    314748
  • uart
    +關注

    關注

    22

    文章

    1264

    瀏覽量

    103217
  • 時鐘信號
    +關注

    關注

    4

    文章

    465

    瀏覽量

    29063
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    Openwrt開發指南 24 配置開發板支持U盤

    Openwrt開發指南 24 配置開發板支持U盤
    的頭像 發表于 07-13 08:55 ?4498次閱讀
    Openwrt<b class='flag-5'>開發</b>指南 <b class='flag-5'>第</b>24<b class='flag-5'>章</b> 配置<b class='flag-5'>開發</b>板支持U盤

    數字邏輯電路3的PPT

    數字邏輯電路3的PPT,一些難度大,質量很高。
    發表于 06-03 16:57 ?0次下載

    輕松學會DSP——3_DSP匯編指令

    輕松學會DSP——3_DSP匯編指令
    發表于 06-17 14:59 ?12次下載

    3 MAXPLUS軟件的使用(1節)

    3 MAXPLUS軟件的使用(1節)
    發表于 07-13 10:08 ?0次下載

    3 MAXPLUS軟件的使用(2節)

    3 MAXPLUS軟件的使用(2節)
    發表于 08-01 14:32 ?0次下載

    3 MAXPLUS軟件的使用(6節)

    3 MAXPLUS軟件的使用(6節)
    發表于 07-13 10:07 ?0次下載

    3 MAXPLUS軟件的使用(7節)

    3 MAXPLUS軟件的使用(7節)
    發表于 07-11 17:00 ?0次下載

    3 MAXPLUS軟件的使用(4節2)

    3 MAXPLUS軟件的使用(4節 2)
    發表于 07-11 16:58 ?0次下載

    信號與系統10大例題(3

    信號與系統10大例題(3
    發表于 08-07 11:27 ?0次下載

    DSP嵌入式系統開發典型案例, 3 中低速數據采集系統設計

    DSP嵌入式系統開發典型案例, 3 中低速數據采集系統設計
    發表于 10-20 14:36 ?1次下載
    DSP嵌入式系統<b class='flag-5'>開發</b>典型案例, <b class='flag-5'>第</b><b class='flag-5'>3</b><b class='flag-5'>章</b> 中低速數據采集系統設計

    7 嵌入式uClinux及應用開發

    7 嵌入式uClinux及應用開發
    發表于 10-27 09:40 ?2次下載
    <b class='flag-5'>第</b>7<b class='flag-5'>章</b> 嵌入式uClinux及應用<b class='flag-5'>開發</b>

    PIC24F系列中文參考手冊—21 UART

    PIC24F系列中文參考手冊—21 UART
    發表于 05-25 17:19 ?9次下載

    慕課嵌入式開發及應用(第二.UART驅動構件的設計方法)

    慕課蘇州大學.嵌入式開發及應用.第二.入門與軟件框架.UART驅動構件的設計方法0 目錄2 入門與軟件框架2.1 UART驅動構件的設計方法2.1.1 課堂重點2.1.2 測試與作業
    發表于 11-03 13:51 ?5次下載
    慕課嵌入式<b class='flag-5'>開發</b>及應用(第二<b class='flag-5'>章</b>.<b class='flag-5'>UART</b>驅動構件的設計方法)

    嵌入式Linux應用程序開發詳解-3

    電子發燒友網站提供《嵌入式Linux應用程序開發詳解-3.pdf》資料免費下載
    發表于 11-16 11:19 ?0次下載
    嵌入式Linux應用程序<b class='flag-5'>開發</b>詳解-<b class='flag-5'>第</b><b class='flag-5'>3</b><b class='flag-5'>章</b>

    【北京迅為】iTOP-RK3568開發板OpenHarmony系統南向驅動開發-4 UART基礎知識

    【北京迅為】iTOP-RK3568開發板OpenHarmony系統南向驅動開發-4 UART基礎知識
    的頭像 發表于 03-17 15:50 ?368次閱讀
    【北京迅為】iTOP-RK3568<b class='flag-5'>開發</b>板OpenHarmony系統南向驅動<b class='flag-5'>開發</b>-<b class='flag-5'>第</b>4<b class='flag-5'>章</b> <b class='flag-5'>UART</b>基礎知識