本帖最后由 tree844 于 2021-11-20 21:10 编辑
#include <xc.h>
#define _XTAL_FREQ 4000000
const unsigned char TABLE[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
unsigned int time;
void init(void);
void init_TIM0(void);
void disp(void);
void main(void)
{
init();
init_TIM0();
while(1)
{
disp();
}
}
void init(void)
{
PORTD = 0x00;
TRISD = 0x00;
PORTA = 0x00;
TRISA = 0x00;
ADCON1 = 0x06;
}
void init_TIM0(void)
{
TMR0 = 58; //256-200=56;56+2=58
OPTION_REG = 0x01; //0000 0001 4分频,定时周期200us*4=800us
INTCON = 0xA0; //1010 0000
}
void __interrupt() isr_TMR0(void)
{
static unsigned char i = 0;
if(T0IE && T0IF)
{
TMR0 = TMR0 + 58;
if(i < 124)
{
i++;
}
else //0.8ms*125 = 100ms
{
i = 0;
if(time < 999)
{
time++;
}
else
{
time = 0;
}
}
T0IF = 0;
}
}
void disp(void)
{
PORTD = TABLE[time % 10];
PORTA = 0x01;
__delay_ms(1);
PORTA = 0x00;
PORTD = TABLE[time /10 % 10] | 0x80;
PORTA = 0x02;
__delay_ms(1);
PORTA = 0x00;
PORTD = TABLE[time/100];
PORTA = 0x04;
__delay_ms(1);
PORTA = 0x00;
}
|
@wangchangwenqq :我懂这一点。我的疑惑主要是TMR1没有加上这段累加的数值,而观测结果却没有偏差。不过我现在有点想明白了,我在最新的跟帖下面有说。谢谢您的讨论。
@tree844 : 因为是8位机 TMR0 ,TMR1 是16位定时器没有周期寄存器, 所以每次都要装载初值, 溢出0xFFFF ,此时有中断指令开销以及其它中断可能会影响, 但是定时器的计数在还在计数, 你直接附初值,不是把溢出之后计数的值清零,所以 加上计数的值可以消除产生的误差
@tree844 :TMR2, TMR4 都有周期寄存器, 每次都是0x00开始, 到周期匹配, 时序理论不会有误差, TMR1 ,TMR0,TMR3 是要装载初值的 一直到溢出0xFFFF, 这里就有延迟, 在TMR计数寄存器加上初值 可以将误差降低
@wangchangwenqq :有一定道理。但是TM1和TM2为什么可以直接赋值而不用加上这段时间的累加值呢?我最在意的一点是,这个逻辑有没有相关文档有直接的说明?
16F877A 没有高优先级中断, 这就和你把中断有没有放最前面有关了,而且 就算你 进入中断 最先判断 TMR0的中断条件, 此时在之前产生了其它的中断 而且中断没有运行完成,中断触发都会默认的关闭总中断GIE,是不会立即运行TMR0的中断, 造成时序延迟