询问一下STC8定时器自动重装受中断优先级影响吗?
比如说我使用T4定时器,其中断优先级天生就是最低的,它的自动重装功能应该是硬件实现的吧?也就是说定时器溢出后应该立即自动重装初值,仅仅是中断响应滞后于其他优先级中断。
还是等待中断响应后才能由硬件重装初值,要是这样话,自动重装的意义也就是一条指令的优势了。
DATASHEET里面并没有详细的描述,斑竹能确认下是什么样的方式吗?
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作。所以,STC的MCU可以轻易的用定时器分频输出几MHZ的方波(50KHZ以上最好不要开中断,中断太频繁了)。 小李非刀 发表于 2018-9-11 21:45
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作 ...
谢谢版主,开始我也这么认为的。
建议版主测试下t4,开启中断,同时在开几个高级别中断,就会发现这定时器变慢了,并且慢的还挺夸张,我用25ms定时测试,其他中断频繁时要慢1%以上,需要的话可以从项目中剥离出demo程序。
自动重装是不依赖中断的,所以这慢只能说重装参数的时刻和cpu忙不忙相关。 本帖最后由 makesoft 于 2018-9-12 05:48 编辑
补充下,同时测试了自身rc和使用晶体两种模式,结果相同。
后来改为t0定时器,使用最高级别中断解决了问题。 不是慢了,其它高的中断占用了时间 硬邦邦 发表于 2018-9-12 06:19
不是慢了,其它高的中断占用了时间
同学,俺是老司机,不是幼稚园的儿童哦。 本帖最后由 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;
}
其实BUG并不可怕,版主应该建议STC出一份详细的BUGLIST这样我们才能放心使用。 //清除中断标志T4IF
AUXINTIF&=B0000_0100;
清0,难道不是 AUXINTIF &= ~B0000_0100;{:lol:}
本帖最后由 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;
}
修改后的DEMO测试程序,欢迎下载测试。 小李非刀 发表于 2018-9-11 21:45
自动重装是硬件级的,跟中断无关,跟中断优先级无关。你开不开中断,用什么优先级,都不会影响自动重装动作 ...
版主帮帮忙确认一下这个问题? 本帖最后由 makesoft 于 2018-9-12 15:03 编辑
给STC8打败了,中断函数优化的只有反转一条指令了,可以确认了,就是丢失中断请求信号,估计和多级流水线有关系,解决这个问题的办法是T3/T4只用一个定时器。
最简单的测试程序打包备份
看一下编译后的汇编列表文件,看看AUXINTIF&=~B0000_0100编译为了什么指令 本帖最后由 makesoft 于 2018-9-12 20:10 编辑
上面文件包里面有编译代码,肯定是没有问题的,谢谢你的关注。
+代码编译结果
刚才下载打开看了下,没有问题的。
本帖最后由 modbus 于 2018-9-12 20:53 编辑
makesoft 发表于 2018-9-12 17:46
上面文件包里面有编译代码,肯定是没有问题的,谢谢你的关注。
+代码编译结果
那估计真是BUG了,逻辑运算指令属于读、修改、写指令,当某个时钟执行ANL指令清T3标记,在这个时钟内先把 AUXINTIF读出,然后再与上常数,在下个时钟才把相与后的值写回AUXINTIF,如果在读出后写回前之间正好T4也产生了标记,那么写回的值实际上把T4产生的标记给覆盖了,这个问题实际上在最原始的51上也存在,有经验的CPU设计者会避免把完全不相干的事件标记放在一个寄存器上,或者在内核上做好互斥和保护 包括STC8的PCA高速输出管脚和同一个端口上的普通输出管脚冲突那个BUG,也属于这一类问题:指令和事件之间没有解决好写冲突这个问题 是的,还有第二功能口设置自动变为强输出,这些BUG不致命,但需要事先了解,不然太浪费时间了。 感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能给破译掉 modbus 发表于 2018-9-12 21:16
感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能 ...
{:smile:} 这么简单的芯片,也就是防君子吧 modbus 发表于 2018-9-12 21:16
感觉STC的有些设计思想很那个,比如STC8的唯一ID加密,只要能把二进制代码开盖读出来,我都不用反汇编就能 ...
我对开盖读取二进制代码不了解,这么容易实现? 不知道开盖后,怎么读啊? makesoft 发表于 2018-9-12 05:44
谢谢版主,开始我也这么认为的。
建议版主测试下t4,开启中断,同时在开几个高级别中断,就会发现这定时 ...
楼主,你让T2、T3或T4自动取反对应的输出IO看看。你用中断,如果别的中断占着CPU,就没机会进去定时器中断了,T2、T3、T4不能设置高优先级中断。但是能不能进中断,不会影响重装的动作的,再强调一次,重装是硬件动作,什么流水线之类无关的。 本帖最后由 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楼下载。 问下15w系列有没有这些问题:包括STC8的PCA高速输出管脚和同一个端口上的普通输出管脚冲突那个BUG;
第二功能口设置自动变为强输出 版主有没有测试过我的问题,T3/T4相互干涉{:sad:} 有T3/T4相互干涉的隐患或BUG,那就不用T4,避开就是了。 楼上,弄清楚是不是bug不仅仅为了自己,自己踏过的坑一定需要后来者再踏一遍吗?
makesoft 发表于 2018-9-16 13:21
楼上,弄清楚是不是bug不仅仅为了自己,自己踏过的坑一定需要后来者再踏一遍吗?
...
STC也一直没有给正面给你回复啊,到底是不是BUG,需要怎么避免! 我使用精确的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 不知道为什么,我发不了附件,提示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:54 编辑
小李非刀 发表于 2019-12-30 22:12
不知道为什么,我发不了附件,提示Server(IO) Error。
我将程序贴在下面:
想测试斑竹的程序,请上传一个完整的工程,你的寄存器名称(比如压根就没有CLKSEL,只有CKSEL)都和公开的STC8.H不一样,还有好多定义的宏没有。
另外我13楼测试程序只有几行,看的更明白更简单,打包好的工程很容易,希望斑主可以下载测试,最起码几年的问题弄清楚就好。 小李非刀 发表于 2019-12-30 22:12
不知道为什么,我发不了附件,提示Server(IO) Error。
我将程序贴在下面:
T2、T3、T4中断程序中难道不用清除中断标记吗 modbus 发表于 2019-12-31 10:18
T2、T3、T4中断程序中难道不用清除中断标记吗
斑竹在交差 (∪。∪)。。。zzz
页:
[1]