【问题标题】:Timer based interrupt in PIC microcontroller using mikroC for PICPIC 微控制器中基于定时器的中断使用 mikroC for PIC
【发布时间】:2017-06-26 10:40:21
【问题描述】:

在 mikroC for PIC 中实现基于定时器的中断时遇到问题。

如果 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;
   }
  }
 }
}

没有任何工作。有人可以帮我更正代码吗?

【问题讨论】:

  • “没有任何效果”不是问题描述。 什么不起作用?
  • 事后看来,Nothing is working 确实是一个非常模糊的评论。我正在尝试使用定时器中断每 100 毫秒执行一次 PORT 切换恰好 8 次。我尝试了很多选项,但没有一个对我有用。我最接近的是使用中断在一定时间延迟后切换端口。但无法阻止它在 n 次后切换。

标签: c pic c89 mikroc


【解决方案1】:

这看起来不对:

  if (flag==1)
  {
   for (i=0;i<=8;i++)
   {
    PORTB=~PORTB;
    flag=0;
   }
  }

当您第一次看到 flag 已设置时,您会立即循环并切换输出 8 次,无需等待 flag 变回 1。这是不对的,它过于简化了.

您需要查找flag,然后切换输出并清除flag,并等待它再次被设置,同时保持计数器并行。 for 循环不适合这种情况,因为它会“锁定”程序的其余部分,并可能导致错过按键。

【讨论】:

  • 我确实尝试过按照您的建议...而不是 for 循环,在切换端口并清除标志后,我增加了另一个变量 i。我确实提出了if (i&gt;=8) {PORTB=0x00; i=0;}This 的条件语句,这不起作用。基本上,我可以在一定的延迟后启动 PORT 来切换,但不明白如何在 n 个周期后阻止它切换。
【解决方案2】:

当你初始化你的计时器时:

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 的第一次“闪烁”可能会持续长达 200 毫秒……这就是为什么许多人喜欢使用更快的定时器中断(这通常也有其他用途),控制LED 需要添加一个软后缩放器

   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;
}

这应该让你第一次眨眼更均匀。

【讨论】:

  • 感谢迈克尔的帮助。我确实解决了问题,请您检查方法是否正确? while(i&lt;8) { if (flag==1){ i++; PORTB.F0 = ~PORTB.F0; cnt=0;flag=0; } } 这确实会切换端口引脚 8 次,并且设置 cnt 的值允许精确设置切换端口引脚的延迟。这种方法正确吗?
  • 它是正确的,但它会阻塞你的主循环。您可能需要执行哪些其他操作?
猜你喜欢
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多