makesoft 发表于 2018-9-11 06:30:46

询问一下STC8定时器自动重装受中断优先级影响吗?

比如说我使用T4定时器,其中断优先级天生就是最低的,它的自动重装功能应该是硬件实现的吧?

也就是说定时器溢出后应该立即自动重装初值,仅仅是中断响应滞后于其他优先级中断。

还是等待中断响应后才能由硬件重装初值,要是这样话,自动重装的意义也就是一条指令的优势了。

DATASHEET里面并没有详细的描述,斑竹能确认下是什么样的方式吗?

小李非刀 发表于 2018-9-11 21:45:52

自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作。所以,STC的MCU可以轻易的用定时器分频输出几MHZ的方波(50KHZ以上最好不要开中断,中断太频繁了)。

makesoft 发表于 2018-9-12 05:44:40

小李非刀 发表于 2018-9-11 21:45
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作 ...

谢谢版主,开始我也这么认为的。
建议版主测试下t4,开启中断,同时在开几个高级别中断,就会发现这定时器变慢了,并且慢的还挺夸张,我用25ms定时测试,其他中断频繁时要慢1%以上,需要的话可以从项目中剥离出demo程序。
自动重装是不依赖中断的,所以这慢只能说重装参数的时刻和cpu忙不忙相关。

makesoft 发表于 2018-9-12 05:47:16

本帖最后由 makesoft 于 2018-9-12 05:48 编辑

补充下,同时测试了自身rc和使用晶体两种模式,结果相同。

后来改为t0定时器,使用最高级别中断解决了问题。

硬邦邦 发表于 2018-9-12 06:19:08

不是慢了,其它高的中断占用了时间

makesoft 发表于 2018-9-12 07:27:43

硬邦邦 发表于 2018-9-12 06:19
不是慢了,其它高的中断占用了时间

同学,俺是老司机,不是幼稚园的儿童哦。

makesoft 发表于 2018-9-12 10:40:22

本帖最后由 makesoft 于 2018-9-12 10:41 编辑

程序中T0和T4应该是相同周期,可是逻辑分析抓图T4是T0的倍数了{:smile:}
从程序判断,应该是T3和T4相互干涉,T3取消T4就正常了,这BUG算是很严重了吧?

#define INIT
#include "CONFIG.H"

//初始化端口的工作模式
void Port_init(void) {

//启动扩展寄存器修改模式
P_SW2=B1000_0000;
//启动外部晶体
XOSCCR=B1100_0000;
//等待时钟稳定
while(0==(XOSCCR&B0000_0001));
//时钟不分频
CLKDIV=0x00;
//选择外部晶振
CKSEL=0x01;
//关闭扩展寄存器修改模式
P_SW2&=(~B1000_0000);

        //串口2重新定位管脚(p4.0 p4.1)
P_SW2|=B0000_0001;
//SPI重新定位管脚(p3.4 p3.3 p3.2)
//暂时改模拟管脚测试
//P_SW1=B0000_1100;

/*
PnM1   0      0          1      1
PnM0   0      1          0      1
      准双向   推挽输出高阻输入    开漏
*/
//打印机数据口,推挽输出
//P0.7 PD7,P0.6 PD6,P0.5 PD5,P0.4 PD4
//P0.3 PD3,P0.2 PD2,P0.1 PD1,P0.0 PD0
P0    = B0000_0000;
P0M1= B0000_0000;
P0M0= B1111_1111;

//P1.7 XTAL1, P1.6 XTAL2,   P1.5 NTC,    P1.4 n485SEND
//P1.3 Sel_nErr,P1.2PE,   P1.1 BUSY,   P1.0 nACK
//UART2(n485SEND、TXD2、RXD2)用于485联网PLC通讯
P1    = B1110_1111;
P1M1= B0010_0000;
P1M0= B0001_0000;

//P2.7 nSTB,         P2.6 NC,   P2.5 nKEY,       P2.4 nLED_D9
//P2.3 nLED_D8,      P2.2 NC,   P2.1 NC,         P2.0 NC
P2    = B1111_1111;
P2M1= B0000_0000;
P2M0= B1000_0000;

//P3.7 NC,    P3.6 nFALSH,   P3.5 NC,   P3.4 MOSI
//P3.3 MISO,P3.2 SCLK,   P3.1 TXD1,   P3.0 RXD1
//UART1 用于下载程序或者连接串口打印机
P3    = B1111_1111;
P3M1= B0101_1100;
P3M0= B0101_1110;

//P4.7   ,   P4.6   ,       P4.5   ,   P4.4 NC
//P4.3 NC,   P4.2 485TXD,   P4.1 NC,   P4.0 485RXD
P4    = B1111_1111;
P4M1= B0000_0000;
P4M0= B0000_0100;

//P5.7      P5.6         P5.5 NC       P5.4 SBUSY
//P5.3      P5.2         P5.1          P5.0
P5    = B1111_1111;
P5M1= B0000_0000;
P5M0= B0000_0000;
}

