CH552的T2自動(dòng)重載中斷周期受代碼影響

你好,

我在調(diào)試代碼時(shí)發(fā)現(xiàn)有一處T2自動(dòng)重載中斷比理論值長5%。經(jīng)反復(fù)測試,似乎是中斷里的代碼會(huì)影響T2的周期。我寫了一個(gè)測試代碼,可在多片CH552上復(fù)現(xiàn)此問題。暫時(shí)代碼用Arduino框架執(zhí)行。

void?Timer2Interrupt(void)?__interrupt?(INT_NO_TMR2)
{
??timer2IntrHandler();//debugwire?related
}

void?timer2IntrHandler()?{
??//
??if?(TF2)?{
????TF2?=?0;

????P1_4?=?0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
????????P1_4=0;
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
//????__asm__("nop");
????
????P1_4?=?1;

??}

}


void?setup()?{
??//?put?your?setup?code?here,?to?run?once:

??TR2?=?0;
??//
??RCLK?=?0;
??TCLK?=?0;???????????//?clear?RCLK,TCLK?in?T2CON
??C_T2?=?0;???????????//?clear?C_T2?in?T2CON?for?using?internal?clk
??EXEN2?=?0;??????????//?clear?EXEN2?in?T2CON?to?disable?T2EX
??T2MOD?|=?(bT2_CLK)?|?bTMR_CLK;?//?set?bT2_CLK,?for?fast?clk.Using?Fsys/4
??CP_RL2?=?0;?????????//?clear?CP_RL2?in?T2CON?for?16bit?timer,?reload?mode

??RCAP2?=?65536?-?128;

??TF2?=?0;
??EXF2?=?0;



??TR2?=?1;?//?start?timer

??TL2?=?0x00;?//?seem?only?work?when?timer?is?on?
??TH2?=?0xFF;

??ET2?=?1;
}

void?loop()?{
??//?put?your?main?code?here,?to?run?repeatedly:

}

16M時(shí)鐘下中斷應(yīng)該是125K的頻率,一次8us。

但是如果我寫一大堆P1_4=0,中斷就會(huì)變慢。

Screen Shot 2024-10-07 at 2.45.53 AM.png如果我把多余的P1_4=0換成nop,就正常許多。

Screen Shot 2024-10-07 at 2.44.49 AM.png

請問這是我對定時(shí)器理解不對還是芯片Bug?

我用SDCC構(gòu)建了一個(gè)工程,單文件,仍然可以重現(xiàn)問題。該代碼大部分時(shí)候周期為8.5us,隔幾個(gè)也會(huì)出現(xiàn)11us。

#include?"ch554.h"

SBIT(P1_4,??0x90,?4);

void?Timer2Interrupt(void)?__interrupt?(INT_NO_TMR2)??__naked
{
???
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????__asm__("push???acc");
????timer2IntrHandler();//debugwire?related
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");
????__asm__("pop????acc");


????__asm__("mov??r0,?SP");
????__asm__("dec??r0");
????__asm__("push???acc");
????__asm__("pop????acc");
????__asm__("push???acc");
????__asm__("pop????acc");

????__asm__("reti");

}

void?timer2IntrHandler()?{
??if?(TF2)?{
????TF2?=?0;

????P1_4?=?0;

????//?P1_4?=?0;

????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");

????P1_4?=?1;
??}
}
void?main(void){
????//?set?internal?clock
????SAFE_MOD?=?0x55;
????SAFE_MOD?=?0xAA;
????CLOCK_CFG?=?CLOCK_CFG?&?~MASK_SYS_CK_SEL?|?0x05;?//?16MHz
????SAFE_MOD?=?0x00;

????for?(int?i=0;i<5000;i++){
????????__asm__("nop");
????}

????//delayMicroseconds(5000);?//?needed?to?stablize?internal?RC

????EA?=?1;?//?millis?and?delay?needs?interrupt

????T2MOD?|=?bTMR_CLK;?//?set?bTMR_CLK
????TR2?=?0;

????RCLK?=?0;
????TCLK?=?0;???????????//?clear?RCLK,TCLK?in?T2CON
????C_T2?=?0;???????????//?clear?C_T2?in?T2CON?for?using?internal?clk
????EXEN2?=?0;??????????//?clear?EXEN2?in?T2CON?to?disable?T2EX
????T2MOD?|=?(bT2_CLK);?//?set?bT2_CLK,?for?fast?clk.Using?Fsys/1
????CP_RL2?=?0;?????????//?clear?CP_RL2?in?T2CON?for?16bit?timer,?reload?mode
????RCAP2?=?65535?-?128?+?1;


????TF2?=?0;
????EXF2?=?0;

????TR2?=?1;?//?start?timer

????TL2?=?0x00;?//?seem?only?work?when?timer?is?on?
????TH2?=?0xFF;

????ET2?=?1;

????while(1){
???????
????}
???

}

