用计数器中断实现100以内的按键计数
- 格式:doc
- 大小:448.50 KB
- 文档页数:5
51单⽚机:中断实现按键按⼀下数码管从00加到99循环(C语⾔)51单⽚机:中断实现按键按⼀下数码管从00加到99循环(C语⾔)
题⽬要求:
在51单⽚机上通过C语⾔编写代码,使⽤中断,按键按⼀下数码管上⾯的数字从00开始加1,实现00——99的循环
准备⼯作:
keil建⽴⼯程
proteus仿真验证
代码如下:
/*
*功能:⽤中断实现开关每按⼀次,数码管数字加⼀,
*实现00-99的循环
*/
#include<reg52.h>
sbit SEG1 = P1^0;//定义显⽰⼗位数码管
sbit SEG2 = P2^0;//定义显⽰个位数码管
sbit key = P3^2;//定义按键
int sum =0;
int i,j;
unsigned char code DSY_CODE[]={0xC0,0xF9,0xA4,
0xB0,0x99,0x92,
0x82,0xF8,0x80,0x90};//共阳极数码管
void main()
{
IE =0x81;//使⽤外部中断0
IT0 =1;
while(1);
}
void EX0_INT(void) interrupt 0
{
sum++;
i = sum/10;//⼗位数字
j = sum%10;//个位数字
if(sum ==100)
{
sum =0;
}
P1 = DSY_CODE[i];//数码管显⽰⼗位数字
P2 = DSY_CODE[j];//数码管显⽰个位数字
}
(写的不是很规范,仅供参考)
仿真结果:。
100进制减法计数器程序计数器一般都是用十进制数计数,但是在某些场景中,需要使用其他进制数进行计数。
100进制是一种常见的进制数,它的进制基数为100,每一位可以表示0-99的数字。
本文将介绍如何实现100进制的减法计数器程序。
首先,我们需要明确100进制的基本概念。
100进制一般可以使用两位来表示一个数位,例如45在100进制中可以表示成45,而120可以表示成1*100+20,即1020。
在程序中,我们可以用数组来表示100进制数,每一位用一个两位数来表示。
在实现减法计数器程序之前,我们需要先了解一下10进制减法的计算方法。
当我们做10进制减法时,如果被减数的某一位小于减数的对应位,我们需要从高位借位,并将被减数该位加上10,然后再计算减法。
在100进制中也是一样的,需要借位和进位操作。
下面,我们来看一下100进制减法计数器程序的具体实现。
首先,我们需要定义一个数组来表示计数器的值,例如:```int counter[4] = {0, 0, 0, 0}; //初始化为0```这个数组的长度为4,表示计数器能够计数的最大值为9999,因为100^4=10000。
接下来,我们定义一个函数来实现100进制减法:```void subtract(int* counter, int value) {int borrow = 0;for (int i = 3; i >= 0; i--) {int diff = counter[i] - (value % 100) - borrow;if (diff < 0) {diff += 100;borrow = 1;} else {borrow = 0;}counter[i] = diff;value /= 100;}}```这个函数接收一个计数器数组和一个减数,然后通过循环实现计数器减去减数的功能。
在每一次循环中,我们将被减的两个两位数相减,并考虑是否需要借位。
数字式100进制加减计数电路的工作原理及制作工作原理1、振荡与分频:晶振X1与集成电路ICl(4060)内部的非门电路共同产生32768Hz的方波信号,经IC1进行214分频后由IC1的13脚输出频率为2Hz的方波信号,再经IC2(集成触发器74LS73)分频一次,输出1Hz的方波信号作为计数器的计数脉冲,送入到个位计数器IC4进行计数。
振荡电路中的R1为反馈电阻;其数值较大(10MΩ)有利于提高振荡频率的稳定性。
电容C1、C2与晶体构成一个谐振型网络,实现对振荡频率的控制,同时提供180度相移,从而和IC1内部的非门构成一个正反馈网络满足振荡条件,使振荡电路正常电工作。
2、计数:计数电路由二块74LS190(IC4、IC5)构成个位和十位的计数。
IC4的13脚为进位输出端/借位输出端)与IC5的14脚(计数脉冲输入端)相连,完成个位向十位进位或借位的功能。
3、译码与显示:该部分电路由两块74LS48(IC6、IC7)和两个数码管组成,IC6对个位计数电路输出的8421BCD码进行译码驱动,数码管显示,IC7对十位计数电路输出8421BCD码进行译码驱动,数码管显示。
4、控制电路:主要由三个按钮SB1、SB2、SB3和一块双JK触发器74LS73构成。
①加法计数控制:接通电源的瞬间,由于电容C4两端的电压不能突变而为0,故IC3A、IC3B的CLR=O,故两触发器清零,即1Q=2Q=O,1Q=2Q=1,2Q=0送到IC2的CLR端,使其清零,此时IC2无计数脉冲输出到计数器74LS190,又因IC3B的Q(的反)=1,该信号送到74LS190的使能控制端(CTEN),则计数器工作在保持状态,故开机后,数码显示不变。
再按一次SB2,IC4、IC5的LOAD变为低水平,使IC4、IC5处于并行输入状态,同时因A=D=U/D=0,B=C=0,故IC4、IC5的QA=QB=QC=QD=0,故显示为00(置0),再按一次SB3(启动)使IC3B获得一个下降脉冲,则IC3B输出从O翻转为1,使IC2输出计数脉冲,送至IC4,同时因IC3B的Q(的反)转为0,则IC4、IC5的CTEN=0,此时虽然C4充电后变为高电平,但IC3A无下降脉冲触、发,故其Q保持为0,则U/D=0,。
单片机中断实现按键一、引言在嵌入式系统中,往往需要通过外部输入设备如按键来与系统进行交互。
为了能够及时响应按键操作,避免忙等的情况发生,通常会使用中断技术来实现按键的检测和处理。
本文将介绍如何使用中断来实现按键检测,并具体以8051单片机作为示例进行说明。
二、中断基础知识在单片机中,中断是一种由硬件触发的特殊事件,当一些中断条件满足时,单片机会暂停当前任务,跳转到中断服务程序中执行对应的处理代码,待中断处理结束后再返回到原来的任务中。
中断的触发方式一般有两种:外部触发中断和内部触发中断。
对于按键这种外部输入设备,一般通过外部触发中断来实现。
三、实现原理1、按键电路:按键通常由一个导电片和两个触点组成,平时靠两个触点之间的弹簧将导电片与触点隔开,当按下按键时,弹簧压缩,导电片与触点接触形成通路。
为了能够检测按键操作,需要将按键引脚连接到单片机的外部中断引脚上。
2、中断设置:在单片机的程序中,需要设置好相应的中断向量表和中断服务程序。
中断向量表是一个存放中断服务程序地址的表格,当中断触发时,单片机会根据中断号从中断向量表中找到相应的中断服务程序地址并跳转到该地址执行对应代码。
3、中断触发条件:在按键电路中,按键的两个触点状态变化(从断开到接通或从接通到断开)时会产生干扰信号,为了避免干扰,通常会使用软件消抖技术。
当按键被按下,并经过一段时间的消抖后,会产生一个稳定的按键信号,此时可以检测到按键变化,并触发相应的中断。
四、实现步骤1、硬件连接:将按键引脚连接到单片机的外部中断引脚上。
2、中断设置:在单片机的程序中,需要设置中断的相关寄存器,包括中断向量表和中断控制寄存器。
中断向量表保存中断服务程序的入口地址,中断控制寄存器用于设置中断触发条件和中断优先级等参数。
3、中断服务程序:编写中断服务程序,在按键中断触发时执行对应的处理代码。
中断服务程序一般需要包括中断触发条件的判断和处理代码的执行。
4、主程序:在主程序中调用中断服务程序,并添加相应的处理代码,实现按键操作的具体功能。
简述计数器的几种工作模式和内容
计数器是一种常见的数字电路模块,用于计数脉冲信号或时钟信号的计数。
常见的计数器工作模式包括:
1. 手动重置模式:计数器可以在手动重置按钮或者其他控制信号的作用下进行重置。
在这种模式下,计数器的计数器会从零开始重新计数。
2. 自动重置模式:计数器可以在外部信号的作用下自动进行重置。
在这种模式下,计数器的计数器会随着时间的流逝而从零开始重新计数。
3. 连续计数模式:计数器可以持续计数,不受外部信号的控制。
在这种模式下,计数器的计数器会随着时间的流逝而不断增加。
4. 暂停计数模式:计数器可以在外部信号的作用下暂停计数。
在这种模式下,计数器的计数器会停止计数,直到外部信号再次清零为止。
5. 单次计数模式:计数器可以进行一次计数,不受外部信号的控制。
在这种模式下,计数器的计数器会从零开始计数,并在计数完成后停止计数。
不同的计数器工作模式适用于不同的应用需求。
在设计和使用时,需要根据实际需要选择合适的计数器工作模式。
“按键计数”说明(一)设计思路和方法按键计数是通过按键来控制数据的加减然后在LED数码管上进行显示,其中涉及按键消抖,每1mS(可在不同TASK中改变)查看一次按键,如果在100mS、即100次中(由NMAX_KEY定义)中有2/3(N_KEY)以上按键按下,则认为按键有效按下。
一次有效按下,仅做一次动作。
动作设计在按键按下时执行(也可编成在在按键松开后执行),本实验是在按下时执行动作,key1对应加1,key2对应减1,key3对应清0。
(二)数字钟电路原理图(三)L ED数码管电路(左边部分)(四)(五)按键电路(六)(七)电路工作原理在实验2中已经分别说明了LED数码管的电路工作原理,在实验3中已经说明按键的电路工作原理,因此这里不再复述。
这里着重讲一下按键消抖过程,通过设定按键检测统计次数,每个一段时间去检测按键值是否为0,超过统计次数的较大比例,如2/3,我们则认为按键按下,然后通过对比按键上一个状态Key_P、当前状态Key_C来确定按键动作何时进行,下降沿操作Key_P、Key_C 组合10,上升沿操作Key_P、Key_C组合01等。
(八)程序总框图设计流程如下所示(九)(十)相关寄存器配置1. P0(8位)和P2.3需要设置成推挽输出,以驱动电路正常发光。
按键作为输入,不需推挽,涉及寄存器及配置值如下:P2M1=0x00;P2M0=0xff;P0M1=0x00;P0M0=0xff;P3M0=0x00;P3M1=0x00;P1M0=0x7f;2.P1M1=0x00;3.通过定时器0,采用方式1,在定时器中断中进行计数值的累加,涉及寄存器(含可位寻址)及配置如下:AUXR |= 0x80; //定时器时钟1T模式TMOD &= 0x80; //设置定时器模式TL0 = 0xAE; //设置定时初值TH0 = 0xFB; //设置定时初值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时IE=0x82;(十一)案例代码见“数字钟工程”(十二)测试方法1. 用STC ISP默认设置,打开工程中的HEX并下载2. 下载后观察现象为:左边3个数码管显示000,其他数码管均灭1.辅助操作:当显示为000,按下key2,显示255,在按下key2,显示254,每按一次key2,显示数字减1;按下key1,显示数字加1;按下key3,显示清零000。
一、实验目的1. 熟悉单片机中断系统的工作原理和中断响应过程。
2. 掌握使用外部中断实现单个按键控制的实验方法。
3. 学习通过编程设置中断源、中断优先级和中断服务程序。
二、实验原理单片机的中断系统允许CPU在执行程序的过程中,暂停当前程序的执行,转而处理由外部事件引起的中断请求。
在本实验中,我们使用外部中断0(INT0)来实现单个按键的控制。
当按键按下时,通过外部中断0引脚(P3.2)向CPU发送中断请求。
CPU响应中断后,暂停当前程序的执行,转而执行外部中断0的中断服务程序(ISR)。
在中断服务程序中,我们可以根据按键的状态来执行相应的操作,例如点亮或熄灭LED灯。
三、实验设备1. 单片机开发板(如STC89C52)2. 按键3. LED灯4. 连接线5. 仿真软件(如Keil uVision)四、实验步骤1. 硬件连接:- 将按键的一个引脚连接到单片机的P3.2引脚(外部中断0)。
- 将按键的另一个引脚连接到地(GND)。
- 将LED灯的正极连接到单片机的P1.0引脚,负极连接到地(GND)。
2. 编写程序:- 使用Keil uVision软件编写程序。
- 初始化外部中断0,设置中断优先级和中断服务程序。
- 编写中断服务程序,根据按键状态控制LED灯的亮灭。
3. 编译程序:- 使用Keil uVision软件编译程序,生成可执行文件。
4. 下载程序:- 将编译好的程序下载到单片机开发板上。
5. 运行程序:- 观察按键按下时LED灯的亮灭状态,验证中断功能是否正常。
五、实验代码```c#include <reg52.h>#define LED P1_0#define BUTTON P3_2void main(void) {EA = 1; // 开启总中断EX0 = 1; // 开启外部中断0IT0 = 1; // 设置外部中断0为下降沿触发while (1) {// 主循环,等待中断}}void ext0_isr(void) interrupt 0 {LED = !LED; // 切换LED灯状态}```六、实验结果与分析1. 实验结果:- 按键按下时,LED灯亮;按键释放时,LED灯灭。
LPC2138实验程序(尾部附有电路图)①实现键盘1中断(1~9数字),数码管1显示按键数字,同时用7个LED显示数码管1的相应位,即每个LED对应数码管相应位(a~g)。
②实现按键1中断,7个LED实现流水灯;实现按键2中断,7个LED实现跑马灯。
③实现按键3中断,7个LED闪烁10次,延时采用定时器#include <LPC213X.H>#define uchar unsigned charint k=0; //定时器中断计数器uchar a=0; //LED闪烁函数标志void delay(int x) //普通延时函数{int i;for(;x>0;x--)for(i=10000;i>0;i--);}void ms(unsigned int x) //定时器中断延时函数{T0TCR = 0X01;while(k!=x);T0TCR = 0X00;T0TC = 0;T0PC = 0;k=0;}void LED_1() //流水灯函数{unsigned char i;for(i=0;i<7;i++){IO1SET = 1<<(i+16);delay(20);IO1CLR = 1<<(i+16);}}void LED_2() //跑马灯函数{unsigned char i;for(i=0;i<15;i++){if(i<7){IO1SET = 1<<(i+16);delay(20);IO1CLR = 1<<(i+16);}else{IO1SET = 1<<(29-i);delay(20);IO1CLR = 1<<(29-i);}}}void LED_3() //LED闪烁函数{unsigned char i;for(i=0;i<10;i++){IO1SET = 0x7F<<16;delay(20);IO1CLR = 0X7F<<16;delay(20);}}void display(uchar x) /*数码管显示函数x为显示的数字*/ {unsigned char table[10]={0x00, 0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};IO0SET = (table[x]<<25);IO1SET = (table[x]<<16);delay(20);IO0CLR = (table[x]<<25);IO1CLR = (table[x]<<16);}void key_w() //键盘按行低电平扫描函数{IO0SET = 0X7<<20;IO0CLR = 1<<20;delay(2);IO0SET = 1<<20;IO0CLR =1<<21;delay(2);IO0SET =1<<21;IO0CLR =1<<22;delay(2);IO0SET =1<<22;}unsigned char key_r() /*键盘按列读取扫描数值返回值为键盘对应数字*/ {int a=0,b;switch(IO0PIN&(7<<16)){case 0x00060000:b=1;break;case 0x00050000:b=2;break;case 0x00030000:b=3;break;default:break;}switch(IO0PIN&(7<<20)){case 0x00600000:a=1;break;case 0x00500000:a=2;break;case 0x00300000:a=3;break;default :break;}if(a!=0)a=(a-1)*3+b;else a=0;return(a);}void EINT0()__irq //外部中断0服务函数,对应矩阵键盘{unsigned char num;num=key_r();display(num);EXTINT = 0x0f;VICVectAddr=0;}void EINT1()__irq //外部中断1服务函数,对应流水灯{LED_1();VICVectAddr=0;}void EINT2()__irq //外部中断2服务函数,对应跑马灯{LED_2();EXTINT = 0x0f;VICVectAddr=0;}void EINT3()__irq //外部中断3服务函数,对应LED闪烁标志a=1 {a=1;EXTINT = 0x0f;VICVectAddr=0;}void time0()__irq //定时器服务函数,对应k++{k++;T0IR = 1;VICVectAddr = 0;}void init () //初始化函数,引脚功能设置{PINSEL0 = 0X000CC0CC;PINSEL1 = 0X0;IO0DIR = 0XFE700000;IO1DIR = 0X00FF0000;}void EXTinit (uchar x,uchar y) /*外部中断初始化设置x为中断触发方式,y为中端极性,x,y为两位HEX*/{EXTMODE = x;EXTPOLAR = y;}void TIMEinit() //定时器初始化(未给使能){T0TC = 0;T0PR = 0;T0PC = 0;T0MCR= 0x03;T0MR0= 1105920;}void VIC() //中断标志,优先级,指向函数设置{VICIntSelect&= (~(0xF<<14));VICIntSelect&= (~(0x1<<4));VICVectCntl1 = 0x20|14;VICVectAddr1 = (unsigned int)EINT0;VICVectCntl2 = 0x20|15;VICVectAddr2 = (unsigned int)EINT1;VICVectCntl3 = 0x20|16;VICVectAddr3 = (unsigned int)EINT2;VICVectCntl4 = 0x20|17;VICVectAddr4 = (unsigned int)EINT3;VICVectCntl0 = 0x20|4;VICVectAddr0 = (unsigned int)time0;EXTINT = 0x0f;VICIntEnable|= 0xF<<14;VICIntEnable|= 0x1<<4;}int main(void) //主函数{init();EXTinit(0x00,0x00);VIC();TIMEinit();while(1){key_w();if(a==1){LED_3();a=0;}}}。
3.33 用计数器中断实现100以内的按键计数
一. 单片机系统功能简介:
本例利用计数器中断实现按键计数,这与此前的按键计数程序看起来比较相似,但是用方法完全不同。
本例用T0计数器中断实现按键计数,由于计数寄存器初值为1,因此P3.4引脚的每次负跳变都会触发T0中断,实现计数值累加。
二.单片机系统硬件电路设计:
2.1 proteus原理图:
2.2 原件清单:
器件名:数量
三.软件设计:
3.1 主程序流程图:
3.2 程序清单:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
uchar code
DSY_CODE[]={0X3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00 };
uchar Count=100;
void main()
{
P0=0x00;
P2=0x00;
TMOD=0X06;
TH0=TL0=256-1;
ET0=1;
EX0=1;
EA=1;
IP=0X02;
IT0=1;
TR0=1;
while (1)
{
P0=DSY_CODE[Count/10];
P2=DSY_CODE[Count%10];
}
}
void Clear_Counter()interrupt 0
{
Count=0;
}
void Key_Counter() interrupt 1
{
Count=(Count-1)%100;
}
四.系统调试
4.1 在PROTEUS7.5仿真步骤
1将程序在KEIL中编译,直到达到要求的功能为止;
2在PROTEUS中绘制硬件图(在PROTEUS仿真时可以不添加最小系统电路;实际电路中需要);
3将KEIL C中编译好的HEX文档加载到PROTEUS中;
4按下K1开始计数,按下K2可以清零。
仿真效果:按下K1可以看到数码管开始计数,按一次记一次,从0-99,按下K2按键,可以看到数码管变0。
4.2硬件电路调试步骤
1 按照原理图焊接好线路板,布线规范;
2 利用单片机开发工具将程序的HEX文档,烧写入芯片当中;
3 将芯片插入在芯片的底座当中;
4 将电路的VCC端接到电池盒的正极,将接地端接到电池盒的负极;
5 分别调试按键K1 ,K2观察效果;
6 如果没有效果或者效果不对插错;
实物图:
效果图:
运行结果:按下K1数码管开始计数,按一次计数1次,从0可以最大计数到99,再按下K2,数码管显示为0,可以重新计数。
五.单片机设计感受:
这是我第一次做单片机实验,说起来有一些紧张和新奇。
在此之前我并没有接触过单片机,我本以为与之前的光学实验及其它实验差不多,可我做完设计之后,我就改变了这个看法。
单片机实验要求的是一种思维的创新,而不是简单的重复老师所说的实验步骤。
因此第一次实验,实验老师向我们讲解了KEILC的情况及使用方法和技巧。
编完程序之后,知道我们如何使用PROTEUS达到将编好的程序输入到单片机中来使其运行。
经过我的不断努力,我终于实现了简单的用计数器中断实现100以内的按键计数的仿真运行。
我感到兴奋极了,我得到莫大成就感和自信。
但在做实物的时候,由于焊接技术的欠缺,有几个地方接线接的很不好,不能正常运行。
虽然很努力了,但是依旧不能运行。
在这次实验中,我体会到了合作的重要性。
一个人在实现这一系列的过程,要花费很多精力和时间。
群策群力,可以使我更好、更快地完成我的工作。
在此期间,我可以更好知道自己的不足和缺陷,来得到改正。
还可以知道自己的优势所在,把握好自己的优势。
以上便是我做这次实验的心得体会。