单片机蓝桥杯——定时中断实现数码管显示、按键判断

2023-10-26

1、1ms定时中断T0,控制数码管显示

(1) 关于中断

        关于定时中断的初始化函数可直接在STC-ISP软件上生成,如下图所示:

        

        注意:初始化函数中并没有打开EA和ET0,需要自己加上。

(2)关于数码管显示:

        数码管段码:

                segCode[0]~segCode[9]为0~9的段码(不带小数点);

                segCode[10]~segCode[19]为0~9的段码(带小数点);

                segCode[20]为数码管全灭的代码。

uchar segCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,       //0~9的段码(不带小数点)
                                 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭

        数码管显示数组:

                uchar segVal[] = {1,2,3,4,11,12,13,14};  //数码管初始化显示1 2 3 4 1. 2. 3. 4.

                直接更改数组里面的值便可以控制数码管显示,例如

                让数码管的第0位显示数字8:

 segVal[0]= 8;

        让数码管的第1位显示数字8(带小数点):

segVal[1] = 18;

         总代码如下:

#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sfr AUXR = 0x8e;	
uchar segCode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,       //0~9的段码(不带小数点)
								 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={1,2,3,4,11,12,13,14};  //数码管初始化显示1 2 3 4 1. 2. 3. 4.

void SelectHC573(uchar val) 
{
	switch(val)
	{
		case 4 : P2 = (P2 & 0x1f) | 0x80; break;
		case 5 : P2 = (P2 & 0x1f) | 0xa0; break;
		case 6 : P2 = (P2 & 0x1f) | 0xc0; break;
		case 7 : P2 = (P2 & 0x1f) | 0xe0; break;
		default: P2 = (P2 & 0x1f); break;		
	}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
	SelectHC573(5);
	P0 = 0xbf;      //由于不同板子的引脚接法不同,此时的初始值也不同
	SelectHC573(4);	
	P0 = 0xff;     //LED全灭
}


void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
uchar segFlag = 0;
void ServiceTimer0() interrupt 1
{
	uchar pushp0,pushp2;
	pushp0 = P0;
	pushp2 = P2;//入栈
	SelectHC573(6);
	P0 = (0x01<<segFlag);
	SelectHC573(7);	
	P0 = segCode[segVal[segFlag]];
	segFlag++;
	if(segFlag == 8) segFlag = 0;
	P2 = pushp2;//出栈
	P0 = pushp0;
}
void main()
{
	InitSystem();
	Timer0Init();
	while(1)
	{
		;
	}
}

2、1ms定时中断T0,检测按键按下(独立按键)

        当S4按下时,数码管第0位显示数字0;当S5按下时,数码管第0位显示数字1;

        当S6按下时,数码管第0位显示数字2;当S7按下时,数码管第0位显示数字3;

#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
sfr AUXR = 0x8e;	
uchar segCode[25]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,       //0~9的段码(不带小数点)
								 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={20,20,20,20,20,20,20,20};  //数码管初始化显示1 2 3 4 1. 2. 3. 4.

sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
void SelectHC573(uchar val) 
{
	switch(val)
	{
		case 4 : P2 = (P2 & 0x1f) | 0x80; break;
		case 5 : P2 = (P2 & 0x1f) | 0xa0; break;
		case 6 : P2 = (P2 & 0x1f) | 0xc0; break;
		case 7 : P2 = (P2 & 0x1f) | 0xe0; break;
		default: P2 = (P2 & 0x1f); break;		
	}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
	SelectHC573(5);
	P0 = 0xbf;      //由于不同板子的引脚接法不同,此时的初始值也不同
	SelectHC573(4);	
	P0 = 0xff;     //LED全灭
}