Timer2Interrupt 里插入的匯編應(yīng)該不會(huì)有任何影響。但是注釋掉

__asm__("mov??r0,?SP");
__asm__("dec??r0");

或者是對ACC的出入棧,就會(huì)讓周期恢復(fù)正常。


附上代碼,makefile和所有編譯出來的文件。壓縮包里的hex文件在Proteus里用AT89C52仿真,12M時(shí)鐘下周期是穩(wěn)定的128us。

icon_rar.gifch552_test_t2_sdcc.zip



實(shí)際代碼測試,如果Timer2中斷調(diào)用其他函數(shù),那編譯器默認(rèn)會(huì)把所有R0~R7在中斷中壓棧,很容易觸發(fā)此問題,但是把被調(diào)用函數(shù)改為inline,讓編譯器少壓6~8個(gè)寄存器,問題就能得到極大改善。


yes saving all regs on irq entry is a problem with SDCC. Keil does a much better job on that. Have you tried to change the register bank?


@usbman I just elimated all function call in ISR in this case to avoid some register saving.

But it the additional Push/Pop should not affect T2 timer, and in test, it affects in an unstable way.


我又仔細(xì)看了看,問題有可能是中斷執(zhí)行時(shí)間超過了定時(shí)器周期,我這邊再做一下測試。

usbman 在這個(gè)帖子http://www.findthetime.net/bbs/thread-124719-1.html里提到了 中斷跳轉(zhuǎn)的時(shí)間。加上變量保護(hù),128時(shí)鐘確實(shí)有可能會(huì)超。


測試結(jié)果,確實(shí)是我的中斷執(zhí)行時(shí)間太長了。我測試往里面加nop。一旦超過界限,中斷就無法在T2溢出時(shí)執(zhí)行。當(dāng)T2多轉(zhuǎn)一圈時(shí)會(huì)有一些空閑,也就是不穩(wěn)定的原因。


1728494851885416.png

1728494851103098.png

#include?"ch554.h"

SBIT(P1_4,??0x90,?4);
SBIT(P1_1,??0x90,?1);

void?Timer2Interrupt(void)?__interrupt?(INT_NO_TMR2)??__naked
{
??//12?clk?to?enter?interrupt
????P1_4?=?0;
????TF2?=?0;
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");??//10clk
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");?__asm__("nop\nnop\n");
???
????__asm__("nop\nnop\n");?__asm__("nop\nnop\n");

????__asm__("nop\nnop\n");

????P1_4?=?1;
????__asm__("reti");
????//reti?4~5?clk
}

void?main(void){
????//?set?internal?clock
????SAFE_MOD?=?0x55;
????SAFE_MOD?=?0xAA;
????CLOCK_CFG?=?CLOCK_CFG?&?~MASK_SYS_CK_SEL?|?0x05;?//?16MHz
????SAFE_MOD?=?0x00;

????for?(int?i=0;i<5000;i++){
????????__asm__("nop");
????}

????//delayMicroseconds(5000);?//?needed?to?stablize?internal?RC

????EA?=?1;?//?millis?and?delay?needs?interrupt

????T2MOD?|=?bTMR_CLK;?//?set?bTMR_CLK
????TR2?=?0;

????RCLK?=?0;
????TCLK?=?0;???????????//?clear?RCLK,TCLK?in?T2CON
????C_T2?=?0;???????????//?clear?C_T2?in?T2CON?for?using?internal?clk
????EXEN2?=?0;??????????//?clear?EXEN2?in?T2CON?to?disable?T2EX
????T2MOD?|=?(bT2_CLK);?//?set?bT2_CLK,?for?fast?clk.Using?Fsys/1
????CP_RL2?=?0;?????????//?clear?CP_RL2?in?T2CON?for?16bit?timer,?reload?mode
????RCAP2?=?65535?-?128?+?1;


????TF2?=?0;
????EXF2?=?0;

????TR2?=?1;?//?start?timer

????TL2?=?0x00;?//?seem?only?work?when?timer?is?on?
????TH2?=?0xFF;

????ET2?=?1;

????while(1){
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
??????P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;P1_1=0;P1_1=1;
????}
???

}



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

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