【STC15F2K60S2学习笔记】练习一.时钟及其设置功能实现

写在前面

        经过一段时间的学习,我们已经学会了基本C51语言的逻辑及框架,现在让我们来实现第一个有实际意义的程序吧

一、要求

        定义矩阵键盘S5为闹钟设置界面,按下后进入闹钟设置界面

        定义矩阵键盘S6为时钟设置界面,按下后进入时钟设置界面

        定义矩阵键盘S7为时钟显示按键,按下后进入时钟显示界面

        定义矩阵键盘S8为数加按键,处于设置模式时对当前设置位减一

        定义矩阵键盘S9为数加按键,处于设置模式时对当前设置位增一

        定义矩阵键盘S10为位减按键,处于设置模式时切换上一个设置位

        定义矩阵键盘S11为位加按键,处于设置模式时切换下一个设置位

        定义矩阵键盘S16为数加按键,处于设置模式时保存当前设置

二、实现思路

1.组成部分

        定时器、按键处理、数码管处理、蜂鸣器处理、中断服务、主函数

2.思路

        按键处理把按键输入转成Key_void,检测下降沿给Key_down,通过switch语句把按键输入功能对印上,用Seg_mod区分数码管显示状态,通过按键输入改变Seg_mod,设置三种状态,分别是:0-时钟显示、1-时钟设置、2-闹钟设置,用临时变量Seg_set存储设置数据,在按下设置按键(S6、S5)时把时钟数据或闹钟数据赋值给Seg_set,设置完成后按下保存(S16),将Seg_set赋值给时钟数据或者闹钟数据,当Clock==Seg_time时,使能蜂鸣器

三、代码

1.头文件
Seg.h(位选、段选)
#include "Seg.h"

unsigned char code Seg_duan[] = {
                                0xc0,0xf9,0xa4,0xb0,0x99,//0~5
							    0x92,0x82,0xf8,0x80,0x90,//6~10
								0x88,0x83,0xc6,0xa1,0x86,//A~E
								0x8e,0xbf,0x7f,0x00,0xff,//F,-,.
								0x40,0x79,0x24,0x30,0x19,//0~5
								0x12,0x02,0x78,0x00,0x10,//6~10
								0x08,0x03,0x46,0x21,0x06,//A~E
								0x0e//F
								};
unsigned char code Seg_dian[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e}; 
unsigned char code Seg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

void Seg_disp(unsigned char wei,duan)
{
	//消影
	P2=(P2&0x1f)|0xc0;
	P0=0x00;
	P2&=0x1f;

	//段选
	P2=(P2&0x1f)|0xe0;
	P0=Seg_duan[duan]; 
	P2&=0x1f;

	//位选
	P2=(P2&0x1f)|0xc0;
	P0=Seg_wei[wei];
	P2&=0x1f;
}
Key.h(矩阵键盘)
#include "Key.h"

void Delay_ms(int xms)	//15单片机延时函数
{
	int i;
	long a;
	for (i = xms; i > 0; i --)
		for(a = 810; a > 0; a --);
}
 
unsigned char Key_read()
{
	unsigned char KeyNumber = 0;
	unsigned char temp;
	
	//第一列
	P3 = 0x7F;	//P37 = 0,其他是1,检测第一列
	P4 = 0xEF;	//P44 = 0; P42 = 1;	//15单片机第一列占用的引脚
	temp = P3;	//按键检测,输入
	temp &= 0x0F;
	if(temp != 0x0F)
	{
		Delay_ms(20);	//延时20ms来确认是否真正按下按键
		temp = P3;
		temp &= 0x0F;//检测是第一列哪个按键
		if(temp != 0x0F)
		{
			temp = P3;
			switch (temp)
			{
				case 0x7E : KeyNumber = 7; break;
				case 0x7D : KeyNumber = 6; break;
				case 0x7B : KeyNumber = 5; break;
				case 0x77 : KeyNumber = 4; break;
			}
			while(temp != 0x0f)
			{
				temp = P3;
				temp &= 0x0F;	//因为这条,所以松手检测才写成 temp != 0x0f
			}
		}
		
	}
	
	//第二列
	P3 = 0xBF;
	P4 = 0xFB;	//P42 = 0; P44 = 1;	//15单片机第二列占用的引脚	
	temp = P3;
	temp &= 0x0F;
	if(temp != 0x0F)
	{
		Delay_ms(20);
		temp = P3;
		temp &= 0x0F;
		if(temp != 0x0F)
		{
			temp = P3;
			switch (temp)
			{
				case 0xBE : KeyNumber = 11; break;
				case 0xBD : KeyNumber = 10; break;
				case 0xBB : KeyNumber = 9; break;
				case 0xB7 : KeyNumber = 8; break;
			}
			while(temp != 0x0f)
			{
				temp = P3;
				temp &= 0x0F;	//因为这条,所以松手检测才写成 temp != 0x0f
			}
		}	
	}
	
	//第三列
	P3 = 0xDF;	
	P4 = 0xFF;
	temp = P3;
	temp &= 0x0F;
	if(temp != 0x0F)
	{
		Delay_ms(20);
		temp = P3;
		temp &= 0x0F;
		if(temp != 0x0F)
		{
			temp = P3;
			switch (temp)
			{
				case 0xDE : KeyNumber = 15; break;
				case 0xDD : KeyNumber = 14; break;
				case 0xDB : KeyNumber = 13; break;
				case 0xD7 : KeyNumber = 12; break;
			}
			while(temp != 0x0f)
			{
				temp = P3;
				temp &= 0x0F;	//因为这条,所以松手检测才写成 temp != 0x0f
			}
		}	
	}	
	
	//第四列
	P3 = 0xEF;	
	temp = P3;
	temp &= 0x0F;
	if(temp != 0x0F)
	{
		Delay_ms(20);
		temp = P3;
		temp &= 0x0F;
		if(temp != 0x0F)
		{
			temp = P3;
			switch (temp)
			{
				case 0xEE : KeyNumber = 19; break;
				case 0xED : KeyNumber = 18; break;
				case 0xEB : KeyNumber = 17; break;
				case 0xE7 : KeyNumber = 16; break;
			}
			while(temp != 0x0f)
			{
				temp = P3;
				temp &= 0x0F;	//因为这条,所以松手检测才写成 temp != 0x0f
			}
		}	
	}
	
	return KeyNumber;
}
Seg.c
#include <stc15f2k60s2.h>

