以下是一个基于ATMEGA16单片机的电子时钟程序的示例代码,使用四位数码管显示时间,其中右两位显示秒,左两位显示分。该程序使用定时器1产生1秒的中断,每秒更新秒和分的值。三个按钮分别控制选择数码管的位数,以及该位数的数码管显示的数字的增减。

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

#define F_CPU 8000000UL

volatile uint8_t seconds = 0;
volatile uint8_t minutes = 0;

void init_timer()
{
    // 设置定时器1为CTC模式
    TCCR1B |= (1 << WGM12);
    // 设置预分频为1024
    TCCR1B |= (1 << CS12) | (1 << CS10);
    // 设置比较值为7812,产生1秒的中断
    OCR1A = 7812;
    // 启用比较匹配A中断
    TIMSK |= (1 << OCIE1A);
}

void init_buttons()
{
    // 设置按钮引脚为输入
    DDRD &= ~((1 << PD0) | (1 << PD1) | (1 << PD2));
    // 启用上拉电阻
    PORTD |= (1 << PD0) | (1 << PD1) | (1 << PD2);
}

void init_seven_segment()
{
    // 设置数码管引脚为输出
    DDRB |= 0x0F;
    DDRC |= 0xF0;
}

void display_seven_segment(uint8_t value)
{
    // 将value的十位数和个位数分别取出
    uint8_t tens = value / 10;
    uint8_t ones = value % 10;
    
    // 使用BCD码显示数值
    PORTB = (PORTB & 0xF0) | (ones & 0x0F);
    PORTC = (PORTC & 0x0F) | ((tens << 4) & 0xF0);
}

int main(void)
{
    init_timer();
    init_buttons();
    init_seven_segment();
    
    sei(); // 启用全局中断
    
    uint8_t selected_digit = 0;
    
    while (1)
    {
        // 显示秒和分
        if (selected_digit == 0)
        {
            display_seven_segment(seconds);
        }
        else if (selected_digit == 1)
        {
            display_seven_segment(minutes);
        }
        
        // 检查按钮状态
        if (!(PIND & (1 << PD0))) // 按钮1按下
        {
            selected_digit++;
            if (selected_digit > 1)
            {
                selected_digit = 0;
            }
            
            // 延时一段时间以避免按钮抖动
            _delay_ms(200);
        }
        else if (!(PIND & (1 << PD1))) // 按钮2按下
        {
            if (selected_digit == 0)
            {
                seconds++;
                if (seconds > 60)
                {
                    seconds = 0;
                    minutes++;
                    if (minutes > 60)
                    {
                        minutes = 0;
                    }
                }
            }
            else if (selected_digit == 1)
            {
                minutes++;
                if (minutes > 60)
                {
                    minutes = 0;
                }
            }
            
            // 延时一段时间以避免按钮抖动
            _delay_ms(200);
        }
        else if (!(PIND & (1 << PD2))) // 按钮3按下
        {
            if (selected_digit == 0)
            {
                seconds--;
                if (seconds > 60)
                {
                    seconds = 60;
                    minutes--;
                    if (minutes > 60)
                    {
                        minutes = 60;
                    }
                }
            }
            else if (selected_digit == 1)
            {
                minutes--;
                if (minutes > 60)
                {
                    minutes = 60;
                }
            }
            
            // 延时一段时间以避免按钮抖动
            _delay_ms(200);
        }
    }
}

ISR(TIMER1_COMPA_vect)
{
    seconds++;
    if (seconds > 60)
    {
        seconds = 0;
        minutes++;
        if (minutes > 60)
        {
            minutes = 0;
        }
    }
}

该程序使用定时器1产生1秒的中断,每秒更新秒和分的值。按钮1用于选择要显示的数码管位数,按钮2和按钮3用于增加和减少该位数的数码管显示的数字。数码管的显示使用BCD码进行,通过设置PORTB和PORTC的相应位来显示数值。

功能说明

  • init_timer():初始化定时器1,设置为CTC模式,预分频为1024,比较值为7812,每秒产生一次中断。
  • init_buttons():初始化按钮引脚,设置为输入模式,并开启上拉电阻。
  • init_seven_segment():初始化数码管引脚,设置为输出模式。
  • display_seven_segment(uint8_t value):将传入的数值value显示到数码管上,使用BCD码进行显示。
  • main():程序主函数,初始化定时器、按钮和数码管,并进入循环,根据按钮状态控制数码管的显示。
  • ISR(TIMER1_COMPA_vect):定时器1中断服务函数,每秒更新秒和分的值。

注意事项

  • 代码需要根据具体硬件电路进行修改。
  • 需要根据实际需求调整定时器参数和按钮引脚。
  • 程序中使用了_delay_ms()函数进行延时,为了避免按钮抖动。
  • 数码管的连接方式需要根据具体硬件电路进行调整。

该代码只是一个示例,可以根据实际需求进行修改和扩展。

基于ATMEGA16单片机的电子时钟程序代码示例

原文地址: https://www.cveoy.top/t/topic/fAbj 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录