📄 main.c
字号:
/*****************************************************
File name : main.c 迎奥运会倒计时钟系统软件
Chip type : ATmega16
Program type : Application
Clock frequency : 8.000000 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega16.h>
/* the DS1302 is connected to PORTD */
/* the SCLK signal is bit 4 */
/* the IO signal is bit 5 */
/* the RST signal is bit 6 */
#asm
.equ __ds1302_port=0x12
.equ __ds1302_sclk=4
.equ __ds1302_io=5
.equ __ds1302_rst=6
#endasm
#include <ds1302.h>
flash unsigned char led_7[14]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x01,0x02,0x00}; // 7 段码表
// 系统工作状态定义
#define clock_nomal 0 // 正常显示状态
#define clock_set_1 1 // 时间设置状态
#define clock_set_2 2 // 当前日期设置状态
#define clock_set_3 3 // 终止日期设置状态
eeprom unsigned char e_date_flag; // EEPROM数据有效标记
eeprom unsigned char e_date_set[3]; // 存放终点日期,如奥运会开幕日期
unsigned char date[3]; // 年、月、日计数和设置单元
unsigned char time[3],time_set[3]; // 时、分、秒计数和设置单元
signed int tian,tian_1,tian_2; // 天数单元
unsigned char dis_buff[10]; // 显示缓冲区,存放要显示的10个字符的段码值
unsigned char time_1s_counter,key_stime_counter,time_20s_counter;
unsigned char clock_state, set_state,return_time;
bit time_add,point_on,set_on,time_1s_ok,key_stime_ok,time_dis_on;
void display(void) // 10位LED数管动态扫描函数
{
static unsigned char posit;
PORTA = 0xff;PORTC = 0xff; // 关显示消影
PORTB = led_7[dis_buff[posit]]; // 输出段码
if (set_on && clock_state != clock_nomal && posit==set_state)
PORTB= 0x00; // 日期时间设置闪烁
switch(posit)
{
case 0:PORTA.0 = 0;break; // 动态扫描显示
case 1:PORTA.1 = 0;break;
case 2:PORTA.2 = 0;break;
case 3:PORTA.3 = 0;break;
case 4:PORTA.4 = 0;break;
case 5:PORTA.5 = 0;break;
case 6:PORTA.6 = 0;break;
case 7:PORTA.7 = 0;break;
case 8:PORTC.7 = 0;break;
case 9:PORTC.6 = 0;break; // 秒闪烁位
}
if (++posit >= 10 ) posit = 0;
}
// Timer 0 比较匹配中断服务,1ms定时
interrupt [TIM0_COMP] void timer0_comp_isr(void)
{
time_add = !time_add;
if (time_add)
display();
else
{
if (++key_stime_counter >= 5)
{
key_stime_counter = 0; // 10ms到
key_stime_ok = 1;
if (!(++time_1s_counter %25))set_on = !set_on; // 设置日期时间设置闪烁标志
if (!(time_1s_counter %50))point_on = !point_on; // 设置秒闪烁标志
if (time_1s_counter >= 100)
{
time_1s_counter = 0;
time_1s_ok = 1; // 1s到
if (++time_20s_counter<=5)
time_dis_on = 0;
else
time_dis_on = 1;
if (time_20s_counter >= 20) time_20s_counter = 0;
}
}
}
}
void time_to_disbuffer(unsigned char *time) // 日期、时钟、天数送显示缓冲区函数
{
unsigned char i,j=0;
for (i=0;i<=2;i++)
{
dis_buff[j++] = time[i] / 10;
dis_buff[j++] = time[i] % 10;
}
}
#define key_input PINC // 按键输入口
#define key_mask 0b00001111 // 按键输入屏蔽码
#define key_no 0
#define key_set_1 1 // 日期、时间设置
#define key_up 2 // 加一键
#define key_enter 3 // 确认键
#define key_set_2 4 // 终点日期设置
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
unsigned char read_key(void)
{
static unsigned char key_state = 0,key_press;
unsigned char key_return = key_no;
key_press = key_input & key_mask; // 读按键I/O电平
switch (key_state)
{
case key_state_0: // 按键初始态
if (key_press != key_mask) key_state = key_state_1;
break; // 键被按下,状态转换到键确认态
case key_state_1: // 按键确认态
if (key_press == (key_input & key_mask))
{
if (key_press == 0b00001110) key_return = key_set_1;
else if (key_press == 0b00001101) key_return = key_up;
else if (key_press == 0b00001011) key_return = key_enter;
else if (key_press == 0b00000111) key_return = key_set_2;
key_state = key_state_2; // 状态转换到键释放态
}
else
key_state = key_state_0; // 按键已抬起,转换到按键初始态
break;
case key_state_2:
if (key_press == key_mask) key_state = key_state_3;
break; //按键已释放,转再次确认释放
case key_state_3:
if (key_press == key_mask) key_state = key_state_0;
break; //按键已释放,转换到按键初始态
}
return key_return;
}
void main(void)
{
unsigned char key_temp,i;
unsigned char date_set[3];
int y_temp;
PORTA=0x00;
DDRA=0xFF;
PORTB=0x00;
DDRB=0x7F;
PORTC=0x0F;
DDRC=0xC0;
PORTD=0x80;
DDRD=0x80;
//TIMER0 initialize - prescale:64 8M
// WGM: CTC
// desired value: 1mSec
// actual value: 1.004mSec (-0.4%)
TCCR0 = 0x00; //stop
OCR0 = 0x7D; //set compare
TCCR0 = 0x0B; //start timer
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
if (e_date_flag != 0xa5) // 第一次运行设置终点日期到EEPROM
{
e_date_set[0] = 8; // 北京奥运会开幕时间
e_date_set[1] = 8; // 08年8月8日
e_date_set[2] = 8;
e_date_flag = 0xa5;
}
date_set [0] = e_date_set[0]; // 读出终点日期值
date_set [1] = e_date_set[1];
date_set [2] = e_date_set[2];
/* initialize the DS1302 RTC:
use trickle charge,
with 1 diode and 8K resistor */
rtc_init(1,2,3); // 初始化DS1302
date[0] = 7; date[1] = 8; date[2] = 1; // 设日期初值07-08-1
time[0] = 23; time[1] = 58; time[2] = 55; // 设时间初值23:58:55
// Global enable interrupts
#asm("sei")
while (1)
{
if (key_stime_ok) // 10ms到,键处理或日期处理
{
key_stime_ok = 0;
if (time_1s_ok) // 1秒到
{
time_1s_ok = 0;
rtc_get_date(&date[2],&date[1],&date[0]); // 读出DS1302中的当前日期
// 以下计算当前日期到终点日期还有多少天数,注意考虑闰年的因素
tian = 0;tian_1 = 0;tian_2 = 0;
if (date[0] < date_set[0] || ((date[0] == date_set[0]) && (date[1] < date_set[1])) ||((date[0] == date_set[0]) && (date[1] == date_set[1]) && (date[2] <date_set[2])))
{
for (i=date[0]; i<date_set[0];i++)
{
y_temp = 2000+(int)i;
if ((y_temp % 400 == 0) || ((y_temp % 4 == 0) && (y_temp % 100 != 0)))
tian += 366; // 闰年为366天
else
tian += 365; // 通常一年为365天
}
for (i=1;i<date[1];i++)
{
if ( i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12 )
{
tian_1 += 31; // 大月为31天
}
else if (i == 2)
{
y_temp = 2000 + (int) date[0];
if ((y_temp % 400 == 0) || ((y_temp % 4 == 0) && (y_temp % 100 != 0)))
tian_1 += 29; // 闰年2月为29天
else
tian_1 += 28; // 通常2月为28天
}
else
{
tian_1 += 30; // 小月为30天
}
}
for (i=1;i<date_set[1];i++)
{
if ( i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12 )
tian_2 += 31;
else if (i == 2)
{
y_temp = 2000 + (int) date_set[0];
if ((y_temp % 400 == 0) || ((y_temp % 4 == 0) && (y_temp % 100 != 0)))
tian_2 += 29;
else
tian_2 += 28;
}
else
tian_2 += 30;
}
tian = tian + tian_2 - tian_1 + (int)date_set[2] - (int)date[2];
}
else
{
for (i=date_set[0]; i<date[0];i++)
{
y_temp = 2000+(int)i;
if ((y_temp % 400 == 0) || ((y_temp % 4 == 0) && (y_temp % 100 != 0)))
tian += 366;
else
tian += 365;
}
for (i=1;i<date[1];i++)
{
if ( i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12 )
tian_1 += 31;
else if (i == 2)
{
y_temp = 2000 + (int) date[0];
if ((y_temp % 400 == 0) || ((y_temp % 4 == 0) && (y_temp % 100 != 0)))
tian_1 += 29;
else
tian_1 += 28;
}
else
tian_1 += 30;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -