網絡消費網 >  5G > > 正文
        第4課:UART串口編程
        時間:2021-12-11 22:22:04
        首先明確一點:我們學習的串口是異步串口。在傳輸時,他們各自有各自的時鐘。就是我們說的波特率。

        我們學習的RS232與UART的區別是,UART使用標準的TTL/COMS電平 進過一個芯片使它的高低電平從TTL中0與3.3V 變成了 低電平5v到15v

        高電平-3v到-12v。

        首先說一下串口的數據幀格式。它由一個開始位,數據位,校驗位和停止位組成。

        平時數據處于1狀態。

        當要開始發送時,從UART改變TxD數據變成0狀態1個位的時間,在接受端到0之后的1.5位的時間,接收端開始接受數據。

        數據位分為5,6,7,8。四種類型的數據位。之后就是校驗位站1位,可以設置也可以不設置。最后的是停止位。可以是1位,1.5位,2位。這個是高電平1。

        UART可以用中斷或DMA來工作。它有3個單獨的通道。它由4部分組成,發送器,接收器,波特率發生器,控制邏輯組成。

        這些部分的設置都是通過寄存器來實現的。

        發送的過程是這樣的,UART只能通過shifter一位一位的來發數據。它先把要發的數據放到它的緩存FIFO里,當然緩存也可以取消。然后放入shifter里面來發出去。接受也是一樣的。通過緩存來接受,然后再通過接受的shifter來接。

        具體繼電器的設置主要由以下幾個:

        ULCON 邏輯數據楨格式控制器

        UCON 串口的控制繼電器

        UFCON FIFO控制寄存器

        UMCON 串口MODEN控制器 (可以控制AFC 自動流控制)

        以下是狀態寄存器,用來確定狀態的,比如說shifter發送器的狀態,接收器的狀態。

        UTRSTAT 接受發送控制器

        UERSTAT 錯誤狀態寄存器

        UFSTAT FIFO狀態寄存器

        最后一個單獨的設置寄存器,它用來設置波特率

        UBRDIV 波特率發生器

        以下來寫個簡單的串口例子。

        它不使用FIFO 中斷 而直接用shifter收發,采用輪詢的方式來檢測數據是否發送或被接受。然后通過minicom向開發板發送1表示亮燈,發送2表示熄燈。

        文件總共是7個 一個crt0.s main.c addr.h uart.h uart.c uart.lds makefile

        crt0.s 是關閉watchdog 并跳轉到mian 之后用個deadloop。

        .text.globl _start_start:ldrr0, =0x53000000 @ WATCHDOG closemovr1, #0x0strr1, [r0]ldr sp, =1024*4 @set stack,but the capitcy of cache is only 4k

        bl mainhalt_loop: b halt_loop

        第2個是addr.h用來寫寄存器的宏定義。

        #ifndef ADDR_H#define ADDR_H#define GPECON (*(volatile unsigned int *)0x56000040)#define GPEDAT (*(volatile unsigned int *)0x56000044)

        #define GPE12_out (1<<(12*2))#define GPE13_out (1<<(13*2))

        #define GPHCON (*(volatile unsigned int *)0x56000070)#define GPHUP (*(volatile unsigned int *)0x56000074)#define ULCON0 (*(volatile unsigned int *)0x50000000)#define UCON0 (*(volatile unsigned int *)0x50000004)#define UFCON0 (*(volatile unsigned int *)0x50000008)#define UMCON0 (*(volatile unsigned int *)0x5000000C)#define UTRSTAT0 (*(volatile unsigned int *)0x50000010)#define UFSTAT0 (*(volatile unsigned int *)0x50000018)#define UTXH0 (*(volatile unsigned int *)0x50000020)#define URXH0 (*(volatile unsigned int *)0x50000024)#define UBRDIV0 (*(volatile unsigned int *)0x50000028)

        #endif

        第3個文件來寫uart.h,這是個我們的功能

        #ifndef UART_H#define UART_Hvoid uart_init(); //初始化繼電器

        void uart_write(char *a); //串口寫一行

        void uart_read(char *a,int n);//串口讀n個字

        void uart_read_line(char *a); //讀一行

        void led_on(); //開燈

        void led_off();//關燈#endif

        第4個文件具體來寫uart.C

        #include"uart.h"#include"addr.h"#define UART_CLK 50000000 //我們用的是PCLK 50MHz#define UART_BAUD_RATE 115200 //比特率是115200#define UART_BRD (int)(UART_CLK/(UART_BAUD_RATE *16))-1 //計算公式的宏void uart_init(){GPHCON |=0xa0;//這個是TXD0與RXD0的設置,他們用的是GPH2和3復用的特殊GPHUP = 0x0c;//功能,所以還要在這設置上拉電阻,以區別高低電平的。ULCON0 = 0x3; //楨格式的設置8個數據位,無校驗UCON0 = 0x5;//選擇的是中斷與輪詢模式UFCON0 = 0;//不設FIFOUMCON0 = 0;//不設AFCUBRDIV0 = UART_BRD; //設置波特率}

        void uart_write(char *a){do{while(!(UTRSTAT0&2)); //UTRSTAT0的第2位是1的話表示發送數據的shifter內的數據已經被發送了,現在數據為空。如果里面的數據沒有空的話!(U&2)會一直是1,造成一直循環,知道出現UTRSTAT0第2位為1的情況。

        UTXH0 = *(a++); //發送寄存器只能一次最多發8位}while(*a!=\0);}

        void uart_read(char *a,int n){do{

        while(!(UTRSTAT0&1));//第1位為1表示shifter內的數據已經有了,可以讀了,如果為0的話將一直循環,知道有數據可讀。*(a++) = (char)URXH0;n--;}while(n>0);}

        void uart_read_line(char *a){do{

        while(!(UTRSTAT0&1));*(a++) = URXH0;}while(*a!=\0);}

        void led_on(){ GPEDAT = 0;}

        void led_off(){GPEDAT = (3<<12);}

        第5個文件main.c文件

        #include"addr.h"#include"uart.h"

        int main(){char *t = "Welcome to bootloader...\r\n";//這里只能用指針來傳遞,指針指向常量字符串的首地址傳入。char *t1 = "press 1 to light loop on\r\n";char *t2 ="press 2 to light loop off\r\n";char *t3 ="please input your choice\r\n";char r[10] ;//這里指針務必用數組來分配,一個沒有malloc函數。GPECON = GPE12_out|GPE13_out;uart_init();uart_write(t);uart_write(t1);uart_write(t2);uart_write(t3);while(1){uart_read(r,1);UTXH0 = *r;//這里是為了回顯switch(*r){case 1:led_on();break;case 2:led_off();break;}}return 0;}

        第6個連接文件

        SECTIONS {. = 0x00; .text : { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) } .bss ALIGN(4) : { *(.bss) *(COMMON) }}最后介紹下makefile比較好的寫法。

        SRC := $(wildcard *.c) //設定直接變量SRC,$(wildcard )表示使用通配符OBJC := $(patsubst %.c,%.o,$(SRC)) //表示把SRC里的值是.c結尾的換成.o結尾的結果保存到OBJC中

        uart.bin:uart.elfarm-linux-objcopy -O binary -S $^ $@//表示$@目標文件$^所有依賴arm-linux-objdump -D -m arm $^ >uart.disuart.elf:crt0.o $(OBJC)arm-linux-ld -T uart.lds $^ -o $@%.o:%.c //任意.o的依賴為.carm-linux-gcc -c $^ -o $@%.o:%.sarm-linux-gcc -c $^ -o $@

        clean:rm -f uart.bin uart.dis uart.elf uart.o crt0.o main.o

        然后用jtag燒入0x0內部SRAM的4k容量內,并在minicom里輸入數據來控制led

        關鍵詞: UART串口編

        版權聲明:
            凡注明來網絡消費網的作品,版權均屬網絡消費網所有,未經授權不得轉載、摘編或利用其它方式使用上述作品。已經本網授權使用作品的,應在授權范圍內使用,并注明"來源:網絡消費網"。違反上述聲明者,本網將追究其相關法律責任。
            除來源署名為網絡消費網稿件外,其他所轉載內容之原創性、真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考并自行核實。
        熱文

        網站首頁 |網站簡介 | 關于我們 | 廣告業務 | 投稿信箱
         

        Copyright © 2000-2020 www.fnsyft.com All Rights Reserved.
         

        中國網絡消費網 版權所有 未經書面授權 不得復制或建立鏡像
         

        聯系郵箱:920 891 263@qq.com

        備案號:京ICP備2022016840號-15

        營業執照公示信息

        亚洲欧洲视频在线观看| 亚洲AV香蕉一区区二区三区| 自拍偷自拍亚洲精品播放| 国产AV旡码专区亚洲AV苍井空 | 久久久无码精品亚洲日韩蜜臀浪潮| 亚洲精品国偷自产在线| 国内精品99亚洲免费高清| 亚洲精品视频久久久| 亚洲av高清在线观看一区二区 | 久久精品亚洲一区二区| 久久久久亚洲精品美女| 久久精品亚洲中文字幕无码网站| 亚洲AV永久无码精品成人| 亚洲成AV人片在线观看ww| 亚洲va在线va天堂va四虎| 亚洲人成电影福利在线播放| 亚洲午夜久久久精品影院| 中文字幕亚洲综合精品一区| 亚洲国产精品久久久久| 亚洲精品综合久久中文字幕| 亚洲国产精品白丝在线观看| 亚洲1234区乱码| 亚洲砖码砖专无区2023| 亚洲av永久无码一区二区三区| 日韩亚洲翔田千里在线| 亚洲爽爽一区二区三区| 亚洲精品蜜桃久久久久久| 亚洲av无码不卡一区二区三区| 亚洲一区二区中文| 亚洲国产成人手机在线电影bd| 国产精品亚洲自在线播放页码| 亚洲精品无码成人片久久不卡| 久久久久亚洲国产AV麻豆 | 亚洲视频一区在线观看| 亚洲另类自拍丝袜第1页| 亚洲一区二区三区高清在线观看| 亚洲国产av玩弄放荡人妇| 亚洲精品动漫人成3d在线| 亚洲女同成av人片在线观看| 亚洲精品自产拍在线观看动漫| 亚洲成综合人影院在院播放|