参照51做了一个4位数码管的闹钟程序,但是不知怎么回事,刚上电就是4个8,然后调时间,但是就显示一些乱码,不走动时间。
//定义读取时间和日期存放表格
char table1[3];//定义读取时间存放表格
const char table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳数码管编码
int clock1[3]={0}; //设置闹钟存放表格
int i,j=0,flag1=0;
void delay(uint xms)
{
uint x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
void sand_bm(uchar a) //串行数据输入到595
{
uchar i;
for(i=0;i<8;i++)
{
if((a&0x80)==0) //取数据的最高位
{
DAT=0;
NOP();
}
else
{
DAT=1;
NOP();
}
SCK=0; //11脚移位脉冲下降沿移位寄存器数据不变
NOP();
SCK=1; //11脚移位脉冲上升沿时数据寄存器的数据移位
a=a<<1;
}
}
void init()//初始化
{
TRISA=0B00100000; //设置A口RA5为输入,其余为输出
TRISC=0X00; //设置D口全输出
ADCON1=0B00000110; //设置A口为普通I/O口
TRISB=0B00000111; //设置RB0,1,2为输入,其他为输出
OPTION=0X00; //开启B口弱上拉
PORTC=0;
}
void display(uchar miaog,uchar miaos,uchar feng,uchar fens,uchar shig,uchar shis)//数码管动态显示
{
uchar M1,M2,F1,F2,S1,S2;
int i; //定义查表变量
F1=feng;
F2=fens;
S1=shig;
S2=shis;
RCK=0; //12脚存储脉冲下降沿时存储寄存器数据不变
// sand_bm(M1);
// sand_bm(M2);
sand_bm(0x01);
sand_bm(F1);
delay(1);
RCK=1;
NOP();
RCK=0;
sand_bm(0x02);
sand_bm(F2);
delay(1);
RCK=1;
NOP();
RCK=0;
sand_bm(0x04);
sand_bm(S1);
delay(1);
RCK=1;
NOP();
RCK=0;
sand_bm(0x08);
sand_bm(S2);
delay(1);
RCK=1; // 12脚存储脉冲上升沿时移位寄存器的数据进入数据存储寄存器,
// 当出现一个几十纳秒的正脉冲时,更新显示数据
}
void write_sfm(uchar miao,uchar fen,uchar shi) //写入到数码管
{
uchar miaog,miaos,feng,fens,shig,shis;
miaog=miao%10;
miaos=miao/10;
feng=fen%10;
fens=fen/10;
shig=shi%10;
shis=shi/10;
display(miaog,miaos,feng,fens,shig,shis);
}
void didi() //发声程序
{
buzzer=0;
delay(50);
buzzer=1;
}
void keyscan()//按键扫描程序
{
uchar temp;
if(key1==0) //时间设置键,按一下,关闭,按四下,开启
{
if(key1==0)
{
while(!key1);
key1n=key1n++;
if(key1n==5)
key1n=1;
switch(key1n)
{
case 1://didi();按第一下,(key1n==1)关闭时钟
temp=(miao/10*16)+(miao%10);//将秒转化成bcd码,没这句秒就变化,不知为什么
write_1302(0x8e,0x00); //写保护寄存器允许写入寄存器
write_1302(0x80,0x80|temp); //时钟暂停
write_1302(0x8e,0x80); //写保护寄存器禁止写入
break;
case 2 ://didi();
break;
case 3 ://didi();
break;
case 4 ://didi();按第四下,(key1n==4)开启时钟
temp=miao/10*16+miao%10;
write_1302(0x8e,0x00); //写保护寄存器允许写入寄存器
write_1302(0x80,0x00|temp);//时钟开始
write_1302(0x8e,0x80); //写保护寄存器禁止写入
break;
}
}
}
if(key4==0) //闹钟键 按下此键进入闹钟设置模式
{
if(key4==0)
{
while(!key4);
keyn++;
if(keyn==4)
keyn=0;
while(keyn) //如果keyn的值非0,进入下面的程序
{
TMR1IE=0; //闹钟键 禁止总中断?
GIE=0; //禁止总中断
if(key4==0)
if(key4==0)
{
while(!key4);
keyn++;
if(keyn==4)
keyn=0;
}
write_sfm(clock1[2],clock1[1],clock1[0]);
if(keyn==1) //时修改
{
if(key3==0) //减键
{
//delay(3);
if(key3==0)
{
while(!key3);
clock1[0]--;
if(clock1[0]<0) clock1[0]=24;
}
}
if(key2==0) //加键
{
//delay(3);
if(key2==0)
{
while(!key2);
clock1[0]++;
if(clock1[0]>24)clock1[0]=0;
}
}
}
if(keyn==2) //分修改
{
if(key3==0) //减键
{
//delay(3);
if(key3==0)
{
while(!key3);
clock1[1]--;
if(clock1[1]<0) clock1[1]=59;
}
}
if(key2==0) //加键
{
//delay(3);
if(key2==0)
{
while(!key2);
clock1[1]++;
if(clock1[1]>59)clock1[1]=0;
}
}
}
if(keyn==3) //秒修改
{
if(key3==0) //减键
{
//delay(3);
if(key3==0)
{
while(!key3);
clock1[2]--;
if(clock1[2]<0) clock1[2]=59;
}
}
if(key2==0) //加键
{
//delay(3);
if(key2==0)
{
while(!key2);
clock1[2]++;
if(clock1[2]>59)clock1[2]=0;
}
}
}
}
}
TMR1IE=1;
GIE=1; //禁止使能总中断
}
if(key1n!=0) //当按下功能键key1,按以下才有用
{
if(key2==0) //加键
{
delay(3);
if(key2==0)
{
while(!key2);
switch(key1n)
{
case 1 : //didi(); //如果key1n等于1,进入设置秒程序
temp=(miao+1)/10*16+(miao+1)%10;
if(miao==59)
temp=0;
write_1302 (0x8e,0x00); //禁止写保护
write_1302 (0x80,0x80|temp);
write_1302 (0x8e,0x80); //允许写保护
break;
case 2 : // didi(); //如果key1n等于2,进入设置分程序
temp=(fen+1)/10*16+(fen+1)%10;
if(fen==59)
temp=0;
write_1302 (0x8e,0x00); //禁止写保护
write_1302 (0x82,temp);
write_1302 (0x8e,0x80); //允许写保护
break;
case 3 :// didi(); //如果key1n等于3,进入设置时程序
temp=(shi+1)/10*16+(shi+1)%10; //时
if(shi==23)
temp=0;
write_1302 (0x8e,0x00); //禁止写保护
write_1302 (0x84,temp);
write_1302 (0x8e,0x80); //允许写保护
break;
}
}
}
if(key3==0) //减键
{
delay(3);
if(key3==0)
{
while(!key3);
switch(key1n)
{
case 1 ://didi();
temp=(miao-1)/10*16+(miao-1)%10; //秒
if(miao==0)
temp=89;
write_1302 (0x8e,0x00); //禁止写保护
write_1302 (0x80,0x80|temp);
write_1302 (0x8e,0x80); //允许写保护
break;
case 2 ://didi();
temp=(fen-1)/10*16+(fen-1)%10; //分
if(fen==0)
temp=89;
write_1302 (0x8e,0x00); //禁止写保护
write_1302 (0x82,temp);
write_1302 (0x8e,0x80); //允许写保护
break;
case 3 ://didi();
temp=(shi-1)/10*16+(shi-1)%10; //时
if(shi==0)
temp=35;
write_1302 (0x8e,0x00); //禁止写保护
write_1302 (0x84,temp);
write_1302 (0x8e,0x80); //允许写保护
break;
}
}
}
}
}
void main()
{
init();
while(1)
{
miao=BCD_Decimal(read_1302(0x81));//将DS1302秒寄存器的值赋与miao
fen=BCD_Decimal(read_1302(0x83)); //将DS1302分寄存器的值赋与fen
shi=BCD_Decimal(read_1302(0x85));//将DS1302时寄存器的值赋与shi
keyscan(); //调取按键扫描程序
if((miao==clock1[2])&&(fen==clock1[1])&&(shi==clock1[0]))
{
for(i=0;i<10;i++)didi();
}
write_sfm(miao,fen,shi);
}
}
void write_byte(uchar dat)
{
uchar a;
time_rx=dat;
for(a=8;a>0;a--)
{
SCLK=0; //拉低时钟,便于产生上升沿
IO=time_rx0;
//delayus(10);
SCLK=1; //上升沿时,DS1302接收单片机发来的数据
time_rx=time_rx>>1;
}
}
//向1302读出一字节
uchar read_byte()
{
uchar a;
TRISB4=1; //设置数据口方向为输入
for(a=8;a>0;a--)
{
SCLK=0; //在下降沿时,DS1302被单片机读出数据
time_rx=time_rx>>1;
time_rx7=IO;
SCLK=1; //拉高电平,以便于产生下降沿
}
TRISB4=0; //恢复数据口方向为输出
SCLK=0;
return(time_rx);
}
//向1302写入数据
void write_1302(uchar add,uchar dat)
{
RST=0;
SCLK=0;
//delayus(5);
RST=1;
write_byte(add);
write_byte(dat);
//delayus(5);
SCLK=1;
RST=0;
}
//向1302读出数据
uchar read_1302(uchar add)
{
uchar temp;
RST=0;
SCLK=0; //只有在SCLK为低电平时才能将RST置为高电平
//delayus(5);
RST=1; //RST只有被置为高电平,才允许进行所有的操作
write_byte(add);
temp=read_byte();
//delayus(5);
SCLK=1;
RST=0;
return (temp);
}
uchar BCD_Decimal(uchar bcd)
{
uchar Decimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
} |