用ATmega64设计一个通过矩阵键盘实现ADC电量显示、温度显示器、精度为秒的计时器集一身的智能时钟 ,并写出相应C语言代码( 1) 显示时间(包括秒分时)、日期(包括年月日),并可以通过按键调整时间日期 ( 2) 通过按键切换为秒表模式,实现记表、停表、归零的功能 ( 3) 通过按键切换为闹钟模式,实现设定闹钟,喇叭响应的功能
时间: 2023-06-20 07:08:16 浏览: 169
设计一个以AT89C51为核心的电子钟。可以实现时间显示和设置闹钟功能
4星 · 用户满意度95%
以下是ATmega64智能时钟的C语言代码:
```c
#include <avr/io.h>
#include <avr/interrupt.h>
// 定义矩阵键盘引脚
#define ROW_1 PINA0
#define ROW_2 PINA1
#define ROW_3 PINA2
#define ROW_4 PINA3
#define COL_1 PINA4
#define COL_2 PINA5
#define COL_3 PINA6
#define COL_4 PINA7
// 定义ADC引脚
#define ADC_PIN PINB0
// 定义温度传感器引脚
#define TEMP_SENSOR_PIN PINB1
// 定义喇叭引脚
#define SPEAKER_PIN PINC0
// 定义闹钟引脚
#define ALARM_PIN PINC1
// 定义时间结构体
typedef struct {
uint8_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
} Time;
// 定义闹钟结构体
typedef struct {
uint8_t hour;
uint8_t minute;
} Alarm;
// 全局变量
volatile Time currentTime;
volatile Alarm alarmTime;
volatile uint8_t stopwatchOn;
volatile uint8_t stopwatchPaused;
volatile uint8_t stopwatchSeconds;
volatile uint8_t alarmOn;
// 函数声明
void initADC();
void initTempSensor();
void initSpeaker();
void initAlarm();
void updateTime();
void updateDisplay();
void setAlarm();
void resetAlarm();
void toggleStopwatch();
void pauseStopwatch();
void resetStopwatch();
// 主函数
int main() {
// 初始化IO口
DDRA = 0b00001111; // 矩阵键盘行为输入,列为输出
PORTA = 0b11110000; // 上拉输入
DDRB = 0b00000000; // ADC和温度传感器为输入
PORTB = 0b11111111; // 上拉输入
DDRC = 0b00000011; // 喇叭和闹钟为输出
PORTC = 0b00000000; // 初始关闭喇叭和闹钟
DDRD = 0b11111111; // 显示器为输出
// 初始化定时器
TCCR1B |= (1 << WGM12); // CTC模式
OCR1A = 31250; // 1秒钟
TIMSK |= (1 << OCIE1A); // 中断使能
sei(); // 全局中断使能
// 初始化变量
currentTime.year = 21;
currentTime.month = 5;
currentTime.day = 1;
currentTime.hour = 0;
currentTime.minute = 0;
currentTime.second = 0;
stopwatchOn = 0;
stopwatchPaused = 0;
stopwatchSeconds = 0;
alarmOn = 0;
// 初始化ADC、温度传感器、喇叭、闹钟
initADC();
initTempSensor();
initSpeaker();
initAlarm();
while (1) {
// 检测矩阵键盘
PORTA |= (1 << ROW_1);
PORTA &= ~(1 << ROW_2);
PORTA &= ~(1 << ROW_3);
PORTA &= ~(1 << ROW_4);
if (!(PINA & (1 << COL_1))) { // 按键1
currentTime.second++;
if (currentTime.second >= 60) {
currentTime.second = 0;
currentTime.minute++;
if (currentTime.minute >= 60) {
currentTime.minute = 0;
currentTime.hour++;
if (currentTime.hour >= 24) {
currentTime.hour = 0;
}
}
}
} else if (!(PINA & (1 << COL_2))) { // 按键2
currentTime.day++;
if (currentTime.day > 31) {
currentTime.day = 1;
currentTime.month++;
if (currentTime.month > 12) {
currentTime.month = 1;
currentTime.year++;
}
}
} else if (!(PINA & (1 << COL_3))) { // 按键3
toggleStopwatch();
} else if (!(PINA & (1 << COL_4))) { // 按键4
setAlarm();
}
PORTA |= (1 << ROW_2);
PORTA &= ~(1 << ROW_1);
if (!(PINA & (1 << COL_1))) { // 按键5
currentTime.second--;
if (currentTime.second >= 60) {
currentTime.second = 59;
currentTime.minute--;
if (currentTime.minute >= 60) {
currentTime.minute = 59;
currentTime.hour--;
if (currentTime.hour >= 24) {
currentTime.hour = 23;
}
}
}
} else if (!(PINA & (1 << COL_2))) { // 按键6
currentTime.day--;
if (currentTime.day < 1) {
currentTime.day = 31;
currentTime.month--;
if (currentTime.month < 1) {
currentTime.month = 12;
currentTime.year--;
}
}
} else if (!(PINA & (1 << COL_3))) { // 按键7
pauseStopwatch();
} else if (!(PINA & (1 << COL_4))) { // 按键8
resetStopwatch();
}
PORTA |= (1 << ROW_3);
PORTA &= ~(1 << ROW_2);
if (stopwatchOn && !stopwatchPaused) { // 秒表未暂停时更新秒表计时
stopwatchSeconds++;
if (stopwatchSeconds >= 60) {
stopwatchSeconds = 0;
}
}
if (alarmOn) { // 闹钟开启时检测是否响铃
if (currentTime.hour == alarmTime.hour && currentTime.minute == alarmTime.minute) {
PORTC |= (1 << SPEAKER_PIN); // 开启喇叭
} else {
PORTC &= ~(1 << SPEAKER_PIN); // 关闭喇叭
}
}
PORTA |= (1 << ROW_4);
PORTA &= ~(1 << ROW_3);
updateDisplay(); // 更新显示
}
return 0;
}
// 初始化ADC
void initADC() {
ADMUX |= (1 << ADLAR); // 左对齐输出
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // 分频系数128
ADCSRA |= (1 << ADEN); // ADC使能
}
// 初始化温度传感器
void initTempSensor() {
ADMUX |= (1 << MUX0); // 设置ADC输入为温度传感器引脚
}
// 初始化喇叭
void initSpeaker() {
TCCR2 |= (1 << WGM21); // CTC模式
TCCR2 |= (1 << CS22); // 分频系数64
OCR2 = 124; // 1kHz
}
// 初始化闹钟
void initAlarm() {
alarmTime.hour = 0;
alarmTime.minute = 0;
}
// 更新时间
void updateTime() {
uint8_t adcValue = 0;
ADCSRA |= (1 << ADSC); // 开始ADC转换
while (ADCSRA & (1 << ADSC)); // 等待转换完成
adcValue = ADCH; // 读取ADC值
uint16_t tempValue = (adcValue * 500UL) / 255UL; // 计算温度值
currentTime.second++; // 秒钟加一
if (currentTime.second >= 60) {
currentTime.second = 0;
currentTime.minute++;
if (currentTime.minute >= 60) {
currentTime.minute = 0;
currentTime.hour++;
if (currentTime.hour >= 24) {
currentTime.hour = 0;
}
}
}
}
// 更新显示
void updateDisplay() {
uint8_t digit = 0;
uint8_t value = 0;
// 显示秒钟
digit = 0;
value = currentTime.second % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 1;
value = currentTime.second / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
// 显示分钟
digit = 2;
value = currentTime.minute % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 3;
value = currentTime.minute / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
// 显示小时
digit = 4;
value = currentTime.hour % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 5;
value = currentTime.hour / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
// 显示日期
digit = 6;
value = currentTime.day % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 7;
value = currentTime.day / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
// 显示月份
digit = 8;
value = currentTime.month % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 9;
value = currentTime.month / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
// 显示年份
digit = 10;
value = currentTime.year % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 11;
value = currentTime.year / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
// 显示温度
digit = 12;
value = tempValue % 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
digit = 13;
value = tempValue / 10;
PORTD = ~(1 << digit);
PORTB = value;
_delay_ms(2);
}
// 设置闹钟
void setAlarm() {
uint8_t hour = 0;
uint8_t minute = 0;
// 输入小时
while (1) {
PORTA |= (1 << ROW_1);
PORTA &= ~(1 << ROW_2);
PORTA &= ~(1 << ROW_3);
PORTA &= ~(1 << ROW_4);
if (!(PINA & (1 << COL_1))) { // 按键1
hour++;
if (hour >= 24) {
hour = 0;
}
} else if (!(PINA & (1 << COL_2))) { // 按键2
minute++;
if (minute >= 60) {
minute = 0;
}
} else if (!(PINA & (1 << COL_3))) { // 按键3
break;
}
PORTA |= (1 << ROW_2);
PORTA &= ~(1 << ROW_1);
if (!(PINA & (1 << COL_1))) { // 按键4
hour--;
if (hour >= 24) {
hour = 23;
}
} else if (!(PINA & (1 << COL_2))) { // 按键5
minute--;
if (minute >= 60) {
minute = 59;
}
} else if (!(PINA & (1 << COL_3))) { // 按键6
break;
}
PORTA |= (1 << ROW_3);
PORTA &= ~(1 << ROW_2);
PORTA |= (1 << ROW_4);
PORTA &= ~(1 << ROW_3);
}
alarmTime.hour = hour;
alarmTime.minute = minute;
alarmOn = 1;
}
// 重置闹钟
void resetAlarm() {
alarmOn = 0;
PORTC &= ~(1 << ALARM_PIN);
}
// 切换秒表
void toggleStopwatch() {
if (stopwatchOn) {
stopwatchOn = 0;
} else {
stopwatchOn = 1;
}
}
// 暂停秒表
void pauseStopwatch() {
if (stopwatchOn) {
if (stopwatchPaused) {
stopwatchPaused = 0;
} else {
stopwatchPaused = 1;
}
}
}
// 重置秒表
void resetStopwatch() {
stopwatchOn = 0;
stopwatchPaused = 0;
stopwatchSeconds = 0;
}
// 定时器中断
ISR(TIMER1_COMPA_vect) {
updateTime();
}
// 喇叭定时器中断
ISR(TIMER2_COMP_vect) {
PORTC ^= (1 << SPEAKER_PIN); // 反转喇叭引脚
if (alarmOn) {
if (PORTC & (1 << SPEAKER_PIN)) { // 喇叭开启时检测是否关闭闹钟
if (currentTime.hour != alarmTime.hour || currentTime.minute != alarmTime.minute) {
resetAlarm();
}
}
}
}
```
阅读全文