蓝桥开发板(CT107D)学习记录————17.数字时钟

数字时钟设计

功能描述

1、初始化

1)关闭蜂鸣器、继电器等无关外设;

2)DS1302设备初始化时钟为 23 时 59 分 50 秒。

2、显示功能

蓝桥开发板(CT107D)学习记录————17.数字时钟

3、按键功能

1)按键 S4 定义为时钟启停按键,控制DS1302的启动和暂停(可使用中断方式)。

2)按键 S5、S6、S7 定义为“加”按键,每次在暂停状态下,按下该按键对应的时、分、秒单元增加 1 个单位。(S5–>时、S6–>分、S7–>秒)

这里要用到SPI总线协议

SPI(Serial Peripheral Interface,串行外围设备接口),是Motorola公司提出的一种同步串行接口技术,是一种高速、全双工、同步通信总线,在芯片中只占用四根管脚用来控制及数据传输,节约了芯片pin的数目,同时为PCB在布局上节省了空间。正是由于这种简单易用的特性,现在越来越多的芯片上都集成了SPI技术。
SPI主要用于EEPROM、Flash、RTC(实时时钟)、ADC(数模转换器)、DSP(数字信号处理器)以及数字信号解码器上。目前应用中的数据速率可达几Mbps。

ds1302.h 头文件代码如下

#ifndef __ds1302_h
#define __ds1302_h

void Write_Ds1302(unsigned  char temp);//写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );//写字节
unsigned char Read_Ds1302_Byte ( unsigned char address );//读取字节
#endif

ds1302.c 底层驱动,比赛中会提供,不做要求

#include <STC15F2K60S2.H>
#include <intrins.h>
sbit SCK=P1^7;	//时钟引脚	
sbit SDA=P2^3;		
sbit RST = P1^3;   //复位引脚,当RST=1时,所有数据传输初始化,允许对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;
		SCK=0;
	}
}   
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;
		SCK=0;
	} 
 	RST=0;	_nop_();
 	//SCK=0;	_nop_();
	//SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

#include <STC15F2K60S2.H>
#include"ds1302.h"
#define uchar unsigned char
#define uint unsigned int
uchar code display_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//0-9数码管编码表
uchar code adress[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};位选表左到右
uchar buff[8],flag=0;//buff数组存储要显示的每位数字 flag=1才能进行加操作
uchar Trg,cont,i=0,shi,fen,miao,keycount=0;keyflag=0;
static uchar setfen,setmiao,setshi;
void init() 				//初始化单片机
{
	P2=0xa0;P0=0x00;P2=0x00;//关继电器蜂鸣器
	P2=0x80;P0=0xff;P2=0x00;//关led灯
}
void stop()//启停子函数
{
	Write_Ds1302_Byte(0x8e,0);//写保护,置零,关掉保护才能写数据
	if(miao<0x80)
	{
		Write_Ds1302_Byte(0x80,miao|0x80);//高位为1,停止
		flag=1;//可以进行加操作
	}
	else
	{
		Write_Ds1302_Byte(0x80,miao&0x7f);//高位值0,启动
		flag=0;
	}
	Write_Ds1302_Byte(0x8e,0x80);//打开保护
}
void readtime()//读取时间
{
	    EA=0;//关中断
		shi=Read_Ds1302_Byte(0x85);//时存在0x85里
		fen=Read_Ds1302_Byte(0x83);//同理,这些地址都是固定的
		miao=Read_Ds1302_Byte(0x81);
		EA=1;//开中断
	  	buff[0]=shi/16;//注意读出来的时bsd码,十六进制,要转换成十进制
		buff[1]=shi%16;
		buff[2]=10;//显示横杠
		buff[3]=fen/16;
		buff[4]=fen%16;
		buff[5]=10;
		buff[6]=(miao/16)&0x07;
		buff[7]=miao%16;	
}
void readkey()//读取键值
{
		uchar ReadData=P3^0xff;
		Trg=ReadData&(ReadData^cont);
		cont=ReadData;
}
void key_function()//按键功能
{
	if(Trg&0x08)//启停
		stop();
	if((Trg&0x01)&&flag==1)//s7£¬Ãë
	{
		setmiao=Read_Ds1302_Byte(0x81);//读秒,注意setmiao是bcd码
		Write_Ds1302_Byte(0x8e,0x00);//关写保护
		setmiao=((setmiao>>4)&0x07)*10+(setmiao&0x0f)+1;//变成十进制,加一
		setmiao=setmiao%60;//边界情况
		Write_Ds1302_Byte(0x80,(setmiao/10<<4|setmiao%10)|0x80);//写入,但是要注意|0x80高位置1,不然数据出错,意思是暂停,停止秒
		Write_Ds1302_Byte(0x8e,0x80);//关闭写保护
	}
			if((Trg&0x02)&&flag==1)//同理设置分,但是发送时不要|0x80
			{
				setfen=Read_Ds1302_Byte(0x83);
				Write_Ds1302_Byte(0x8e,0x00);
				setfen=(setfen/16)*10+setfen%16+1;
				setfen=setfen%60;
				Write_Ds1302_Byte(0x82,(setfen/10)*16+setfen%10);
				Write_Ds1302_Byte(0x8e,0x80);
			}
			if((Trg&0x04)&&flag==1)//s5,时
			{
				setshi=Read_Ds1302_Byte(0x85);
				Write_Ds1302_Byte(0x8e,0x00);
				setshi=(setshi/16)*10+setshi%16+1;
				setshi=setshi%24;
				Write_Ds1302_Byte(0x84,(setshi/10)*16+setshi%10);
				Write_Ds1302_Byte(0x8e,0x80);
			}
}
void Timer0Init(void)		//1ms,STC生成
{
	EA=1;ET0=1;//这两个启动一定要加,否则不生效
	AUXR |= 0x80;		//
	TMOD &= 0xF0;		//
	TMOD |= 0x01;		
	TL0 = 0xCD;		//赋初值
	TH0 = 0xD4;		
	TF0 = 0;		//清除标志位
	TR0 = 1;		//启动T0
}

void time0()interrupt 1
{
    TL0 = 0xCD;		//可以不要,会自动重载的
	TH0 = 0xD4;		
	keycount++;
	if(keycount==10)
	{
		keyflag=1;
		keycount=0;
	}//10ms扫描一次键盘
	P2=0xc0;P0=adress[i];P2=0x00;
	P2=0xe0;P0=display_num[buff[i]];P2=0x00;
	i++;
	if(i==8)
		i=0;
}
void set_sfm(uchar shi,uchar fen,uchar miao)//发送时分秒
{
	Write_Ds1302_Byte(0x8e,0);
	Write_Ds1302_Byte(0x80,(miao/10)*16+miao%10);
	Write_Ds1302_Byte(0x82,(fen/10)*16+fen%10);
	Write_Ds1302_Byte(0x84,(shi/10)*16+shi%10);
	Write_Ds1302_Byte(0x8e,0x80);
}
void main()
{
	init();
	Timer0Init();
	set_sfm(23,59,50);//初始化时间
	while(1)
	{	
		readtime();//读取时间
		if(keyflag)
		{
			readkey();
			key_function();	
		}
	}
}

此题需要注意,启停,还有bcd码转化,还有秒位的控制。显示部分,按键部分都很常规。

上一篇:蓝桥杯——DS1302时钟


下一篇:ESP8266 SDK开发: 外设篇-时钟芯片DS1302使用和拓展知识的使用