關(guān)于CH432中斷的問(wèn)題

我在用中斷的方式處理CH432接收數(shù)據(jù)時(shí),發(fā)現(xiàn)一個(gè)奇怪的問(wèn)題,詳細(xì)如下:

?

CH432初始化:

?

void InitCH432(void)??? /* 初始化CH432 */
{
??? UINT16 CH432div;
??
?? UINT8 DLM;
? UINT8 CH432DLL;
/**************************************************************************
????????? 設(shè)置CH432串口0的寄存器

**************************************************************************/
?? ?
??? CH432div = ( Fpclk >> 4 ) / CH432_BPS;
??? DLM = CH432div >> 8;
??? CH432DLL = CH432div & 0xff;
?
??? WriteCH432Data( CH432_IER_PORT,? BIT_IER_RESET);? //端口復(fù)位//
??? WriteCH432Data( CH432_LCR_PORT, BIT_LCR_DLAB );??? /* 設(shè)置DLAB為1 */
??? WriteCH432Data( CH432_DLL_PORT, CH432DLL );??? /* 設(shè)置波特率 */
??? WriteCH432Data( CH432_DLM_PORT, DLM );
??? WriteCH432Data( CH432_FCR_PORT,? BIT_FCR_FIFOEN? );??? /* 設(shè)置FIFO模式,觸發(fā)點(diǎn)為1 */
??? WriteCH432Data( CH432_LCR_PORT, BIT_LCR_WORDSZ1
????????????????????????????????? | BIT_LCR_WORDSZ0 );??? /* 字長(zhǎng)8位,1位停止位、無(wú)校驗(yàn) */

/**************************************************************************
????????? 設(shè)置CH432串口1的寄存器

**************************************************************************/
??? CH432div = ( Fpclk >> 4 ) / CH432_BPS1;
??? DLM = CH432div >> 8;
??? CH432DLL = CH432div & 0xff;
??
??WriteCH432Data( CH432_IER1_PORT,? BIT_IER_RESET);? //端口復(fù)位//
??? WriteCH432Data( CH432_LCR1_PORT, BIT_LCR_DLAB );??? /* 設(shè)置DLAB為1 */
??? WriteCH432Data( CH432_DLL1_PORT, CH432DLL );??? /* 設(shè)置波特率 */
??? WriteCH432Data( CH432_DLM1_PORT, DLM );
??? WriteCH432Data( CH432_FCR1_PORT,? BIT_FCR_RECVTG1 | BIT_FCR_FIFOEN );??? /* 設(shè)置FIFO模式,觸發(fā)點(diǎn)為8 bytes */
??? WriteCH432Data( CH432_LCR1_PORT,
???????????????????????????????????? BIT_LCR_WORDSZ1
????????????????????????????????? | BIT_LCR_WORDSZ0 );??? /* 字長(zhǎng)8位,1位停止位、無(wú)校驗(yàn) */
??? WriteCH432Data( CH432_IER1_PORT,?? BIT_IER_IERECV? );??? /* 允許接收到數(shù)據(jù)中斷 */
??? WriteCH432Data( CH432_MCR1_PORT, BIT_MCR_OUT2? );??? /* 允許中斷輸出,DTR,RTS為1 */
}

?

?

中斷處理子程序:

?

