51单片机学习笔记,简易时钟

阅读更多

使用芯片STC89C52RC, 2个锁存器

6个带小数点共阴极数码管显示一个24时制时钟

没有时钟芯片,所以掉电后时间会复位

原理图为TX-1C开发板

 

暂时显示了半小时,一秒不差,

未验证有无其他bug,代码贴上来,欢迎高手指点

 

 

==============================

最终显示的<时.分.秒>是 16.31.37  形式

#include 
#include "MY51.H"

void show();
uint8  shi=15;   //初始时间15:45:00  按复位按钮对时
uint8  fen=45;
uint8  miao=0;

void main() 	
{
	startT0(1000);  //开始定时器
	while(1)
	{		
		show();
	}
}

void show()  //显示时钟
{
	uint8 oneWela,twoWela,threeWela,foreWela,fiveWela,sixWela; //oneWela是最左边的数码管
	sixWela =miao%10;
	fiveWela=miao/10;	
	foreWela=fen%10;
	threeWela=fen/10;
	twoWela=shi%10;
	oneWela=shi/10;
	displaySMG(oneWela,twoWela,threeWela,foreWela,fiveWela,sixWela,0xf5); //0xf5小数点位置
}

void T0_Work()  //T0定时器调用的工作函数
{  
   miao++;
	if(miao>59)
	{
		miao=0;
		fen++;
	}

	if(fen>59)
	{
		fen=0;
		shi++;
	} 
	
	if(shi>23)
	{
		shi=0;
	}
}


 

 

#ifndef _MY51_H_
#define _MY51_H_
#include 
#include 

typedef int   				int16  ;
typedef int   				INT16  ;
typedef unsigned int    uint16 ;
typedef unsigned int    UINT16 ;
typedef unsigned short  uint ;
typedef unsigned short  UINT ;
typedef unsigned short  word ;
typedef unsigned short  WORD ;
typedef unsigned long   uint32 ;
typedef unsigned long   UINT32 ;
typedef unsigned long   DWORD ;
typedef unsigned long   dword ;
typedef signed long	   int32	 ;
typedef signed long	   INT32  ;
typedef float		    	    float32	 ;
typedef double		    	double64  ;
typedef signed char		int8 ;
typedef signed char 		INT8 ;
typedef unsigned char	byte ;
typedef unsigned char    BYTE 	 ;		//WINDOWS的windef.h里面是这么定义的
typedef unsigned char	uchar ;
typedef unsigned char	UCHAR ;
typedef unsigned char	UINT8 ;
typedef unsigned char	uint8 ;
typedef unsigned char	BOOL	 ;		//windows中定义BOOL为int
typedef unsigned char	bool	 ;		    //bool是c++的内置类型

#define TRUE     1
#define true     1
#define FALSE    0
#define false    0

#define open     1    //open和close用于 标志打开和关闭状态
#define OPEN     1
#define close    0
#define CLOSE    0
#define lock     0
#define start    1
#define START    1
#define stop     0
#define STOP     0

uint8    dulaIndex=0;     	//数码管0~F段编码索引号
uint8    welaIndex=0;     	//0~5位的数码管位索引号

sbit dula =P2^6;  //段选锁存器控制  控制笔段
sbit wela =P2^7;  //位选锁存器控制  控制位置

#define led P1    //灯总线控制
sbit led0=P1^0;   //8个led灯
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit led4=P1^4;
sbit led5=P1^5;
sbit led6=P1^6;
sbit led7=P1^7;
sbit keyS2=P3^4; //4个独立按键
sbit keyS3=P3^5;
sbit keyS4=P3^6;
sbit keyS5=P3^7;

void displaySMG(uint8 one,uint8 two,uint8 three,uint8 four,uint8 five,uint8 six,uint8 dot); 
void delayms(uint16 ms);
void T0_Work();
//////////////////////////////////////////////////////////////////////////
void delayms(uint16 ms)  //软延时函数
{
	uint16 i,j;
	for(i=83;i>0;i--)
	{
        for(j=ms;j>0;j--)
        {}
	}
}

///////////////////////////////////////////////////////////////////////////
#define dark	0x11  //也就是索引第17号元素0x00,共阴极数码管正极全部输入低电平
uint8 code table[]= { 			//0~F外加小数点和空输出的数码管编码
 0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
 0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
 0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
 0x39 , 0x5e , 0x79 , 0x71 , // C D E F
 0x80 , 0x00                 // . 空     空时是第0x11号也就是第17号元素
 };

/////////////////////////////////////////////////////////////////////////////
uint8   TH0Cout=0 ;	    //初值	
uint8   TL0Cout=0 ;	   
uint16  T0IntCout=0;     //中断计数
uint16  T0IntCountAll=0; //(N-1)/65536+1;  //总中断次数
bool    bT0Delay=false;  //使用延时函数标志,初始未用
bool    bT0Over=false; 	 //中断处理函数执行结果之一

void startT0(uint32 ms)  //开启定时器
{	
	float32   t=ms/1000.0;		   		 //定时时间
	double64    fox =11.0592*(pow(10,6));  //晶振频率
	uint32    N=(t*fox)/12 ; 				 //定时器总计数值

	TH0Cout =(65536-N%65536)/256;      	 //装入计时值零头计数初值
	TL0Cout =(65536-N%65536)%256;
	T0IntCountAll=(N-1)/65536+1;			 //总中断次数
	TMOD=TMOD | 0x01; 						 //设置定时器0的工作方式为1
	
	EA =open;   //打开总中断
	ET0=open;   //打开定时器中断

	TH0=TH0Cout;  //定时器装入初值
	TL0=TL0Cout;
	TR0=start;	 //启动定时器
}

void delayT0(uint32 ms)		//硬延时函数,自己乱写的不好用,求指点
{
	startT0(ms);				//启动定时器
	bT0Delay=true;    		//告诉T0定时器,起用延时模式
	while(bT0Over==false);	//时间没到的话继续检测
	bT0Over=false;				//时间到了,让标志复位
}

void T0_times() interrupt 1 //T0定时器中断函数
{
	T0IntCout++;
	if(T0IntCout==T0IntCountAll)  //达到总中断次数值
	{	
		T0IntCout=0; 		 //中断次数清零,重新计时
		bT0Over=true;     //时间真的到了
		if(bT0Delay)			 //本次中断是用来延时的吗
		{
			TR0=stop; 		 //如果是由延时函数开启T0的话,关闭T0
			return;
		}

		TH0=TH0Cout;   		//循环定时的话要重装初值,每次定时1秒,重装一次
		TL0=TL0Cout;
		T0_Work();     		   //工作函数
	}
}

////////////////////////////////////////////////////////////////////////////////
void displaySMG(uint8 oneWela,uint8 twoWela,uint8 threeWela,uint8 fourWela,uint8 fiveWela,uint8 sixWela,uint8 dot)
{		//控制6位数码管显示函数,不显示的位用参数 dark
		dula=1;			//小数点
		P0=table[16];
		dula=0;
		P0=0xff;
		wela=1;
		P0=dot;        
		wela=0;
		delayms(1);

         dula=1;
		P0=table[oneWela];   //送段数据
		dula=0;
		P0=0xff;	//送位数据前关闭所有显示,防止打开位选锁存后段选数据通过位选锁存器
		wela=1;
		P0=0xfe;
		wela=0;
		delayms(1);

		dula=1;
		P0=table[twoWela];
		dula=0;
		P0=0xff;
		wela=1;
		P0=0xfd;
		wela=0;
		delayms(1);

		dula=1;
		P0=table[threeWela];
		dula=0;
		P0=0xff;
		wela=1;
		P0=0xfb;
		wela=0;
		delayms(1);

		dula=1;
		P0=table[fourWela];
		dula=0;
		P0=0xff;
		wela=1;
		P0=0xf7;
		wela=0;
		delayms(1);

		dula=1;
		P0=table[fiveWela];
		dula=0;
		P0=0xff;
		wela=1;
		P0=0xef;
		wela=0;
		delayms(1);

		dula=1;
		P0=table[sixWela];
		dula=0;
		P0=0xff;
		wela=1;
		P0=0xdf;
		wela=0;
		delayms(1);
}

#endif

 

你可能感兴趣的:(单片机,时钟)