void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
uchar segFlag = 0;
uchar keySta[]  = {1,1,1,1}; //当前按键状态
uchar keyBack[] = {1,1,1,1};//按键值备份,保存前一次的值(上一次的按键状态)
uchar keyBuf[]  = {0xff,0xff,0xff,0xff};
void ServiceTimer0() interrupt 1
{
	uchar pushp0,pushp2,k;
	pushp0 = P0;
	pushp2 = P2;//入栈
//数码管
	SelectHC573(6);
	P0 = (0x01<<segFlag);
	SelectHC573(7);	
	P0 = segCode[segVal[segFlag]];
	segFlag++;
	if(segFlag == 8) segFlag = 0;
//按键检测	
	keyBuf[0] = (keyBuf[0]<<1) | S4;
	keyBuf[1] = (keyBuf[1]<<1) | S5;
	keyBuf[2] = (keyBuf[2]<<1) | S6;
	keyBuf[3] = (keyBuf[3]<<1) | S7;	
	for(k=0; k<4; k++)
	{
		if(keyBuf[k] == 0x00)
			keySta[k] = 0;
		else
			keySta[k] = 1;			
	}
	P2 = pushp2;//出栈
	P0 = pushp0;
}
void main()
{
	InitSystem();
	Timer0Init();
	while(1)
	{
//S4
		if(keySta[0] != keyBack[0])  //当前值与前次值不相等说明此时按键有动作(按下或弹起)
		{
			if(keySta[0] == 0)				//如果这一次值为 0,则说明当前是按下动作

			{
				segVal[0] = 0;					//数码管第0位显示0
			}
			keyBack[0] = keySta[0];		//更新前一次的备份
		}
//S5
		if(keySta[1] != keyBack[1])
		{
			if(keySta[1] == 0)
			{
				segVal[0] = 1;
			}
			keyBack[1] = keySta[1];
		}
//S6
		if(keySta[2] != keyBack[2])
		{
			if(keySta[2] == 0)
			{
				segVal[0] = 2;
			}
			keyBack[2] = keySta[2];
		}
//S7
		if(keySta[3] != keyBack[3])
		{
			if(keySta[3] == 0)
			{
				segVal[0] = 3;
			}
			keyBack[3] = keySta[3];
		}		
	}
}

   

3、1ms定时中断T0,检测按键按下(矩阵键盘)

        当按键按下时,数码管第0位显示行(0~3),数码管第1位显示显示列(0~3),例如,当第0行第1列有按键按下时,数码管第0位显示0,第1位显示1。在这个代码里用的是15的头文件STC15F2K60S2.h,此时不用单独定义AUXR寄存器。

#include "STC15F2K60S2.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
//sfr AUXR = 0x8e;	
uchar segCode[25]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,       //0~9的段码(不带小数点)
								 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xff}; //0.~9.的段码(带小数点) 以及0xff全灭
