#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCK=P3^6
sbit SDA=P3^4
sbit RST=P3^5// DS1302复位
sbit set=P3^0//定义按键端口
sbit s1=P3^1
sbit s2=P3^2
sbit s3=P3^3
/************液晶口定义*******/
sbit RS=P2^4//RS为数据/指令选择1/0
sbit RW=P2^5//读写
sbit E=P2^6//E为使能信号
bit flag//是否读取时间的标志位
uchar setn=0//复位键、增加键敏余、减少键按下次数
uchar code time0[]="DATE: - - "
uchar code time1[]="TIME: : : "
uchar l_tmpdate[7]={0,55,16,22,8,6,9}//秒分时日月周年// 可随时更改
uchar code write_add[7]={0x80,0x82,0x84,0x86,
0x88,0x8a,0x8c}//秒分时日月周年 写的寄存器地址
uchar code read_add[7]={0x81,0x83,0x85,0x87,
0x89,0x8b,0x8d}//秒分时日月周年 读的寄存器地址
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d
,0x7d,0x07,0x7f,0x6f,0x40}//共阴数码管 0-9加'-'熄灭表
void delay(uint z)
{
while(--z)
}
void write_com(uchar com)//液晶写命令函数
{
RS=0//写命令使能
RW=0//写
delay(5000)
/****在高脉冲下命令输入*****/
E=0
P0=com
delay(500)
E=1
delay(500)
E=0
}
void write_data(uchar dat)//液晶写数据函数
{
RS=1//写数据使能胡裂
RW=0
delay(5000)
/****在高脉冲下数据输入*****/
E=0
P0=dat
delay(500)
E=1
delay(500)
E=0
}
void init()//液晶初始化
{
uchar num
E=0
write_com(0x38)//显示模式设置
delay(500)
write_com(0x38)
delay(500)
write_com(0x38)
write_com(0x08)//显示关闭
delay(500)
write_com(0x01)//裤拿闭显示清屏
write_com(0x06)//光标移动设置整屏不移动
write_com(0x0c)//屏幕开、光标不闪(0)不显示(0)
delay(500)
write_com(0x80)
for(num=0num<16num++)
{
write_data(time0[num])
delay(5)
}
write_com(0x80+0x40)
for(num=0num<13num++)
{
write_data(time1[num])
delay(5)
}
}
void Write_Ds1302_Byte(uchar temp) //写一个字节
{
uchar i
for (i=0i<8i++)//循环8次写入数据
{
SCK=0
SDA=temp&0x01 //每次传输低字节
temp>>=1 //右移一位
SCK=1
}
}
/****************************************************************************/
void Write_Ds1302(uchar add,uchar dat )//向寄存器写数据
{
RST=0
_nop_()
SCK=0
_nop_()
RST=1//启动
_nop_()
Write_Ds1302_Byte(add)//发送地址
Write_Ds1302_Byte(dat)//发送数据
RST=0 //恢复
}
uchar Read_Ds1302_Byte()//读一个字节
{
uchar i,temp=0x00
for (i=0i<8i++) //循环8次 读取数据
{
if(SDA)
temp|=0x80 //每次传输低字节
SCK=0
temp>>=1 //右移一位
SCK=1
}
return(temp)
}
uchar Read_Ds1302(uchar address )//从寄存器读数据
{
uchar date
RST=0
_nop_()
SCK=0
_nop_()
RST=1
_nop_()
Write_Ds1302_Byte(address)
date=Read_Ds1302_Byte()
RST=0
_nop_() //以下为DS1302复位的稳定时间
RST=0
SCK=0
_nop_()
SCK=1
_nop_()
SDA=0
_nop_()
SDA=1
_nop_()
return (date)
}
/*********************************************************/
void Read_RTC(void) //读取日历
{
uchar i,*p
p=read_add //读的地址传递
for(i=0i<7i++) //分7次读取 秒分时日月周年
{
l_tmpdate[i]=Read_Ds1302(*p)
p++
}
}
/******************************************************/
void Set_RTC(void) //设定日历
{
uchar i,*p,tmp
for(i=0i<7i++)
{ //BCD处理,将十六进制转换成十进制
tmp=l_tmpdate[i]/10
l_tmpdate[i]=l_tmpdate[i]%10
l_tmpdate[i]=l_tmpdate[i]+tmp*16
}
Write_Ds1302(0x8E,0X00)//关闭写保护
p=write_add//传要写的寄存器地址
for(i=0i<7i++) //7次写入秒分时日月周年
{
Write_Ds1302(*p,l_tmpdate[i])
p++
}
Write_Ds1302(0x8E,0x80)//打开写保护
}
void write_lcd()
{
static uchar i,temp[2]
switch(i)
{
case 0: write_com(0x80+0x40+0x0b)break//秒
case 1: write_com(0x80+0x40+8)break//分
case 2: write_com(0x80+0x40+5)break//时
case 3: write_com(0x80+0x0b)break//日
case 4: write_com(0x80+8)break//月
case 5: write_com(0x80+0x0e)break//星期
case 6: write_com(0x80+5)break//年
}
temp[0]=l_tmpdate[i]/16//数据的转换
temp[1]=l_tmpdate[i]&0x0f
write_data(0x30+temp[0])
write_data(0x30+temp[1])
i++
if(i==7)
i=0
}
uchar change(uchar x)//十进制转换成十六进制
{
uchar tep,y
y=x
tep=y/16
y=y%16
y=y+tep*10
return y
}
void keyscan()
{
uchar tem[2],tp,Flag//存储要更改的时间数据
if(set==0)
{
flag=1//时间停止
delay(500)//去键盘按下抖动
if(set==0)
{
delay(500)
while(!set)
delay(500)//去键盘抬起时抖动
while(!set)
delay(500)
setn++
if(setn==1)
{
write_com(0x80+0x40+12)//将光标移动到秒个位
write_com(0x0f)//显示光标并且闪烁
}
if(setn==2)
{
write_com(0x80+0x40+9)//将光标移动到分个位
write_com(0x0f)//显示光标并且闪烁
}
if(setn==3)
{
write_com(0x80+0x40+6)//将光标移动到时个位
write_com(0x0f)//显示光标并且闪烁
}
if(setn==4)
{
write_com(0x80+15)
write_com(0x0f)
}
if(setn==5)
{
write_com(0x80+12)
write_com(0x0f)
}
if(setn==6)
{
write_com(0x80+9)
write_com(0x0f)
}
if(setn==7)
{
write_com(0x80+6)
write_com(0x0f)
}
if(setn==8)
{
setn=0
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[0],l_tmpdate[0])
Write_Ds1302(0x8E,0x80)//打开写保护
flag=0//时钟正常运行
write_com(0x0c)//光标停止闪烁
}
}
}
if(setn!=0)//更改时间
{
if(s1==0)//增加时间
{
delay(5000)
if(s1==0)
{
while(!s1)
delay(5000)//去键盘抬起时抖动
while(!s1)
if(setn==1)
{
l_tmpdate[0]=change(l_tmpdate[0])
l_tmpdate[0]++
if(l_tmpdate[0]>=60)
l_tmpdate[0]=0
{
tp=l_tmpdate[0]/10
l_tmpdate[0]=l_tmpdate[0]%10
l_tmpdate[0]=l_tmpdate[0]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[0],l_tmpdate[0])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+0x40+11)
tem[0]=l_tmpdate[0]/16//数据的转换
tem[1]=l_tmpdate[0]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+0x40+12)
Flag=1
}
if(setn==2)
{ l_tmpdate[1]=change(l_tmpdate[1])
l_tmpdate[1]++
if(l_tmpdate[1]==60)
l_tmpdate[1]=0
{
tp=l_tmpdate[1]/10
l_tmpdate[1]=l_tmpdate[1]%10
l_tmpdate[1]=l_tmpdate[1]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[1],l_tmpdate[1])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+0x40+8)
tem[0]=l_tmpdate[1]/16//数据的转换
tem[1]=l_tmpdate[1]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+0x40+9)
}
if(setn==3)
{ l_tmpdate[2]=change(l_tmpdate[2])
l_tmpdate[2]++
if(l_tmpdate[2]>=24)
l_tmpdate[2]=0
{
tp=l_tmpdate[2]/10
l_tmpdate[2]=l_tmpdate[2]%10
l_tmpdate[2]=l_tmpdate[2]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[2],l_tmpdate[2])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+0x40+5)
tem[0]=l_tmpdate[2]/16//数据的转换
tem[1]=l_tmpdate[2]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+0x40+6)
}
if(setn==4)
{
l_tmpdate[5]=change(l_tmpdate[5])
l_tmpdate[5]++
if(l_tmpdate[5]==8)
l_tmpdate[5]=1
{
tp=l_tmpdate[5]/10
l_tmpdate[5]=l_tmpdate[5]%10
l_tmpdate[5]=l_tmpdate[5]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[5],l_tmpdate[5])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+14)
tem[0]=l_tmpdate[5]/16//数据的转换
tem[1]=l_tmpdate[5]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+15)
}
if(setn==5)
{
l_tmpdate[3]=change(l_tmpdate[3])
l_tmpdate[3]++
if(l_tmpdate[3]==32)
l_tmpdate[3]=0
{
tp=l_tmpdate[3]/10
l_tmpdate[3]=l_tmpdate[3]%10
l_tmpdate[3]=l_tmpdate[3]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[3],l_tmpdate[3])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+11)
tem[0]=l_tmpdate[3]/16//数据的转换
tem[1]=l_tmpdate[3]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+12)
}
if(setn==6)
{
l_tmpdate[4]=change(l_tmpdate[4])
l_tmpdate[4]++
if(l_tmpdate[4]==13)
l_tmpdate[4]=0
write_com(0x80+8)
{
tp=l_tmpdate[4]/10
l_tmpdate[4]=l_tmpdate[4]%10
l_tmpdate[4]=l_tmpdate[4]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[4],l_tmpdate[4])
Write_Ds1302(0x8E,0x80)//打开写保护
}
tem[0]=l_tmpdate[4]/16//数据的转换
tem[1]=l_tmpdate[4]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+9)
}
if(setn==7)
{
l_tmpdate[6]=change(l_tmpdate[6])
l_tmpdate[6]++
if(l_tmpdate[6]==100)
l_tmpdate[6]=0
write_com(0x80+5)
{
tp=l_tmpdate[6]/10
l_tmpdate[6]=l_tmpdate[6]%10
l_tmpdate[6]=l_tmpdate[6]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[6],l_tmpdate[6])
Write_Ds1302(0x8E,0x80)//打开写保护
}
tem[0]=l_tmpdate[6]/16//数据的转换
tem[1]=l_tmpdate[6]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+6)
}
}
}
if(s2==0)//减少时间
{
delay(5000)
if(s2==0)
{
while(!s2)
delay(5000)//去键盘抬起时抖动
while(!s2)
if(setn==1)
{
l_tmpdate[0]=change(l_tmpdate[0])
if(l_tmpdate[0]!=0)
l_tmpdate[0]--
if(l_tmpdate[0]==0)
l_tmpdate[0]=59
{
tp=l_tmpdate[0]/10
l_tmpdate[0]=l_tmpdate[0]%10
l_tmpdate[0]=l_tmpdate[0]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[0],l_tmpdate[0])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+0x40+11)
tem[0]=l_tmpdate[0]/16//数据的转换
tem[1]=l_tmpdate[0]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+0x40+12)
}
if(setn==2)
{
l_tmpdate[1]=change(l_tmpdate[1])
if(l_tmpdate[1]!=0)
l_tmpdate[1]--
if(l_tmpdate[1]==0)
l_tmpdate[1]=59
{
tp=l_tmpdate[1]/10
l_tmpdate[1]=l_tmpdate[1]%10
l_tmpdate[1]=l_tmpdate[1]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[1],l_tmpdate[1])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+0x40+8)
tem[0]=l_tmpdate[1]/16//数据的转换
tem[1]=l_tmpdate[1]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+0x40+9)
}
if(setn==3)
{ l_tmpdate[2]=change(l_tmpdate[2])
if(l_tmpdate[2]!=0)
l_tmpdate[2]--
if(l_tmpdate[2]==0)
l_tmpdate[2]=23
{
tp=l_tmpdate[2]/10
l_tmpdate[2]=l_tmpdate[2]%10
l_tmpdate[2]=l_tmpdate[2]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[2],l_tmpdate[2])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+0x40+5)
tem[0]=l_tmpdate[2]/16//数据的转换
tem[1]=l_tmpdate[2]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+0x40+6)
}
if(setn==4)
{
l_tmpdate[5]=change(l_tmpdate[5])
if(l_tmpdate[5]!=0)
l_tmpdate[5]--
if(l_tmpdate[5]==0)
l_tmpdate[5]=7
{
tp=l_tmpdate[5]/10
l_tmpdate[5]=l_tmpdate[5]%10
l_tmpdate[5]=l_tmpdate[5]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[5],l_tmpdate[5])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+14)
tem[0]=l_tmpdate[5]/16//数据的转换
tem[1]=l_tmpdate[5]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+15)
}
if(setn==5)
{
l_tmpdate[3]=change(l_tmpdate[3])
if(l_tmpdate[3]!=0)
l_tmpdate[3]--
if(l_tmpdate[3]==0)
l_tmpdate[3]=31
{
tp=l_tmpdate[3]/10
l_tmpdate[3]=l_tmpdate[3]%10
l_tmpdate[3]=l_tmpdate[3]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[3],l_tmpdate[3])
Write_Ds1302(0x8E,0x80)//打开写保护
}
write_com(0x80+11)
tem[0]=l_tmpdate[3]/16//数据的转换
tem[1]=l_tmpdate[3]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+12)
}
if(setn==6)
{
l_tmpdate[4]=change(l_tmpdate[4])
if(l_tmpdate[4]!=0)
l_tmpdate[4]--
if(l_tmpdate[4]==0)
l_tmpdate[4]=12
write_com(0x80+8)
{
tp=l_tmpdate[4]/10
l_tmpdate[4]=l_tmpdate[4]%10
l_tmpdate[4]=l_tmpdate[4]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[4],l_tmpdate[4])
Write_Ds1302(0x8E,0x80)//打开写保护
}
tem[0]=l_tmpdate[4]/16//数据的转换
tem[1]=l_tmpdate[4]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+9)
}
if(setn==7)
{
l_tmpdate[6]=change(l_tmpdate[6])
if(l_tmpdate[6]!=0)
l_tmpdate[6]--
if(l_tmpdate[6]==0)
l_tmpdate[6]=99
write_com(0x80+5)
{
tp=l_tmpdate[6]/10
l_tmpdate[6]=l_tmpdate[6]%10
l_tmpdate[6]=l_tmpdate[6]+tp*16
Write_Ds1302(0x8E,0X00)//关闭写保护
Write_Ds1302(write_add[6],l_tmpdate[6])
Write_Ds1302(0x8E,0x80)//打开写保护
}
tem[0]=l_tmpdate[6]/16//数据的转换
tem[1]=l_tmpdate[6]&0x0f
write_data(0x30+tem[0])
write_data(0x30+tem[1])
write_com(0x80+6)
}
}
}
}
}
/*******************************************************/
void main(void)
{
//Set_RTC()//在第一次使用时给ds1302赋初值
init()
while(1)
{
if(flag==0)
{
Read_RTC()
write_lcd()
}
keyscan()
}
}
这是一个PIC16F877A单片机的源液磨程序,你参考一下#include<pic.h> //包含单片机内部资源预定义
__CONFIG(0x1832)
//芯片配置字,看门狗关,上电延时开,掉电检测关,低压编程关,加密,4M晶体HS振荡
#define i_o RB4 //定义DS1302的数据口
#define sclk RB0 //定义DS1302的时钟口
#define rst RB5 //定义DS1302的复位口
// unsigned char time_rx
unsigned char time_rx @ 0x30 //定义接收寄存器
static volatile bit time_rx7 @ (unsigned)&time_rx*8+7 //接收寄存器的最高位
//static volatile bit temp0 @ (unsigned)&temp*8+0
void port_init() //申明引脚初始化函数
void ds1302_init() //申明DS1302初始化函数
void set_time() //申明设置时间函数
void get_time() //申明读取时间函数
void display() //申明显示函数
void time_write_1(unsigned char time_tx) //申明写一个字节函数
unsigned char time_read_1() //申明读一个字节函数
void delay() //申明延时函数
//定义待设置的时间: 秒、 分、 时、 日、月、星期、年、控制字
const char table[]={0x00,0x58,0x12,0x8,0x3,0x06,0x06,0x00}
//定义读取时间和日期存放表格
char table1[7]
//定义0-9的显示代码
const char table2[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}
//----------------------------------------------
//主函数
void main()
{
port_init()//调用引脚初始化函数
ds1302_init() //调用DS1302初始化函数
set_time() //调用设置时间函数
while(1)
{
get_time()//调用取时间函数
display() //调伍孝用显示函数
}
}
//---------------------------------------------
//DS1302初始化函数
void ds1302_init()
{
sclk=0 //拉低时钟信号
rst =0 //复位DS1302
rst=1//使能DS1302
time_write_1(0x8e) //发控制命令
time_write_1(0) //允许腔埋稿写DS1302
rst=0//复位
}
//---------------------------------------------
//设置时间函数
void set_time()
{
int i//定义循环变量
rst=1//使能DS1302
time_write_1(0xbe) //时钟多字节写命令
for(i=0i<8i++) //连续写8个字节数据
{
time_write_1(table[i]) //调用写一个字节函数
}
rst=0//复位
}
//---------------------------------------------
//读取时间函数
void get_time()
{
int i//设置循环变量
rst=1//使能DS1302
time_write_1(0xbf) //发送多字节读取命令
for(i=0i<7i++) //连续读取7个字节数据
{
table1[i]=time_read_1() //调用读取1个字节数据的函数
}
rst=0 //复位DS1302
}
//--------------------------------------------
//写一个字节数据函数
void time_write_1(unsigned char time_tx)
{
int j //设置循环变量
for(j=0j<8j++) //连续写8bit
{
i_o=0 //先设置数据为0
sclk=0 //时钟信号拉低
if(time_tx&0x01) //判断待发送的数据位是0或1
{
i_o=1 //待发送数据位是1
}
time_tx=time_tx>>1 //待发送的数据右移1位
sclk=1 //拉高时钟信号
}
sclk=0//写完一个字节,拉低时钟信号
}
//---------------------------------------------
//读一个字节函数
unsigned char time_read_1()
{
int j //设置循环变量
TRISB4=1//设置数据口方向为输入
for(j=0j<8j++) //连续读取8bit
{
sclk=0 //拉低时钟信号
time_rx=time_rx>>1 //接收寄存器右移1位
time_rx7=i_o //把接收到的数据放到接收寄存器的最高位
sclk=1 //拉高时钟信号
}
TRISB4=0 //恢复数据口方向为输出
sclk=0 //拉低时钟信号
return(time_rx)//返回读取到的数据
}
//--------------------------------------------
//引脚定义函数
void port_init()
{
TRISA=0x00//设置A口全输出
TRISD=0X00//设置D口全输出
ADCON1=0X06 //设置A口为普通I/O口
TRISB=0X02//设置RB1为输入,其他为输出
OPTION=0X00 //开启B口弱上拉
PORTA=0XFF
PORTD=0XFF//先熄灭所有显示
}
//-------------------------------------------
//显示函数
void display()
{
int i//定义查表变量
if(RB1==0) //判断RB1是否按下,如果按下的话显示日期,不按下显示时间
{
table1[0]=table1[3]
table1[1]=table1[4]
table1[2]=table1[6]
}
i=table1[0]&0x0f//求秒的个位
PORTD=table2[i] //送D口显示
PORTA=0x1f //点亮秒的个位
delay() //延长一段时间,保证亮度
i=table1[0]&0xf0//求秒的十位
i=i>>4 //右移4位
PORTD=table2[i] //送D口显示
PORTA=0x2f //点亮秒的十位
delay() //延长一段时间,保证亮度
i=table1[1]&0x0f//求分的个位
PORTD=table2[i]&0x7f//送D口显示,并显示小数点
PORTA=0x37 //点亮分的个位
delay() //延时一定时间,保证亮度
i=table1[1]&0xf0//求分的十位
i=i>>4
PORTD=table2[i] //送D口显示
PORTA=0x3b //点亮分的十位
delay() //延长一段时间,保证亮度
i=table1[2]&0x0f//求时的个位
PORTD=table2[i]&0x7f//送D口显示,并加上小数点
PORTA=0x3d //点亮时的个位
delay() //延时一定时间,保证亮度
i=table1[2]&0xf0//求时的十位
i=i>>4
PORTD=table2[i] //送D口显示
PORTA=0x3e //点亮时的十位
delay() //延长一段时间,保证亮度
}
//------------------------------------------------------------------
//延时程序
void delay() //延时程序
{
int i//定义整形变量
for(i=0x64i--)//延时
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)