单片机之DS1302万年历实验程序
这篇文章是接上一篇《教你玩单片机之DS1302》的内容,有不明白的朋友可以进入我的主页,看我之前发的内容,不喜勿喷。
万年历实验
实验效果 :1602显示时钟,按K3进入时钟设置,按K1选择设置的时分秒日月,按K2选择设置加1。
主程序
#include<reg51.h>
#include"lcd.h"
#include"ds1302.h"
sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;
void Int0Configuration();
void LcdDisplay();
unsigned char SetState,SetPlace;
void Delay10ms(void); //误差 0us
void main()
{
unsigned char i;
Int0Configuration();
LcdInit();
Ds1302Init();
while(1)
{
if(SetState==0)
{
Ds1302ReadTime();
}
else
{
if(K1==0)//检测按键K1是否按下
{
Delay10ms();//消除抖动
if(K1==0)
{
SetPlace++;
if(SetPlace>=7)
SetPlace=0;
}
while((i<50)&&(K1==0)) //检测按键是否松开
{
Delay10ms();
i++;
}
i=0;
}
if(K2==0)//检测按键K2是否按下
{
Delay10ms();//消除抖动
if(K2==0)
{
TIME[SetPlace]++;
if((TIME[SetPlace]&0x0f)>9) //换成BCD码。
{
TIME[SetPlace]=TIME[SetPlace]+6;
}
if((TIME[SetPlace]>=0x60)&&(SetPlace<2))//分秒只能到59
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x24)&&(SetPlace==2))//小时只能到23
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x32)&&(SetPlace==3))//日只能到31
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x13)&&(SetPlace==4))//月只能到12
{
TIME[SetPlace]=0;
}
if((TIME[SetPlace]>=0x7)&&(SetPlace==5))//周只能到7
{
TIME[SetPlace]=1;
}
//if(SetPlace==5)//月只能到12
//{
//TIME[SetPlace]=;
//}
}
while((i<50)&&(K2==0)) //检测按键是否松开
{
Delay10ms();
i++;
}
i=0;
}
}
LcdDisplay();
}
}
void LcdDisplay()
{
LcdWriteCom(0x80+0X40);
LcdWriteData('0'+TIME[2]/16);//时
LcdWriteData('0'+(TIME[2]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[1]/16);//分
LcdWriteData('0'+(TIME[1]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[0]/16);//秒
LcdWriteData('0'+(TIME[0]&0x0f));
LcdWriteCom(0x80);
LcdWriteData('2');
LcdWriteData('0');
LcdWriteData('0'+TIME[6]/16);//年
LcdWriteData('0'+(TIME[6]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[4]/16);//月
LcdWriteData('0'+(TIME[4]&0x0f));
LcdWriteData('-');
LcdWriteData('0'+TIME[3]/16);//日
LcdWriteData('0'+(TIME[3]&0x0f));
LcdWriteCom(0x8D);
LcdWriteData('0'+(TIME[5]&0x07));//星期
}
void Int0Configuration()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
void Int0() interrupt 0
{
Delay10ms();
if(K3==0)
{
SetState=~SetState;
SetPlace=0;
Ds1302Init();
}
}
void Delay10ms(void) //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}
#include"lcd.h"
#include"lcd.h"
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1);//等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //选择写入命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
//Lcd1602_Delay1ms(1);
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat)//写入数据
{
LCD1602_E = 0;//使能清零
LCD1602_RS = 1;//选择输入数据
LCD1602_RW = 0;//选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat)//写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择写入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat;//由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
#ifndefLCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#endif
#include"ds1302.h"
#include"ds1302.h"
//---DS1302写入和读取时分秒的地址命令---//
//---秒分时日月周年 最低位读写位;-------//
uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
//---存储顺序是秒分时日月周年,存储格式是用BCD码---//
uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};
void Ds1302Write(uchar addr, uchar dat)
{
uchar n;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1; //然后将RST(CE)置高电平。
_nop_();
for (n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
for (n=0; n<8; n++)//写入8位数据
{
DSIO = dat & 0x01;
dat >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;
_nop_();
}
RST = 0;//传送数据结束
_nop_();
}
uchar Ds1302Read(uchar addr)
{
uchar n,dat,dat1;
RST = 0;
_nop_();
SCLK = 0;//先将SCLK置低电平。
_nop_();
RST = 1;//然后将RST(CE)置高电平。
_nop_();
for(n=0; n<8; n++)//开始传送八位地址命令
{
DSIO = addr & 0x01;//数据从低位开始传送
addr >>= 1;
SCLK = 1;//数据在上升沿时,DS1302读取数据
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
_nop_();
for(n=0; n<8; n++)//读取8位数据
{
dat1 = DSIO;//从最低位开始接收
dat = (dat>>1) | (dat1<<7);
SCLK = 1;
_nop_();
SCLK = 0;//DS1302下降沿时,放置数据
_nop_();
}
RST = 0;
_nop_();//以下为DS1302复位的稳定时间,必须的。
SCLK = 1;
_nop_();
DSIO = 0;
_nop_();
DSIO = 1;
_nop_();
return dat;
}
void Ds1302Init()
{
uchar n;
Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能
for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
{
Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);
}
Ds1302Write(0x8E,0x80); //打开写保护功能
}
void Ds1302ReadTime()
{
uchar n;
for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
{
TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
}
}
单片机七天小实验
最近萌生了一个想法就是我想试一下用七天的时间每天做一个跟单片机有关的小实验。
为什么会有这样的想法呢?就是工作快三年了我想借此机会复盘总结一下我学到的东西。
这些实验主要是记录一下我从点灯到控制开发板上的其他外设的过程。
1.点灯,呼吸灯
2.机械按键
3.flash读写
4.蜂鸣器
5.uart发送,uart接收
6.RTC
7.触摸按键
敬请期待!!
相关问答
单片机 计数器 清零 -ZOL问答如果你是A01版本的是可以参数设定的,如果是B01版本的那就只能是断电就清零的。你动态扫描到另一个按键有有效信号时(非干扰),就分别TL0,TL1,th0,th1置0在在液...
51 单片机 秒表设计 怎么用按钮控制开始 停止和 清零 ?-ZOL问答sbitZ=P2^5;//清零按钮intaa,temp;chartable[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};/...
设有两个16位无符号数NA,NB分别存放在8051 单片机 内部RAM的4...[最佳回答]子程序形式出现:YCITORG1000HYCIT:CJNE40H,50H,LOPCJNZ41H,51H,LOP1JMPLOP3;相等LOP:MOVA,40HSUBBA,...
单片机 中置位复位概念?单片机中的置位和复位是指通过设置一个特定的信号来控制单片机的状态。当置位信号被设置时,它会将单片机的状态改为“置位”状态,即重置所有寄存器和计数器,并...
单片机 为什么要复位?复位的主要作用是把单片机内部的特殊功能寄存器置于初始状态,使单片机硬件、软件从一个确定的、唯一的起点开始工作。开机时称为上电复位,工作中异常时可以手...
并将原数据区 清零 .帮我编程. 单片机 的._作业帮[最佳回答]程序如下:MOVR0,#20HMOVDPTR,#1000HLOOP:MOVA,@R0MOVX@DPTR,AMOV@R0,#0INCDPTRINCR0CJNER0,#31H,LOOPSJ...
单片机 秒和分钟的进位是如何实现的?在单片机中,秒和分钟的进位通常通过计时器中断来实现。计时器会以固定的时间间隔触发中断,比如每秒触发一次。当计时器中断触发时,单片机会执行中断服务程序,...
单片机 问题。题目:将内部RAM中45h单元的高四位 清零 ,低四位置1。[最佳回答]只用一句,即可。MOV45H,#00001111B这是最简洁的程序。------------哦,993106193|六级最快回答mov45H,#0fH是一样的,这也对。只用一...
51 单片机 秒表程序[回答]这个程序写的太乱了执行的顺序是先定义秒等一些寄存器,然后清零,并定义定时初值,开显示。再打开定时器中断,定时到,中断秒寄存器加1,加到10时清...
8051 单片机 里的计数器溢出后会申请中断吗?计数器溢出后会产生中断请求,但单片机是否产生中断,也就是是否响应这个中断,要看程序是如何配置计数器溢出中断的。如果计数器溢出中断被允许,即IE寄存器中...