下面是一个基于ATMEGA16单片机的电子时钟程序的示例代码:

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

// 定义端口和引脚
#define SEGMENT_PORT PORTA
#define SEGMENT_DDR  DDRA
#define BUTTON_PORT  PORTB
#define BUTTON_PIN   PINB
#define BUTTON_DDR   DDRB

// 定义数码管显示的数字
const unsigned char SEGMENT_NUMBERS[10] = {
    0b00111111, // 0
    0b00000110, // 1
    0b01011011, // 2
    0b01001111, // 3
    0b01100110, // 4
    0b01101101, // 5
    0b01111101, // 6
    0b00000111, // 7
    0b01111111, // 8
    0b01101111  // 9
};

// 定义秒和分的变量
volatile unsigned char seconds = 0;
volatile unsigned char minutes = 0;

// 定义显示的位数和当前位数
unsigned char displayDigit = 0;
unsigned char currentDigit = 0;

// 初始化数码管和按钮
void init() {
    // 设置数码管的引脚为输出
    SEGMENT_DDR = 0xFF;
    
    // 设置按钮的引脚为输入
    BUTTON_DDR &= ~((1 << PB0) | (1 << PB1) | (1 << PB2));
    
    // 使能按钮的上拉电阻
    BUTTON_PORT |= (1 << PB0) | (1 << PB1) | (1 << PB2);
    
    // 设置定时器1为CTC模式,使用外部时钟源
    TCCR1B |= (1 << WGM12) | (1 << CS10);
    
    // 设置定时器1的比较值为1000
    OCR1A = 1000;
    
    // 使能定时器1的比较匹配中断
    TIMSK |= (1 << OCIE1A);
    
    // 允许中断
    sei();
}

// 数码管显示函数
void display(unsigned char digit, unsigned char number) {
    // 清空数码管
    SEGMENT_PORT = 0xFF;
    
    // 设置当前位为低电平
    SEGMENT_PORT &= ~(1 << digit);
    
    // 显示数字
    SEGMENT_PORT = SEGMENT_NUMBERS[number];
}

// 按钮检测函数
void checkButtons() {
    // 检测选择位数的按钮
    if (!(BUTTON_PIN & (1 << PB0))) {
        displayDigit++;
        if (displayDigit >= 4) {
            displayDigit = 0;
        }
        while (!(BUTTON_PIN & (1 << PB0)));
    }
    
    // 检测增加数字的按钮
    if (!(BUTTON_PIN & (1 << PB1))) {
        switch (displayDigit) {
            case 0:
                seconds++;
                if (seconds >= 60) {
                    seconds = 0;
                }
                break;
            case 1:
                minutes++;
                if (minutes >= 60) {
                    minutes = 0;
                }
                break;
        }
        while (!(BUTTON_PIN & (1 << PB1)));
    }
    
    // 检测减少数字的按钮
    if (!(BUTTON_PIN & (1 << PB2))) {
        switch (displayDigit) {
            case 0:
                seconds--;
                if (seconds > 60) {
                    seconds = 59;
                }
                break;
            case 1:
                minutes--;
                if (minutes > 60) {
                    minutes = 59;
                }
                break;
        }
        while (!(BUTTON_PIN & (1 << PB2)));
    }
}

int main(void) {
    // 初始化
    init();
    
    while (1) {
        // 检测按钮
        checkButtons();
        
        // 显示数码管
        display(currentDigit, (currentDigit == 0) ? (seconds % 10) : (minutes % 10));
    }
}

// 定时器1比较匹配中断服务程序
ISR(TIMER1_COMPA_vect) {
    // 更新当前位数
    currentDigit++;
    if (currentDigit >= 2) {
        currentDigit = 0;
    }
}

这个代码使用定时器1来实现定时更新数码管的显示,同时通过中断服务程序来更新当前显示的位数。按钮检测函数用于检测按钮的状态并根据按钮的状态更新时间的值。主循环中不断检测按钮并显示数码管。


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

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