0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一文詳解FIFO處理機(jī)制

我快閉嘴 ? 來源:CSDN技術(shù)社區(qū) ? 作者:離凌寒 ? 2022-09-14 10:52 ? 次閱讀

一、FIFOFIFO

First Input First Output的縮寫,先入先出隊(duì)列。

使用的場(chǎng)景:一般是在不同的時(shí)鐘之間的數(shù)據(jù)傳輸(簡(jiǎn)單理解即:一個(gè)(讀寫)快,另外的一個(gè)(讀寫)慢的場(chǎng)景中。)

本質(zhì)操作:就是將收的數(shù)據(jù)存儲(chǔ)的一個(gè)線性的數(shù)組中,通過指針指向該數(shù)組的自加1(偏移)來遍歷數(shù)據(jù),達(dá)到讀取或者寫入的目的。

作用:起到緩沖環(huán)節(jié),可防止數(shù)據(jù)的丟失。

對(duì)數(shù)據(jù)量大的進(jìn)行存儲(chǔ),避免頻繁的總線操作。并且可滿足dma的操作。

在fifo中需要理解連個(gè)重要成員:

寬度:指一次寫讀操作的數(shù)據(jù)位數(shù)。

深度:存儲(chǔ)多少個(gè)寬度的數(shù)據(jù)。(如:存儲(chǔ)8個(gè)16位寬的數(shù)據(jù))。

第一類、FIFO處理機(jī)制如下:

FIFO信息的定義:

/*
該結(jié)構(gòu)體定義成員有
緩存區(qū),
長(zhǎng)度,
輸出,
輸入的計(jì)數(shù)。
*/
typedefstructfifo_t{
uint8_t*buf;
uint32_tsize;
uint32_tin;
uint32_tout;
}_fifo_str;
#definemin(x,y)((x)
1234567891011121314

1、初始化FIFO

fifo_strfifo_str;

intFifoInit(uint8_t*fifo_addr,uint32_tfifo_size)//初始化fifo
{
_fifo_str*p=&fifo_str;

if(fifo_addr==NULL||fifo_size==0)//判斷數(shù)據(jù)是否為空
return-1;

memset((char*)p,0,sizeof(_fifo_str));//初始化結(jié)構(gòu)體
p->buf=fifo_addr;//對(duì)應(yīng)寬度
p->in=0;//輸入計(jì)數(shù)
p->out=0;//輸出計(jì)數(shù)
p->size=fifo_size;//對(duì)應(yīng)深度
return0;
}
12345678910111213141516

2、數(shù)據(jù)的長(zhǎng)度獲取

//數(shù)據(jù)的實(shí)際使用數(shù)據(jù)空間長(zhǎng)度
intFifoDataLen(void)
{
_fifo_str*p=&fifo_str;
return(p->in-p->out);//輸入計(jì)數(shù)-輸出計(jì)數(shù)
}
//剩余數(shù)據(jù)空間長(zhǎng)度
intFifoSpaceLen(void)
{
_fifo_str*p=&fifo_str;

return(p->size-(p->in-p->out));//定義長(zhǎng)度-(實(shí)際長(zhǎng)度)
}
12345678910111213

3、FIFO的進(jìn)和出處理

//獲取fifo數(shù)據(jù)
//數(shù)據(jù)的內(nèi)容緩存區(qū),要讀的長(zhǎng)度
intFifoRead(uint8_t*buf,uint32_tlen)
{
uint32_ti=0,j=0;
_fifo_str*p=&fifo_str;

j=(p->out%p->size);//獲取剩余空間長(zhǎng)度未讀量
len=min(len,p->in-p->out);//防止長(zhǎng)度為超出實(shí)際擁有的數(shù)據(jù)長(zhǎng)度,即讓讀取的長(zhǎng)度在(0<設(shè)定len<定義的緩存區(qū)長(zhǎng)度len?)這間的實(shí)際長(zhǎng)度
i=min(len,p->size-j);//獲取實(shí)際內(nèi)容的長(zhǎng)度,的數(shù)據(jù)長(zhǎng)度
memcpy(buf,p->buf+j,i);//將數(shù)據(jù)通道里的數(shù)據(jù)拷貝給緩存區(qū)
memcpy(buf+i,p->buf,len-i);//將未有數(shù)據(jù)的區(qū)域存入,對(duì)應(yīng)為寫入數(shù)據(jù)的區(qū)域數(shù)據(jù)(即,有數(shù)據(jù)的填數(shù)據(jù),沒數(shù)據(jù)的地方補(bǔ)0)
p->out+=len;//已讀的數(shù)據(jù)量
returnlen;//實(shí)際讀到的數(shù)據(jù)長(zhǎng)度
}
//對(duì)fifo寫入數(shù)據(jù)
intFifoWrite(uint8_t*buf,uint32_tlen)
{
uint32_ti=0,j=0;
_fifo_str*p=&fifo_str;

j=p->in%p->size;//獲取要寫入的剩余空間長(zhǎng)度
len=min(len,p->size-p->in+p->out);//得到實(shí)際寫入的長(zhǎng)度
i=min(len,p->size-j);//實(shí)際寫入數(shù)據(jù)的長(zhǎng)度
memcpy(p->buf+j,buf,i);//將寫入的數(shù)據(jù)的內(nèi)容拷貝值數(shù)據(jù)中。
memcpy(p->buf,buf+i,len-i);//補(bǔ)充多余空間的內(nèi)容
p->in+=len;//記錄實(shí)際寫入數(shù)據(jù)的數(shù)量
returnlen;//返回寫入的長(zhǎng)度
}

123456789101112131415161718192021222324252627282930

4、置位記錄量

//清空fifo中的記錄量
voidFifoClear(void)
{
_fifo_str*p=&fifo_str;
p->in=0;
p->out=0;
}
1234567

5、應(yīng)用處理機(jī)制

#defineLEN2048
uint8_tpdata[LEN]={0};
FifoInit(pdata,LEN);//初始化FIFO
uint8_tbuf[32]={0};
inttx_len=0;
uint8_ttx_buf[100]={0};

HAL_UART_Receive_IT(&huart1,buf,IT_LEN);//串口的接收中斷開啟
while(1)
{
tx_len=FifoDataLen();//獲取數(shù)據(jù)長(zhǎng)度
if(tx_len>0)
{
tx_len=(tx_len>100)?100:tx_len;//判讀數(shù)據(jù)長(zhǎng)度是否越界
FifoRead(tx_buf,tx_len);//讀取在中斷中寫入FIFO緩存的數(shù)據(jù)
HAL_UART_Transmit(&huart1,tx_buf,tx_len,1000);//將讀到的數(shù)據(jù)通過串口發(fā)送出來
}
}

接收回調(diào)函數(shù)中的處理
HAL_UART_RxCpltCallback(UART_HandleTypeDef*huart)
{
if(FifoSpaceLen()>=串口記錄的接收數(shù)據(jù)長(zhǎng)度)//判斷寫入FIFO空間的數(shù)據(jù)量是否大于接收的數(shù)據(jù)量
{
FifoWrite(huart->pRxBuffPtr,huart->RxXferCount);//想FIFO中寫入數(shù)據(jù)
}
}
123456789101112131415161718192021222324252627

該FIFO的處理機(jī)制中用的記錄是通過uint32t類型進(jìn)行記錄的,可能在遇到超出其數(shù)據(jù)極限的情況,導(dǎo)致數(shù)據(jù)通信異常。(該類型的數(shù)據(jù)極限較大,為特殊情況可能出現(xiàn)的情況)。

第二類、FIFO處理機(jī)制如下:

/*定義串口波特率和FIFO緩沖區(qū)大小,
分為發(fā)送緩沖區(qū)和接收緩沖區(qū)*/
#ifUART1_FIFO_EN==1
#defineUART1_BAUD115200
#defineUART1_TX_BUF_SIZE1*1024
#defineUART1_RX_BUF_SIZE1*1024
#endif

/*串口設(shè)備結(jié)構(gòu)體
設(shè)置發(fā)送、接收緩存區(qū)(長(zhǎng)度),
并設(shè)置兩個(gè)變量,一個(gè)是指針,一個(gè)是計(jì)數(shù)
*/
typedefstruct
{
USART_TypeDef*uart;/*STM32內(nèi)部串口設(shè)備指針*/

uint8_t*pTxBuf;/*發(fā)送緩沖區(qū)*/
uint8_t*pRxBuf;/*接收緩沖區(qū)*/
uint16_tusTxBufSize;/*發(fā)送緩沖區(qū)大小*/
uint16_tusRxBufSize;/*接收緩沖區(qū)大小*/

__IOuint16_tusTxWrite;/*發(fā)送緩沖區(qū)寫指針*/
__IOuint16_tusTxRead;/*發(fā)送緩沖區(qū)讀指針*/
__IOuint16_tusTxCount;/*等待發(fā)送的數(shù)據(jù)個(gè)數(shù)*/

__IOuint16_tusRxWrite;/*接收緩沖區(qū)寫指針*/
__IOuint16_tusRxRead;/*接收緩沖區(qū)讀指針*/
__IOuint16_tusRxCount;/*還未讀取的新數(shù)據(jù)個(gè)數(shù)*/

void(*SendBefor)(void);/*開始發(fā)送之前的回調(diào)函數(shù)指針(主要用于RS485切換到發(fā)送模式)*/
void(*SendOver)(void);/*發(fā)送完畢的回調(diào)函數(shù)指針(主要用于RS485將發(fā)送模式切換為接收模式)*/
void(*ReciveNew)(uint8_t_byte);/*串口收到數(shù)據(jù)的回調(diào)函數(shù)指針*/
uint8_tSending;/*正在發(fā)送中*/

}UART_T;