uchar segVal[]={20,20,20,20,20,20,20,20};  //数码管初始化显示1 2 3 4 1. 2. 3. 4.
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L4 = P3^4;
sbit L3 = P3^5;
sbit L2 = P4^2;
sbit L1 = P4^4;
void SelectHC573(uchar val) 
{
	switch(val)
	{
		case 4 : P2 = (P2 & 0x1f) | 0x80; break;
		case 5 : P2 = (P2 & 0x1f) | 0xa0; break;
		case 6 : P2 = (P2 & 0x1f) | 0xc0; break;
		case 7 : P2 = (P2 & 0x1f) | 0xe0; break;
		default: P2 = (P2 & 0x1f); break;		
	}
}
void InitSystem()//系统初始化关闭蜂鸣器、继电器、LED
{
	SelectHC573(5);
	P0 = 0xbf;      //由于不同板子的引脚接法不同,此时的初始值也不同
	SelectHC573(4);	
	P0 = 0xff;     //LED全灭
}
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}
uchar segFlag = 0;
uchar keySta[4][4]  = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //当前按键状态
uchar keyBack[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}};//按键值备份,保存前一次的值(上一次的按键状态)
uchar keyBuf[4][4]  = {{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};
uchar hang = 0;  //扫描行标志位
void ServiceTimer0() interrupt 1
{
	uchar pushp0,pushp2,k;
	pushp0 = P0;
	pushp2 = P2;//入栈
//数码管
	SelectHC573(6);
	P0 = (0x01<<segFlag);
	SelectHC573(7);	
	P0 = segCode[segVal[segFlag]];
	segFlag++;
	if(segFlag == 8) segFlag = 0;
	switch(hang)//根据扫描行标志位,释放当前输出引脚,拉低下次的输出引脚
	{
		case 0: H1 = 0; H4 = 1; break;
		case 1: H2 = 0; H1 = 1; break;
		case 2: H3 = 0; H2 = 1; break;
		case 3: H4 = 0; H3 = 1; break;		
	}	
//将一行的 4 个按键值移入缓冲区,hang=0,1,2,3
	keyBuf[hang][0] = (keyBuf[hang][0]<<1) | L1;
	keyBuf[hang][1] = (keyBuf[hang][1]<<1) | L2;
	keyBuf[hang][2] = (keyBuf[hang][2]<<1) | L3;
	keyBuf[hang][3] = (keyBuf[hang][3]<<1) | L4;	
	for(k=0; k<4; k++)//每行 4 个按键,所以循环 4 次
	{
		if(keyBuf[hang][k] == 0x00)			//连续8次扫描值为0,可认为按键已稳定的按下
			keySta[hang][k] = 0;
		else if(keyBuf[hang][k] == 0xff)//连续8次扫描值为 1,可认为按键已稳定的弹起
			keySta[hang][k] = 1;			
	}
//执行下一次的扫描输出
	hang++;									//扫描行标志位加一
	if(hang == 4) hang = 0;
	P2 = pushp2;//出栈
	P0 = pushp0;
}
void main()
{
	InitSystem();
	Timer0Init();
	while(1)
	{
		uchar i,j;
//如果有按键按下,则数码管显示按键值
		for(i=0; i<4; i++)
		{
			for(j=0; j<4; j++)
			{
				if(keySta[i][j] != keyBack[i][j]) 
				{
					if(keySta[i][j] == 0)				//如果这一次值为 0,则说明当前是按下动作
					{
						segVal[0] = i;					//数码管第0位显示i,即行值
						segVal[1] = j;					//数码管第1位显示j,即列值
					}
				keyBack[i][j] = keySta[i][j];		//更新前一次的备份
				}	
			}
		}
	}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

单片机蓝桥杯——定时中断实现数码管显示、按键判断 的相关文章

  • linux 在服务器上挂硬盘,linux如何挂载硬盘linux服务器上挂载磁盘(图文详解)...

    博主最近在研究服务器运维 由于Linux服务器相对比较困难 所以博主对她情有独钟 而window服务器几乎跟我们平常使用的电脑一样 相对简单感觉索然无味 下面正式进入主题教大家linux如何挂载硬盘 首先解答一个新手朋友都会问的问题 而且这
  • Inno setup Run Win7管理员运行属性

    runascurrentuser If this flag is specified the spawned process will inherit Setup Uninstall s user credentials typically
  • 《Angular2入门系列实践》——实现页面动画效果

    前言 在前端的路上越走越远 也希望利用angular2使自己的页面效果更加美观 所以从官网上学习了一下 内容 1 写animation ts import animate AnimationEntryMetadata state style
  • leetcode暴力屎山代码(一)——leetcode4

    题目 给定两个大小分别为 m 和 n 的正序 从小到大 数组 nums1 和 nums2 请你找出并返回这两个正序数组的 中位数 思路 由于两数组是有序排列的 所以可以通过计算两个数组中位数的索引 mid 并通过双指针从左到右遍历找到第mi
  • 重学webpack5——生产环境配置

    目录 前言 一 CSS文件 1 提取css 成单独文件 2 CSS兼容性处理 3 压缩CSS 二 Js文件 1 JS语法检查eslint 2 JS兼容性处理 3 JS压缩 三 HTML文件 四 生产环境总结 前言 生产环境是能让代码优化上线
  • selenium应用

    Selenium 学习参考 http selenium python readthedocs io 自动化测试工具 它支持各种浏览器 包括 Chrome Safari Firefox 等主流界面式浏览器 如果在这些浏览器里面安装一个 Sel
  • Elasticsearch RestHighLevelClient API 使用总结

    Elasticsearch RestHighLevelClient API 使用总结 题记 深秋初冬的一个晚上 突然间收到业务一个需求 要在老系统上使用新系统Elasticsearch库的数据 目前项目情况 新 老系统并行运行 根据产品 渠
  • 关于ftp上传文件系统时间差8个小时的时区问题

    2022年5月20日09 14 28 昨天上传代码出现一个奇怪的问题 就是视图缓存一直不更新 一开始以为是解析层waf的缓存不更新 导致waf不更新的原因是因为代码层的生产的视图缓存不更新 导致代码层的缓存不更新的是 就是ftp上传时间和服
  • git php 代码检查,gitlab下对php代码进行检测

    我们都知道 有一个世界上最好的语言 但在实际项目中也要考虑下历史的进程 避免一些错误导致程序无法运行 比如语法上的错误 所以我们要对代码进行检测 实现这个目标需要解决几个问题 什么时候检测代码 并拒绝异常代码的提交 以什么做标准 通过什么工

随机推荐

  • Latex公式太长,换行的两种方式

    latex中公式进行换行 begin equation begin aligned Ttran i j j 1 frac R bd j j 1 ij AR bd j j 1 ij times T ideal tran ij v u in l
  • 2020年总结:互联网思维下的工业软件开发

    2020年的年终总结像往年一样如期而至 今年是个特殊的年份 疫情爆发 全国人民众志成城 支援武汉 把武汉疫情完美控制 接下来经历了一个整年的抗疫生活 见证了一个个门店的倒下 站起 一个个公司申请破产 又一个个公司申请登记注册 这一个年 见证
  • fread函数解析

    fread函数解析 1 size t fread void buffer size t elementsize size t count FILE stream return fread s buffer SIZE MAX elements
  • 微信小程序纯css实现一个弹出的菜单

    1 实现效果 2 实现原理 animation动画 transform属性 rotateZ translate 3 实现代码
  • 必读:学习C语言编程的路线图

    学习C语言编程 可以丰富编程思维的训练和经验 以下是一些学习C语言编程的路线图 设置开发环境 在计算机上安装C编译器 GNU编译器集合 GCC 是一个流行的选择 适用于Windows macOS和Linux等各种操作系统 安装IDE编程环境
  • 数据清洗方法

    来源 我是码农 转载请保留出处和链接 本文链接 http www 54manong com id 1220 1 数据错误 脏数据或错误数据 比如 温度 2003 数据不正确 0 代表真实的0还是代表缺失 数据不一致 2 删除重复值 删除重复
  • Shell脚本——条件语句

    shell脚本 编程条件语句 条件测试 if语句 case分支语句 一 条件测试 1 1 Test命令 1 2 文件测试 1 3整数值比较 1 4字符串比较 1 5逻辑测试 二 if语句 2 1 单分支结构 2 2双分支结构 2 3多分支结
  • Eclipse 语言包下载

    1 登陆http www eclipse org babel downloads php 选择你的eclipse版本 2 找到IDE中文补丁包 INDIGO的地址如下 http download eclipse org technology
  • Maven(六) eclipse 使用Maven deploy命令部署构建到Nexus

    转载于 http blog csdn net jun55xiu article details 43051627 1 应用场景 SYS UTIL 系统工具 项目部署 构建成JAR包 SYS UTIL XXX jar 存储到Nexus私服上
  • spring boot 使用application.properties 进行外部配置

    application properties大家都不陌生 我们在开发的时候 经常使用它来配置一些可以手动修改而且不用编译的变量 这样的作用在于 打成war包或者jar用于生产环境时 我们可以手动修改环境变量而不用再重新编译 spring b
  • python里的pypi是干什么用的_【python工具篇】pip和pypi

    PyPI the Python Package Index The Python Package Index is a repository of software for the Python programming language T
  • HTTP中GET,POST和PUT的区别

    一 HTTP中定义了以下几种请求方法 1 GET 2 POST 3 PUT 4 DELETE 5 HEAD 6 TRACE 7 OPTIONS 二 各个方法介绍 1 GET方法 对这个资源的查操作 2 DELETE方法 对这个资源的删操作
  • 电脑检测不到第二个显示器的解决方法

    一般是因为显示适配器被失效了 右击开始菜单 选择 设备管理器 再选择 显示适配器 这时图标上一般会带上感叹号 右击后选择禁用 再选择启用就能检测到第二个显示器
  • 第一个跑马灯实验

    如何新建一个工程 1 打开工程模板 删除其他不重要的库文件 把main 函数里的内容删除 不用的外设固件库文件可以删掉 节省编译时间 rcc 时钟使能 usart 串口 复用映射 setbits 设置高电平 resetbits 低电平 2
  • 「PAT甲级真题解析」Advanced Level 1006 Sign In and Sign Out

    PAT Advanced Level Practice 1006 Sign In and Sign Out 如果对你有帮助 要点个赞让我知道喔 文章目录 问题分析 完整描述步骤 伪代码描述 完整提交代码 问题分析 题目给出一组学生进入机房的
  • 计量经济学及Stata应用 陈强 第八章自相关习题8.3

    8 3使用数据集gasoline dta估计美国1953 2004年的汽油需求函数 考虑如下回归 其中 被解释变量lgasq为人均汽油消费量的对数 解释变量lincome为人均收入的对数 lgasp为汽油价格指数的对数 lpnc为新车价格指
  • ROS建模仿真(1)-创建机器人模型

    ROS建模仿真 1 创建机器人模型 创建catkin creat pkg功能包 创建机器人描述文件 创建launch文件 创建catkin creat pkg功能包 创建机器人描述文件 创建launch文件 创建catkin creat p
  • Mac OS上使用ffmpeg的“血泪”总结

    标题真不是夸张 这几天在整理视频相关的处理流程 为了获得一些性能数据 打算在自己的MacBook Pro 上面装ffmepg 这一折腾4 5天就过去了 有些问题 在解决之后就豁然开朗了 没有解决之前 真的是百思不得其解 中间就好像隔着一层纱
  • AF_INET和AF_PACKET区别

    http blog csdn net kzm2008 article details 5372834 man 7 ip man 7 packet Packet sockets are used to receive or send raw
  • 单片机蓝桥杯——定时中断实现数码管显示、按键判断

    1 1ms定时中断T0 控制数码管显示 1 关于中断 关于定时中断的初始化函数可直接在STC ISP软件上生成 如下图所示 注意 初始化函数中并没有打开EA和ET0 需要自己加上 2 关于数码管显示 数码管段码 segCode 0 segC