void Seg_disp(unsigned char wei,duan);
Key.c
#include <stc15f2k60s2.h>

unsigned char Key_read();
2.主函数
/* 头文件声明 */
#include <stc15f2k60s2.h>
#include "Key.h"
#include "Seg.h"

/* 定义 */
#define uint unsigned int
#define uchar unsigned char

/* 变量声明 */
uchar Key_slow;//10ms
uchar Key_val,Key_down,Key_old=0;//按键扫描
uchar Seg_pos;
uchar Seg_buf[8];//位选,段选
uchar Seg_mod=0;//数码管模式 0-显示,1-设置2-,闹钟
uchar Seg_time[3]={23,59,55};
uchar Seg_set[3];
uchar Clock[3]={00,00,00};

char Blink_index=0;//0-时,1-分,2-秒

uint Timer_1000ms=0;
uint Timer_500ms=0;
uint Seg_slow;//500ms

bit Blink_flag;

/* 函数声明 */
void Key_proc();//按键处理
void Seg_proc();
void Other_proc();
void Timer0_init();
void Timer0_ISR();
void Buzz();

/* 代码 */
int main()//主函数
{
	Timer0_init();
	while(1)
	{
		Key_proc();
		Seg_proc();
		Other_proc();
	}
}

void Key_proc()//按键处理
{
	if (Key_slow) return;
	Key_slow=1;
	
	Key_val=Key_read();
	Key_down=Key_val&(Key_val^Key_old);//捕捉下降沿
	Key_old=Key_val;//辅助扫描
	
	switch(Key_down)
	{
		case 7://数码管显示界面
			Seg_mod=0;
		break;
		case 6://时间设置界面
			Seg_set[0]=Seg_time[0];
			Seg_set[1]=Seg_time[1];
			Seg_set[2]=Seg_time[2];
			Seg_mod=1;
		break;
		case 11://位增
			if(Seg_mod==1||Seg_mod==2)
			{
				Blink_index++;
				if(Blink_index==3)
				{
					Blink_index=0;
				}
			}
		break;
		case 10://位减
			if(Seg_mod==1||Seg_mod==2)
			{
				Blink_index--;
				if(Blink_index==-1)
				{
					Blink_index=2;
				}
			}
		break;
		case 9://数增
			Seg_set[Blink_index]++;
			if(Seg_set[Blink_index]==(Blink_index==0?24:60))
			{
				Seg_set[Blink_index]=0;
			}
		break;
		case 8://数减
			Seg_set[Blink_index]--;
			if(Seg_set[Blink_index]==0)
			{
				Seg_set[Blink_index]=(Blink_index==0?23:59);
			}
		break;
		case 16://保存
			if(Seg_mod==1)
			{
				Seg_time[0]=Seg_set[0];
				Seg_time[1]=Seg_set[1];
				Seg_time[2]=Seg_set[2];
				Seg_mod=0;
			}
			if(Seg_mod==2)
			{
				Clock[0]=Seg_set[0];
				Clock[1]=Seg_set[1];
				Clock[2]=Seg_set[2];
				Seg_mod=0;
			}
		break;
		case 5:
			Seg_set[0]=Clock[0];
			Seg_set[1]=Clock[1];
			Seg_set[2]=Clock[2];
			Seg_mod=2;
	}
}

void Seg_proc()//数码管处理
{
	if (Seg_slow) return;
	Seg_slow=1;
	
	switch(Seg_mod)
	{
		case 0://时钟
			Seg_buf[0]=Seg_time[0]/10%10;
			Seg_buf[1]=Seg_time[0]%10;
			Seg_buf[2]=16;
			Seg_buf[3]=Seg_time[1]/10%10;
			Seg_buf[4]=Seg_time[1]%10;
			Seg_buf[5]=16;
			Seg_buf[6]=Seg_time[2]/10%10;
			Seg_buf[7]=Seg_time[2]%10;
		break;
		case 1://设置
			Seg_buf[0]=Seg_set[0]/10%10;
			Seg_buf[1]=Seg_set[0]%10;
			Seg_buf[2]=16;
			Seg_buf[3]=Seg_set[1]/10%10;
			Seg_buf[4]=Seg_set[1]%10;
			Seg_buf[5]=16;
			Seg_buf[6]=Seg_set[2]/10%10;
			Seg_buf[7]=Seg_set[2]%10;
			
			switch(Blink_index)
			{
				case 0:
					Seg_buf[0]=Blink_flag?Seg_set[0]/10%10:19;
					Seg_buf[1]=Blink_flag?Seg_set[0]%10:19;
				break;
				case 1:
					Seg_buf[3]=Blink_flag?Seg_set[1]/10%10:19;
					Seg_buf[4]=Blink_flag?Seg_set[1]%10:19;
				break;
				case 2:
					Seg_buf[6]=Blink_flag?Seg_set[2]/10%10:19;
					Seg_buf[7]=Blink_flag?Seg_set[2]%10:19;	
				break;
			}
		break;
		case 2://设置
			Seg_buf[0]=Seg_set[0]/10%10;
			Seg_buf[1]=Seg_set[0]%10;
			Seg_buf[2]=16;
			Seg_buf[3]=Seg_set[1]/10%10;
			Seg_buf[4]=Seg_set[1]%10;
			Seg_buf[5]=16;
			Seg_buf[6]=Seg_set[2]/10%10;
			Seg_buf[7]=Seg_set[2]%10;
			
			switch(Blink_index)
			{
				case 0:
					Seg_buf[0]=Blink_flag?Seg_set[0]/10%10:19;
					Seg_buf[1]=Blink_flag?Seg_set[0]%10:19;
				break;
				case 1:
					Seg_buf[3]=Blink_flag?Seg_set[1]/10%10:19;
					Seg_buf[4]=Blink_flag?Seg_set[1]%10:19;
				break;
				case 2:
					Seg_buf[6]=Blink_flag?Seg_set[2]/10%10:19;
					Seg_buf[7]=Blink_flag?Seg_set[2]%10:19;	
				break;
			}
		break;
	}
}

void Other_proc()//其他处理
{
	if(Clock[0]==Seg_time[0]&&Clock[1]==Seg_time[1]&&Clock[2]==Seg_time[2])
	{
		Buzz();
	}
}

void Timer0_init()//定时器0初始化函数
{
  // 设置定时器0工作方式,使用模式1
  TMOD &= 0xF0;  // 清零低四位
  TMOD |= 0x01;  // 设置定时器0为模式1

  // 设置定时器0的初值,使定时器定时时间为1ms
  TH0 = 252;  // 高八位
  TL0 = 223;  // 低八位

  // 启动定时器0
  TR0 = 1;

  // 允许定时器0中断
  ET0 = 1;
  EA = 1;  // 允许总中断
}

void Timer0_ISR() interrupt 1 //中断服务函数
{
	TH0 = 252;
  TL0 = 223;
	if(++Key_slow==10)Key_slow=0;
	if(++Seg_slow==500)Seg_slow=0;
	if(++Seg_pos==8)Seg_pos=0;
	Seg_disp(Seg_pos,Seg_buf[Seg_pos]);
	Timer_1000ms++;
	if(Timer_1000ms==1000)//1s标志位
	{
		Timer_1000ms=0;
		Seg_time[2]++;
		if(Seg_time[2]==60)
		{
			Seg_time[2]=0;
			Seg_time[1]++;
			if(Seg_time[1]==60)
			{
				Seg_time[1]=0;
				Seg_time[0]++;
				if(Seg_time[0]==24)
				{
					Seg_time[0]=0;
				}
			}
		}
	}
	Timer_500ms++;
	if(Timer_500ms==500)
	{
		Timer_500ms=0;
		Blink_flag^=1;
	}
}

void Buzz()
{
	P2 = (P2&0x1f)|0xa0;//101 Buzz
}

四、上电效果图


無限進步

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这里是扁芒吖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值