/*定義每個(gè)串口結(jié)構(gòu)體變量*/
#ifUART1_FIFO_EN==1
staticUART_Tg_tUart1;
staticuint8_tg_TxBuf1[UART1_TX_BUF_SIZE];/*發(fā)送緩沖區(qū)*/
staticuint8_tg_RxBuf1[UART1_RX_BUF_SIZE];/*接收緩沖區(qū)*/
#endif

12345678910111213141516171819202122232425262728293031323334353637383940414243

怎樣才叫做回調(diào)函數(shù)?回調(diào)函數(shù),是一個(gè)通過函數(shù)指針調(diào)用的函數(shù)。如果你把函數(shù)的指針(地址)作為參數(shù)傳遞給另一個(gè)函數(shù),當(dāng)這個(gè)指針被用為調(diào)用它所指向的函數(shù)時(shí),我們就說這是回調(diào)函數(shù)。

區(qū)別指針函數(shù)和函數(shù)指針:

//指針函數(shù):
int*fun(intx,inty)
int*x=fun(4,5);
在調(diào)用指針函數(shù)時(shí),需要同類型的指針來接收函數(shù)返回值
是函數(shù),返回值時(shí)指針
屬于數(shù)據(jù)類型
123456
//函數(shù)指針:
int(*fun)(intx,inty)
intx(intx,inty);
x=fun;
fun=&x;
x=(*fun)(1,3);
是指針,指向函數(shù)。
屬于函數(shù)名稱
12345678

1.初始化串口FIFO對(duì)應(yīng)的相關(guān)的變量

staticvoidUartVarInit(void)
{
#ifUART1_FIFO_EN==1
g_tUart1.uart=USART1;/*STM32串口設(shè)備*/
g_tUart1.pTxBuf=g_TxBuf1;/*發(fā)送緩沖區(qū)指針*/
g_tUart1.pRxBuf=g_RxBuf1;/*接收緩沖區(qū)指針*/
g_tUart1.usTxBufSize=UART1_TX_BUF_SIZE;/*發(fā)送緩沖區(qū)大小*/
g_tUart1.usRxBufSize=UART1_RX_BUF_SIZE;/*接收緩沖區(qū)大小*/
g_tUart1.usTxWrite=0;/*發(fā)送FIFO寫索引*/
g_tUart1.usTxRead=0;/*發(fā)送FIFO讀索引*/
g_tUart1.usRxWrite=0;/*接收FIFO寫索引*/
g_tUart1.usRxRead=0;/*接收FIFO讀索引*/
g_tUart1.usRxCount=0;/*接收到的新數(shù)據(jù)個(gè)數(shù)*/
g_tUart1.usTxCount=0;/*待發(fā)送的數(shù)據(jù)個(gè)數(shù)*/
g_tUart1.SendBefor=0;/*發(fā)送數(shù)據(jù)前的回調(diào)函數(shù)*/
g_tUart1.SendOver=0;/*發(fā)送完畢后的回調(diào)函數(shù)*/
g_tUart1.ReciveNew=0;/*接收到新數(shù)據(jù)后的回調(diào)函數(shù)*/
g_tUart1.Sending=0;/*正在發(fā)送中標(biāo)志*/
#endif
}
1234567891011121314151617181920

明確中斷服務(wù)程序的順序:中斷函數(shù)處理:void USART1_IRQHandler(void)—》UART中斷請(qǐng)求:HAL_UART_IRQHandler(UART_HandleTypeDef *huart)—》中斷使能:UART_Receive_IT— 》中斷回調(diào)函數(shù) HAL_UART_RxCpltCallback(huart);

