基于ATMEGA16单片机实现电子时钟功能的代码示例
下面是一个基于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 著作权归作者所有。请勿转载和采集!