查看UART在硬件上的信息,閱讀JZ2440原理圖可以看到:
JZ2440開發板的UART0是可以跟USB相接的,用於打印調試,UART1,UART2兩個串口用來外接模塊。所以本文僅對UART0進行操作。
從上圖可以看到,UART0的TXD0和RXD0對應GPH2和GPH3,硬件上獲取的信息大概就就是這些,接下來對芯片手冊的UART部分進行分析:
首先需要設置UART0的TXD0和RXD0引腳,對應的GPHCON,GPHDAT,GPHUP寄存器見下圖:
GPHCON: 將GPH2和GPH3分別設置為TXD0和RXD0
GPHUP: 由於JZ2440的串口采用TTL標准,所以一開始應該是高電位,需要將相應引腳的電位上拉
這里往GPHUP寄存的的bit3和bit2里寫入1,即可完成設置。
下圖是串口的結構圖:
1、發送過程:數據由內存傳遞到發送緩沖寄存器,再由發送移位器通過發送引腳TXD0將數據傳遞出去
2、接收過程:外部數據通過接收引腳RXD0傳至接收移位器,再由接收緩沖寄存器傳遞至內存中。
另外:這里選用非FIFO模式,所以移位寄存器一次只能傳遞1個字節。
想要傳輸數據,波特率和數據格式肯定需要約定好,下面對波特率和數據格式的設置進行分析:
a、波特率
閱讀下方圖片中波特率的說明,可以知道:波特率發生器的設定與UBRDIV0和UART clock有關,UART clock這里選用PCLK=50MHz
波特率選用115200,根據公式UBRDIVn = (int)( UART clock / ( buad rate x 16) ) -1可以計算出:
UBRDIV0 = (int)(50000000 / (115200 x 16) ) -1
= (int)(27.1) -1 (四舍五入到最接近的整數)
= 27 -1 = 26
UART clock選擇:選用PCLK
b、數據格式
這里采用8位數據位,無校驗位,1位停止位,即 8n1
閱讀芯片手冊發現,UTRSATA0寄存器用來判斷UART0是否發送/接收完成:
當bit [2]為1時表明發送完成了
當bit [0]為0時表明接收完成了
傳輸模式寄存器:這里采用中斷/查詢模式
根據發送/接收緩沖寄存器的描述,可以發現:JZ2440采用小字節序,UTXH0和URXH0都是按1個字節發送或者接收。
對UART0的分析大概就是這些了,要實現以上的描述,離不開程序:
uart.c
1 /* UART0的初始化,以及UART0打印調試函數 */ 2 #include "s3c2440_soc.h" 3 void uart0_init(void) //串口0初始化函數 4 { 5 /* 設置UART0串口的引腳 6 ** GPHCON寄存器的bit[7:6]為10(GPH3為RXD[0]),bit[5:4]為10(GPH2為TXD[0]) 7 ** 因為開發板串口采用TTL標准,GPHUP寄存器對應的bit[2]和bit[3]需要設置為電位上拉 8 */ 9 GPHCON &=~((3<<6)|(3<<4)); //先清零 10 GPHCON |= ((2<<6)|(2<<4)); 11 GPHUP &=~((1<<2)|(1<<3)); //對應bit使能上拉 12 13 /* 設置波特率 14 ** UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1 15 ** UART的時鍾默認采用PCLK=50MHz 16 ** UBRDIV0 = (int)( 50000000 / ( 115200 x 16) ) –1 = 26 17 */ 18 19 UBRDIV0 = 26; 20 21 /* 設置數據發送格式:數據位為8位,無校驗位,停止位1位,即8n1 22 ** 設置ULCON0寄存器,bit[5:3]為000,bit2為0,bit[1:0]為11 23 ** 即ULCON0=0x00000003 24 */ 25 26 ULCON0 = 0x00000003; 27 28 /* 設置發送和接收模式為中斷/查詢模式: 29 ** UCON0寄存器的bit[3:2]為01,bit[1:0]為01,UCON0=0x00000005; 30 */ 31 32 UCON0 = 0x00000005; 33 } 34 35 /* 串口的輸入和輸出 */ 36 37 /* 根據UART的發送和接收狀態位寄存器 UTRSTAT0 的狀態,判斷發送/接收完成與否 38 ** 發送:看bit[2]的狀態,當bit[2]為1時表明發送完成了 39 ** 接收:看bit[0]的狀態,當bit[0]為0時表明接收完成了 40 ** 發送緩沖寄存器UTXH0,接收緩沖寄存器URXH0 41 */ 42 int putchar(int c) 43 { 44 while(!(UTRSTAT0 & (1<<2))); //當發送緩沖寄存器和發送移位器不是空的時候,循環等待 45 UTXH0 = (unsigned char)c; //反之,當上一個發送完了,再向發送緩沖寄存器寫入字符(這里是按單個字節發送) 46 } 47 int getchar(void) 48 { 49 while(!(UTRSTAT0 & (1<<0))); //當接收緩沖寄存器是空的時候,循環等待 50 return URXH0; //當接收緩沖寄存器非空的時候,返回接收緩沖寄存器得到的值 51 } 52 int puts(const char *s) 53 { 54 while (*s) //當*s有內容時 55 { 56 putchar(*s); //調用putchar函數 57 s++; //讓s指針加1 58 } 59 60 }
自定義頭文件 uart.h :
1 #ifndef _UART_H // 如果某個文件第一次包含這個頭文件,_UART_H這個宏沒有定義時 2 #define _UART_H // 定義_UART_H這個宏 3 4 void uart0_init(void); 5 int putchar(int c); 6 int getchar(void); 7 int puts(const char *s); 8 9 #endif
主程序 main.c :
1 #include "s3c2440_soc.h" 2 #include "uart.h" 3 int main(void) 4 { unsigned char c; 5 uart0_init(); 6 puts("Hello,world!\n\r"); 7 while(1) 8 { 9 c=getchar(); // 從PC鍵盤上得到輸入字符(串 ) 10 if (c == '\r') // 換行處理 ,不論輸入\n或者\r,都會換行並使光標到行首 11 { 12 putchar('\n'); 13 } 14 if (c == '\n') 15 { 16 putchar('\r'); 17 } 18 putchar(c); // 輸出得到的字符(串 )到PC,PC屏幕會顯示串口傳過來的字符(串 ) 19 } 20 return 0; 21 }
makefile :
all: arm-linux-gcc -c -o led.o led.c arm-linux-gcc -c -o uart.o uart.c arm-linux-gcc -c -o main.o main.c arm-linux-gcc -c -o start.o start.S arm-linux-ld -Ttext 0 start.o led.o uart.o main.o -o uart.elf arm-linux-objcopy -O binary -S uart.elf uart.bin arm-linux-objdump -D uart.elf > uart.dis clean: rm *.bin *.o *.elf *.dis
這里只列出了部分文件,上傳所有文件到 linux 編譯后,得到uart.bin文件,燒寫到JZ2440開發板,可以實現簡單的打印調試功能,見下圖: