娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

IMX6ULL學習筆記(20)——UART串口使用

發布者:溫柔心緒最新更新時間:2025-02-24 來源: jianshu關鍵字:UART  串口使用 手機看文章 掃描二維碼
隨時隨地手機看文章

一、UART簡介

i.MX6U 芯片具有多達 8 個 UART 外設用于串口通訊,UART 是在 USART 基礎上裁剪掉了同步通信功能,只支持異步通信。簡單區分同步和異步就是看通信時需不需要對外提供時鐘輸出,我們平時用的串口通信基本都是 UART。

UART 滿足外部設備對工業標準 NRZ 異步串行數據格式的要求,并且使用了小數波特率發生器,可以提供多種波特率,使得它的應用更加廣泛。UART 支持異步單向通信和半雙工單線通信;還支持局域互連網絡 LIN、智能卡(SmartCard)協議與 lrDA(紅外線數據協會)SIR ENDEC 規范。

i.MX6U 的 UART 主要特性如下:

  • 兼容高速 TIA/EIA-232-F,最高 5.0 Mbit/s。

  • 兼容 IrDA 串行低速紅外接口,最高 115.2 Kbit/s。

  • 支持 9 位或多點(Multidrop mode)模式(RS-485)(自動從地址檢測)。

  • 支持 7 位或 8 位 RS-232 格式或 9 位的 RS-485 格式。

  • 支持 1 或 2 位停止位。

  • 可編程奇校驗或偶校驗。

  • 支持硬件流控(CTS/RTS)。

  • RTS支持邊緣中斷檢測。

  • 自動波特率檢測(最高為115.2kbit/s)。

  • rx_data 輸入和 tx_data 輸出可分別在 rs-232/rs-485 模式下進行交換(軟件可交換 TX、RX 引腳)。

  • 兩個 DMA 請求(TxFIFODMA 請求和 RxFIFODMA 請求)。

  • 支持軟件復位 (Srst_B)。

  • 兩個獨立的 32 輸入 FIFO,用于發送和接收。

二、引腳分布


相比 STM32,i.MX6U 的串口增加了引腳交換功能。通過配置 UFCR[DCEDTE] 寄存器可以交換 TX、RX 引腳以及 CTS、RTS 引腳,如下圖所示。


三、波特率設置

3.1 串口時鐘

串口模塊共有兩個時鐘輸入 Peripheral Clock 和 Module Clock。

  • Peripheral Clock
    外部時鐘。這個時鐘主要用于讀、寫接收和發送的數據,例如讀接收FIFO、寫發送FIFO。 這個時鐘與波特率設置無關,如果沒有特殊需求我們將這個時鐘保持默認即可,在初始代碼中并沒有特意設置這個時鐘。

  • Module Clock
    模塊時鐘,它既可用于接收、發送數據也用于設置波特率,這個時鐘決定了串口最高支持的波特率。Module Clock 時鐘來自根時鐘 UART_CLK_ROOT。

從圖中可以看出,從PLL時鐘到UART時鐘共用用到了兩個時鐘選擇寄存器(標號①和③),兩個時鐘分頻寄存器(標號②和標號④)。 我們最終目的是將PLL3時鐘作為UART根時鐘(UART_CLK_ROOT)的根時鐘。按照標號順序講解如下:

  1. 標號①選擇 PLL3 時鐘還是 CCM_PLL3_BYP。我們選擇 PLL3 輸出時鐘,寄存器 CCSR[PLL3_SW_CLK_SEL] = 0, 則表示選擇 PLL3 時鐘。默認情況下是這樣設置的。所以我們代碼中并沒有設置該寄存器。

  2. 標號②設置時鐘分頻,根據之前的設置,PLL3 的輸出頻率為 480MHz ,這里的時鐘分頻是固定的 6 分頻, 經過分頻后的時鐘為 480MHz / 6 = 80MHz。

  3. 標號③ 再次選擇時鐘源。一個是 PLL3 分頻得到的 80MHz 時鐘,另外一個是 OSC 時鐘即 24MHz 的系統參考時鐘。 設置 CSCDR1[UART_CLK_SEL] = 0,選擇第一個(80MHz)時鐘。

  4. 標號④再次進行時鐘分頻。這是一個 6 位的時鐘分頻寄存器。分頻值為 CSCDR1[UART_CLK_PODF] 寄存器值加一。 程序中將其設置為 1,則分頻系數為 2,UART_CLK_ROOT 時鐘頻率實際為 80MHz / 2 = 40MHz。

