📄 main.i
字号:
/*****************************************************
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
*****************************************************/
// CodeVisionAVR C Compiler
// (C) 1998-2001 Pavel Haiduc, HP InfoTech S.R.L.
// I/O registers definitions for the ATmega16
#pragma used+
#pragma used+
sfrb TWBR=0;
sfrb TWSR=1;
sfrb TWAR=2;
sfrb TWDR=3;
sfrb ADCL=4;
sfrb ADCH=5;
sfrw ADCW=4; // 16 bit access
sfrb ADCSRA=6;
sfrb ADMUX=7;
sfrb ACSR=8;
sfrb UBRRL=9;
sfrb UCSRB=0xa;
sfrb UCSRA=0xb;
sfrb UDR=0xc;
sfrb SPCR=0xd;
sfrb SPSR=0xe;
sfrb SPDR=0xf;
sfrb PIND=0x10;
sfrb DDRD=0x11;
sfrb PORTD=0x12;
sfrb PINC=0x13;
sfrb DDRC=0x14;
sfrb PORTC=0x15;
sfrb PINB=0x16;
sfrb DDRB=0x17;
sfrb PORTB=0x18;
sfrb PINA=0x19;
sfrb DDRA=0x1a;
sfrb PORTA=0x1b;
sfrb EECR=0x1c;
sfrb EEDR=0x1d;
sfrb EEARL=0x1e;
sfrb EEARH=0x1f;
sfrw EEAR=0x1e; // 16 bit access
sfrb UBRRH=0x20;
sfrb UCSRC=0X20;
sfrb WDTCR=0x21;
sfrb ASSR=0x22;
sfrb OCR2=0x23;
sfrb TCNT2=0x24;
sfrb TCCR2=0x25;
sfrb ICR1L=0x26;
sfrb ICR1H=0x27;
sfrb OCR1BL=0x28;
sfrb OCR1BH=0x29;
sfrw OCR1B=0x28; // 16 bit access
sfrb OCR1AL=0x2a;
sfrb OCR1AH=0x2b;
sfrw OCR1A=0x2a; // 16 bit access
sfrb TCNT1L=0x2c;
sfrb TCNT1H=0x2d;
sfrw TCNT1=0x2c; // 16 bit access
sfrb TCCR1B=0x2e;
sfrb TCCR1A=0x2f;
sfrb SFIOR=0x30;
sfrb OSCCAL=0x31;
sfrb OCDR=0x31;
sfrb TCNT0=0x32;
sfrb TCCR0=0x33;
sfrb MCUCSR=0x34;
sfrb MCUCR=0x35;
sfrb TWCR=0x36;
sfrb SPMCR=0x37;
sfrb TIFR=0x38;
sfrb TIMSK=0x39;
sfrb GIFR=0x3a;
sfrb GICR=0x3b;
sfrb OCR0=0X3c;
sfrb SPL=0x3d;
sfrb SPH=0x3e;
sfrb SREG=0x3f;
#pragma used-
// Interrupt vectors definitions
// Needed by the power management functions (sleep.h)
#asm
#ifndef __SLEEP_DEFINED__
#define __SLEEP_DEFINED__
.EQU __se_bit=0x40
.EQU __sm_mask=0xB0
.EQU __sm_powerdown=0x20
.EQU __sm_powersave=0x30
.EQU __sm_standby=0xA0
.EQU __sm_ext_standby=0xB0
.EQU __sm_adc_noise_red=0x10
.SET power_ctrl_reg=mcucr
#endif
#endasm
/* 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
/*
CodeVisionAVR C Compiler
(C) 1998-2000 Pavel Haiduc, HP InfoTech S.R.L.
Prototypes for the Dallas Semiconductors
DS1302 Real Time Clock functions
BEFORE #include -ING THIS FILE YOU
MUST DECLARE THE I/O ADDRESS OF THE
DATA REGISTER OF THE PORT AT WHICH
DS1302 IS CONNECTED AND
THE DATA BITS USED FOR IO, SCLK and RST pins
EXAMPLE FOR PORTB:
#asm
.equ __ds1302_port=0x18
.equ __ds1302_io=2
.equ __ds1302_sclk=1
.equ __ds1302_rst=4
#endasm
#include <ds1302.h>
*/
#pragma used+
#pragma used+
unsigned char ds1302_read(unsigned char addr);
void ds1302_write(unsigned char addr,unsigned char data);
void rtc_init(unsigned char tc_on,unsigned char diodes,unsigned char res);
void rtc_get_time(unsigned char *hour,unsigned char *min,unsigned char *sec);
void rtc_set_time(unsigned char hour,unsigned char min,unsigned char sec);
void rtc_get_date(unsigned char *date,unsigned char *month,unsigned char *year);
void rtc_set_date(unsigned char date,unsigned char month,unsigned char year);
#pragma used-
#pragma library ds1302.lib
flash unsigned char led_7[14]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x01,0x02,0x00}; // 7 段码表
// 系统工作状态定义
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 != 0 && 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 [20] 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;
}
}
unsigned char read_key(void)
{
static unsigned char key_state = 0,key_press;
unsigned char key_return = 0;
key_press = PINC & 0b00001111 ; // 读按键I/O电平
switch (key_state)
{
case 0: // 按键初始态
if (key_press != 0b00001111 ) key_state = 1;
break; // 键被按下,状态转换到键确认态
case 1: // 按键确认态
if (key_press == (PINC & 0b00001111 ))
{
if (key_press == 0b00001110) key_return = 1 ;
else if (key_press == 0b00001101) key_return = 2 ;
else if (key_press == 0b00001011) key_return = 3 ;
else if (key_press == 0b00000111) key_return = 4 ;
key_state = 2; // 状态转换到键释放态
}
else
key_state = 0; // 按键已抬起,转换到按键初始态
break;
case 2:
if (key_press == 0b00001111 ) key_state = 3;
break; //按键已释放,转再次确认释放
case 3:
if (key_press == 0b00001111 ) 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
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -