代码错误预警(逻辑)
###
如果为了图方便
if(mode != 0)
set_clock_f = 1;
else
set_clock_f = 0;
插入到condition函数里面,(第一次按键时,mode++之前就执行这个,就会执行
if(set_time_f == 0 || set_clock_f ==1)
{
set_clock_f = 0; //关闭闹钟设置状态
mode = 0;
}
从而mode 一直=0,所以在写一段代码前(特别是长长的牵连的多的)(一定三思而后行,顺序不一样导致的结果也有十分大的不同)
(具体方案是)
写代码之前脑子里就要有一个良好的构思,优化就在一定要从
- 功能(实现)
- 顺序(会不会影响其他程序)
具体代码
#include<STC15F2K60S2.h>
#include<ds1302.h>
#include<onewire.h>
#define keypress P3
typedef unsigned char u8;
typedef unsigned int u16;
sbit buzzer = P0^6;
u8 smg_count, smg_i, key_count, menu1[8], menu2[8];
u8 shi, fen, miao;
u8 mode;
u8 code T_duan[] = { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
u8 code T_COM[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 code T_dim[8]= {0};
u8 sshi,ffen,mmiao; //闹钟设置状态下的时间数值
u8 temp;//温度
u8 count_clock, clock_blink_start, clock_blink_time;//闹钟5s开始标志和闪烁时长
bit clock_blink;//闹钟0.2s闪烁标志
bit blink_time;//1s dim/lignt
bit key_flag;
bit set_time_f,set_clock_f;//设置闹钟,时间状态
bit show_smg2 ;
typedef unsigned char BYTE;
typedef unsigned int WORD;
void smgshow();
/* define constants */
#define FOSC 11059200L
#define T1MS (65536-FOSC/12/1000) //1ms timer calculation method in 12T mode
/* define SFR */
sbit TEST_LED = P1^0; //work LED, flash once per second
/* define variables */
WORD count; //1000 times counter
void tm0_isr() interrupt 1 using 1
{
TL0 = T1MS;
TH0 = T1MS >> 8;
if(count_clock-- == 0)
{
count_clock = 200;
clock_blink = ~clock_blink;
}
if (count-- == 0)
{
count = 1000;
blink_time = ~blink_time;
if(clock_blink_start)
{
clock_blink_time++;
if(clock_blink_time == 5)
clock_blink_start = 0; //关闭闹钟响的标志
}
}
//smg part
if (smg_count-- == 0)
{
smg_count = 2;
// P2 =(P2 & 0x1f)& 0xef;
P2 = (P2 & 0x1F) | 0xE0;
if( show_smg2 == 0)
P0 = ~menu1[smg_i];
else
P0 = ~menu2[smg_i];
P2 = 0;
P2 = 0xc0;
P0 = T_COM[smg_i]; P2 &= 0x1f;
smg_i++;
if(smg_i == 8)
{
smg_i = 0;
}
}
if(key_count--==0)
{
key_count = 8;
key_flag=1;//按键读取标志
}
}
u8 trg,cont,readdat;
void keyread() //
{
readdat = keypress^0xff;
trg = readdat & (cont^readdat);
cont = readdat ;
}
//-----------------------------------------------
//函数声明
void addmode();
void readtime();
void s7condition();
void s6condition();
void add_time() ;
void subtract_time();
void r_wendu();
void main()
{
buzzer = 0;
set_time (23,59,50);
TMOD = 0x01;
TL0 = T1MS;
TH0 = T1MS >> 8;
TR0 = 1;
ET0 = 1;
EA = 1;
count = 0;
while(1)
{
readtime(); //读取实时时间
smgshow();
//r_wendu();//疑惑2:读取温度时间真是太长了
if( key_flag) //scan keyread
{
key_flag = 0;
keyread();
//检测按键情况
if(trg & 0x01)//press s7(时钟设置按钮)
{
s7condition();
addmode();
if(mode != 0)
set_time_f = 1;//表示时钟设置状态
else
set_time_f = 0;
}
if(trg & 0x02) //press s6
{
s6condition();//设置兼容性,避免按下s7又按下s6的情况,同时将now time赋值给闹钟设置时间的初始值
addmode();
if(mode != 0)
set_clock_f = 1;
else
set_clock_f = 0;
}
if(trg & 0x04) //press s5
{
add_time();
}
if(trg & 0x08) //press s4
{
subtract_time();
}
if( cont & 0x08)
{
if(mode == 0)
show_smg2 = 1;//数码管界面2(温度显示
else
show_smg2 = 0;
}
}
if(clock_blink_start) //闹钟在闪烁的标志
{
if( trg != 0 )
clock_blink_start = 0; //close it
}
}
}
void clock_warn()
{
if( sshi == (shi/16*10)+shi%16 && ffen == (fen/16*10)+fen%16 && mmiao == (miao/16*10)+miao%16)
{
clock_blink_start = 1; //5s的标志
P2 = 0x80;
if(clock_blink) P0 = ~0x01;
else P0 = 0x00;
}
}
void r_wendu()
{
if(blink_time)//read temp
{
EA=0;
temp = readtemp();
EA=1;
}
}
void add_time() //按s5键后不同状态时间数值+1
{
if(set_time_f)//时间设置状态
{
switch(mode)
{
case 1: shi = (shi/16*10)+shi%16 + 1; break;//疑惑1:为什么按下s5后有时候时间会变得飞快
case 2: fen = (fen/16*10+fen%16) + 1; break;
case 3: miao = (miao/16*10+miao%16) + 1; break;
}
EA=0;
set_time(shi,fen,miao);
EA=1;
}
if(set_clock_f)
{
switch(mode)
{
// case 1: sshi = (sshi/16*10)+sshi%16 + 1; break;(改1对应
// case 2: ffen = (ffen/16*10+ffen%16) + 1; break;
// case 3: mmiao = (mmiao/16*10+mmiao%16) + 1; break;(有问题的原因是第二次弄这个的时候就=将十进制当做BCD码形式再转换一次
//所以我现在准备将闹钟设置一开始就设置为十进制形式(牵扯到的就有smg
case 1: sshi++; if(sshi>23) sshi = 0; break;
case 2: ffen++; if(ffen>59) ffen = 0; break;
case 3: mmiao++; if(mmiao>59) mmiao = 0; break;
}
}
}
void subtract_time() //按s4键后不同状态时间数值-1
{
if(set_time_f)//时间设置状态
{
switch(mode)
{
case 1: shi = (shi/16*10)+shi%16 - 1; break;//疑惑3:为什么0按下s4后变成92
case 2: fen = (fen/16*10+fen%16) - 1; break;
case 3: miao = (miao/16*10+miao%16) - 1; break;
}
EA=0;
set_time(shi,fen,miao);
EA=1;
}
if(set_clock_f)
{
switch(mode)
{
case 1: sshi--; if(sshi<0) sshi = 23; break;
case 2: ffen--; if(ffen<0) ffen = 59; break;
case 3: mmiao--; if(mmiao<0) mmiao = 59; break;
}
}
}
void s7condition()
{
if(set_time_f == 0 || set_clock_f ==1)
{
set_clock_f = 0; //关闭闹钟设置状态
mode = 0;
}
}
void s6condition()//设置兼容性,避免按下s7又按下s6的情况,同时将now time赋值给闹钟设置时间的初始值
{
if(set_clock_f == 0 || set_time_f == 1)//以后对if里的条件要小心又小心
{
set_time_f = 0; //关闭时钟设置状态
// sshi = shi;(改1对应
// ffen = fen;
// mmiao = miao;
mmiao = (miao/16*10+miao%16);
ffen = (fen/16*10+fen%16);
sshi = (shi/16*10)+shi%16 ;
mode = 0;
}
}
void readtime()
{
EA = 0;
shi = Read_Ds1302_Byte(0x85);
fen = Read_Ds1302_Byte(0x83);
miao = Read_Ds1302_Byte(0x81); //read current time
EA = 1;
}
void addmode()//按下S7/s6键,模式加1
{
mode++;
if(mode == 4)
mode = 0;
}
void smgshow()
{
u8 i;
for(i = 0; i<5; i++)
{
menu2[i] = 0x00;
}
menu2[5] = T_duan[ temp/10 ];
menu2[6] = T_duan[ temp%10 ];
menu2[7] = 0x39;
if(mode == 0)
{
menu1[0] = T_duan[((shi/16*10)+shi%16)/10];
menu1[1] = T_duan[(shi/16*10+shi%16)%10];
menu1[2] = 0x40;
menu1[3] = T_duan[(fen/16*10+fen%16)/10];
menu1[4] = T_duan[fen%16];
menu1[5] = 0x40;
menu1[6] = T_duan[(miao/16*10+miao%16)/10];
menu1[7] = T_duan[(miao/16*10+(miao%16))%10];
}
if(mode != 0) //区分设置zhuangtaihe 显示状态
{
for( i = (mode-1)*3; i<(mode*3) ;i++ )
{
if(blink_time) //当前显示单元1秒亮灭
{
menu1[i]=T_dim[i];
P2=0x80;P0=0x55;P2=0;
}
else
{
if(set_time_f)//时钟设置状态
{
P2=0x80;P0=~0x55;P2=0;
menu1[0] = T_duan[((shi/16*10)+shi%16)/10];
menu1[1] = T_duan[(shi/16*10+shi%16)%10];
menu1[2] = 0x40;
menu1[3] = T_duan[(fen/16*10+fen%16)/10];
menu1[4] = T_duan[fen%16];
menu1[5] = 0x40;
menu1[6] = T_duan[(miao/16*10+miao%16)/10];
menu1[7] = T_duan[(miao/16*10+(miao%16))%10];
}
if(set_clock_f)//闹钟设置状态
{
// menu1[0] = T_duan[((sshi/16*10)+sshi%16)/10];
// menu1[1] = T_duan[(sshi/16*10+sshi%16)%10];
// menu1[2] = 0x40;
// menu1[3] = T_duan[(ffen/16*10+ffen%16)/10];
// menu1[4] = T_duan[ffen%16];
// menu1[5] = 0x40;
// menu1[6] = T_duan[(mmiao/16*10+miao%16)/10];
// menu1[7] = T_duan[(mmiao/16*10+(mmiao%16))%10];(改1对应,同时注意sshi,ffen..表示一个数值而不是芯片认为的时间了,所以注意临界状态
menu1[0] = T_duan[sshi/10];
menu1[1] = T_duan[sshi%10];
menu1[2] = 0x40;
menu1[3] = T_duan[ffen/10];
menu1[4] = T_duan[ffen%10];
menu1[5] = 0x40;
menu1[6] = T_duan[mmiao/10];
menu1[7] = T_duan[mmiao%10];
}
}
}
}
}
//bit key_flag,sz_blink_time=1, sz_flag;
//u8 code T_duan[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
//typedef unsigned char BYTE;
//typedef unsigned int WORD;
-----------------------------------------------
///* define constants */
//#define FOSC 11059200L
//#define T1MS (65536-FOSC/12/1000) //1ms timer calculation method in 12T mode
///* define SFR */
//sbit TEST_LED = P1^0; //work LED, flash once per second
///* define variables */
//WORD count; //1000 times counter
-----------------------------------------------
///* Timer0 interrupt routine */
//u8 trg,cont,readdat;
//void keyread()
//{
// readdat=0xff^keypress;
// trg=readdat&(readdat^cont);
// cont=readdat;
//}
//void tm0_isr() interrupt 1 using 1
//{
// TL0 = T1MS; //reload timer0 low byte
// TH0 = T1MS >> 8; //reload timer0 high byte
// if (count-- == 0) //1ms * 1000 -> 1s
// {
// count = 1000;
// sz_blink_time=~sz_blink_time;
//
// }
// //smg part
// if (smg_count-- == 0) //1ms * 1000 -> 1s
// {
// smg_count = 3;
// P2=0xe0; P0=~menu1[smg_i];P2=0;
// P2=0xc0; P0=T_COM[smg_i];P2=0;
// smg_i++;
// if(smg_i==8)
// {
// smg_i = 0;
// }
// }
// if(key_count--==0)
// {
// key_count = 8;
// key_flag=1;
//
// }
//}
-----------------------------------------------
///* main program */
//void main()
//{
// buzzer=0;
//
// set_time(23,59,50);
// TMOD = 0x01; //set timer0 as mode1 (16-bit)
// TL0 = T1MS; //initial timer0 low byte
// TH0 = T1MS >> 8; //initial timer0 high byte
// TR0 = 1; //timer0 start running
// ET0 = 1; //enable timer0 interrupt
// EA = 1; //open global interrupt switch
// count = 0; //initial counter
// while (1)
// {
// EA=0;
// shi=Read_Ds1302_Byte (0x85);
// fen=Read_Ds1302_Byte (0x83);
// miao=Read_Ds1302_Byte (0x81);
// EA=1;
// szshi=(shi/16*10+shi%16);
// szfen=(fen/16*10+fen%16);
// szmiao=(miao/16*10+miao%16);
// menu1[0]=T_duan[(shi/16*10+shi%16)/10]; menu1[1]=T_duan[(shi/16*10+shi%16)%10]; menu1[2]=0x40; menu1[3]=T_duan[(fen/16*10+fen%16)/10]; menu1[4]=T_duan[fen%16];
// menu1[5]=0x40; menu1[6]=T_duan[(miao/16*10+miao%16)/10]; menu1[7]=T_duan[(miao/16*10+(miao%16))%10];
// if(key_flag)
// {
// keyread();
// key_flag=0;
// }
// }
// }
//
switch(trg)
{
case 0x01: sz_flag=1;
sz_smg_blink++;
if(sz_smg_blink == 4)
{
sz_smg_blink=0;
sz_flag=0;
}
break;
case 0x02:break;
case 0x04: if(sz_flag)
{
if(sz_smg_blink ==1)
{
szshi++;
if(szshi>=24) szshi=0;
}
if(sz_smg_blink ==2)
{
szfen++;
if(szfen>=61) szfen=0;
}
if(sz_smg_blink ==3)
{
szmiao++;
if(szmiao>=61) szmiao=0;
}
set_time(szshi,szfen,szmiao);
}//s5
case 0x08://s4
if(sz_flag)
{
if(sz_smg_blink ==1)
{
if(szshi>0)
{
szshi--;
}
else
szshi=24;
}
if(sz_smg_blink ==2)
{
if(szfen>0)
szfen--;
}
if(sz_smg_blink == 3)
{
if(szmiao>0)
szmiao--;
}
set_time(szshi,szfen,szmiao);
}break;
break;
}
//switch end
if(sz_flag)
{
if(sz_smg_blink == 1)
{
if(sz_blink_time)
{
menu1[0]=0x00; menu1[1]=0x00;
{
P2=0x80;P0=0x55;P2=0;
}
}
else
{
menu1[0]=T_duan[szshi/10]; menu1[1]=T_duan[szshi%10];
}
}
if(sz_smg_blink == 2)
{
if(sz_blink_time)
{
menu1[3]=0x00; menu1[4]=0x00;
}
else
{
menu1[3]=T_duan[szfen/10];
menu1[4]=T_duan[szfen%10];
}
}
if(sz_smg_blink == 3)
{
if(sz_blink_time)
{
menu1[6]=0x00; menu1[7]=0x00;
}
else
{
menu1[6]=T_duan[szmiao/10];
menu1[7]=T_duan[szmiao%10];
}
}
}
}
}
}
驱动底层代码
ds1302.c
#include <reg52.h>
#include <intrins.h>
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp);
}
void set_time(unsigned char shi,unsigned char fen,unsigned char miao)
{
Write_Ds1302_Byte(0x8e,0); //关闭写保护
Write_Ds1302_Byte(0x80,(miao/10)*16+miao%10); //以BCD码写入秒数据
Write_Ds1302_Byte(0x82,(fen/10)*16+fen%10); //以BCD码写入分数据
Write_Ds1302_Byte(0x84,(shi/10)*16+shi%10); //以BCD码写入时数据,这个是10进制转bcd码,然后后面写出的时间是16进制(bcd))转10进制
Write_Ds1302_Byte(0x8e,0x80); //打开写保护
}
onewire.c
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
unsigned char i;
while(t--)
{
for(i = 0; i<12; i++);
}
}
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
unsigned char readtemp()
{
// unsigned char temp, high, low;
// init_ds18b20();
// Write_DS18B20(0xcc);
// Delay_OneWire(5);
// Write_DS18B20(0x44);
// Delay_OneWire(200);
//
//
// init_ds18b20();
// Write_DS18B20(0xcc);
// Delay_OneWire(5);
// Write_DS18B20(0xbe);
// Delay_OneWire(5);
//
// high = Read_DS18B20();
// low = Read_DS18B20();
// temp = high>>4 | low <<4;
// return temp;
unsigned char low,high,temp;
init_ds18b20();
Delay_OneWire(1);
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Delay_OneWire(1);
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();//温度数据16位存储,小数部分在低四位,符号在高四位。在此均不需要
high=Read_DS18B20();
high=high<<4;
low=low>>4;
temp=high|low;
return temp;
}