3.2 波特率計算公式

UART的發送器和接收器使用相同的波特率。計算公式如下:

  • BaudRate:要設置的波特率。

  • Ref Freq:參考時鐘,這個時鐘是 Module Clock 經過 RFDIV 寄存器分頻后得到的頻率。

  • UBMR:UBMR寄存器值。

  • UBIR:UBIR 寄存器值。

3.3 配置UARTx_UFCR寄存器

假設目標波特率為 115200。

3.3.1 設置時鐘分頻寄存器RFDIV

通過設置時鐘分頻寄存器 RFDIV,得到參考時鐘 Ref Freq。

Ref Freq 時鐘應該被設置為多少,沒有一個準確的數字,遵守以下幾條:

  1. Ref Freq 時鐘要大于波特率的 16 倍。

依據是 module_clock 必須大于等于 16 倍波特率【參考《IMX6ULRM》(參考手冊)53.4.2.1 Clock requirements,而 module_clock 經過 Clock Gating & Divider 之后變為 ref_clk,從功能框圖看 ref_clk 最終作為 uart 模塊參考時鐘】。


  1. UBMR 和 UBIR 的值必須小于 0xFFFF。

module_clock 時鐘經過 UARTx_UFCR[RFDIV] 寄存器分頻后得到 Ref Freq 時鐘,如下圖所示。

在程序中 Module Clock 被設置為 40MHz 而波特率只有 115200,所以這里將分頻值設置為最大值 7,即UARTx_UFCR[RFDIV] = 110B。得到參考時鐘 Ref Freq = 40MHz / 7 = 5.71MHz。

3.3.2 計算UBMR和UBIR的值

已知波特率 115200,參考時鐘 Ref Freq = 5.71MHz,可以計算得到 (UBMR+1) / (UBIR+1) 約為 3.10。 我們設置 (UBIR+1) = 10,(UBMR+1) = 31。

四、接收和發送FIFO

Tx Block 與 Rx Block 包括三部分:

  • 控制單元Control
    控制整個串口的工作, 我們編寫軟件不必過多關心。

  • 電源管理單元 Power Saving

  • TxFIFO (和RxFIFO)
    TxFIFO 與 RxFIFO 大小均為 32 字節,以發送為例,數據通過 UTXD 寄存器自動寫入 TxFIFO,如果 TxFIFO沒有滿,則可以不斷將數據寫入 UTXD 寄存器。UTS[4] 寄存器是 TxFIFO 滿的標志位。如果關閉了發送,仍然可以向 TxFIFO 寫入數據,但這樣做將會產生傳輸錯誤信息。當 TxFIFO 中的數據發送完成后將會自動設置發送緩沖區空中斷標志位,向 TxFIFO 寫入數據將自動清除發送緩沖區空標志位。

五、DMA和中斷請求

每個串口有兩個 DMA 請求,txfifo dma 請求和 rxfifo dma 請求,有多個中斷請求。

這里只介紹幾個常用的中斷:

中斷事件使能位標志位
空閑中斷UARTx_UCR1[TRDYEN]UARTx_USR2[TXFE]
接收溢出中斷UARTx_UCR4[OREN]UARTx_USR2[ORE]
接收緩沖區非空中斷UARTx_UCR4[DREN]UARTx_USR2[RDR]

完整內容請參考《IMX6ULRM》(參考手冊)53.4.1 Interrupts and DMA Requests。

六、編程流程

1. 創建工程文件夾
2. 移植官方SDK寄存器定義文件
3. 移植野火PAD屬性配置文件
4. 編寫啟動文件
5. 編寫鏈接文件
6. 編寫makefile文件
7. 編寫C語言代碼
(1) 設置UART時鐘源
(2) 初始化UART
(3) 使能UART
(4) UART數據接收
(5) UART數據發送

七、創建工程文件夾

  1. 創建一個文件夾 uart

  2. 創建一個用于存放頭文件的文件夾 include

  3. 創建一個用于存放驅動源碼的文件 device

  4. 創建一個啟動文件 start.S

  5. 創建一個源文件 main.c

  6. 創建一個鏈接腳本 base.lds

八、移植官方SDK寄存器定義文件

在 /uart/include 目錄下添加官方SDK寄存器定義文件 MCIMX6Y2.h,位于 SDK_2.2_MCIM6ULL_EBF6ULL/devices/MCIMX6Y2 目錄下。

在官方SDK的頭文件 MCIMX6Y2.h 文件多達4萬多行,包含了i.MX6U芯片幾乎所有的寄存器定義以及中斷編號的定義。

這里只列 GPIO1相關寄存器 的部分代碼。其他寄存器定義與此類似。 添加這些定義之后我們就可以 直接使用 “GPIO1->DR” 語句操作GPIO1的DR寄存器。操作方法與STM32非常相似。


typedef struct {

   __IO uint32_t DR;     /**< GPIO data register, offset: 0x0 */

   __IO uint32_t GDIR;   /**< GPIO direction register, offset: 0x4 */

   __I  uint32_t PSR;    /**< GPIO pad status register, offset: 0x8 */

   __IO uint32_t ICR1;   /**< GPIO interrupt configuration register1,*/

   __IO uint32_t ICR2;   /**< GPIO interrupt configuration register2, */

   __IO uint32_t IMR;   /**< GPIO interrupt mask register, offset: 0x14 */

   __IO uint32_t ISR; /**< GPIO interrupt status register, offset: 0x18 */

   __IO uint32_t EDGE_SEL;/**< GPIO edge select register, offset: 0x1C */

} GPIO_Type;


/*********************以下代碼省略***************************8*/

/** Peripheral GPIO1 base address */

#define GPIO1_BASE                               (0x209C000u)

/** Peripheral GPIO1 base pointer */

#define GPIO1                                    ((GPIO_Type *)GPIO1_BASE)


九、移植野火PAD屬性配置文件

在 /uart/device 目錄下添加 pad_config.h。


通常情況下一個引腳要設置8種PAD屬性,而這些屬性只能通過數字指定。為簡化PAD屬性設置野火編寫了一個PAD屬性配置文件 pad_config.h (embed_linux_driver_tutorial_imx6_code/bare_metal/led_rgb_c/pad_config.h)【源碼下載:https://gitee.com/Embedfire/embed_linux_driver_tutorial_imx6_code.git】,這里使用宏定義了引腳可選的PAD屬性值,并且通過宏定義的名字很容易知道宏代表的屬性值:

/* SPEED 帶寬配置 */

#define SPEED_0_LOW_50MHz       IOMUXC_SW_PAD_CTL_PAD_SPEED(0)

#define SPEED_1_MEDIUM_100MHz   IOMUXC_SW_PAD_CTL_PAD_SPEED(1)

#define SPEED_2_MEDIUM_100MHz   IOMUXC_SW_PAD_CTL_PAD_SPEED(2)

#define SPEED_3_MAX_200MHz      IOMUXC_SW_PAD_CTL_PAD_SPEED(3)



/* PUE 選擇使用保持器還是上下拉 */

#define PUE_0_KEEPER_SELECTED       IOMUXC_SW_PAD_CTL_PAD_PUE(0)

#define PUE_1_PULL_SELECTED         IOMUXC_SW_PAD_CTL_PAD_PUE(1)



/* PUS 上下拉配置 */

#define PUS_0_100K_OHM_PULL_DOWN  IOMUXC_SW_PAD_CTL_PAD_PUS(0)

#define PUS_1_47K_OHM_PULL_UP     IOMUXC_SW_PAD_CTL_PAD_PUS(1)

#define PUS_2_100K_OHM_PULL_UP    IOMUXC_SW_PAD_CTL_PAD_PUS(2)

#define PUS_3_22K_OHM_PULL_UP     IOMUXC_SW_PAD_CTL_PAD_PUS(3)


完整的代碼請閱讀源文件,這里只列出了文件“pad_config.h”部分代碼(embed_linux_driver_tutorial_imx6_code/bare_metal/led_rgb_c/pad_config.h)【源碼下載:https://gitee.com/Embedfire/embed_linux_driver_tutorial_imx6_code.git】。

十、編寫啟動文件

在 /uart 下創建 start.S 文件用于編寫啟動文件。
在匯編文件中設置“棧地址”并執行跳轉命令跳轉到main函數執行C代碼。

10.1 完整代碼

/***********************第一部分*********************/

  .text            //代碼段

  .align 2         //設置2字節對齊

  .global _start   //定義一個全局標號


/*************************第二部分*************************/

  _start:          //程序的開始

    b reset      //跳轉到reset標號處


/*************************第三部分*************************/

reset:

   mrc     p15, 0, r0, c1, c0, 0     /*  將 CP15 協處理器中的寄存器數據讀到 ARM 寄存器中   */

   bic     r0,  r0, #(0x1 << 12)     /*  清除第12位(I位)禁用 I Cache  */

   bic     r0,  r0, #(0x1 <<  2)     /*  清除第 2位(C位)禁用 D Cache  */

   bic     r0,  r0, #0x2             /*  清除第 1位(A位)禁止嚴格對齊   */

   bic     r0,  r0, #(0x1 << 11)     /*  清除第11位(Z位)分支預測   */

   bic     r0,  r0, #0x1             /*  清除第 0位(M位)禁用 MMU   */

   mcr     p15, 0, r0, c1, c0, 0     /*  將 ARM 寄存器的數據寫入到 CP15 協處理器寄存器中   */


/***********************第四部分*********************/

      ldr sp, =0x84000000   //設置棧地址64M

      b main                //跳轉到main函數


/***********************第五部分*******************/

    /*進入死循環*/

  loop:

      b loop


10.2 分析代碼

  • 第一部分
    .text 定義代碼段。
    .align 2 設置字節對齊。
    .global _start 生命全局標號_start。


/*************************第一部分*************************/

.text            //代碼段

.align 2         //設置2字節對齊

.global _start   //定義一個全局標號


  • 第二部分
    _start: 定義標號_start: ,它位于匯編的最前面,說以會首先被執行。
    b reset 使用b指令將程序跳轉到reset標號處。


/*************************第二部分*************************/

_start:          //程序的開始

   b reset      //跳轉到reset標號處


  • 第三部分
    通過修改CP15寄存器(系統控制寄存器) 關閉 I Cache 、D Cache、MMU 等等。
    我們暫時用不到的功能,如果開啟可能會影響我們裸機運行,為避免不必要的麻煩暫時關閉這些功能。


/*************************第三部分*************************/

reset:

   mrc     p15, 0, r0, c1, c0, 0     /*  將 CP15 協處理器中的寄存器數據讀到 ARM 寄存器中   */

   bic     r0,  r0, #(0x1 << 12)     /*  清除第12位(I位)禁用 I Cache  */

   bic     r0,  r0, #(0x1 <<  2)     /*  清除第 2位(C位)禁用 D Cache  */

   bic     r0,  r0, #0x2             /*  清除第 1位(A位)禁止嚴格對齊   */

   bic     r0,  r0, #(0x1 << 11)     /*  清除第11位(Z位)分支預測   */

   bic     r0,  r0, #0x1             /*  清除第 0位(M位)禁用 MMU   */

   mcr     p15, 0, r0, c1, c0, 0     /*  將 ARM 寄存器的數據寫入到 CP15 協處理器寄存器中   */


  • 第四部分
    ldr sp, =0x84000000 用于設置棧指針。野火i.MX6ULL開發板標配512M的DDR內存,裸機開發用不了這么多。程序中我們將棧地址設置到DDR的64M地址處。 這個值也可以根據需要自行定義。
    b main 只用跳轉指令跳轉到main函數中執行。


/***********************第四部分*********************/
      ldr sp, =0x84000000   //設置棧地址64M
      b main                //跳轉到main函數
  • 第五部分
    b loop 是“無返回”的跳轉指令。正常情況下,不會執行第五部分代碼。


/***********************第五部分*******************/
  /*進入死循環*/
  loop:
      b loop

十一、編寫鏈接腳本

寫好的代碼(無論是匯編還是C語言)都要經過編譯、匯編、鏈接等步驟生成二進制文件或者可供下載的文件。在編譯階編譯器會對每個源文件進行語法檢查并生成對應的匯編語言,匯編是將匯編文件轉化為機器碼。

[1] [2] [3] [4]
關鍵字:UART  串口使用 引用地址:IMX6ULL學習筆記(20)——UART串口使用

上一篇:解決方法:編譯IMX6ULL裸機串口程序提示錯誤arm-none-eabi-ld: cannot find -lgcc: 沒有那個文件或目
下一篇:IMX6ULL學習筆記(18)——GPIO中斷

推薦閱讀最新更新時間:2025-07-02 23:57

迅為IMX6ull開發板Linux系統EC20 4G模塊移植
1.4G網絡連接 對于嵌入式Linux而言,4G網絡連接是一個比較容易實現的功能,大多數的4G模塊接口都是MiniPCIE接口,但是深入了解一下就會發現,4G模塊的通信接口都是USB,所以4G模塊的驅動就是USB驅動,只要USB驅動正常,4G模塊在硬件上就能正常通信。下面看一下4G模塊的硬件原理圖: 在原理圖中,U25是4G模塊的MiniPCIE接口,然后通信引腳會接到U15的HUB芯片上,所以4G模塊會被識別成USB設備,CON5是SIM卡接口,在使用4G模塊時,需要先插入SIM卡。在i.MX6UL終結者開發板上使用的EC20 4G模塊,如圖 2. EC20 4G模塊配置 2.1. 添加USB設備信息 要使用EC20 4G
[單片機]
迅為<font color='red'>IMX6ull</font>開發板Linux系統EC20 4G模塊移植
IMX6ULL學習筆記】五、U-BOOT移植與解析
一、移植自定義開發板流程 1、添加 mx6ull_kodo_emmc_defconfig 配置文件(.config) 在 /config s目錄下,復制 mx6ull_14x14_evk_emmc_defconfig 文件,重命名為 mx6ull_kodo_emmc_defconfig 并修改其中內容,如下: CONFIG_SYS_EXTRA_OPTIONS= IMX_CONFIG=board/freescale/mx6ull_kodoboard/imximage.cfg,MX6ULL_EVK_EMMC_REWORK CONFIG_ARM=y CONFIG_ARCH_MX6=y CONFIG_TARGET_MX6ULL_K
[單片機]
【<font color='red'>IMX6ULL</font>學習筆記】五、U-BOOT移植與解析
一例使用STM32外設庫設置串口速度與實際不一樣的解決
最近手上有了塊金牛的stm32實驗板,興致勃勃的測試各種功能,但是碰到一個問題,用stm32 的外設庫寫串口程序,發現串口速度與實際不一樣。一度懷疑是外設庫的問題,但是用mdk的外設監控查看后,發現實際的串口速度為自定義的3倍,如圖 很疑惑,本人有一種鉆牛角尖的精神,因此一度debug下去,發現這個設置是在如下關鍵語句 (位于 外設庫 中的 USART_Init定義語句,在stm32f10x_usart.c中) USART_Init初始化函數 RCC_GetClocksFreq(&RCC_ClocksStatus); if (usartxbase == USART1_BASE) { apbclock = RCC_ClocksSt
[單片機]
使用FlyMCU對STM32串口下載程序出錯的解決方法
1,問題:使用FlyMCU對STM32進行串口下載程序時出現0KB出錯,如下圖所示: 2,分析:出現上述所示錯誤是因為勾選 了 編程到FLASH是寫選項字節 3,解決方法: (1)安裝 STM32 ST-LINK Utility 軟件(百度 搜索 “STM32 ST-LINK Utility” 即可獲得下載) (2)安裝軟件 (3)使用管理員身份運行該軟件 (4)操作: 步驟如下:Target -- Connect -- Option Bytes... 進入Option Bytes后 直接點擊Apply (5)使用STM32 ST-LINK Utility下載自己提供的 xxx.hex 文件 步驟如下:File -
[單片機]
<font color='red'>使用</font>FlyMCU對STM32<font color='red'>串口</font>下載程序出錯的解決方法
教你使用stm32接收串口的一幀數據
stm32支持接受單個數據或者一幀數據,若配置單個數據接收中斷的話,會出現接收包丟包,數據不完整的情況!因此在stm32的串口中斷中,還有一個IDLE中斷,用來產生串口接受一幀數據而產生的中斷,比如說串口發來n個數據,會產生n次接收中斷和一次IDLE中斷,因此方便使用者來接收主機發送或者從機返回的數據!若想發送一幀數據到串口請參照我博客中的另一篇文章——教你如何使用stm32發送一幀數據! 為了方便大家移植,提醒大家此次代碼中的代碼不需要任何修改,只需要復制粘貼即可! 第一步:首先配置串口中斷! (我配置的是串口3,可根據自己的使用情況更改配置。需要更改的地方:時 鐘RCC,GPIO_PIN,中斷入口,將所 有的USAR
[單片機]
stm32f407的串口使用集合(USART1,USART2,USART3,USART6)
由于項目需要使用多串口,因此基于正點原子探索者開發板的串口例程里的串口不夠用,在此基礎之上,自己對需要用的幾個串口操作做了簡要的封裝,其中已經實現的串口有串口1,串口2,串口3以及串口六,如果有大神能夠幫忙完善,本菜鳥在此先謝過,請多多指教 其中的頭文件內容如下: /* * file: usart.h * author: Jeans Oyoung * create on June 23, 2016 */ #include string.h #define USE_USART1 #define USE_USART2 #define USE_USART3 #define USE_USART4 #define USE_U
[單片機]
LPC1768串口使用
Lpc1768內置了四個串口通訊模塊,都是異步通訊模塊,其中,串口0/2/3是普通串口通訊,串口1與 UART0/2/3 基本相同,只是增加了一個 Modem 接口和 RS-486/EIA-486 模 式,不支持 IrDA,我們今天以串口0來演示串口的使用. 首先,使用串口0要打開串口0的時鐘 然后要配置相應的輸入輸出IO口為串口通訊功能 然后,要控制串口0的時鐘源,1768的大部分外設時鐘都可以選擇從cpu時鐘中進行分頻 接著,需要設置串口的通訊位,停止位以及波特率等 通過該寄存器能夠設置波特率 通過該寄存器可以設置通訊模式 記住,初始化完成之后需要將除數鎖存變為0,使其他人不能隨意修改波特率,接著對
[單片機]
LPC1768<font color='red'>串口</font><font color='red'>使用</font>
實驗八--uart
一。環境   系統:ubuntu12.04   開發板:jz2440   編譯器:gcc 二。說明 有空補上 三。代碼 head.S 1 @****************************************************************************** 2 @ File:head.S 3 @ 功能:設置SDRAM,將程序復制到SDRAM,然后跳到SDRAM繼續執行 4 @****************************************************************************** 5
[單片機]
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 革吉县| 青铜峡市| 孙吴县| 五峰| 会昌县| 常山县| 额尔古纳市| 桦南县| 高陵县| 平陆县| 上思县| 陈巴尔虎旗| 柳州市| 石嘴山市| 故城县| 宁明县| 基隆市| 陈巴尔虎旗| 济宁市| 亚东县| 曲沃县| 伊春市| 长乐市| 康定县| 临西县| 广灵县| 新巴尔虎右旗| 遵义市| 乐亭县| 舞钢市| 江北区| 洛南县| 西城区| 铁力市| 湾仔区| 中超| 张北县| 那曲县| 易门县| 芦山县| 通山县|