我打算設置鬧鐘響10s(count2==1000),但是鬧鐘會響11s.請問是什么原因。新手單片機入門,結果處處碰壁。單片機好難
//時鐘頻率8M
#include<iom16v.h>
#include"lcd1602.h"
#define key_state0 0
#define key_state1 1
#define key_state2 2
#define key_off 0
#define key1 1
#define key2 2
#define key3 3
#define time_display 0
#define clock_set 1
#define alarm_set 2
#define set_h 0
#define set_m 1
#define set_s 2
void main(void);
void io_init(void);
void time_init(void);
void cpu_init(void);
void time_10ms(void);
char key_scan(void);
void Pattern(void);//模式
void Alarm(void);//鬧鐘響
void Set(void);//設置狀態
void time(void);
const char num[] = {"0123456789"};
char cs = 0,cm = 0,ch = 0;//實時時鐘
char as = 5,am = 0,ah = 0;//鬧鐘
char ss,sm,sh;
char time_10ms_ok;//10ms按鍵掃描標志
char time_10s_ok;//10s鬧鈴標志
char key_sign;//存儲按鍵狀態
char set = set_h;
uint count1 = 0, count2 = 0;
void io_init(void)
{
DDRA |= 1<<7;
PORTA |= 1<<7;
DDRB = 0X00;
PORTB = 0XFF;
DDRC = 0XFF;
PORTC = 0XFF;
DDRD |= (1<<7)|(1<<6)|(1<<5);
PORTD |= (1<<7)|(1<<6)|(1<<5);
}
void time_init(void)
{
TCCR1A = 0X00;
TCCR1B = (1<<WGM12)|(3<<CS10);//CTC,64分頻
OCR1AH = 1250>>8;
OCR1AL = 1250;
TCNT1 = 0;
TIMSK = 1<<OCIE1A;
SREG = 1<<7;
}
void cpu_init(void)
{
io_init();
time_init();
lcd_init();
}
#pragma interrupt_handler time_10ms:7
void time_10ms(void)
{
count1++;
count2++;
time_10ms_ok = 1;//10ms按鍵掃描標志
}
char key_scan(void)
{
static char key_press, key_state = 0;
char key_return = key_off;
key_press = PINB;
switch(key_state)
{
case key_state0:
{
if(key_press != 0XFF)//若有按鍵按下,則進入確認狀態
{
key_state = key_state1;
}
break;
}
case key_state1:
{
if(key_press != 0XFF)//確認有按鍵按下,開始識別按鍵按下位置
{
if(!(key_press & (1<<PB0))) key_return = key1;//按鍵1
else if(!(key_press & (1<<PB1))) key_return = key2;//按鍵2
else if(!(key_press & (1<<PB2))) key_return = key3;//按鍵3
key_state = key_state2;
}
else key_state = key_state0;//若按鍵抬起則回到初始狀態
break;
}
case key_state2:
{
if(key_press == 0XFF)//若按鍵抬起則回到初始狀態
{
key_state = key_state0;
}
break;
}
default: key_state = key_state0; break;
}
return key_return;
}
void Pattern(void)//模式函數
{
static char pattern = time_display;
switch(pattern)
{
case time_display://模式1,實時時鐘顯示
{
if(time_10ms_ok)
{
time_10ms_ok = 0;
key_sign = key_scan();
if(key_sign == key1)
{
pattern = clock_set;//時鐘設置
set = set_h;//回到小時位調整
ss = cs;
sm = cm;
sh = ch;
}
else time();
}
break;
}
case clock_set://模式2,時鐘設置
{
if(time_10ms_ok)
{
time_10ms_ok = 0;
key_sign = key_scan();
if(key_sign == key1)
{
pattern = alarm_set;//鬧鐘設置
set = set_h;//回到小時位調整
cs = ss;
cm = sm;
ch = sh;
ss = as;
sm = am;
sh = ah;
TCNT1 = 0;//計數器清零
}
else Set();
}
break;
}
case alarm_set://模式3,鬧鐘設置
{
if(time_10ms_ok)
{
time_10ms_ok = 0;
key_sign = key_scan();
if(key_sign == key1)
{
pattern = time_display;
as = ss;
am = sm;
ah = sh;
}
else Set();
}
break;
}
default: pattern = time_display; break;
}
}
void Set(void)
{
lcd_write_char(4,0,num[sh/10]);
lcd_write_char(5,0,num[sh%10]);
lcd_write_char(7,0,num[sm/10]);
lcd_write_char(8,0,num[sm%10]);
lcd_write_char(10,0,num[ss/10]);
lcd_write_char(11,0,num[ss%10]);
switch(set)
{
case set_h://調整小時位
{
if(key_sign == key2)
{
sh = (++sh)%24;
}
else if(key_sign == key3) set = set_m;
break;
}
case set_m://調整分鐘位
{
if(key_sign == key2)
{
sm = (++sm)%60;
}
else if(key_sign == key3) set = set_s;
break;
}
case set_s://調整秒位
{
if(key_sign == key2)
{
ss = (++ss)%60;
}
else if(key_sign == key3) set = set_h;
break;
}
default: set = set_h; break;
}
}
void time(void)
{
lcd_write_char(4,0,num[ch/10]);
lcd_write_char(5,0,num[ch%10]);
lcd_write_char(7,0,num[cm/10]);
lcd_write_char(8,0,num[cm%10]);
lcd_write_char(10,0,num[cs/10]);
lcd_write_char(11,0,num[cs%10]);
}
void Alarm(void)
{
if(count2 == 1000) time_10s_ok = 1;
if((ch == ah) && (cm == am) && (cs == as))
{
PORTA &= ~(1<<PA7);
count2 =0;
time_10s_ok = 0;
}
else if(time_10s_ok) PORTA |= (1<<PA7);
}
void time_send(void)
{
if((cs == 0)&&(cm == 0)) ;
}
void main(void)//主函數
{
cpu_init();
time_display_init();
while(1)
{
if(count1 == 100)//實時時間計時
{
cs++;
count1 = 0;
if(cs == 60)
{
cm++;
cs = 0;
if(cm == 60)
{
ch++;
cm = 0;
if(ch == 24) ch = 0;
}
}
}
Pattern();
Alarm();
}
} |