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

S5PV210串口

發布者:真誠的友誼最新更新時間:2024-12-03 來源: cnblogs關鍵字:S5PV210  串口  UART 手機看文章 掃描二維碼
隨時隨地手機看文章

串口設置之輸入輸出字符

S5PV210 UART相關說明
        通用異步收發器簡稱UART,即UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER,它用來傳輸串行數據。發送數據時,CPU將并行數據寫入UART,UART按照一定的格式在一根電線上串行發出;接收數據時,UART檢測另一根電線的信號,將串行收集在緩沖區中,CPU即可讀取UART獲得這些數據。
        在S5PV210中,UART提供了4對獨立的異步串口I/O端口,有4個獨立的通道,每個通道可以工作于DMA模式或者中斷模式。其中,通道0有256byte的的發送FIFO和256byte的接收FIFO,通道1有64byte的的發送FIFO和64byte的接收FIFO,而通道2和3只有16byte的的發送FIFO和16byte的接收FIFO。
S5PV210的uart結構圖如下:

image

S5PV210的uart結構圖

UART使用標準的TTL/CMCOS邏輯電平來表示數據,為了增強數據抗干擾能力和提高傳輸長度,通常將TTL/CMOS邏輯電平轉換為RS-232邏輯電平,查看原理圖可知Mini210S使用的是MAX3232SOP芯片,使用的是TX0和DX0:

image

搜索“XuTXD0”,可知:

image

通過設置UART相關寄存器,我們就可以驅動UART工作,達到發送和接收字符的目的。

程序例子:(完整代碼見鏈接)

/*main.c*/
int main()
{
char c;
uart_init(); // 初始化串口
while (1)
{
c = getc (); // 接收一個字符c
putc(c+1); // 發送字符c+1
}
return 0;
}
在main函數中,先會調用uart_init()初始化UART,然后使用getc接收PC發過來的字符,再調用putc()將該字符+1回復給PC。
/*uart.c*/
void uart_init()
{
// 1 配置引腳用于RX/TX功能
GPA0CON = 0x22222222;
GPA1CON = 0x2222;
// 2 設置數據格式等
UFCON0 = 0x1; // 使能FIFO
UMCON0 = 0x0; // 無流控
ULCON0 = 0x3; // 數據位:8, 無校驗, 停止位: 1
UCON0 = 0x5; // 時鐘:PCLK,禁止中斷,使能UART發送、接收 // 3 設置波特率
UBRDIV0 = UART_UBRDIV_VAL; // 35
UDIVSLOT0 = UART_UDIVSLOT_VAL; // 0x1
}
上述代碼共有3個步驟,下面我們來一一講解每一個步驟:
第一步 配置引腳用于RX/TX功能
參考UART引腳連接圖,我們需要設置GPA0CON和GPA1CON寄存器使GPA0和GPA1引腳用于UART功能。

image

GPA0CON寄存器圖

image

GPA1CON寄存器圖

第二步 設置數據格式等
<1> ULCON0用來設置數據格式,見下圖

image

Word Length = 11,8bit的數據;
Number of Stop Bit = 0,1bit的停止位;
Parity Mode = 000,無校驗;
Infrared Mode =0,使用普通模式;
所以ULCON0=0x3

<2> 9UCON0是UART的配置寄存器,見下圖

image

image

Receive Mode = 01 ,使用中斷模式或者輪詢模式;
Transmit Mode = 01,使用中斷模式或者輪詢模式;
Send Break Signal = 0,普通傳輸;
Loop-back Mode = 0,不使用回環方式;
我們采用輪詢的方式接受和發送數據,不使用中斷,所以bit[6-9]均為0;
Clock Selection = 0,使用PCLK作為UART的工作時鐘;
我們不使用DMA,所以bit[16]和bit[20]均為0;
所以UCON0 = 0x5

<3> UFCON0和UMCON0
這兩個寄存器比較簡單,UFCON0用來使能FIFO,UMCON0用來設置無流控。

第三步 設置波特率
波特率即每秒傳輸的數據位數,涉及兩個寄存器:UBRDIV0和UDIVSLOT0

image

image

波特率設置相關公式:UBRDIVn + (num of 1's in UDIVSLOTn)/16 = (PCLK / (bps x 16)) ?1
其中,由Maximum Operating Frequency for Each Sub-block圖可知,UART工作于PSYS下,所以PCLK即PCLK_PSYS = 66.5MHz,我們的波特率bps設置為115200,所以
(66.5MHz/(115200 x 16)) – 1 = 35.08 = UBRDIVn + (num of 1's in UDIVSLOTn)/16,所以我們設置UBRDIV0=35,UDIVSLOT0=0x1
getc()和putc()的代碼如下:
// 接收一個字符
char getc(void)
{
while ((UFSTAT0 & 0xff) == 0); // 如果RX FIFO空,等待
return URXH0; // 取數據
}
// 發送一個字符
void putc(char c)
{
while (UFSTAT0 & (1<<24)); // 如果TX FIFO滿,等待
UTXH0 = c; // 寫數據
}

image

UART數據發送寄存器

image

UART數據接收寄存器

image

發送/接收狀態寄存器

通過讀UTRSTAT0 發送/接收狀態寄存器,當Receive buffer data ready= 1時說明接收到數據,讀URXH0寄存器可以得到8bit的數據;當Transmitter empty = 1時說明可以發送數據,寫8bit的數據到UTXH0。

 

移植printf和scanf功能

第一節 移植的途徑
對于如何移植printf和scanf,我們有許多選擇:
1) 移植linux的printk功能,版本越新越難移植,但是功能也越強大;
2) 移植uboot的printf和scanf功能,實際uboot也是從linux內核中移植而來的;
3) 完全自己編寫,但是功能比較弱;
在保證整個裸機其他代碼部分沒有任何問題,且編譯器也沒有任何問題的情況下,上述三種方法都是可行的。下面我們只是直接利用網友從linux中移植好的printk,為我們的裸機代碼增加上該部分功能。
第二節 移植步驟
第一步 解壓printf.rar到uart_stdio目錄,解壓成功后會多出include 和lib兩個目錄,其中include放的是相關頭文件,lib放的是printf和scanf相關的代碼。
第二步 修改uart_stdio目錄下的makefile,將lib目錄下的代碼編譯鏈接成lib.a,然后將lib.a編譯進bin中,具體修改見源碼。
第三步 編寫main函數進行測試。
第三節 程序相關講解
完整代碼見目錄uart_stdio,與前一章的代碼相比,BL1目錄的代碼沒有任何變化,BL2目錄的代碼多了include和lib目錄以及main.c的內容被修改了。
1. /lib/printf.c

