AVR C编程延迟按键的两个功能
我对AVR编程非常陌生。 我有一台ATMEGA8,想做这样的东西: 如果你按下一个按钮,一个LED灯应该打开和关闭10次。作品 但是只要你按下按钮,压电管就会发出声音。 问题是我不能同时完成这两个功能 闪烁LED功能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);
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语言的通用方法