AVR C编程延迟按键的两个功能

AVR C编程延迟按键的两个功能,c,embedded,avr,atmega,C,Embedded,Avr,Atmega,我对AVR编程非常陌生。 我有一台ATMEGA8,想做这样的东西: 如果你按下一个按钮,一个LED灯应该打开和关闭10次。作品 但是只要你按下按钮,压电管就会发出声音。 问题是我不能同时完成这两个功能 闪烁LED功能 int i; void led(void) { for (i = 0; i < 10; i++) { PORTB |= (1 << PB0); //LED on _delay_ms(250);

我对AVR编程非常陌生。 我有一台ATMEGA8,想做这样的东西:

如果你按下一个按钮,一个LED灯应该打开和关闭10次。作品 但是只要你按下按钮,压电管就会发出声音。 问题是我不能同时完成这两个功能

闪烁LED功能

 int i;
 void led(void) 
 {
     for (i = 0; i < 10; i++)
     {
         PORTB |= (1 << PB0);  //LED on
         _delay_ms(250);       //wait 250ms

         PORTB &= ~(1 << PB0); //LED off
         _delay_ms(250);       //wait 250ms
     }
 }
inti;
无效led(无效)
{
对于(i=0;i<10;i++)
{

PORTB |=(1实现目标的最简单方法可能是轮询LED循环中的按钮,因为您已经处于按钮循环中。但是,作为一般解决方案,它的内聚性较差,无法扩展到更复杂的应用程序

实现并发性的一种通用方法是使用状态机进行LED控制,而无需借助中断或多任务调度器

而不是调用
led()
并且要求它在返回之前完成整个闪烁序列,状态机只需确定按钮是否按下以及是否是改变LED状态的时候,然后立即返回。它跟踪时间和状态,但不会在一次调用中执行完整的LED序列

这是在下面实现的,但是请注意,计时是粗糙的,并且是使用您已经使用过的延迟功能实现的,因为我无法告诉您还有哪些其他服务可供您使用。如果任何处理需要花费大量时间,这可能会影响闪存计时。它依赖于每10毫秒调用一次LED状态机,并且mply对调用进行计数。状态机最好使用一个独立的时钟源(例如标准库
clock()
函数),那么它是否被非周期调用就无关紧要了——与其计算调用的数量,不如根据实际经过的时间来切换状态

注意使用
static
变量来维护状态。
static
在调用函数之间维护其值

#define TICK 10            // milliseconds 
#define FLASH_ON_TICKS 25  // 250ms
#define FLASH_OFF_TICKS 25 // 250ms
#define FLASH_COUNT 10

static void ledUpdate( int start_flashing ) ;

int main( void )
{
  for(;;)
  {
    // Perform loop on each tick (10ms)
    // Assumes loop processing time is not significant! 
    _delay_ms( TICK ) ;

    if (!(PINB & (1<<PB7)) )
    {
      PORTB |= (1 << PB1); // Piezo on
      ledUpdate( 1 ) ;  
    }
    else
    {
      PORTB &= ~(1 << PB1); // Piezo off
      ledUpdate( 0 ) ;  
    }
  }

  return 0 ;
}

void ledUpdate( int start_flashing )
{
  static enum
  {
    LED_IDLE,
    LED_FLASH_ON,
    LED_FLASH_OFF

  } led_state = LED_IDLE ;

  static int led_tick = 0 ;
  static int flash_count = 0 ;

  switch( led_state )
  {
    case LED_IDLE :
    {
      if( start_flashing )
      {
        led_state = LED_FLASH_ON ;
        PORTB |= (1 << PB0);  //LED on
      }
    }
    break ;

    case LED_FLASH_ON :
    {
      led_tick++ ;
      flash_count++ ;
      if( led_tick >= FLASH_ON_TICKS )
      {
        led_state = LED_FLASH_OFF ;
        led_tick = 0 ;
        PORTB &= ~(1 << PB0); //LED off
      }
    }
    break ;

    case LED_FLASH_OFF :
    {
      if( flash_count >= FLASH_COUNT )
      {
        led_state = LED_IDLE ;
      }
      else
      {
        led_tick++ ;
        if( led_tick >= FLASH_ON_TICKS )
        {
          led_state = LED_FLASH_ON ;
          led_tick = 0 ;
          PORTB |= (1 << PB0);  //LED on
        }
    }
    break ;
  }
}

在软件设计中,两个有用的目标是实现代码的可维护性和可重用性。

实现目标的最简单方法可能是在LED循环中轮询按钮,因为您已经在按钮循环中。但是,作为一个通用解决方案,它的内聚性较差,不可扩展可扩展到更复杂的应用程序

实现并发性的一种通用方法是使用状态机进行LED控制,而无需借助中断或多任务调度器

而不是调用
led()
并且要求它在返回之前完成整个闪烁序列,状态机只需确定按钮是否按下以及是否是改变LED状态的时候,然后立即返回。它跟踪时间和状态,但不会在一次调用中执行完整的LED序列

这是在下面实现的,但是请注意,计时是粗糙的,并且是使用您已经使用过的延迟功能实现的,因为我无法告诉您还有哪些其他服务可供您使用。如果任何处理需要花费大量时间,这可能会影响闪存计时。它依赖于每10毫秒调用一次LED状态机,并且mply对调用进行计数。状态机最好使用一个独立的时钟源(例如标准库
clock()
函数),那么它是否被非周期调用就无关紧要了——与其计算调用的数量,不如根据实际经过的时间来切换状态

注意使用
static
变量来维护状态。
static
在调用函数之间维护其值

#define TICK 10            // milliseconds 
#define FLASH_ON_TICKS 25  // 250ms
#define FLASH_OFF_TICKS 25 // 250ms
#define FLASH_COUNT 10

static void ledUpdate( int start_flashing ) ;

int main( void )
{
  for(;;)
  {
    // Perform loop on each tick (10ms)
    // Assumes loop processing time is not significant! 
    _delay_ms( TICK ) ;

    if (!(PINB & (1<<PB7)) )
    {
      PORTB |= (1 << PB1); // Piezo on
      ledUpdate( 1 ) ;  
    }
    else
    {
      PORTB &= ~(1 << PB1); // Piezo off
      ledUpdate( 0 ) ;  
    }
  }

  return 0 ;
}

void ledUpdate( int start_flashing )
{
  static enum
  {
    LED_IDLE,
    LED_FLASH_ON,
    LED_FLASH_OFF

  } led_state = LED_IDLE ;

  static int led_tick = 0 ;
  static int flash_count = 0 ;

  switch( led_state )
  {
    case LED_IDLE :
    {
      if( start_flashing )
      {
        led_state = LED_FLASH_ON ;
        PORTB |= (1 << PB0);  //LED on
      }
    }
    break ;

    case LED_FLASH_ON :
    {
      led_tick++ ;
      flash_count++ ;
      if( led_tick >= FLASH_ON_TICKS )
      {
        led_state = LED_FLASH_OFF ;
        led_tick = 0 ;
        PORTB &= ~(1 << PB0); //LED off
      }
    }
    break ;

    case LED_FLASH_OFF :
    {
      if( flash_count >= FLASH_COUNT )
      {
        led_state = LED_IDLE ;
      }
      else
      {
        led_tick++ ;
        if( led_tick >= FLASH_ON_TICKS )
        {
          led_state = LED_FLASH_ON ;
          led_tick = 0 ;
          PORTB |= (1 << PB0);  //LED on
        }
    }
    break ;
  }
}

在软件设计中,两个有用的目标是实现代码的可维护性和可重用性。

实现目标的最简单方法可能是在LED循环中轮询按钮,因为您已经在按钮循环中。但是,作为一个通用解决方案,它的内聚性较差,不可扩展可扩展到更复杂的应用程序

实现并发性的一种通用方法是使用状态机进行LED控制,而无需借助中断或多任务调度器

而不是调用
led()
并且要求它在返回之前完成整个闪烁序列,状态机只需确定按钮是否按下以及是否是改变LED状态的时候,然后立即返回。它跟踪时间和状态,但不会在一次调用中执行完整的LED序列

这是在下面实现的,但是请注意,计时是粗糙的,并且是使用您已经使用过的延迟功能实现的,因为我无法告诉您还有哪些其他服务可供您使用。如果任何处理需要花费大量时间,这可能会影响闪存计时。它依赖于每10毫秒调用一次LED状态机,并且mply对调用进行计数。状态机最好使用一个独立的时钟源(例如标准库
clock()
函数),那么它是否被非周期调用就无关紧要了——与其计算调用的数量,不如根据实际经过的时间来切换状态

注意使用
static
变量来维护状态。
static
在调用函数之间维护其值

#define TICK 10            // milliseconds 
#define FLASH_ON_TICKS 25  // 250ms
#define FLASH_OFF_TICKS 25 // 250ms
#define FLASH_COUNT 10

static void ledUpdate( int start_flashing ) ;

int main( void )
{
  for(;;)
  {
    // Perform loop on each tick (10ms)
    // Assumes loop processing time is not significant! 
    _delay_ms( TICK ) ;

    if (!(PINB & (1<<PB7)) )
    {
      PORTB |= (1 << PB1); // Piezo on
      ledUpdate( 1 ) ;  
    }
    else
    {
      PORTB &= ~(1 << PB1); // Piezo off
      ledUpdate( 0 ) ;  
    }
  }

  return 0 ;
}

void ledUpdate( int start_flashing )
{
  static enum
  {
    LED_IDLE,
    LED_FLASH_ON,
    LED_FLASH_OFF

  } led_state = LED_IDLE ;

  static int led_tick = 0 ;
  static int flash_count = 0 ;

  switch( led_state )
  {
    case LED_IDLE :
    {
      if( start_flashing )
      {
        led_state = LED_FLASH_ON ;
        PORTB |= (1 << PB0);  //LED on
      }
    }
    break ;

    case LED_FLASH_ON :
    {
      led_tick++ ;
      flash_count++ ;
      if( led_tick >= FLASH_ON_TICKS )
      {
        led_state = LED_FLASH_OFF ;
        led_tick = 0 ;
        PORTB &= ~(1 << PB0); //LED off
      }
    }
    break ;

    case LED_FLASH_OFF :
    {
      if( flash_count >= FLASH_COUNT )
      {
        led_state = LED_IDLE ;
      }
      else
      {
        led_tick++ ;
        if( led_tick >= FLASH_ON_TICKS )
        {
          led_state = LED_FLASH_ON ;
          led_tick = 0 ;
          PORTB |= (1 << PB0);  //LED on
        }
    }
    break ;
  }
}

在软件设计中,两个有用的目标是实现代码的可维护性和可重用性。

实现目标的最简单方法可能是在LED循环中轮询按钮,因为您已经在按钮循环中。但是,作为一个通用解决方案,它的内聚性较差,不可扩展可扩展到更复杂的应用程序

实现c语言的通用方法