#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// 共陰極7段顯示器數字對應表
uint8_t segment_map[10] = {
0b01111110, // 0
0b00110000, // 1
0b01101101, // 2
0b01111001, // 3
0b00110011, // 4
0b01011011, // 5
0b01011111, // 6
0b01110000, // 7
0b01111111, // 8
0b01111011 // 9
};
// 全域變數
volatile uint8_t digits[2] = {0, 0}; // 用於顯示的十位數與個位數
volatile uint8_t active_digit = 0; // 當前掃瞄的顯示器編號
// 初始化 SPI
void SPI_init() {
DDRB |= (1 << PB3) | (1 << PB5) | (1 << PB2); // 設置 MOSI, SCK, SS 為輸出
SPCR = (1 << SPE) | (1 << MSTR); // 啟用 SPI,設置為主控模式
}
// SPI 傳輸資料
void SPI_send(uint8_t data) {
SPDR = data; // 傳輸資料
while (!(SPSR & (1 << SPIF))); // 等待傳輸完成
}
// 更新顯示數字
void update_display(uint8_t digit, uint8_t position) {
PORTB &= ~(1 << PB2); // SS 拉低
SPI_send(segment_map[digit]); // 傳送數字對應的 7 段顯示器資料
PORTB |= (1 << PB2); // SS 拉高
// 控制共陰極
if (position == 0) {
PORTD &= ~(1 << PD3);
PORTD |= (1 << PD2); // 啟用第一個顯示器
} else {
PORTD &= ~(1 << PD2);
PORTD |= (1 << PD3); // 啟用第二個顯示器
}
}
// 初始化 Timer1
void setupTimer1() {
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10); // CTC 模式,分頻 1024
OCR1A = 200; // 設置比較值
OCR1B = 100;
TIMSK1 = (1 << OCIE1A) | (1 << OCIE1B); // 啟用比較匹配中斷
}
// Timer1 中斷服務例程
ISR(TIMER1_COMPA_vect) {
//Serial.println(active_digit);
update_display(digits[active_digit], active_digit); // 更新當前位數字
// Serial.println(active_digit);
if (active_digit == 1)
active_digit = 0;
else
active_digit = 1; // 切換至下一位
//Serial.println(active_digit);
}
ISR(TIMER1_COMPB_vect) {
}
// 初始化 ADC
void ADC_init() {
ADMUX = (1 << REFS0); // 使用 AVCC 作為參考電壓
ADCSRA = (1 << ADEN) | (1 << ADATE) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1); // 啟用 ADC,自動觸發,中斷使能,分頻 64
ADCSRB = (1 << ADTS2) | (1 << ADTS0); // 觸發源為 Timer1 比較匹配 B
ADCSRA |= (1 << ADSC); // 啟動 ADC
}
// ADC 中斷服務例程
ISR(ADC_vect) {
uint16_t adc_value = ADC; // 讀取 ADC
uint8_t percentage = (uint32_t)adc_value * 100 / 1024; // 計算百分比
Serial.println(percentage);
// 更新十位數與個位數
digits[1] = percentage / 10; // 十位數
digits[0] = percentage % 10; // 個位數
//Serial.println(digits[0]);
}
void setup() {
SPI_init(); // 初始化 SPI
setupTimer1(); // 初始化 Timer1
ADC_init(); // 初始化 ADC
DDRD |= (1 << PD2) | (1 << PD3); // 設置 PD2 和 PD3 為輸出(控制共陰極)
sei();
Serial.begin(115200);
pinMode(8, OUTPUT);
}
void loop() {
}