使用fifo的好處有:
?1:串口的數(shù)據(jù)發(fā)送的數(shù)據(jù)量較大時(shí),使用fifo可以大大降低MCU的開(kāi)銷(xiāo)。
(有點(diǎn)類(lèi)似串入并出的cput處理模型,本質(zhì)上還是串行收發(fā))
?2:在某些特殊場(chǎng)合,例如制定較復(fù)雜的協(xié)議時(shí),可以使用fifo特性來(lái)做協(xié)議簡(jiǎn)化,比如一包
數(shù)據(jù)包含8個(gè)字節(jié),(并且fifo設(shè)置的長(zhǎng)度為8),這樣相當(dāng)于把uart轉(zhuǎn)換為類(lèi)似CAN/以太網(wǎng)模型,
這樣信息可擴(kuò)展性得到了質(zhì)的提高,當(dāng)然,這里需要同步協(xié)調(diào)。
?fifo分析拓展:
? ? ? ? ?? 1. 如果要用中斷來(lái)處理接收到的數(shù)據(jù),就是說(shuō),接收完數(shù)據(jù)然后產(chǎn)生中斷,再于中斷里處理接收的數(shù)據(jù)。如果要實(shí)現(xiàn)這個(gè)本意,要設(shè)置好觸發(fā)點(diǎn)。
? ??????? 至于超時(shí)中斷之類(lèi),那是另外一回事了。
?????????? 2. 就UART的中斷類(lèi)型而言,還包括:RBR中斷使能、THRE中斷使能、RX線(xiàn)狀態(tài)中斷使能、自動(dòng)波特率超時(shí)中斷使能等。
? ? ? ? ??
3.
FIFO定義說(shuō)了,先入先出緩沖區(qū),在UART中有什么用呢。我們可以用它來(lái)批量發(fā)送 數(shù)據(jù)(而非FIFO模式,只能一字節(jié)一字節(jié)的發(fā),而且發(fā)每個(gè)字節(jié)都需要等待緩沖區(qū)變空才能發(fā)送下一字節(jié)),這樣能在一定程度上提高數(shù)據(jù)發(fā)送速度。還有就是 避免數(shù)據(jù)包的的丟失(這個(gè)問(wèn)題,目前還沒(méi)體會(huì))。
?需要了解的相關(guān)知識(shí):
HCLK主要為 S3C2440 AHB 總線(xiàn)( Advanced High performance Bus )上掛接硬件提供工作頻率, AHB 總線(xiàn)主要掛接有內(nèi)存, NAND , LCD 控制器等硬件
FCLK 主要為 ARM920T 內(nèi)核提供工作頻率;
PCLK 主要為 APB 總線(xiàn)提供工作頻率, APB 總線(xiàn)主要掛接 UART 串口, Watchdog 等硬件控制器。 【所以在這里我們用PCLK作為UART的時(shí)鐘源】
外接設(shè)備 |
起始地址 |
結(jié)束地址 |
存儲(chǔ)控制器 |
0x48000000 |
0x48000030 |
USB Host控制器 |
0x49000000 |
0x49000058 |
中斷控制器 |
0x4A000000 |
0x4A00001C |
DMA |
0x4B000000 |
0x4B0000E0 |
時(shí)鐘和電源管理 |
0x4C000000 |
0x4C000014 |
LCD控制器 |
0x4D000000 |
0x4D000060 |
NAND FLASH控制器 |
0x4E000000 |
0x4E000014 |
攝像頭接口 |
0x4F000000 |
0x4F0000A0 |
UART |
0x50000000 |
0x50008028 |
脈寬調(diào)制計(jì)時(shí)器 |
0x51000000 |
0x51000040 |
USB設(shè)備 |
0x52000140 |
0x5200026F |
WATCHDOG計(jì)時(shí)器 |
0x53000000 |
0x53000008 |
IIC控制器 |
0x54000000 |
0x5400000C |
IIS控制器 |
0x55000000 |
0x55000012 |
I/O端口 |
0x56000000 |
0x560000B0 |
實(shí)時(shí)時(shí)鐘RTC |
0x57000040 |
0x5700008B |
A/D轉(zhuǎn)換器 |
0x58000000 |
0x58000010 |
SPI |
0x59000000 |
0x59000034 |
SD接口 |
0x5A000000 |
0x5A000040 |
AC97音頻編碼接口 |
0x5B000000 |
0x5B00001C
|
?
在start.s中完成對(duì)看門(mén)狗,內(nèi)存等進(jìn)行初始化: ?????
GPBCON???
? EQU????? 0x56000010
GPBDAT???????????? EQU????? 0x56000014
? AREA Init,CODE,READONLY? ? ? ? ? ??
//聲明一個(gè)只讀性質(zhì)的代碼段Init.
ENTRY??????????????????? ? ? ? ? ? ??
//入口
start
close watchdog
??? ldr r0,=0x53000000;????????????
? //將看門(mén)狗控制寄存器地址放入r0
??? mov r1,#0????????????????????? ?
??? str r1,[r0];???????????????????
? //將r1的值0放到r0中,即設(shè)置看門(mén)/
??? 狗控制寄存器的值為0
??? bl initmem;??????????????????? ??
//跳轉(zhuǎn)到initmem代碼段,初始化內(nèi)存
?? ?
??? IMPORT main;?????????? ? ? ? ? ??
//引入main.c中的main函數(shù)
??? ldr sp,=0x34000000;?????? ?? ?? ?
//調(diào)用c程序前先初始化桟指針
??? ldr lr,=loop;????????????????????
//設(shè)置main函數(shù)的返回地址
??? ldr pc,=main;????????????????? ??
//跳轉(zhuǎn)到c程序的main函數(shù)的入口處執(zhí)行
loop
??? b loop????? ;??????????????? ?
?? //死循環(huán)
initmen????????????????????????? ??
? //內(nèi)存初始化
??? ldr r0,=0x48000000;?????????????
? //加載內(nèi)存相關(guān)寄存器首地址r0
??? ldr r1,=0x48000034;??????????????
//加載內(nèi)存相關(guān)寄存器尾地址到r1
??? adr r2,memdata;???????????????? ?
//將寄存器配置數(shù)據(jù)地址段首地址加載到r2
?initmemloop
??? ldr r3,[r2],#4;??????????????????
//循環(huán)設(shè)置存寄存器
??? str r3,[r0],#4
??? teq r0,r1
??? bne initmemloop;????????????????
? //循環(huán)到最后一個(gè)寄存器時(shí)退出函數(shù)
??? mov pc,lr
?memdata?????????????????????????????
// 存放內(nèi)存控制器設(shè)置數(shù)據(jù)
?????????? DCD 0x22000000???????????????? ;BWSCON
?????????? DCD 0x00000700???????????????? ;BANKCON0?? ?
?????????? DCD 0x00000700???????????????? ;BANKCON1?? ?
?????????? DCD 0x00000700???????????????? ;BANKCON2?? ?
?????????? DCD 0x00000700???????????????? ;BANKCON3??????????? ?
?????????? DCD 0x00000700???????????????? ;BANKCON4?? ?
?????????? DCD 0x00000700???????????????? ;BANKCON5?? ?
?????????? DCD 0x00018005???????????????? ;BANKCON6?? ?
?????????? DCD 0x00018005???????????????? ;BANKCON7?? ?
?????????? DCD 0x008e07a3???????????????? ;REFRESH?????? ?
?????????? DCD 0x000000b1???????????????? ;BANKSIZE???? ?
?????????? DCD 0x00000030???????????????? ;MRSRB6
?????????? DCD 0x00000030???????????????? ;MRSRB7
?????????? END
在uart.c中: ?
#define GPHCON? (*(volitile unsigned long *)0X56000070)
#define GPHDAT? (*(volitile unsigned long *)0X56000074)
#define GPHUP?? (*(volitile unsigned long *)0X56000078)
#define UFCON0? (*(volitile unsigned long *)0x50000008)
#define UMCON0? (*(volitile unsigned long *)0X5000000C)
#define UCON0?? (*(volitile unsigned long *)0X50000004)
#define ULCON0? (*(volitile unsigned long *)0X50000000)
#define UART_CLK??????????? PCKL??????? ? ? ??
//UART0的時(shí)鐘源為PCLK
#define UART_BAUD_DATE????? 115200???? ? ? ? ?
//波特率
#define UART_BRD?????????? ((UART_CLK/(UART_BAUD_DATE*16))-1)
void uart_init(void)
{
????????????????? ?
??
? UFCON0=0xbf;?????? ? ? ? ? ? ?
? ? ? ? ? ?
//使用fifo(發(fā)送fifo和接收f(shuō)ifo的觸發(fā)深度都為32字節(jié))
【在中斷模式下的fifo要設(shè)置觸發(fā)方式(超時(shí)觸發(fā)或字節(jié)觸發(fā))】
??? UMCON0=0x00;?????? ? ? ? ? ? ?? ? ? ? ? ??
//不使用流控
??? UBRDIV0=UART_BRD;???????????????? ? ? ?? ?
//波特率為115200
??? GPHCON? |=0xa0;????????? ? ? ? ? ? ? ? ???
//GPH2,GPH3用作TXD0,RXD0
??? GPHUP=0x0c;????????????????????? ? ? ? ? ?
//GPH2,GPH3內(nèi)部上拉
??? UCON0=0X05
???????????????????????????????
?
//時(shí)鐘源為PCKL
??? ULCON0 &=0X03;???? ? ? ? ? ? ? ? ? ? ? ?
? //正常模式,數(shù)據(jù)格式:8個(gè)數(shù)據(jù)位,沒(méi)有流控,1個(gè)數(shù)據(jù)位
}
當(dāng)發(fā)送緩沖區(qū)里有數(shù)據(jù)需要傳送時(shí),我們就需要中斷,來(lái)完成發(fā)送數(shù)據(jù)的任務(wù)。這個(gè)中斷的產(chǎn)生,是由 s3c24xx_serial_start_tx()函數(shù)來(lái)完成的,具體來(lái)說(shuō),是它所調(diào)用的一個(gè)是中斷使能的函數(shù) enable_irq(TX_IRQ(port))來(lái)完成的。而此中斷一旦使能,就會(huì)調(diào)用該中斷的服務(wù)函數(shù) s3c24xx_serial_tx_chars()去做后續(xù)的工作。
其次,在響應(yīng)函數(shù)中,要注意檢測(cè)TxFIFO是否已滿(mǎn)。
發(fā) 送FIFO,是串口傳送數(shù)據(jù)非常重要的機(jī)制。相當(dāng)于提供了一個(gè)發(fā)送前的緩沖區(qū),給我們的發(fā)送工作的多樣化的處理帶來(lái)了可能。我們的中斷響應(yīng)函數(shù)需要把數(shù)據(jù) 從發(fā)送緩沖區(qū)先搬送到TxFIFO中,但搬送之前需要做的工作就是判斷FIFO是不是已經(jīng)滿(mǎn)了,如果已經(jīng)滿(mǎn)了,就不能再往里放數(shù)據(jù)了。
再次,在響應(yīng)函數(shù)中,要注意檢測(cè)傳送緩沖區(qū)是否已空。
這一點(diǎn)也很重要,我們要發(fā)送的數(shù)據(jù)來(lái)源于數(shù)據(jù)緩沖區(qū),如果該緩沖區(qū)的數(shù)據(jù)是空的,那我們就不需要去傳送了。
最后,如何做到連續(xù)不斷地傳送數(shù)據(jù)。
我們從數(shù)據(jù)緩沖區(qū)里把數(shù)據(jù)傳到TxFIFO中,要想持續(xù)地傳送數(shù)據(jù),很顯然還需要有人往數(shù)據(jù)緩沖區(qū)里不斷地放入新的數(shù)據(jù)。
void putc(unsigned char c)
{
? while(UFSTAT0 & (UFSTAT0=0<<14))
{
? UTXH0=C;
}
unsigined char getc(void)
{
?while(UFSTAT0 &(UFSTAT0=0<<6)
)
{
return URXH0;
}
在main.c中:
#include "start.s"
#include "uart.h"
int main()
{
? unsigned char c;
? uart_init();
?while(1)
?{
?
c=getc();
??? if(isDigit(c)||isLetter(c))
??? putc(c);
?
??? return 0;
?? ?
??? }
?
??
?
用FIFO發(fā)送數(shù)據(jù)時(shí),若所用為輪詢(xún)法(用在非高速場(chǎng)合,高速場(chǎng)合最好用BDMA或中 斷法,故此輪詢(xún)法很少用)需要保證接受FIFO不溢出,類(lèi)似中斷法,通過(guò)軟件來(lái)設(shè)置觸發(fā)條件。例如 if(rUFSTAT0&0x000f>0x0008)觸發(fā)讀為FIFO內(nèi)有8字節(jié)數(shù)據(jù)。但是我們同時(shí)還要考慮,不能空讀接收FIFO,例 如while((rUFSTAT0&0x000F)>0x0000){ 讀接收FIFO}。這種輪詢(xún)法比較山寨,穩(wěn)定性不咋地,適用低速。不提倡使用。
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