//晶体频率19.6608MHZ
//初始化T0定时器, 作为系统只要任务调度使用, 定时周期10mS
//65536 - 10000/(12/19.660800) = 49152(0xc000)
void T0_init(void) {

TH0=0xc0;
TL0=0x00;
//T0时钟为MCLK/12
AUXR&=B0111_1111;
//设置定时器模式
        TMOD &= B1111_0000;               
        TMOD |= B0000_0001;               
        TF0 = 0;                //清除TF0标志
        TR0 = 1;                //定时器0开始计时
//中断优先级最高.
IPH |= B0000_0010;
IP|= B0000_0010;
//允许中断
ET0 = 1;
}

//初始化T4定时器, 作为系统只要任务调度使用, 定时周期25mS
//65536 - 25000/(12/19.660800) = 24576(0x6000)
void T4_init(void) {

T4H=0x60;
T4L=0x00;
//启动T4运行,12T模式,关闭时钟引脚(P0.7)输出
T4T3M&=B0000_1111;
T4T3M|=B1000_0000;
//允许定时器4中断
IE2|=B0100_0000;
//中断优先级最低,硬件决定的.
}

//初始化T2定时器,作为串口1/2的波特率发生器,波特率为9600
//65536 - 19660800/(4*9600) = 65024(0xfe00)
void T2_init(void) {

T2H=0xfe;
T2L=0x00;
//关闭T2时钟引脚(P1.3)输出
INTCLKO&=B1111_1011;
//T2CLKO=0,T2工作在定时器模式
AUXR&=B1111_0111;
//T2R=1 启动T2定时器运行, T2x12=1 设置T2时钟不分频
AUXR|=B0001_0100;
//波特率发生器不需要中断
}

//初始化T3定时器, 作为输出任务使用, 定时周期1.25mS
//65536 - 1250/(12/19.660800) = 63488(0xf800)
void T3_init(void) {

T3H=0xf8;
T3L=0x00;
//启动T3运行,12T模式,关闭时钟引脚(P0.5)输出
T4T3M&=B1111_0000;
T4T3M|=B0000_1000;
//允许定时器3中断
IE2|=B0010_0000;
//中断优先级最低,硬件决定的.
}



#define TIMER
#include "CONFIG.H"

#define sbxTestTimer4 P25
#define sbxTestTimer0 P54
#define sbxTestTimer3 P31

//10mS定时周期
void T0_ISR(void) interrupt 1 {
static U8 ihClkCnt=1;
U16 wh;
       
TH0=0xc0;
if(ihClkCnt<100)
                ihClkCnt++;
        else {
    ihClkCnt=1;
    //周期2秒方波
    sbxTestTimer0^=1;
}
        //人为增加一些占用中断的时间 508uS
for(wh=1000U;0!=wh;wh--)
    ;
}