#ifUART1_FIFO_EN==1
voidUSART1_IRQHandler(void)//系統(tǒng)中串口的中斷函數(shù)入口
{
UartIRQ(&g_tUart1);
}
#endif

1234567

2.編輯自定義的UART中斷請(qǐng)求

staticvoidUartIRQ(UART_T*_pUart)
{
uint32_tisrflags=READ_REG(_pUart->uart->ISR);
uint32_tcr1its=READ_REG(_pUart->uart->CR1);
uint32_tcr3its=READ_REG(_pUart->uart->CR3);

if((isrflags&USART_ISR_RXNE)!=RESET)
{
/*從串口接收數(shù)據(jù)寄存器讀取數(shù)據(jù)存放到接收FIFO*/
uint8_tch;
ch=READ_REG(pUart->uart->RDR);
/*讀串口接收數(shù)據(jù)寄存器*/
_pUart->pRxBuf[_pUart->usRxWrite]=ch;/*填入串口接收FIFO*/
if(++_pUart->usRxWrite>=_pUart->usRxBufSize)/*接收FIFO的寫指針+1*/
{
_pUart->usRxWrite=0;
}
if(_pUart->usRxCountusRxBufSize)/*統(tǒng)計(jì)未處理的字節(jié)個(gè)數(shù)*/
{
_pUart->usRxCount++;
}
/*回調(diào)函數(shù),通知應(yīng)用程序收到新數(shù)據(jù),一般是發(fā)送1個(gè)消息或者設(shè)置一個(gè)標(biāo)記*/
//if(_pUart->usRxWrite==_pUart->usRxRead)
//if(_pUart->usRxCount==1)
{
if(_pUart->ReciveNew)
{
_pUart->ReciveNew(ch);/*比如,交給MODBUS解碼程序處理字節(jié)流*/
}
}
}
/*處理發(fā)送緩沖區(qū)空中斷*/
if(((isrflags&USART_ISR_TXE)!=RESET)&&(cr1its&USART_CR1_TXEIE)!=RESET)
{
//if(_pUart->usTxRead==_pUart->usTxWrite)
if(_pUart->usTxCount==0)/*發(fā)送緩沖區(qū)已無數(shù)據(jù)可取*/
{
/*發(fā)送緩沖區(qū)的數(shù)據(jù)已取完時(shí),禁止發(fā)送緩沖區(qū)空中斷(注意:此時(shí)最后1個(gè)數(shù)據(jù)還未真正發(fā)送完畢)*/
//USART_ITConfig(_pUart->uart,USART_IT_TXE,DISABLE);
CLEAR_BIT(_pUart->uart->CR1,USART_CR1_TXEIE);/*使能數(shù)據(jù)發(fā)送完畢中斷*/
//USART_ITConfig(_pUart->uart,USART_IT_TC,ENABLE);
SET_BIT(_pUart->uart->CR1,USART_CR1_TCIE);
}
Else/*還有數(shù)據(jù)等待發(fā)送*/
{
_pUart->Sending=1;/*從發(fā)送FIFO取1個(gè)字節(jié)寫入串口發(fā)送數(shù)據(jù)寄存器*/
//USART_SendData(_pUart->uart,_pUart->pTxBuf[_pUart->usTxRead]);
_pUart->uart->TDR=_pUart->pTxBuf[_pUart->usTxRead];
if(++_pUart->usTxRead>=_pUart->usTxBufSize)
{
_pUart->usTxRead=0;
}
_pUart->usTxCount--;
}
}
/*數(shù)據(jù)bit位全部發(fā)送完畢的中斷*/
if(((isrflags&USART_ISR_TC)!=RESET)&&((cr1its&USART_CR1_TCIE)!=RESET))
{
//if(_pUart->usTxRead==_pUart->usTxWrite)
if(_pUart->usTxCount==0)
{/*如果發(fā)送FIFO的數(shù)據(jù)全部發(fā)送完畢,禁止數(shù)據(jù)發(fā)送完畢中斷*/
//USART_ITConfig(_pUart->uart,USART_IT_TC,DISABLE);
CLEAR_BIT(_pUart->uart->CR1,USART_CR1_TCIE);/*回調(diào)函數(shù),一般用來處理RS485通信,將RS485芯片設(shè)置為接收模式,避免搶占總線*/
if(_pUart->SendOver)
{
_pUart->SendOver();
}
_pUart->Sending=0;
}

else
{/*正常情況下,不會(huì)進(jìn)入此分支*/
/*如果發(fā)送FIFO的數(shù)據(jù)還未完畢,則從發(fā)送FIFO取1個(gè)數(shù)據(jù)寫入發(fā)送數(shù)據(jù)寄存器*/
//USART_SendData(_pUart->uart,_pUart->pTxBuf[_pUart->usTxRead]);
_pUart->uart->TDR=_pUart->pTxBuf[_pUart->usTxRead];
if(++_pUart->usTxRead>=_pUart->usTxBufSize)
{
_pUart->usTxRead=0;
}
_pUart->usTxCount--;
}
}/*清除中斷標(biāo)志*/
SET_BIT(_pUart->uart->ICR,UART_CLEAR_PEF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_FEF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_NEF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_OREF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_IDLEF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_TCF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_LBDF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_CTSF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_CMF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_WUF);
SET_BIT(_pUart->uart->ICR,UART_CLEAR_TXFECF);
}
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394

