【问题标题】:How to delay a output about 15 minutes after pressing a button?按下按钮后如何延迟输出约 15 分钟?
【发布时间】:2023-06-19 05:52:02
【问题描述】:

我正在学习微控制器编程。我需要帮助才能使用 Atmega8L-8PU 在 WinAVR 上完成我的程序。 我添加了 3 个按钮,当按下按钮时:第一个按钮将提供 15 分钟的输出,第二个按钮将提供 30 分钟,最后一个按钮将提供 45 分钟。每次经过后,应自动重置以供下次按下。

这是我编写的代码,但我无法添加持续时间。如果有人能做到,那对我很有帮助。提前谢谢:)。

#define numberofButtons 3

#include <avr/io.h>
#include"buttonpress.h"

int main(void)
{

    DDRB = 0b00000000;
    DDRD = 0b00000111;
    PORTB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2);

    while(1)
    {
        if (buttonpressed(0, PINB, 0, 100))
        {
            PORTD ^= (1<<PIND0);
        }

        if (buttonpressed(1, PINB, 1, 100))
        {
            PORTD ^= (1<<PIND1);
        }
        if (buttonpressed(2, PINB, 2, 100))
        {
            PORTD ^= (1<<PIND2);
        }
    }
}

我已经尝试过这种方式,但它也不起作用........ :(

#define numberofButtons 3

#include"buttonpress.h"
#include <avr/io.h>
#include <avr/interrupt.h>

unsigned char seconds =0;
int minutes;

int main () 
{ 
    DDRB = 0b00000000;
    DDRD = 0b00000111; 
    PORTB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2);

    volatile int seconds;
    DDRD |= (1<<PIND0)|(1<<PIND1)|(1<<PIND2);
    TCCR1B |= (1 << WGM12);                     // Configure timer 1 for CTC mode 
    TIMSK |= (1 << OCIE1A);                     // Enable CTC interrupt

    sei();                                      // Enable global interrupts
    OCR1A = 15624;                              // Set CTC compare value to   1Hz at 8MHz AVR clock, with a prescaler of 64 
    TCCR1B |= ((1 << CS10) | (1 << CS11));  // Start timer at Fcpu/64

    while (1) 
    { 

        if(seconds==60) 
        { 
            minutes++;
            seconds=0;
        }
        {
            if (buttonpressed(0, PINB, 0, 100))
            { 
                 PORTD ^= (1<<PIND0);
                 int total_seconds=900;

                 while(total_seconds-seconds!=0) 
                 { 
                     //Delay of 15 min 
                 } 
             }

          } return 0; 
      }
   }

 ISR (TIMER1_COMPA_vect)
 {
    seconds++;
 }

【问题讨论】:

  • 是否有可用的函数以秒(或其他类似单位)获取当前时间?
  • 我不明白,先生,因为我是编程新手,但我认为 15 分钟可以在 900 秒内计算,如果您有延迟代码,请提供给我。
  • 这是默认时钟。这里没有外部时钟。

标签: c++ atmega winavr


【解决方案1】:

例如,您可以设置 Timer0 以每秒调用一次中断。在每次中断期间,您必须增加内部计数器。经过所需时间(15、30、45 分钟)后,实现您自己的逻辑(如关闭所需端口)。