//25mS定时周期
void T4_ISR(void) interrupt 20 {
static U8 ihClkCnt=1;

//清除中断标志T4IF
AUXINTIF&=B0000_0100;
if(ihClkCnt<40)
                ihClkCnt++;
        else {
    ihClkCnt=1;
    //周期2秒方波,最大误差应该是TIMER0中的人为延迟,并且不可累积
    sbxTestTimer4^=1;
}
}

//1.25mS定时周期
//输出用
void T3_ISR(void) interrupt 19 {

//清除中断标志T3IF
AUXINTIF&=B0000_0010;
        sbxTestTimer3^=1;

}



makesoft 发表于 2018-9-12 11:06:58

其实BUG并不可怕,版主应该建议STC出一份详细的BUGLIST这样我们才能放心使用。

su33691 发表于 2018-9-12 11:59:05

//清除中断标志T4IF
AUXINTIF&=B0000_0100;

清0,难道不是 AUXINTIF &= ~B0000_0100;{:lol:}

makesoft 发表于 2018-9-12 12:01:31

本帖最后由 makesoft 于 2018-9-12 12:32 编辑

su33691 发表于 2018-9-12 11:59
//清除中断标志T4IF
AUXINTIF&=B0000_0100;



看DATASHEET,置1清零。

错了,你说的是对的,那估计是STC15是置1清零,谢谢我在测试下。

不过改正后问题依然存在,DEMO程序匆忙中写的有些问题,但不影响问题的本质,图中20个周期的T4竟然多出7.5S。

最后一副图传错了无法删除,前两幅说明问题。

#define TIMER
#include "CONFIG.H"

#define sbxTestTimer4 P25
#define sbxTestTimer0 P54
#define sbxTestTimer3 P31

//10mS定时周期
void T0_ISR(void) interrupt 1 {
static U8 ihClkCnt=1;
U16 wh;
       
TH0=0xc0;
if(ihClkCnt<100)
                ihClkCnt++;
        else {
    ihClkCnt=1;
    //周期2秒方波
    sbxTestTimer0^=1;
}
        //人为增加一些占用中断的时间 508uS
for(wh=1000U;0!=wh;wh--)
    ;
}

//25mS定时周期
void T4_ISR(void) interrupt 20 {
static U8 ihClkCnt=1;

//清除中断标志T4IF
AUXINTIF&=~B0000_0100;
if(ihClkCnt<40)
                ihClkCnt++;
        else {
    ihClkCnt=1;
    //周期2秒方波,最大误差应该是TIMER0中的人为延迟,并且不可累积
    sbxTestTimer4^=1;
}
}

//1.25mS定时周期
//输出用
void T3_ISR(void) interrupt 19 {

//清除中断标志T3IF
AUXINTIF&=~B0000_0010;
        sbxTestTimer3^=1;

}




makesoft 发表于 2018-9-12 12:35:38



修改后的DEMO测试程序,欢迎下载测试。

makesoft 发表于 2018-9-12 13:38:37

小李非刀 发表于 2018-9-11 21:45
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作 ...

版主帮帮忙确认一下这个问题?

makesoft 发表于 2018-9-12 15:00:30

本帖最后由 makesoft 于 2018-9-12 15:03 编辑

给STC8打败了,中断函数优化的只有反转一条指令了,可以确认了,就是丢失中断请求信号,估计和多级流水线有关系,解决这个问题的办法是T3/T4只用一个定时器。



最简单的测试程序打包备份

modbus 发表于 2018-9-12 16:40:12

看一下编译后的汇编列表文件,看看AUXINTIF&=~B0000_0100编译为了什么指令

makesoft 发表于 2018-9-12 17:46:46

本帖最后由 makesoft 于 2018-9-12 20:10 编辑

上面文件包里面有编译代码,肯定是没有问题的,谢谢你的关注。

+代码编译结果

刚才下载打开看了下,没有问题的。

modbus 发表于 2018-9-12 20:50:38

本帖最后由 modbus 于 2018-9-12 20:53 编辑

makesoft 发表于 2018-9-12 17:46
上面文件包里面有编译代码,肯定是没有问题的,谢谢你的关注。

+代码编译结果


那估计真是BUG了,逻辑运算指令属于读、修改、写指令,当某个时钟执行ANL指令清T3标记,在这个时钟内先把 AUXINTIF读出,然后再与上常数,在下个时钟才把相与后的值写回AUXINTIF,如果在读出后写回前之间正好T4也产生了标记,那么写回的值实际上把T4产生的标记给覆盖了,这个问题实际上在最原始的51上也存在,有经验的CPU设计者会避免把完全不相干的事件标记放在一个寄存器上,或者在内核上做好互斥和保护

modbus 发表于 2018-9-12 20:58:35

包括STC8的PCA高速输出管脚和同一个端口上的普通输出管脚冲突那个BUG,也属于这一类问题:指令和事件之间没有解决好写冲突这个问题

makesoft 发表于 2018-9-12 21:01:12

是的,还有第二功能口设置自动变为强输出,这些BUG不致命,但需要事先了解,不然太浪费时间了。

modbus 发表于 2018-9-12 21:16:57

感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能给破译掉

makesoft 发表于 2018-9-12 21:24:43

modbus 发表于 2018-9-12 21:16
感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能 ...

{:smile:} 这么简单的芯片,也就是防君子吧

小李非刀 发表于 2018-9-12 22:45:55

modbus 发表于 2018-9-12 21:16
感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能 ...

我对开盖读取二进制代码不了解,这么容易实现? 不知道开盖后,怎么读啊?

小李非刀 发表于 2018-9-12 22:50:09

makesoft 发表于 2018-9-12 05:44
谢谢版主,开始我也这么认为的。
建议版主测试下t4,开启中断,同时在开几个高级别中断,就会发现这定时 ...

楼主,你让T2、T3或T4自动取反对应的输出IO看看。你用中断,如果别的中断占着CPU,就没机会进去定时器中断了,T2、T3、T4不能设置高优先级中断。但是能不能进中断,不会影响重装的动作的,再强调一次,重装是硬件动作,什么流水线之类无关的。

makesoft 发表于 2018-9-12 23:07:51

本帖最后由 makesoft 于 2018-9-12 23:09 编辑

小李非刀 发表于 2018-9-12 22:50
楼主,你让T2、T3或T4自动取反对应的输出IO看看。你用中断,如果别的中断占着CPU,就没机会进去定时器中 ...

版主没有认真看我测试程序,每个中断函数里面只有一句端口反转,并且三个定时器时间为1.25MS/10MS/25MS,夸张点也就是说CPU 99.999999%时间都是空闲的,所以不存在中断占用的问题。

bug就是bug, 程序问题就是程序问题,希望能弄清楚,谢谢!

测试程序可以在13楼下载。

hailing 发表于 2018-9-13 07:24:03

问下15w系列有没有这些问题:包括STC8的PCA高速输出管脚和同一个端口上的普通输出管脚冲突那个BUG;
第二功能口设置自动变为强输出

makesoft 发表于 2018-9-14 08:42:49

版主有没有测试过我的问题,T3/T4相互干涉{:sad:}

su33691 发表于 2018-9-14 09:13:48

有T3/T4相互干涉的隐患或BUG,那就不用T4,避开就是了。

makesoft 发表于 2018-9-16 13:21:34

楼上,弄清楚是不是bug不仅仅为了自己,自己踏过的坑一定需要后来者再踏一遍吗?

dxm123 发表于 2019-12-26 00:07:39

makesoft 发表于 2018-9-16 13:21
楼上,弄清楚是不是bug不仅仅为了自己,自己踏过的坑一定需要后来者再踏一遍吗?
...

STC也一直没有给正面给你回复啊,到底是不是BUG,需要怎么避免!

