amobbs.com 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
回复: 32

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

[复制链接]
(57546576)

打赏出0元收入1元

发表于 2018-9-11 06:30:46 | 显示全部楼层 |阅读模式
比如说我使用T4定时器,其中断优先级天生就是最低的,它的自动重装功能应该是硬件实现的吧?

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

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

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

捕获.JPG
(57491670)

打赏出0元收入0元

发表于 2018-9-11 21:45:52 | 显示全部楼层
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作。所以,STC的MCU可以轻易的用定时器分频输出几MHZ的方波(50KHZ以上最好不要开中断,中断太频繁了)。
(57462942)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 05:44:40 来自手机 | 显示全部楼层
小李非刀 发表于 2018-9-11 21:45
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作 ...

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

打赏出0元收入1元

 楼主| 发表于 2018-9-12 05:47:16 来自手机 | 显示全部楼层
本帖最后由 makesoft 于 2018-9-12 05:48 编辑

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

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

打赏出0元收入0元

发表于 2018-9-12 06:19:08 来自手机 | 显示全部楼层
不是慢了,其它高的中断占用了时间
(57456759)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 07:27:43 来自手机 | 显示全部楼层
硬邦邦 发表于 2018-9-12 06:19
不是慢了,其它高的中断占用了时间

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

打赏出0元收入1元

 楼主| 发表于 2018-9-12 10:40:22 | 显示全部楼层
本帖最后由 makesoft 于 2018-9-12 10:41 编辑

程序中T0和T4应该是相同周期,可是逻辑分析抓图T4是T0的倍数了
从程序判断,应该是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.2  PE,   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;

}


捕获.JPG
DEMO.zip (82.19 KB)
(57443604)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 11:06:58 | 显示全部楼层
其实BUG并不可怕,版主应该建议STC出一份详细的BUGLIST这样我们才能放心使用。
(57440477)

打赏出0元收入0元

发表于 2018-9-12 11:59:05 | 显示全部楼层
//清除中断标志T4IF
  AUXINTIF&=B0000_0100;

清0,难道不是 AUXINTIF &= ~B0000_0100;
(57440331)

打赏出0元收入1元

 楼主| 发表于 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;

}

T4.jpg

捕获T0.JPG
T0.jpg
(57438284)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 12:35:38 | 显示全部楼层
修改后的DEMO测试程序.zip (82.2 KB)
(57434505)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 13:38:37 | 显示全部楼层
小李非刀 发表于 2018-9-11 21:45
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作 ...

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

打赏出0元收入1元

 楼主| 发表于 2018-9-12 15:00:30 | 显示全部楼层
本帖最后由 makesoft 于 2018-9-12 15:03 编辑

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

最简单的测试程序打包备份
STC8T3T4相互干涉测试DEMO_1.zip (81.17 KB)
(57423610)

打赏出0元收入0元

发表于 2018-9-12 16:40:12 | 显示全部楼层
看一下编译后的汇编列表文件,看看AUXINTIF&=~B0000_0100编译为了什么指令
(57419616)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 17:46:46 来自手机 | 显示全部楼层
本帖最后由 makesoft 于 2018-9-12 20:10 编辑

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

+代码编译结果

刚才下载打开看了下,没有问题的。
捕获11.JPG
(57408584)

打赏出0元收入0元

发表于 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设计者会避免把完全不相干的事件标记放在一个寄存器上,或者在内核上做好互斥和保护
(57408107)

打赏出0元收入0元

发表于 2018-9-12 20:58:35 | 显示全部楼层
包括STC8的PCA高速输出管脚和同一个端口上的普通输出管脚冲突那个BUG,也属于这一类问题:指令和事件之间没有解决好写冲突这个问题
(57407950)

打赏出0元收入1元

 楼主| 发表于 2018-9-12 21:01:12 | 显示全部楼层
是的,还有第二功能口设置自动变为强输出,这些BUG不致命,但需要事先了解,不然太浪费时间了。
(57407005)

打赏出0元收入0元

发表于 2018-9-12 21:16:57 | 显示全部楼层
感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能给破译掉
(57406539)

打赏出0元收入1元

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

这么简单的芯片,也就是防君子吧
(57401667)

打赏出0元收入0元

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

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

打赏出0元收入0元

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

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

打赏出0元收入1元

 楼主| 发表于 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楼下载。
(57370579)

打赏出0元收入8元

发表于 2018-9-13 07:24:03 | 显示全部楼层
问下15w系列有没有这些问题:包括STC8的PCA高速输出管脚和同一个端口上的普通输出管脚冲突那个BUG;
第二功能口设置自动变为强输出
(57279453)

打赏出0元收入1元

 楼主| 发表于 2018-9-14 08:42:49 | 显示全部楼层
版主有没有测试过我的问题,T3/T4相互干涉
(57277594)

打赏出0元收入0元

发表于 2018-9-14 09:13:48 | 显示全部楼层
有T3/T4相互干涉的隐患或BUG,那就不用T4,避开就是了。
(57089928)

打赏出0元收入1元

 楼主| 发表于 2018-9-16 13:21:34 | 显示全部楼层
楼上,弄清楚是不是bug不仅仅为了自己,自己踏过的坑一定需要后来者再踏一遍吗?
(16875163)

打赏出0元收入0元

发表于 2019-12-26 00:07:39 | 显示全部楼层
makesoft 发表于 2018-9-16 13:21
楼上,弄清楚是不是bug不仅仅为了自己,自己踏过的坑一定需要后来者再踏一遍吗?
...

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

打赏出0元收入0元

发表于 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
(16450068)

打赏出0元收入0元

发表于 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;
}

(16411702)

打赏出0元收入1元

 楼主| 发表于 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楼测试程序只有几行,看的更明白更简单,打包好的工程很容易,希望斑主可以下载测试,最起码几年的问题弄清楚就好。
(16406491)

打赏出0元收入0元

发表于 2019-12-31 10:18:51 | 显示全部楼层
小李非刀 发表于 2019-12-30 22:12
不知道为什么,我发不了附件,提示Server(IO) Error。

我将程序贴在下面:

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

打赏出0元收入1元

 楼主| 发表于 2019-12-31 22:37:35 来自手机 | 显示全部楼层
modbus 发表于 2019-12-31 10:18
T2、T3、T4中断程序中难道不用清除中断标记吗

斑竹在交差   (∪。∪)。。。zzz
回帖提示: 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子论坛 ( 公安交互式论坛备案:44190002001997 粤ICP备09047143号-1 )

GMT+8, 2020-7-8 07:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表