【讨论】:

    【解决方案2】:

    如果你有从 CPU 获取计数器的函数,那就很简单了,一个可以计算的特定间隔增加的计数器。

    然后,当按下按钮时,您将变量设置为计数器的当前值加上对应于 15 分钟的量。在循环中,您将计数器的当前值与您在按键上设置的变量相比较。当当前计数器等于或大于变量时,15 分钟过去了。


    一些伪代码

    int main(void)
    {
        int eventHapening = 0;
    
        while (1)
        {
            if (keypress)
            {
                eventHappening = currentCounter + 15 minutes;
            }
    
            // Check that eventHappening is non-zero to prevent false positives
            if (eventHappening != 0 && currentCounter >= eventHappening)
            {
                // Do something
                eventHappening = 0; // Reset, and disable event
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果您可以访问头文件time.h,那么以下可能是一个解决方案:

      #define numberofButtons 3
      
      #include <avr/io.h>
      #include<time.h>
      #include"buttonpress.h"
      
      void wait(double x)
      {
          clock_t begin, end;
          double time_spent, limit=1000*60*x;
          begin = clock();
          while(time_spent<= limit)
          {
              end = clock();
              time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
          }
      }
      
      
      int main(void)
      {
          DDRB = 0b00000000;
          DDRD = 0b00000111;
          PORTB = (1<<PINB0)|(1<<PINB1)|(1<<PINB2);
      
          while(1)
          {
              if (buttonpressed(0, PINB, 0, 100))
              {
                  PORTD ^= (1<<PIND0);
                  wait(15);
              }
      
              if (buttonpressed(1, PINB, 1, 100))
              {
                  PORTD ^= (1<<PIND1);
                  wait(15);
              }
              if (buttonpressed(2, PINB, 2, 100))
              {
                  PORTD ^= (1<<PIND2);
                  wait(15);
              }
          }
      }
      

      上面的代码很可能不会出现任何错误。由于代码有一些依赖关系,我可以成功编译下面给出的类似程序。

      #define numberofButtons 3
      
      #include <stdio.h>
      #include<time.h>
      
      void wait(double x)
      {
          clock_t begin, end;
          double time_spent, limit=1000*60*x;
          begin = clock();
          while(time_spent<= limit)
          {
              end = clock();
              time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
          }
      }
      
      
      int main(void)
      {
          char c;
          while((c = getchar())!='e')
          {
              if (c == 'a')
              {
                  printf("I am in a! Come after 15 min!\n");
                  wait(15);
                  printf("WOW! How could you pass 15 min!!\n");
              }
              if (c == 'b')
              {
                  printf("I am in b! Come after 15 min!\n");
                  wait(15);
                  printf("WOW! How could you pass 15 min!!\n");
              }
              if (c == 'c')
              {
                  printf("I am in c! Come after 15 min!\n");
                  wait(15);
                  printf("WOW! How could you pass 15 min!!\n");
              }
          }
      }
      

      可以看到here用c编译时没有编译错误。

      【讨论】:

      • 先生能给我time.h文件吗??
      • @Sohel 你可以查看here
      • ./time.h:73: error: '=', ',', ';', 'asm' or 'attribute' before 'clock'
      • @Sohel 我不知道您使用的是什么编译器。但它正在使用 C 编译器。在更新的答案中查看我的工作代码。
      • @Sohel 你能提供一些关于你的设备的更多信息吗?
      【解决方案4】:

      您没有将您的问题标记为 AVR,这就是为什么现有答案忽略了您拥有实际 AVR 计时器这一事实。

      更准确地说,这些计时器是 CPU 周期计数器。 TIMER1 特别是一个 16 位计数器。如果您将TCCR1 时钟选择位设置为101,这将每1024 个CPU 周期计数一个滴答声。让我们假设一个 16 Mhz 时钟,这意味着每秒 16000000 个 CPU 周期 = 每秒 15625 个滴答声。

      由于TIMER1 是一个 16 位值,它每 4.2 秒溢出一次。您可以将此溢出用于generate an interrupt。 900 秒只是 214.6 次中断——你能逃脱 898 秒吗?当然,您也可以计算TIMER0 的溢出。由于这只有 8 位,因此溢出次数是 256 倍:900 秒内发生 54931 次。

      【讨论】:

      • 我如何在我的代码中使用指令?你能把我想在 15、30 和 40 分钟后停止的代码分配给我吗?
      • 示例代码见我回答中的链接。当然,它使用 50 毫秒而不是 90000 毫秒,但请考虑练习的这一部分。您不是从复制代码中学习的,而是从编写代码中学习的。
      • 感谢您宝贵的指导先生,我已经尝试过,但我无法将其关闭。如果您帮助我在哪里输入这些数据,它将更容易学习。如果你有几分钟.......
      • 在我的帖子中,我添加了 3 个正在工作的按钮。当我按下按钮时,LED 会打开,我想在一段时间后将它们关闭。我尝试了很多方法,但我做不到。请帮帮我。
      • @Sohel:澄清一下,您能否创建一个立即关灯的按钮?学习编程就是将艰巨的任务分解成简单的部分。
      最近更新 更多