小李非刀 发表于 2019-12-30 22:11:06

我使用精确的22.1184MHz外部时钟(温补可调有源晶振50元一个那种),5个计数器都16位自动重装,高速取反输出,同时中断取反一个IO,使用精确的频率计来测量频率,没有发现有问题,输出频率非常准确。

定时器0配置为16位自动重装, 110592HZ中断率.
         允许高速时钟输出时从P3.5输出55296HZ时钟信号.
         中断时从P2.0取反输出55296HZ方波信号.

定时器1配置为16位自动重装, 73728HZ中断率.
         允许高速时钟输出时从P3.4输出36864HZ时钟信号.
         中断时从P2.1取反输出36864HZ方波信号.

定时器2固定为16位自动重装, 55296HZ中断率.
         允许高速时钟输出时从P1.3输出27648HZ时钟信号.
         中断时从P2.2取反输出27648HZ方波信号.

定时器3固定为16位自动重装, 36864Hz中断率.
         允许高速时钟输出时从P0.5输出18432HZ时钟信号.
         中断时从P2.3取反输出18432HZ方波信号.

定时器4固定为16位自动重装, 27648Hz中断率.
         允许高速时钟输出时从P0.7输出13824HZ时钟信号.
         中断时从P2.4取反输出13824HZ方波信号.

不知道为什么,我发不了附件,提示Server(IO) Error

小李非刀 发表于 2019-12-30 22:12:34

不知道为什么,我发不了附件,提示Server(IO) Error。

我将程序贴在下面:
/*************        功能说明        **************

本程序演示5个定时器的使用, 设置时, 可以指定定时时间(us)或系统时钟数.

当设置不当, 将会返回错误(数值过大).

====================================================

定时器0配置为16位自动重装, 110592HZ中断率.
         允许高速时钟输出时从P3.5输出55296HZ时钟信号.
         中断时从P2.0取反输出55296HZ方波信号.

定时器1配置为16位自动重装, 73728HZ中断率.
         允许高速时钟输出时从P3.4输出36864HZ时钟信号.
         中断时从P2.1取反输出36864HZ方波信号.

定时器2固定为16位自动重装, 55296HZ中断率.
         允许高速时钟输出时从P1.3输出27648HZ时钟信号.
         中断时从P2.2取反输出27648HZ方波信号.

定时器3固定为16位自动重装, 36864Hz中断率.
         允许高速时钟输出时从P0.5输出18432HZ时钟信号.
         中断时从P2.3取反输出18432HZ方波信号.

定时器4固定为16位自动重装, 27648Hz中断率.
         允许高速时钟输出时从P0.7输出13824HZ时钟信号.
         中断时从P2.4取反输出13824HZ方波信号.

用户可以修改输出频率,但注意时间不要太高(一般100KHZ以下)。

******************************************/


#define         MAIN_Fosc                22118400UL        //定义主时钟

#include        "..\..\STC8xxxx.H"


u8        Timer0_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
u8        Timer1_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
u8        Timer2_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
u8        Timer3_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.
u8        Timer4_Config(u8 t, u32 reload);        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us), 返回0正确, 返回1装载值过大错误.



//========================================================================
// 函数: void main(void)
// 描述: 主函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void main(void)
{
        P_SW2 |= 0x80;                //XSFR enable   

        XOSCCR = 0xc0;                              //启动外部晶振
        while (!(XOSCCR & 1));                      //等待时钟稳定
        CLKDIV = 0x00;                               //时钟不分频
        CLKSEL = 0x01;                               //选择外部晶振

        MainFosc_OutP54();        // 主时钟从P5.4分频输出,        头文件定义的宏
//        MainFosc_OutP16();        // 主时钟从P1.6分频输出,        头文件定义的宏
        MCLKO_DIV4();                // 分频数为16 (1,2,4,8,16,32,64,128),        头文件定义的宏

        P_SW2 &= ~0x80;                //XDATA enable   

        Timer0_Config(0, 200);        //t=0: reload值是主时钟周期数,(中断频率, 110592次/秒)
        Timer1_Config(0, 300);        //t=0: reload值是主时钟周期数,(中断频率,73728次/秒)
        Timer2_Config(0, 400);        //t=0: reload值是主时钟周期数,(中断频率,55296次/秒)
        Timer3_Config(0, 600);        //t=0: reload值是主时钟周期数,(中断频率,36864次/秒)
        Timer4_Config(0, 800);        //t=0: reload值是主时钟周期数,(中断频率,27648次/秒)

        EA = 1;                //打开总中断

        while (1)
        {

        }
}

