uboot step-14 串口初始化UART
關于串口
對于嵌入式設備的開發,剛開始好多設備都無法使用,由于無法獲得程序的運行狀態,調試程序需要花費好多時間和精力,因此串口對于嵌入式程序的調試的作用顯而易見,當串口不能用時,可能只能用led的亮滅來略微指示程序的運行狀態,有了串口后,就能獲得更多的調試信息了。S3C6410的串口使用和其它設備都差不多,初始化配置串口后,就可以收發數據了。首先來看下芯片手冊上的串口框圖:
uart.png
串口信號線有發送數據信號線TXDn,接受數據信號線RXDn,如上圖,這兩根信號線分別連到了發送移位寄存器和接收移位寄存器,另外串口模塊還包含了兩個64Bytes的FIFO用來收發數據。除此外還有一個控制單元和波特率產生模塊,相應的部分都被連到了系統的外圍總線上面。
串口寄存器
先來看下相關的寄存器:
uart1.png
S3C6410有UART0,1,2,3四個串口,上面只列出了串口0的相關寄存器,其他幾個串口的寄存器說明和這個一樣,下面來詳細的說下:
ULCONx: 串口數據格式設置 數據長度,停止位長度 ,奇偶校驗位
ulcon0.png
UCONx: 串口控制寄存器 選擇時鐘源,發送接收方式
ucon1.png
ucon2.png
UFCONx: FIFO控制寄存器 設置FIFO觸發等級 使能
ufcon.png
UTRSTATx: 發送接收狀態寄存器
utrstat.png
UERSTATx: 錯誤狀態寄存器 幀錯誤,奇偶校驗錯誤等
uerstat.png
UFSTATx: FIFO 狀態寄存器
ufstat.png
UTXx: 發送數據寄存器 將要發送的數據丟給它
UTX.png
URXx: 接收數據寄存器 從這個寄存器獲得收到的數據
URX.png
UBRDIV : 波特率分頻值寄存器
UBRDIV.png
UDIVSLOT: 波特率分頻值小數部分(我起的名字。。。)
slot.png
串口初始化
串口初始化中需要完成的任務主要有以下幾個:
- 配置相關GPIO引腳功能為從串口功能
- 設置ULCONx寄存器來設置串口數據格式,數據位長度,停止位長度,奇偶校驗位等
- 設置串口控制寄存器UCONx,選擇串口時鐘源,收發數據模式:中斷,輪詢,DMA中斷等
- 設置波特率分頻數寄存器和波特率分頻值小數部分寄存器
- 設置FIFO控制寄存器,是否使能FIFO等
波特率設置
baud.png
波特率分頻值設置:
DIV_VAL=(PCLK/(bps * 16 ))-1
eg:
PCLK=66.5M=66500000
bps=115200 波特率
DIV_VAL=(66500000/115200*16)-1=35.078
UBRDIVn=35
小數部分為0.078
UDIVSLOTn中1的個數 除以16=0.078
UDIVSLOTn中1的個數 =1.248=1
根據上表,所以UDIVSLOTn的值為0x0080;
代碼實現
#define ULCON0 (*((volatile unsigned long *)0x7F005000))
#define UCON0 (*((volatile unsigned long *)0x7F005004))
#define UFCON0 (*((volatile unsigned long *)0x7F005008))
#define UMCON0 (*((volatile unsigned long *)0x7F00500C))
#define UTRSTAT0 (*((volatile unsigned long *)0x7F005010))
#define UFSTAT0 (*((volatile unsigned long *)0x7F005018))
#define UTXH0 (*((volatile unsigned char *)0x7F005020))
#define URXH0 (*((volatile unsigned char *)0x7F005024))
#define UBRDIV0 (*((volatile unsigned short *)0x7F005028))
#define UDIVSLOT0 (*((volatile unsigned short *)0x7F00502C))
#define GPACON (*((volatile unsigned long *)0x7F008000))
#define PCLK 66500000
#define BOUD 115200
void uart_init(void)
{
GPACON &= ~0xff;
GPACON |= 0x22;
/* ULCON0 */
ULCON0 = 0x3; /* 數據位:8, 無較驗, 停止位: 1, 8n1 */
UCON0 = 0x5; /* 使能UART發送、接收 */
UFCON0 = 0x01; /* FIFO ENABLE */
UMCON0 = 0;
/* 波特率 */
/* DIV_VAL = (PCLK / (bps x 16 ) ) - 1
* bps = 115200
* DIV_VAL = (66000000 / (115200 x 16 ) ) - 1
* = 35.08
*/
UBRDIV0 = (int)(PCLK/(BOUD*16)-1);
/* x/16 = 0.08
* x = 1
*/
UDIVSLOT0 = 0x1;
}
void putc(unsigned char c)
{
while (UFSTAT0 & (1<<14)); /* 如果TX FIFO滿,等待 */
UTXH0 = c; /* 寫數據 */
}
unsigned char getc(void)
{
unsigned char ret;
while ((UFSTAT0 & 0x7f) == 0); /* 如果RX FIFO空,等待 */
ret = URXH0; /* 取數據 */
if((ret == 0x0d) || (ret == 0x0a))
{
putc(0x0d);
putc(0x0a);
}
else
{
putc(ret);
}
return ret;
}
void uart_send_string(char *str)
{
while(*str)
{
putc(*str++);
}
putc(0x0d);
putc(0x0a);
}
此去經年
zhaiyk@sina.cn
August 12, 2016