3.填寫數(shù)據(jù)到UART發(fā)送緩沖區(qū)。

并啟動(dòng)發(fā)送中斷,中斷處理函數(shù)發(fā)送完畢后,自動(dòng)關(guān)閉發(fā)送中斷 .

staticvoidUartSend(UART_T*_pUart,uint8_t*_ucaBuf,uint16_t_usLen)
{
uint16_ti;
for(i=0;i/*如果發(fā)送緩沖區(qū)已經(jīng)滿了,則等待緩沖區(qū)空*/
while(1)
{
__IOuint16_tusCount;DISABLE_INT();
usCount=_pUart->usTxCount;
ENABLE_INT();
if(usCountusTxBufSize)
{
break;
}
elseif(usCount==_pUart->usTxBufSize)/*數(shù)據(jù)已填滿緩沖區(qū)*/
{
if((_pUart->uart->CR1&USART_CR1_TXEIE)==0)
{
SET_BIT(_pUart->uart->CR1,USART_CR1_TXEIE);
}
}
}/*將新數(shù)據(jù)填入發(fā)送緩沖區(qū)*/
_pUart->pTxBuf[_pUart->usTxWrite]=_ucaBuf[i];
DISABLE_INT();
if(++_pUart->usTxWrite>=_pUart->usTxBufSize)
{
_pUart->usTxWrite=0;
}
_pUart->usTxCount++;
ENABLE_INT();
}
SET_BIT(_pUart->uart->CR1,USART_CR1_TXEIE);/*使能發(fā)送中斷(緩沖區(qū)空)*/
}

12345678910111213141516171819202122232425262728293031323334

4.向串口發(fā)送一組數(shù)據(jù)。

數(shù)據(jù)放到發(fā)送緩沖區(qū)后立即返回,由中斷服務(wù)程序在后臺(tái)完成發(fā)送

voidcomSendBuf(COM_PORT_E_ucPort,uint8_t*_ucaBuf,uint16_t_usLen)
{
UART_T*pUart;
pUart=ComToUart(_ucPort);
if(pUart==0)
{
return;
}
if(pUart->!=0)
{
pUart->SendBefor();/*如果是RS485通信,可以在這個(gè)函數(shù)中將RS485設(shè)置為發(fā)送模式*/
}
UartSend(pUart,_ucaBuf,_usLen);
}

123456789101112131415

向串口發(fā)送1個(gè)字節(jié)。數(shù)據(jù)放到發(fā)送緩沖區(qū)后立即返回,由中斷服務(wù)程序在后臺(tái)完成發(fā)送

voidcomSendChar(COM_PORT_E_ucPort,uint8_t_ucByte)
{
comSendBuf(_ucPort,&_ucByte,1);
}

123456

函數(shù)comSendChar是發(fā)送一個(gè)字節(jié),通過調(diào)用函數(shù)comSendBuf實(shí)現(xiàn),而函數(shù)comSendBuf又是通過調(diào)用函數(shù)UartSend實(shí)現(xiàn),這個(gè)函數(shù)是重點(diǎn)。

5.將COM端口號(hào)轉(zhuǎn)換為UART指針

UART_T*ComToUart(COM_PORT_E_ucPort)
{
if(_ucPort==COM1)
{
#ifUART1_FIFO_EN==1
return&g_tUart1;
#else
return0;
#endif
}
else
{
Error_Handler(__FILE__,__LINE__);
return0;
}
}

1234567891011121314151617

6.從串口接收緩沖區(qū)讀取1字節(jié)數(shù)據(jù)

staticuint8_tUartGetChar(UART_T*_pUart,uint8_t*_pByte)
{

uint16_tusCount;/*usRxWrite變量在中斷函數(shù)中被改寫,主程序讀取該變量時(shí),必須進(jìn)行臨界區(qū)保護(hù)*/

DISABLE_INT();usCount=_pUart->usRxCount;ENABLE_INT();/*如果讀和寫索引相同,則返回0*/

//if(_pUart->usRxRead==usRxWrite)
if(usCount==0)/*已經(jīng)沒有數(shù)據(jù)*/
{
return0;
}
else
{
*_pByte=_pUart->pRxBuf[_pUart->usRxRead];/*從串口接收FIFO取1個(gè)數(shù)據(jù)*/
/*改寫FIFO讀索引*/

DISABLE_INT();

if(++_pUart->usRxRead>=_pUart->usRxBufSize)
{
_pUart->usRxRead=0;
}
_pUart->usRxCount--;
ENABLE_INT();
return1;
}

}
1234567891011121314151617181920212223242526272829

從接收緩沖區(qū)讀取1字節(jié),非阻塞。無論有無數(shù)據(jù)均立即返回。

uint8_tcomGetChar(COM_PORT_E_ucPort,uint8_t*_pByte)
{

UART_T*pUart;
pUart=ComToUart(_ucPort);
if(pUart==0)
{
return0;
}
returnUartGetChar(pUart,_pByte);
}
123456789101112

接收數(shù)據(jù)的調(diào)用順序是:comGetChar–》UartGetChar

7.判斷發(fā)送緩沖區(qū)是否為空

uint8_tUartTxEmpty(COM_PORT_E_ucPort)
{
UART_T*pUart;
uint8_tSending;

pUart=ComToUart(_ucPort);
if(pUart==0)
{
return0;
}

Sending=pUart->Sending;

if(Sending!=0)
{
return0;
}
return1;
}

1234567891011121314151617181920

8.清零串口接收緩沖區(qū)

voidcomClearRxFifo(COM_PORT_E_ucPort)
{
UART_T*pUart;
pUart=ComToUart(_ucPort);
if(pUart==0)
{
return;
}
pUart->usRxWrite=0;
pUart->usRxRead=0;
pUart->usRxCount=0;
}
123456789101112

9.清零串口發(fā)送緩沖區(qū)

voidcomClearTxFifo(COM_PORT_E_ucPort)
{
UART_T*pUart;

pUart=ComToUart(_ucPort);
if(pUart==0)
{
return;
}

pUart->usTxWrite=0;
pUart->usTxRead=0;
pUart->usTxCount=0;
}
1234567891011121314

10.輸入輸出的重定向

intfputc(intch,FILE*f)
{
#if1/*將需要printf的字符通過串口中斷FIFO發(fā)送出去,printf函數(shù)會(huì)立即返回*/
comSendChar(COM1,ch);
returnch;
#else/*采用阻塞方式發(fā)送每個(gè)字符,等待數(shù)據(jù)發(fā)送完畢*/
/*寫一個(gè)字節(jié)到USART1*/
USART1->DR=ch;
/*等待發(fā)送結(jié)束*/
while((USART1->SR&USART_SR_TC)==0)
{}
returnch;
#endif
}


intfgetc(FILE*f)
{
#if1/*從串口接收FIFO中取1個(gè)數(shù)據(jù),只有取到數(shù)據(jù)才返回*/
uint8_tucData;
while(comGetChar(COM1,&ucData)==0);
returnucData;
#else
/*等待接收到數(shù)據(jù)*/
while((USART1->SR&USART_SR_RXNE)==0)
{}
return(int)USART1->DR;
#endif
}
1234567891011121314151617181920212223242526272829

11.應(yīng)用層初始化:

//FIFO串口初始化
UartVarInit(void);
//串口參數(shù)配置
voidbsp_SetUartParam(USART_TypeDef*Instance,uint32_tBaudRate,uint32_tParity,uint32_tMode)
{
UART_HandleTypeDefUartHandle;
/*##-1-配置串口硬件參數(shù)######################################*/
/*異步串口模式(UARTMode)*/
/*配置如下:
-字長(zhǎng)=8位
-停止位=1個(gè)停止位
-校驗(yàn)=參數(shù)Parity
-波特率=參數(shù)BaudRate
-硬件流控制關(guān)閉(RTSandCTSsignals)*/
UartHandle.Instance=Instance;
UartHandle.Init.BaudRate=BaudRate;
UartHandle.Init.WordLength=UART_WORDLENGTH_8B;
UartHandle.Init.StopBits=UART_STOPBITS_1;
UartHandle.Init.Parity=Parity;
UartHandle.Init.HwFlowCtl=UART_HWCONTROL_NONE;
UartHandle.Init.Mode=Mode;
UartHandle.Init.OverSampling=UART_OVERSAMPLING_16;

if(HAL_UART_Init(&UartHandle)!=HAL_OK)
{
Error_Handler(__FILE__,__LINE__);
}
}
//對(duì)應(yīng)的串口波特率配置
voidcomSetBaud(COM_PORT_E_ucPort,uint32_t_BaudRate)
{
USART_TypeDef*USARTx;
USARTx=ComToUSARTx(_ucPort);
if(USARTx==0)
{
return;
}
bsp_SetUartParam(USARTx,_BaudRate,UART_PARITY_NONE,UART_MODE_TX_RX);
}
//硬件初始化
voidInitHardUart(void)
{
GPIO復(fù)用....
/*配置NVICtheNVICforUART*/
HAL_NVIC_SetPriority(USART1_IRQn,0,1);
HAL_NVIC_EnableIRQ(USART1_IRQn);

/*配置波特率、奇偶校驗(yàn)*/
bsp_SetUartParam(USART1,UART1_BAUD,UART_PARITY_NONE,UART_MODE_TX_RX);

CLEAR_BIT(USART1->SR,USART_SR_TC);/*清除TC發(fā)送完成標(biāo)志*/
CLEAR_BIT(USART1->SR,USART_SR_RXNE);/*清除RXNE接收標(biāo)志*/
//USART_CR1_PEIE|USART_CR1_RXNEIE
SET_BIT(USART1->CR1,USART_CR1_RXNEIE);/*使能PE.RX接受中斷*/
}
在主循環(huán)中

comGetChar(COM1,&read);//獲取一個(gè)字節(jié)數(shù)據(jù)
comSendBuf(COM1,(uint8_t*)buf,strlen(buf));//發(fā)送數(shù)據(jù)
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • fifo
    +關(guān)注

    關(guān)注

    3

    文章

    385

    瀏覽量

    43462
  • FIRST
    +關(guān)注

    關(guān)注

    0

    文章

    11

    瀏覽量

    11672
  • 串口
    +關(guān)注

    關(guān)注

    14

    文章

    1539

    瀏覽量

    75901

原文標(biāo)題:對(duì)串口接收FIFO處理機(jī)制的解讀

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    寄存器/指令集/中斷、異常處理機(jī)制介紹

    寄存器指令集中斷、異常處理機(jī)制
    發(fā)表于 01-13 07:56

    INtime RTOS內(nèi)部的關(guān)鍵處理機(jī)制是什么

    INtime RTOS內(nèi)部的關(guān)鍵處理機(jī)制是什么?INtime RTOS內(nèi)部的關(guān)鍵處理機(jī)制有哪些相關(guān)的應(yīng)用案例?
    發(fā)表于 09-29 06:28

    單片機(jī)的中斷處理機(jī)制

    單片機(jī)的中斷處理機(jī)制什么是中斷?為什么要使用中斷(中斷的特點(diǎn))什么是中斷源?中斷源有哪些中斷機(jī)制的流程中斷優(yōu)先級(jí)多個(gè)中斷同時(shí)發(fā)生什么是中斷?當(dāng)CPU執(zhí)行程序時(shí),由于發(fā)生了某種隨機(jī)的事件(內(nèi)部或外部
    發(fā)表于 12-07 11:14

    基于stm32串口環(huán)形緩沖隊(duì)列處理機(jī)制是什么

    基于stm32串口環(huán)形緩沖隊(duì)列處理機(jī)制是什么
    發(fā)表于 12-08 07:06

    VxWorks下FMPC860的中斷處理機(jī)制及其應(yīng)用

    嵌入式實(shí)時(shí)操作系統(tǒng)VxW0rks提供的中斷處理機(jī)制中斷延遲小.應(yīng)用編程方便。MPC860是目前在網(wǎng)絡(luò)與通信領(lǐng)域應(yīng)用非常廣泛的款微處理器芯片。論文詳細(xì)分析了VxWorks及MPC860的中斷處
    發(fā)表于 12-16 14:15 ?5次下載

    VxWorks下MPC860的中斷處理機(jī)制及其應(yīng)用

    嵌入式實(shí)時(shí)操作系統(tǒng)VxWorks提供的中斷處理機(jī)制中斷延遲小,應(yīng)用編程方便。MPC860是目前在網(wǎng)絡(luò)與通信領(lǐng)域應(yīng)用非常廣泛的款微處理器芯片。論文詳細(xì)分析了VxWorks及MPC860的中斷
    發(fā)表于 06-10 14:08 ?12次下載

    VxWorks下MPC860的中斷處理機(jī)制及其應(yīng)用

    嵌入式實(shí)時(shí)操作系統(tǒng)VxW0rks提供的中斷處理機(jī)制中斷延遲?。畱?yīng)用編程方便。MPC860是目前在網(wǎng)絡(luò)與通信領(lǐng)域應(yīng)用非常廣泛的款微處理器芯片。論文詳細(xì)分析了VxWorks及MPC860的中斷
    發(fā)表于 11-28 16:32 ?15次下載

    iFix組態(tài)軟件中基于隊(duì)列的命令處理機(jī)制研究

    提出了種在iFix 組態(tài)軟件中創(chuàng)建消息隊(duì)列的方法,利用這種消息隊(duì)列實(shí)現(xiàn)了對(duì)控制命令的執(zhí)行情況的跟蹤與處理。這種基于隊(duì)列的命令處理機(jī)制確保了組態(tài)軟件的控制命令能夠
    發(fā)表于 12-23 14:06 ?22次下載

    VxWorks下MPC860的中斷處理機(jī)制及其應(yīng)用

    嵌入式實(shí)時(shí)操作系統(tǒng)VxW0rks提供的中斷處理機(jī)制中斷延遲?。畱?yīng)用編程方便。MPC860是目前在網(wǎng)絡(luò)與通信領(lǐng)域應(yīng)用非常廣泛的款微處理器芯片。論文詳細(xì)分析了VxWorks及MPC860的中斷處
    發(fā)表于 01-09 15:09 ?40次下載

    Cortex-M3的異常處理機(jī)制分析

    Cortex-M3的異常處理機(jī)制分析  詳細(xì)闡述CortexM3異常的分類、優(yōu)先級(jí)、進(jìn)入和退出,以及在CortexM3異常處理機(jī)制中使用的新技術(shù)——遲到(late?arriving)和
    發(fā)表于 03-29 15:07 ?1951次閱讀
    Cortex-M3的異常<b class='flag-5'>處理機(jī)制</b>分析

    TTNT數(shù)據(jù)鏈?zhǔn)瞻l(fā)機(jī)消息處理機(jī)制的MATLAB仿真

    TTNT數(shù)據(jù)鏈?zhǔn)瞻l(fā)機(jī)消息處理機(jī)制的MATLAB仿真
    發(fā)表于 01-04 14:59 ?0次下載

    STM32Cube HAL庫中斷處理機(jī)制 以及回調(diào)函數(shù)實(shí)現(xiàn)原理

    STM32Cube HAL庫中斷處理機(jī)制,以及回調(diào)函數(shù)實(shí)現(xiàn)原理
    的頭像 發(fā)表于 03-03 14:01 ?1.3w次閱讀

    C++程序異常處理機(jī)制是什么

    那么C++設(shè)計(jì)了套異常處理機(jī)制,方面能夠使得異常處理和正常運(yùn)行代碼進(jìn)行分離,使得程序更加模塊化;另方面,C++的異常
    的頭像 發(fā)表于 02-21 10:37 ?802次閱讀
    C++程序異常<b class='flag-5'>處理機(jī)制</b>是什么

    基于ARM核的嵌入式系統(tǒng)異常處理機(jī)制的設(shè)計(jì)

    電子發(fā)燒友網(wǎng)站提供《基于ARM核的嵌入式系統(tǒng)異常處理機(jī)制的設(shè)計(jì).pdf》資料免費(fèi)下載
    發(fā)表于 10-27 09:00 ?0次下載
    基于ARM核的嵌入式系統(tǒng)異常<b class='flag-5'>處理機(jī)制</b>的設(shè)計(jì)

    西門子博圖:錯(cuò)誤處理機(jī)制概覽

    可通過以下幾種不同的錯(cuò)誤處理機(jī)制進(jìn)行參數(shù)跟蹤或編程或訪問錯(cuò)誤
    的頭像 發(fā)表于 11-25 11:35 ?2456次閱讀
    西門子博圖:錯(cuò)誤<b class='flag-5'>處理機(jī)制</b>概覽