📄 avrcalendar.cpp
字号:
#include "AvrCalendar.h"
#include "EEprom.h"
#include "Ring.h"
CAvrCalendar AvrCalendar;
int main(void)
{
AvrCalendar.InitPort();
AvrCalendar.InitTimer();
asm("sei"); //__enable_interrupt();
while(1)
{
AvrCalendar.OnPaintTick();
}
}
#define WDTOE 4
#define WDCE 4
#define WDE 3
#define WDP2 2
#define WDP1 1
#define WDP0 0
void CAvrCalendar::DisableWatchdog()
{
/* 复位WDT */
asm("wdr");
/* 置位WDCE 和 WDE */
WDTCR |= (1<<WDCE) | (1<<WDE);
/* 关闭WDT */
WDTCR = 0x00;
}
void CAvrCalendar::InitPort()
{
//PB0: OUT, low, 暂时不用
//PB1: OUT, low, 蜂鸣
//PB2-5: IN, pullup, 键盘扫描
//PB6,7: IN, 32768Hz晶振
PORTB = 0x3e;// 00111100
DDRB = 0x3; // 00000011
//PC0-3: OUT, hight, LED段选择
//PC4-6: IN, pullup, Reset保留(jtag)
PORTC = 0x7f;
DDRC = 0x3f;
//PD: OUT, low, LED位选择
PORTD = 0x00;
DDRD = 0xff;
//关闭看门狗
DisableWatchdog();
//关闭模拟比较
ACSR = 0x80;
}
void CAvrCalendar::InitTimer()
{
// 0------- 不强制比较输出
// -0--0--- 普通模式
// --00---- 不连接OC0引脚
// -----001 不分频
TCCR0 = 0x00; //关闭TC0
//TC1: 频率可调CTC比较匹配触发OC1A输出, 不中断
//用于蜂鸣器输出
// TCCR1A TCCR1B
// 01------|-------- 比较,OC1A电平取反
// --00----|-------- 不连接OC1B引脚
// ----00--|-------- A,B 都不强制比较
// ------00|---01--- 和OCR1A比较的CTC模式
// --------|0------- 不抑制噪音
// --------|-0------ 不捕获输入
// --------|-----001 不分频
//000:时钟停止,001:不分频,010:8分频,011:64分频
//100:256分频,101:1024分频,110:T1下降沿驱动,111:T1上升沿驱动
TCCR1A = 0x00;
TCCR1B = 0x08;
//TC2: 64Hz异步模式定时中断
//用于日历计时,铃声演奏控制,键盘显示扫描
// ----1--- TC2由TOSC1引脚上的晶振驱动
ASSR = 0x08;
OCR2 = 0x10;
TCNT2 = 0xf0;
// 0------- 不强制比较
// -0--1--- 和OCR2比较的CTC模式
// --00---- 不连接OC2引脚
// -----011 32分频
TCCR2 = 0x0b;
// 10------ TC2比较匹配中断,无溢出中断
// --0--0-- TC1无捕获中断, 无溢出中断
// ---00--- TC1无A比较匹配中断, 无B比较匹配中断
// -------0 TC0溢出中断
TIMSK = 0x80;
}
CAvrCalendar::CAvrCalendar()
{
//启动时检查声音显示sh8是否正常
CRing::Beep(1000, 16);
memset(&m_ledbuff, 0xff, sizeof(LEDBUFF));
}
CAvrCalendar::~CAvrCalendar()
{
}
UCHAR CAvrCalendar::GetKeyState()
{
UCHAR state = ~PINB;
return (state >> 2) & 0x0f;
}
void CAvrCalendar::OnPaintTick()
{
for(UCHAR i = 0; i < sizeof(LEDBUFF); i++){//那么多个LED
PORTC |= 0x0f; //消隐
UCHAR data = ((UCHAR*)&m_ledbuff)[i];
if(m_ledflashspeed){
UCHAR flash = ((UCHAR*)&m_ledflash)[i];
if(flash && (m_clock.m_tick & (16>>m_ledflashspeed))){
//关闭要闪烁的段,起到闪烁的效果
data &= ~flash;
}
}
if(!data) continue;
//硬件线路的设计,可能从第m位之后空开n位
//if(i < m) PORTC &= i | 0xf0;
//else PORTC &= (i + n) | 0xf0;
PORTC &= (i | 0xf0);
//PORTD = data;
for(UCHAR j = 0; j < 8; j++){//每个LED那么多段
UCHAR light = m_led_lum << 1;
//显示,同时进行亮度控制
//时分用的是大的LED,比较暗,让它们的所有段同时亮
asm("cli");//显示的时候关中断,这样LED灯不闪烁
if(i >= 6 && i <= 9) PORTD = data;
//其它的用的是小的LED, 一段一段的显示
else if(!(PORTD = (1<<j) & data))continue;
for(UCHAR volatile p = 0; p < light; p++);
PORTD = 0; //关闭
asm("sei");
for(; light < 8; light++);
}
}
}
void CAvrCalendar::Display(const LEDBUFF &led)
{
m_ledbuff = led;
}
void CAvrCalendar::Flash(const LEDBUFF *led, UCHAR hightspeed)
{
if(led){
m_ledflash = *led;
m_ledflashspeed = hightspeed;
}else{
m_ledflashspeed = 0;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -