秒表(定时器扫秒按键数码管)

主函数

#include <REGX52.H>
#include "Timer0.h"
#include "Delay.h"
#include "Nixie.h"
#include "I2C.H"
#include "AT24C02.H"

unsigned char KeyNum;
unsigned char Min,Sec ,MiniSec;
unsigned char RunFlag;


void main()
{
	Timer0_Init();
	while(1)
	{
		KeyNum = Key();
		if(KeyNum == 1)			 //K1按键按下
		{
			RunFlag = !RunFlag;  //启动标志位翻转
			
		}
		
		if(KeyNum == 2)			 //K2按键按下
		{
			Min = 0;			 //分秒清0
			Sec = 0;
			MiniSec = 0;
		}
		
		if(KeyNum == 3)			//K3按键按下
		{
			AT24C02_WriteByte(0,Min);		//将分秒写入AT24C02
			Delay(5);
			AT24C02_WriteByte(1,Sec);
			Delay(5);
			AT24C02_WriteByte(2,MiniSec);
			Delay(5);
		}
		
		if(KeyNum == 4) 		//K4按键按下
		{
			Min = AT24C02_ReadByte(0);		//读出AT24C02数据
			Sec = AT24C02_ReadByte(1);
			MiniSec = AT24C02_ReadByte(2);
		}
		Nixie_SetBuf(1,Min/10);			//设置显示缓存,显示数据
		Nixie_SetBuf(2,Min%10);
		Nixie_SetBuf(3,11);
		
		Nixie_SetBuf(4,Sec/10);
		Nixie_SetBuf(5,Sec%10);
		Nixie_SetBuf(6,11);
		
		Nixie_SetBuf(7,MiniSec/10);
		Nixie_SetBuf(8,MiniSec%10);
	}
}

/**
  * @brief  秒表驱动函数,在中断中调用
  * @param  无
  * @retval 无
  */

void Sec_Loop(void)
{
	if(RunFlag)
	{
		MiniSec++;
		if(MiniSec >= 100)
		{
			MiniSec = 0;
			Sec++;
			
			if(Sec>=60)
			{
				Sec = 0;
				Min++;
				if(Min >= 60)
				{
					Min = 0;
				}
			}
		}
	}
	
}

// 定时器中断函数模板
void  Timer0_Routine() interrupt 1
{
	static unsigned int T0Count1, T0Count2 ,T0Count3;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count1++;
	if(T0Count1 >= 20)
	{
		T0Count1 = 0;
		Key_Loop();	//20ms调用一次按键驱动函数
	}
	
	
	T0Count2++;
	if(T0Count2 >= 2)
	{
		T0Count2 = 0;
		Nixie_Loop();	//2ms调用一次数码管驱动函数
	}
	
	
	T0Count3++;
	if(T0Count3>=10)
	{
		T0Count3=0;
		Sec_Loop();	//10ms调用一次数秒表驱动函数
	}
}

独立按键(key)

#ifndef __Key_H__
#define __Key_H__
	
	unsigned char Key(void);
	void Key_Loop(void);
#endif
#include <REGX52.H>
#include "Delay.H"


unsigned char Key_KeyNumber;


/**
  * @brief  获取按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0,1~4,0表示无按键按下
  */
unsigned char Key(void)
{
	unsigned char Temp;
	Temp = Key_KeyNumber;
	Key_KeyNumber = 0;
	return Temp;
}


/**
  * @brief  获取当前按键的状态,无消抖及松手检测
  * @param  无
  * @retval 按下按键的键码,范围:0,1~4,0表示无按键按下
  */
unsigned char Key_GetState()
{
	unsigned char KeyNumber = 0;
	if(P3_1 == 0){KeyNumber = 1;}
	if(P3_0 == 0){KeyNumber = 2;}
	if(P3_2 == 0){KeyNumber = 3;}
	if(P3_3 == 0){KeyNumber = 4;}
	return KeyNumber;
}


/**
  * @brief  按键驱动函数,在中断中调用
  * @param  无
  * @retval 无
  */
void Key_Loop(void)
{
	static unsigned char NowState,LastState;
	LastState = NowState;					//按键状态更新
	NowState = Key_GetState();				//获取当前按键状态
	
	//如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测
	if(LastState == 1 && NowState == 0)
	{
		Key_KeyNumber = 1;
	}
	
	if(LastState == 2 && NowState == 0)
	{
		Key_KeyNumber = 2;
	}
	
	if(LastState == 3 && NowState == 0)
	{
		Key_KeyNumber = 3;
	}
	
	if(LastState == 4 && NowState == 0)
	{
		Key_KeyNumber = 4;
	}
}




I2C

#ifndef __I2C_H__
#define __I2C_H__

	void I2C_Start();
	void I2C_Stop();
	void I2C_SendByte(unsigned char Byte);
	unsigned char I2C_ReseveByte();
	void I2C_SendAck(unsigned char AckBit);
	unsigned char I2C_ReceiveAck();
		
#endif
#include <REGX52.H>


sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;


/**
  * @brief  I2C开始
  * @param  无
  * @retval 无
  */
void I2C_Start()
{
	I2C_SDA = 1;
	I2C_SCL = 1;
	I2C_SDA = 0;
	I2C_SCL = 0;
}


/**
  * @brief  I2C停止
  * @param  无
  * @retval 无
  */
void I2C_Stop()
{
	I2C_SDA = 0;
	I2C_SCL = 1;
	I2C_SDA = 1;
	I2C_SCL = 0;
}

/**
  * @brief  I2C发送一个字节
  * @param  Byte 要发送的字节
  * @retval 无
  */
void I2C_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i = 0;i<8;i++)
	{
		I2C_SDA = Byte & (0x80 >> i);
		I2C_SCL = 1;
		I2C_SCL = 0;
	}
}

/**
  * @brief  I2C接收一个字节
  * @param  无
  * @retval 接收到的一个字节数据
  */
unsigned char I2C_ReseveByte()
{
	unsigned char i,Byte = 0x00;
	I2C_SDA = 1;
	for(i = 0;i<8;i++)
	{
		I2C_SCL = 1;
		if(I2C_SDA){ Byte |= (0x80>>i);}
		I2C_SCL = 0;
	}
	
	return Byte;
}


/**
  * @brief  I2C发送应答
  * @param  AckBit 应答位,0为应答,1为非应答
  * @retval 无
  */
void I2C_SendAck(unsigned char AckBit)
{
	I2C_SDA = AckBit;
	I2C_SCL = 1;
	I2C_SCL = 0;
}


/**
  * @brief  I2C接收应答位
  * @param  无
  * @retval 接收到的应答位,0为应答,1为非应答
  */
unsigned char I2C_ReceiveAck()
{
	unsigned char AckBit;
	I2C_SDA = 1;
	I2C_SCL = 1;
	AckBit = I2C_SDA;
	I2C_SCL = 0;
	return AckBit;
}



存储器(AT24C02)
#ifndef __AT24C02_H__
#define __AT24C02_H__
	
	void AT24C02_WriteByte(unsigned char WordAddress,Data);
	unsigned char AT24C02_ReadByte(unsigned char WordAddress);
#endif
#include <REGX52.H>
#include "I2C.H"

#define AT24C02_ADDRESS 0xA0 //从机写地址


/**
  * @brief  AT24C02写入一个字节
  * @param  WordAddress 要写入字节的地址
  * @param  Data 要写入的数据
  * @retval 无
  */
void AT24C02_WriteByte(unsigned char WordAddress,Data)
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

/**
  * @brief  AT24C02读取一个字节
  * @param  WordAddress 要读出字节的地址
  * @retval 读出的数据
  */
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS | 0x01);
	I2C_ReceiveAck();
	Data = I2C_ReseveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}

时钟中断(Timer0)
#ifndef __TIMER0_H__
#define __TIMER0_H__
	
	void Timer0_Init();
#endif
#include <REGX52.H>


/**	
   * @brief 定时器初始化
   * @param 无
   * @retval 无
   */
void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
	PT0 = 0;
}



/* 定时器中断函数模板
void  Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count >= 1000)
	{
		T0Count = 0;
		
	}
	
}
*/

数码管(Nixie)
#ifndef __NIXIE_H__
#define __NIXIE_H__
 
void Nixie_Scan(unsigned char Location,Number);
void Nixie_SetBuf(unsigned char Location , Number);
void Nixie_Loop(void);

#endif
#include <REGX52.H>
#include "Delay.h"
//数码管显示缓存区
unsigned char Nixie_Buf[9] = {0,10,10,10,10,10,10,10,10};

//数码管段码表
unsigned char NixieTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};


/**
  * @brief  设置显示缓存区
  * @param  Location 要设置的位置,范围:1~8
  * @param  Number 要设置的数字,范围:段码表索引范围
  * @retval 无
  */
void Nixie_SetBuf(unsigned char Location , Number)
{
	Nixie_Buf[Location] = Number;
}

/**
  * @brief  数码管扫描显示
  * @param  Location 要显示的位置,范围:1~8
  * @param  Number 要显示的数字,范围:段码表索引范围
  * @retval 无
  */
void Nixie_Scan(unsigned char Location,Number)
{
	P0 = 0x00;   			//段码清0,消影
	switch(Location)   	 	//位码输出
	{ 
		case 1:P2_4 = 1;P2_3 = 1;P2_2 = 1;break;
		case 2:P2_4 = 1;P2_3 = 1;P2_2 = 0;break;
		case 3:P2_4 = 1;P2_3 = 0;P2_2 = 1;break;
		case 4:P2_4 = 1;P2_3 = 0;P2_2 = 0;break;
		case 5:P2_4 = 0;P2_3 = 1;P2_2 = 1;break;
		case 6:P2_4 = 0;P2_3 = 1;P2_2 = 0;break;
		case 7:P2_4 = 0;P2_3 = 0;P2_2 = 1;break;
		case 8:P2_4 = 0;P2_3 = 0;P2_2 = 0;break;
	}
	P0 = NixieTable[Number];		//段码输出
	
}


/**
  * @brief  数码管驱动函数,在中断中调用
  * @param  无
  * @retval 无
  */
void Nixie_Loop(void)
{
	static unsigned char i = 1;
	Nixie_Scan(i,Nixie_Buf[i]);
	i++;
	if(i>=9) {i=1;}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值