//========================================================================
// 函数:u8        Timer0_Config(u8 t, u32 reload)
// 描述: timer0初始化函数.
// 参数:      t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
//       reload: 重装值.
// 返回: 0: 初始化正确, 1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer0_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us)
{
        TR0 = 0;        //停止计数

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        AUXR |= 0x80;                //1T mode
        else
        {
                AUXR &= ~0x80;        //12T mode
                reload = reload / 12;
        }
        reload = 65536UL - reload;
        TH0 = (u8)(reload >> 8);
        TL0 = (u8)(reload);

        ET0 = 1;        //允许中断
//        PT0 = 1;        //高优先级中断
        TMOD = (TMOD & ~0x03) | 0;        //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装, 3: 16位自动重装, 不可屏蔽中断
//        TMOD |=0x04;        //对外计数或分频
        INT_CLKO |=0x01;        //输出时钟
        TR0 = 1;        //开始运行
        return 0;
}


//========================================================================
// 函数: u8        Timer1_Config(u8 t, u32 reload)
// 描述: timer1初始化函数.
// 参数:      t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
//       reload: 重装值.
// 返回: 0: 初始化正确,1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer1_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us)
{
        TR1 = 0;        //停止计数

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        AUXR |= 0x40;                //1T mode
        else
        {
                AUXR &= ~0x40;        //12T mode
                reload = reload / 12;
        }
        reload = 65536UL - reload;
        TH1 = (u8)(reload >> 8);
        TL1 = (u8)(reload);

        ET1 = 1;        //允许中断
//        PT1 = 1;        //高优先级中断
        TMOD = (TMOD & ~0x30) | (0 << 4);        //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
//        TMOD |=0x40;        //对外计数或分频
        INT_CLKO |=0x02;        //输出时钟
        TR1 = 1;        //开始运行
        return 0;
}

//========================================================================
// 函数: u8        Timer2_Config(u8 t, u32 reload)
// 描述: timer2初始化函数.
// 参数:      t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
//       reload: 重装值.
// 返回: 0: 初始化正确,1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer2_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us)
{
        AUXR &= ~0x1c;                //停止计数, 定时模式, 12T模式

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        AUXR |= (1<<2);                //1T mode
        else        reload = reload / 12;        //12T mode
        reload = 65536UL - reload;
        T2H = (u8)(reload >> 8);
        T2L = (u8)(reload);

        IE2|=(1<<2);        //允许中断
        INT_CLKO |=0x04;        //允许输出时钟
//        AUXR |=(1<<3);        //对外计数或分频
        AUXR |=(1<<4);        //开始运行
        return 0;
}


//========================================================================
// 函数: u8        Timer3_Config(u8 t, u32 reload)
// 描述: timer3初始化函数.
// 参数:      t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
//       reload: 重装值.
// 返回: 0: 初始化正确,1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer3_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us)
{
        T4T3M &= 0xf0;                //停止计数, 定时模式, 12T模式, 不输出时钟

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        T4T3M |=(1<<1);        //1T mode
        else        reload = reload / 12;        //12T mode
        reload = 65536UL - reload;
        T3H = (u8)(reload >> 8);
        T3L = (u8)(reload);

        IE2   |=(1<<5);        //允许中断
//        T4T3M |=(1<<2);        //对外计数或分频
        T4T3M |=1;                //允许输出时钟
        T4T3M |=(1<<3);        //开始运行
        return 0;
}