void CH432Interrupt(void)??? /* 中斷方式處理 */
{
??? UINT8 InterruptStatus;
??? UINT8 RcvNum = 0;
?? UINT8 i;
//?? UINT8 Status;
?
??? InterruptStatus = ReadCH432Data( CH432_IIR_PORT ) & ( ~ CH432_IIR_FIFOS_ENABLED );
??? if( ( InterruptStatus & 0x01 ) )??? /* 沒(méi)有中斷轉(zhuǎn)到串口1 */
??? {
??????? InterruptStatus = ReadCH432Data( CH432_IIR1_PORT ) & ( ~ CH432_IIR_FIFOS_ENABLED );??? /* 讀串口1的中斷狀態(tài) */
??????? if( ( InterruptStatus & 0x01 ) ) return;??? /* 沒(méi)有中斷退出 */
??????? else
??????? {
????????????Delay_ms(30);//必須加上
??????????? ReadCH432Data( CH432_FCR1_PORT );? //這句不知什么意思,必須加上才接收正常
??????????? ReadCH432Data( CH432_LSR1_PORT );? //這句不知什么意思,必須加上才接收正常
?????????? ReadCH432Data( CH432_MCR1_PORT );? //這句不知什么意思,必須加上才接收正常
????
??????????? switch( InterruptStatus )
??????????? {
???????? case INT_MODEM_CHANGE:
?????????? ReadCH432Data(CH432_MSR1_PORT);? //不處理
?????????? break;
??????????????? case INT_NOINT:??? /* 沒(méi)有中斷 */
??????????????????? break;
??????????????? case INT_THR_EMPTY:??? /* 發(fā)送保持寄存器空中斷 */
??????????????????? ReadCH432Data(CH432_IIR1_PORT);? //不處理
??????????????????? break;
??????????????? case INT_RCV_SUCCESS:??? /* 串口接收可用數(shù)據(jù)中斷 */
????????case INT_RCV_OVERTIME:??? /* 接收數(shù)據(jù)超時(shí)中斷 */?
??????????????????? RcvNum = CH432Seril1Rcv( buf );
??????????for(i=0;i??????????{
???????????if(rb_can_write(&u_ring_buff) > 0)
???????????{
????????????rb_write(&u_ring_buff, &buf[i], 1);
???????????}?????
??????????}?
??????????print_buf((U8 *)u_ring_buff.rb_buff,RcvNum,"RcvData");
??????????????????? break;
??????????????? case INT_RCV_LINES:??? /* 接收線路狀態(tài)中斷 */
??????????????????? ReadCH432Data( CH432_LSR1_PORT);? //不處理
??????????????????? break;
??????????????
??????????????? default:??? /* 不可能發(fā)生的中斷 */
??????????????????? break;
??????????? }
??????? }
??? }
??? else
??? {
???
??????? switch( InterruptStatus )
??????? {
??????????? case INT_MODEM_CHANGE:
??????????????? ReadCH432Data( CH432_MSR_PORT );? //不處理
??????????????? break;
??????????? case INT_NOINT:??? /* 沒(méi)有中斷 */
??????????????????? break;
??????????? case INT_THR_EMPTY:??? /* 發(fā)送保持寄存器空中斷 */
??????????????????? ReadCH432Data(CH432_IIR_PORT);? //不處理
??????????????????? break;
??????????? case INT_RCV_SUCCESS:??? /* 串口接收可用數(shù)據(jù)中斷 */
?????????????
??????????????????? RcvNum = CH432Seril0Rcv( buf );
??????????for(i=0;i??????????{
???????????if(rb_can_write(&u_ring_buff) > 0)
???????????{
????????????rb_write(&u_ring_buff, &buf[i], 1);
???????????}?????
??????????}?
??????
??????????????????? break;
??????????? case INT_RCV_LINES:??? /* 接收線路狀態(tài)中斷 */
??????????????????? ReadCH432Data( CH432_LSR_PORT);? //不處理
??????????????????? break;
??????????? case INT_RCV_OVERTIME:??? /* 接收數(shù)據(jù)超時(shí)中斷 */
??????????????????? RcvNum = CH432Seril0Rcv( buf );
??????????for(i=0;i??????????{
???????????if(rb_can_write(&u_ring_buff) > 0)
???????????{
????????????rb_write(&u_ring_buff, &buf[i], 1);
???????????}?????
??????????}??
??????????????????? break;
??????????? default:??? /* 不可能發(fā)生的中斷 */
??????????????????? break;
??????? }
??? }
}

現(xiàn)在問(wèn)題就是,在中斷子程序里必須加上下面這四個(gè)語(yǔ)句,接收數(shù)據(jù)才正常,不加的話就無(wú)法接收到任何數(shù)據(jù):

????????????Delay_ms(30);//必須加上
??????????? ReadCH432Data( CH432_FCR1_PORT );? //這句不知什么意思,必須加上才接收正常
??????????? ReadCH432Data( CH432_LSR1_PORT );? //這句不知什么意思,必須加上才接收正常
?????????? ReadCH432Data( CH432_MCR1_PORT );? //這句不知什么意思,必須加上才接收正常

?

不加上這四句,LSR的數(shù)值就一直為0xE3,而且INT中斷引腳一直被拉低,無(wú)法恢復(fù)到高電平,不知是什么原因,有哪位大神知道原因的,麻煩幫解答一下,謝謝了

補(bǔ)充一下,串口第一次接收到數(shù)據(jù)時(shí)的寄存器值:


IER1: 01

IIR1: C4

FCR1: C4

MCR1: 08

LSR1: 63

MSR1: 00


從LSR看,是FIFO溢出了,但官方的示例程序是在沒(méi)溢出的情況下才會(huì)讀數(shù)據(jù),看來(lái)是官方示例代碼的問(wèn)題,F(xiàn)IFO的深度只有14 bytes,如果串口數(shù)據(jù)多,很容易就溢出了,官方的示例代碼就無(wú)法正確執(zhí)行,有什么辦法解決這個(gè)問(wèn)題呢?


而且Datasheet里描述的是:

串口接收的數(shù)據(jù)可用中斷(IIR寄存器的低4 位為04H)是指接收FIFO中的已有數(shù)據(jù)字節(jié)數(shù)已經(jīng)

達(dá)到或超過(guò)由FCR 寄存器的RECVTG1 和RECVTG0選擇的FIFO 觸發(fā)點(diǎn)。當(dāng)從RBR 讀取數(shù)據(jù)使FIFO 中字

節(jié)數(shù)低于FIFO 觸發(fā)點(diǎn)時(shí),該中斷被清除。串口接收的數(shù)據(jù)超時(shí)中斷(IIR 寄存器的低4 位為0CH)是

指接收FIFO 中至少有一個(gè)字節(jié)的數(shù)據(jù),并且從上一次串口接收到數(shù)據(jù)和從上一次被單片機(jī)取走數(shù)據(jù)

開始,已經(jīng)等待了相當(dāng)于接收4 個(gè)數(shù)據(jù)的時(shí)間。當(dāng)再次接收到一個(gè)新的數(shù)據(jù)后,該中斷被清除,或者

當(dāng)單片機(jī)讀取一次RBR 寄存器后,該中斷也能被清除。當(dāng)接收FIFO 全空時(shí),LSR 寄存器的DATARDY

位為0,當(dāng)接收FIFO 中有數(shù)據(jù)時(shí),DATARDY 位為1 有效。


那么,當(dāng)FIFO滿時(shí),才會(huì)觸發(fā)接收數(shù)據(jù)中斷,但如果串口數(shù)據(jù)比FIFO大很多,肯定就會(huì)溢出,官方的代碼并沒(méi)有考慮這種情況。


再補(bǔ)充一下,第一次收到數(shù)據(jù)后,LSR的值是0xF3,也就是說(shuō)出現(xiàn)了break線路間隔錯(cuò)誤,不是很理解這個(gè)線路間隔是什么意思


你好:


本身CH432內(nèi)部串口的fifo大小就16個(gè)字節(jié),如果數(shù)據(jù)滿了你還沒(méi)有取走,下一字節(jié)數(shù)據(jù)肯定觸發(fā)fifo溢出。不管設(shè)計(jì)多大的fifo空間,如果取數(shù)據(jù)慢,數(shù)據(jù)量總會(huì)在達(dá)到某一數(shù)量級(jí)時(shí)出現(xiàn)溢出現(xiàn)象。所以會(huì)設(shè)置“fifo觸發(fā)點(diǎn)”這種中斷。

如果你設(shè)置觸發(fā)點(diǎn)為14字節(jié),那么當(dāng)fifo報(bào)出次中斷后,要及時(shí)取走14字節(jié)(不用判斷),否則還有2字節(jié)當(dāng)前通訊波特率的數(shù)據(jù)就會(huì)滿,這段時(shí)間你取數(shù)據(jù)的速度和串口送進(jìn)來(lái)的數(shù)據(jù)就是一個(gè)速度賽跑。

如果你本身操作慢,那么觸發(fā)級(jí)別可以設(shè)低,留有足夠的余量。


例程本身只是簡(jiǎn)單操作演示的例子,里面只有出口收發(fā)部分并沒(méi)有涉及到其他功能,可以說(shuō)整個(gè)程序都在等待收發(fā)。而且例程中使用的cpu速度(操作432寄存器)遠(yuǎn)大于當(dāng)前串口通訊速度。所以不會(huì)出現(xiàn)fifo溢



只有登錄才能回復(fù),可以選擇微信賬號(hào)登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频