<1> printf的定義如下:
int printf(const char *fmt, ...)
{
    int i;
    int len;
    va_list args; // va_list 即 char *   
    va_start(args, fmt);
    len = vsprintf(g_PCOutBuf,fmt,args);// 內部使用了va_arg()
    va_end(args);
    for (i = 0; i < strlen(g_PCOutBuf); i++)
    {
        putc(g_PCOutBuf[i]);
    }
    return len;
}

<2> printf函數是個變參函數,什么是變參函數:
可變參數函數的原型聲明為type VAFunction(type arg1, type arg2, … ); 參數可以分為兩部分:個數確定的固定參數和個數可變 的可選參數。函數至少需要一個固定參數,固定參數的聲明和普通函數一樣;可選參數由于個數不確定,聲明時用'...'表示。固定參數和可選參數公同構成一個函數的參數列表。
<3> printf函數涉及了3個十分重要的宏:
宏1: #define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND))))
宏2: #define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND))))

宏3: #define va_end(ap) (void) 0
在這些宏中,va 就是 variable argument(可變參數)的意思;
ap:是指向可變參數表的指針;
A:指可變參數表的前一個固定參數;
T:可變參數的類型。
va_list 也是一個宏,其定義為 typedef char * va_list,實質上是一char型指針。

<4> 三個宏的作用:
1) va_start 宏 作用:
根據v取得可變參數表的首指針并賦值給ap,方法:最后一個固定參數A的地址 + 第一個變參對A的偏移地址,然后賦值給 ap,這樣 ap 就是可變參數表的首地址。 舉例:
如果有變參函數的聲明是 void va_test(char a, char b,char c, …),則它的固定參數依次是 a,b,c,最后一個固定參數 為 c,因此就是 va_start(ap, c)。
2) va_arg 宏 作用:
指取出當前 ap 所指的可變參數并將 ap 指針指向下一可變參數。
3) va_end 宏 作用:
結束可變參數的獲取。va_end ( list )實際上被定義為空,沒有任何真實對應的代碼,用于代碼對稱,與 va_start 對應。
<5> 得到可變參數個數的三種辦法:
1) 函數的第一個參數,指定后續的參數個數,如 func(int num,...);
2) 根據隱含參數,判斷參數個數,如 printf 系列的,通過字符串中%的個數判斷;
3) 特殊情況下(如參數都是不大于 0xFFFF 的 int),可以一直向低處訪問堆棧,直到返回地址。

有了上述知識我們就可以看懂printf()函數的內容了,首先va_start(args, fmt);會將可變參數的首地址保存在args中,然后調用vsprintf(g_PCOutBuf,fmt,args)進行處理,在vsprintf()中,會調用va_arg()逐個的取出變參,然后進行解析。如果是普通字符則無須轉換,直接保存在g_PCOutBuf;如果是字符串,則從可變參數表中拿到指向字符串的指針,將字符串的內容拷貝到g_PCOutBuf;如果是數字,則調用number函數進行處理,并把解析的結果存放在g_PCOutBuf。所有,最后只調用putC函數把g_PCOutBuf里的字符一個個的打印出來就可以了。scanf函數的原理和printf類似,這里不再進行解釋.

2. main.c
完整代碼如下:
int main()
{
int a = 0,b = 0;
char *str = 'hello world';
uart_init();
printf('%sn',str);
while (1)
{
printf('please enter two number: rn');
scanf('%d %d', &a, &b);
printf('rn');
printf('the sum is: %drn', a+b);
}
return 0;
}
首先會打印“hello world”,然后從串口接收兩個數字,最后輸出它們的和。


關鍵字:S5PV210  串口  UART 引用地址:S5PV210串口

上一篇:S5PV210按鍵控制LED
下一篇:S5PV210 NAND Flash

小廣播
設計資源 培訓 開發板 精華推薦

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

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

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 高要市| 鹿泉市| 大化| 大姚县| 玛纳斯县| 翼城县| 泸定县| 京山县| 怀仁县| 左贡县| 沙雅县| 岳池县| 江门市| 廉江市| 保山市| 海伦市| 鹤庆县| 阿鲁科尔沁旗| 竹溪县| 雅江县| 彰化市| 新龙县| 河西区| 白朗县| 应用必备| 瓮安县| 宝山区| 隆子县| 泗洪县| 兴文县| 平江县| 绥德县| 洪雅县| 社旗县| 洮南市| 开平市| 石屏县| 土默特左旗| 缙云县| 江陵县| 咸宁市|