//========================================================================
// 函数: u8        Timer4_Config(u8 t, u32 reload)
// 描述: timer3初始化函数.
// 参数:      t: 重装值类型, 0表示重装的是系统时钟数, 其余值表示重装的是时间(us).
//       reload: 重装值.
// 返回: 0: 初始化正确,1: 重装值过大, 初始化错误.
// 版本: V1.0, 2018-3-5
//========================================================================
u8        Timer4_Config(u8 t, u32 reload)        //t=0: reload值是主时钟周期数,t=1: reload值是时间(单位us)
{
        T4T3M &= 0x0f;                //停止计数, 定时模式, 12T模式, 不输出时钟

        if(t != 0)        reload = (u32)(((float)MAIN_Fosc * (float)reload)/1000000UL);        //重装的是时间(us), 计算所需要的系统时钟数.
        if(reload >= (65536UL * 12))        return 1;        //值过大, 返回错误
        if(reload < 65536UL)        T4T3M |=(1<<5);        //1T mode
        else        reload = reload / 12;        //12T mode
        reload = 65536UL - reload;
        T4H = (u8)(reload >> 8);
        T4L = (u8)(reload);

        IE2   |=(1<<6);        //允许中断
//        T4T3M |=(1<<6);        //对外计数或分频
        T4T3M |=(1<<4);        //允许输出时钟
        T4T3M |=(1<<7);        //开始运行
        return 0;
}

//========================================================================
// 函数: void timer0_int (void) interrupt TIMER0_VECTOR
// 描述:timer0中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer0_int (void) interrupt TIMER0_VECTOR
{
   P20 = ~P20;
}

//========================================================================
// 函数: void timer1_int (void) interrupt TIMER1_VECTOR
// 描述:timer1中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer1_int (void) interrupt TIMER1_VECTOR
{
   P21 = ~P21;

}

//========================================================================
// 函数: void timer2_int (void) interrupt TIMER2_VECTOR
// 描述:timer2中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer2_int (void) interrupt TIMER2_VECTOR
{
        P22 = ~P22;
}

//========================================================================
// 函数: void timer3_int (void) interrupt TIMER3_VECTOR
// 描述:timer3中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer3_int (void) interrupt TIMER3_VECTOR
{
        P23 = ~P23;
}

//========================================================================
// 函数: void timer4_int (void) interrupt TIMER4_VECTOR
// 描述:timer4中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2016-5-12
//========================================================================
void timer4_int (void) interrupt TIMER4_VECTOR
{
        P24 = ~P24;
}

makesoft 发表于 2019-12-31 08:52:00

本帖最后由 makesoft 于 2019-12-31 08:54 编辑

小李非刀 发表于 2019-12-30 22:12
不知道为什么,我发不了附件,提示Server(IO) Error。

我将程序贴在下面:


想测试斑竹的程序,请上传一个完整的工程,你的寄存器名称(比如压根就没有CLKSEL,只有CKSEL)都和公开的STC8.H不一样,还有好多定义的宏没有。

另外我13楼测试程序只有几行,看的更明白更简单,打包好的工程很容易,希望斑主可以下载测试,最起码几年的问题弄清楚就好。

modbus 发表于 2019-12-31 10:18:51

小李非刀 发表于 2019-12-30 22:12
不知道为什么,我发不了附件,提示Server(IO) Error。

我将程序贴在下面:


T2、T3、T4中断程序中难道不用清除中断标记吗

makesoft 发表于 2019-12-31 22:37:35

modbus 发表于 2019-12-31 10:18
T2、T3、T4中断程序中难道不用清除中断标记吗

斑竹在交差   (∪。∪)。。。zzz
页: [1]
查看完整版本: 询问一下STC8定时器自动重装受中断优先级影响吗?