使用 mikroC for PIC 的 PIC 微控制器中基于定时器的中断
Timer based interrupt in PIC microcontroller using mikroC for PIC
我在为 PIC 在 mikroC 中实现基于定时器的中断时遇到问题。
如果在 PORTC.F0 有按键,我想切换端口引脚 8 次,并且切换之间应该有 100 毫秒的延迟。
通常这会很容易使用延迟功能
for (i=0;i<=8;i++)
{
PORTB.F0=~PORTB.F0;
Delay_ms(100);
}
但是在此期间,系统会错过任何其他按键。所以我想到了使用中断来实现解决方案。
#define SW PORTC.F0
char ttime,i;
volatile flag;
void Inittimer()
{
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0x06;
TMR1L = 0x00;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
void Interrupt()
{
if (TMR1IF_bit)
{
TMR1IF_bit = 0;
TMR1H = 0x06;
TMR1L = 0x00;
ttime--;
if (ttime==0)
{
flag=1;
}
}
}
void main()
{
Inittimer1();
TRISB = 0;
TRISC.F0 = 1;
PORTB = 0x00;
while(1)
{
if (SW==0)
{
ttime=3;
}
if (flag==1)
{
for (i=0;i<=8;i++)
{
PORTB=~PORTB;
flag=0;
}
}
}
}
没有任何效果。有人可以帮我更正代码吗?
嗯,这看起来不对:
if (flag==1)
{
for (i=0;i<=8;i++)
{
PORTB=~PORTB;
flag=0;
}
}
当您第一次看到 flag
已设置时,您会立即循环并切换输出 8 次,而无需 等待 flag
返回1. 不对,太简单了
您需要寻找 flag
,然后切换输出并清除 flag
,并等待它再次设置,同时保持计数器。 for
循环不是适合此目的的结构,因为它将 "lock out" 程序的其余部分并可能导致按键丢失。
当您初始化计时器时:
void Inittimer()
{
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0x06; // No prescaler? I doubt your clock speed is 40-some KHz!
TMR1L = 0x00;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
为什么不直接从 ISR 控制 LED?
if (ttime)
PORTB.F0 = (--ttime & 1); // ttime is not decremented when led is not blinking.
else
PORTB.F0 = 0; // ensures the LED is off.
要开始闪烁 8 次:
if (SW==0)
{
PORTB.F0 = 1;
ttime = 16;
}
请注意,对于 100 毫秒的时钟中断,LED 的第一个 'blink' 可能会持续长达 200 毫秒...这就是为什么许多人喜欢使用更快的定时器中断(这通常有其他用途,如好吧),控制 LED 需要添加一个软 post-scaler
if (blinking)
{
if (--blinkTimer == 0)
{
blinkTimer = BLINK_DELAY; // whatever number it takes for 100ms.
PORTB.F0 = (--blinking & 1);
}
}
else
{
PORTB.F0 = 0
}
开始闪烁:
if (SW==0)
{
blinking = (2 * BLINKS) - 1;
blinkTimer = BLINK_DELAY;
PORTB.F0 = 1;
}
这应该会让您第一次眨眼时更加均匀。
我在为 PIC 在 mikroC 中实现基于定时器的中断时遇到问题。
如果在 PORTC.F0 有按键,我想切换端口引脚 8 次,并且切换之间应该有 100 毫秒的延迟。
通常这会很容易使用延迟功能
for (i=0;i<=8;i++)
{
PORTB.F0=~PORTB.F0;
Delay_ms(100);
}
但是在此期间,系统会错过任何其他按键。所以我想到了使用中断来实现解决方案。
#define SW PORTC.F0
char ttime,i;
volatile flag;
void Inittimer()
{
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0x06;
TMR1L = 0x00;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
void Interrupt()
{
if (TMR1IF_bit)
{
TMR1IF_bit = 0;
TMR1H = 0x06;
TMR1L = 0x00;
ttime--;
if (ttime==0)
{
flag=1;
}
}
}
void main()
{
Inittimer1();
TRISB = 0;
TRISC.F0 = 1;
PORTB = 0x00;
while(1)
{
if (SW==0)
{
ttime=3;
}
if (flag==1)
{
for (i=0;i<=8;i++)
{
PORTB=~PORTB;
flag=0;
}
}
}
}
没有任何效果。有人可以帮我更正代码吗?
嗯,这看起来不对:
if (flag==1)
{
for (i=0;i<=8;i++)
{
PORTB=~PORTB;
flag=0;
}
}
当您第一次看到 flag
已设置时,您会立即循环并切换输出 8 次,而无需 等待 flag
返回1. 不对,太简单了
您需要寻找 flag
,然后切换输出并清除 flag
,并等待它再次设置,同时保持计数器。 for
循环不是适合此目的的结构,因为它将 "lock out" 程序的其余部分并可能导致按键丢失。
当您初始化计时器时:
void Inittimer()
{
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0x06; // No prescaler? I doubt your clock speed is 40-some KHz!
TMR1L = 0x00;
TMR1IE_bit = 1;
INTCON = 0xC0;
}
为什么不直接从 ISR 控制 LED?
if (ttime)
PORTB.F0 = (--ttime & 1); // ttime is not decremented when led is not blinking.
else
PORTB.F0 = 0; // ensures the LED is off.
要开始闪烁 8 次:
if (SW==0)
{
PORTB.F0 = 1;
ttime = 16;
}
请注意,对于 100 毫秒的时钟中断,LED 的第一个 'blink' 可能会持续长达 200 毫秒...这就是为什么许多人喜欢使用更快的定时器中断(这通常有其他用途,如好吧),控制 LED 需要添加一个软 post-scaler
if (blinking)
{
if (--blinkTimer == 0)
{
blinkTimer = BLINK_DELAY; // whatever number it takes for 100ms.
PORTB.F0 = (--blinking & 1);
}
}
else
{
PORTB.F0 = 0
}
开始闪烁:
if (SW==0)
{
blinking = (2 * BLINKS) - 1;
blinkTimer = BLINK_DELAY;
PORTB.F0 = 1;
}
这应该会让您第一次眨眼时更加均匀。