版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、中断是单片机系统的重点中的重点 , 因为有了中断, 单片机C 语言的数组 6.1.1 数组的差不多概念我们第四章学过变量的差不多类型, 比如 char 、 int 等等。 这种类型描述的数据是比较有限的, 当我们要处理特别大量数据的时候, 就能够用到数组了, 比如我 们上节课的那个数码管的真值表,我们就能够用一个数组来表达。从概念上讲, 数组是具有相同数据类型的有序数据的组合, 一般来讲, 数组定义 后满足以下三个条件。具有相同的数据类型;具有相同的名字;在存储器中是被连续存放的。比如我们上节课定义的那个数码管真值表, 假如我们把关键字code 去掉,数组元素将被保存在RAMfr,在程序中可读
2、可写,同时我们也能够在中括号里边 标明那个数组元素的个数,比如:unsigned char LedChar16 = 0 xC0,0 xF9,0 xA4,0 xB0,0 x99,0 x92,0 x82,0 xF8, 0 x80,0 x90,0 x88,0 x83,0 xC6,0 xA1,0 x86,0 x8e; 在那个数组中的每个值都称之为数组的一个元素, 这些元素都具备相同的数据类 型确实是unsigned char型,他们有一个共同的名字 LedChar,不管放到RAMfr 依旧FLASHY,他们基本上存放在一块连续的存储空间里的。有一点要特别注意,那个数组一共有16中括号里面的数值个元素,
3、然而数组的元素的表达方式下标是从0 开始,因此实际上上边那个数组的首个元素LedChar0的值是0 xC0,而LedChar15的值是0 x8e,下标从0至U 15一共是16 个元素。LedChar那个数组只有一个下标,我们称之为一维数组,还有两个下标或者多个下标的,我们称之为多维数组。比如 unsigned char a23; 表示这是一个2行 3 列的二维数组。 在大多数情况下我们使用的是一维数组, 关于初学来说, 我 们先来研究一维数组,多维数组遇到了再了解。.2 数组的声明一维数组的声明格式如下:数据类型数组名 数组长度;(1) 数组的数据类型声明的是该数组的每个元素的类型,即一个数组
4、中的元素具有相同的数据类型。数组名的声明要符合C语言固定的标识符的声明要求,只能由字母、数字、 下划线这三种符号组成,且第一个字符只能是字母或者下划线。(3) 方括号中的数组长度是一个常量或常量表达式,同时必须是正整数。6.1.3 数组的初始化数组在进行声明的同时能够进行初始化操作,格式如下:数据类型数组名 数组长度 = 初值列表 ;依旧以上节课我们用的数码管的真值表为例来讲解考前须知。unsigned char LedChar16 = 0 xC0,0 xF9,0 xA4,0 xB0,0 x99,0 x92,0 x82,0 xF8, 0 x80,0 x90,0 x88,0 x83,0 xC6,
5、0 xA1,0 x86,0 x8e; (1) 初值列表里的数据之间要用逗号隔开。初值列表里的初值的数量必须小于或者等于数组长度,当小于数组长度时,数组的后边没有赋初值的元素由系统自动赋值0。假设给数组的所有元素赋初值,能够省略数组的长度,上节课的例子中我们实际上差不多省略了数组的长度。系统为数组分配连续的存储单元的时候, 数组元素的相对次序由下标来决定,确实是说 LedChar0 、 LedChar1LedChar15 是按照顺序排下来的。6.1.4 数组的使用和赋值在 C 语言程序中,是不能一次使用整个数组的, 只能使用单个数组元素。 一个数组元素相当于一个变量, 使用数组元素的时候与使用相
6、同数据类型的变量的方法一样。比如那个LedChar那个数组,假如没加code关键字,那么它可读可写,我们能够写成a = LedChar0 如此来把数组的一个元素的值送个a 那个变量,也能够写成LedChar0 = a 如此把 a 那个变量的值送给数组的一个元素,以下* 1 、三点要注意:引用数组的时候,那个方括号里的数字代表的是数组元素的下标,而数组初始化的时候方括号里的数字代表的是那个数组元素的个数。数组元素的方括号里的下标能够是整型常数,整型变量或者表达式,而数组初始化的时候方括号里的数字必须是常数不能是变量。数组整体赋值只能够在初始化的时候操作,功能程序只能对单个元素赋值。if 语句if
7、 语句差不多不陌生了,前边程序我们事实上差不多用过了,那个地方我们系统的介绍一下,方便后边的深入学习。 if 语句有两个关键字: if 和 else ,把这两个关键字翻译一下确实是:“假如”和“否那么”。 if 语句一共有三种格式,我们分别来看。f 语句的默认形式。if ( 条件表达式 ) 语句 1;其执行过程是, if( 假如 ) 条件表达式的值为“真”,那么执行语句 1;假如条件表达式的值为“假”,那么不执行语句1。真和假的概念不再赘述,参考第五章。那个地方要提醒一句,C语言一个分号表示一句语句的结束,因此假如if后边只有一条执行语句的时候, 能够省略大括号, 然而假如有多条执行语句的话,
8、必须加上大括号。我们上节课的语句就很好理解了 if(16 =j) j = 0; ,假如 j 等于 16的时候,括号里的值才是“真”,那么就执行j=0 这一句,假如 j 不等于16,那么里边就为“假”,就不执行这一句。f.else语句有些情况下,我们除了判断一下if 括号里的是否满足条件,执行相应的语句, 在不满足条件的时候, 我们又要执行另外相应的语句, 那个时候就用到了if.else语句,它的差不多的语法形式是:if ( 条件表达式 )语句 1;else语句 2;比如上节课的后半段程序我们也能够写成:P0 = LedCharj;/ 把数组里的对应值送给P0if(15 = j)/ 当显示到 F
9、 后,归0 重新开始j = 0; elsej+;那个程序大伙能够改改下载进去试试,程序逻辑大伙自己动脑分析一下,我就不解释了。f else if语句if.esle语句是一个二选一的语句,或者执行if 条件下的语句,或者执行 else 条件下的语句。 还有一种多项选择一的用法确实是if.elseif 语句。他的差不多语法格式是:if ( 条件表达式 1) 语句 1;else if (条件表达式2)语句2; else if (条件表达式3)语句3; else语句 n;他的执行过程是:依次判断条件表达式的值,当出现某个值为“真”时,那么执行相对应的语句,然后跳出整个if的语句块,执行“语句n”后边的
10、程序;假 如所有的表达式都为“假”,那么执行“语句 n”后,再执行“语句n”后边的 程序。if语句在C语言编程的过程中使用频率很高,用法也简单,因此必须要熟练学握。switch 语句用 ifelse 语句在处理多分支的时候,分支太多就会显得不方便,且容易出现if和else配对出现错误的情况,在C语言中提供了另外一种多分支选择的语句 switch 语句,它的差不多语法格式如下:switch ( 表达式 )case 常量表达式1:执行语句1;case 常量表达式2:执行语句2; case常量表达式n:执行语句n;default:执行语句 n+1;它的执行过程是:首先计算“表达式”的值,然后从第一个
11、case 开始,与“常量表达式 x ”进行比较,假如与当前常量表达式的值不相等,那么就不执行冒号后边的程序, 一旦发明和一个常量表达式的值相等了, 那么他会执行之后所有的,注意是所有的“执行语句”,显然这不是我们想要的结果。在 C 语言中, 有一条 break 语句, 作用是跳出当前循环语句, 不管是 for 和 while循环, 依旧 switch 循环, 都能够用其搭配使用跳出循环。 switch 语句一共有n+1种可能, 而我们盼望要的是一条多项选择一的语句, 只执行其中一条然后直截了当退出该循环, 不再执行下边的任何语句,那个时候就需要用到 break 语句, 比如我们在 switch
12、 表达式上加上break 语句,如下:switch ( 表达式 )case 常量表达式1:执行语句1; break ;case 常量表达式2:执行语句2; break ;case 常量表达式 n:执行语句 n; break;default: 语句 n+1;加了那个 break 语句后,一旦“常量表达式 x ”与“表达式”相等了,那就执行“执行语句x”,执行完毕后,由于有了 break,直截了当跳出switch语句,执 行 switch 语句循环后边的程序了,如此就能够幸免执行不必要的语句。了解了那个 switch 语句,我们将会在本章程序中使用巩固。数码管的动态显示6.4.1 动态显示的差不多
13、原理我们在上一章学习数码管静态显示的时候说到,74HC138只能在同一时刻导通一个三极管, 而我们的数码管是靠了 6 个三极管来操纵, 那我们如何来让数码管同时显示呢?这就用到了我们这节课的动态显示。多个数码管显示数字的时候, 我们实际上是轮流点亮数码管 一个时刻内只有一个数码管是亮的,利用人眼的视觉暂留现象也叫余辉效应,就能够做到看起来是所有数码管都同时亮了,这确实是动态扫描显示的含义。例如:我们有2 个数码管,我们要显示“ 12”那个数字,让高位的位选三极管导通,然后给它赋值“1”,延时一定时间后让低位的位选三极管导通,然后给它赋值“2”。把那个流程以一定的速度循环运行就能够让数码管显示出
14、“12”,由于交替速度特别快,人肉眼识别到的确实是“12”那个数字。那么一个数码管需要点亮多长时间呢?也确实是说要多长时间完成一次全部数码管的扫描呢 很明显: 整体扫描时间=单个数码管点亮时间*数码管个数?答案是:10ms以内。当电视机和显示器还处在 CRT电子显像管时代时,有一句 很流行的广告语一一“ 100Hz无闪烁,没错,只要刷新率大于100Hz,即刷新时间小于10ms就能够做到无闪烁,这也确实是我们的动态扫描的硬性指标。那么你也许会问, 有最小值的限制吗?理论上没有, 但实际上做到更快的刷新却没有任何进步的意义了, 因为差不多无闪烁了, 再快也依旧无闪烁, 只是徒然增加CPU勺负荷而已
15、因为1秒内要执行更多次的扫描程序。因此,通常我们设计程序的时候,基本上取一个接近10ms又比较规整的值就行了。我们板子上有 6 个数码管,我们下面用程序来验证一下数码管动态显示程序。#include / 包含寄存器的库文件sbitADDR0= P1A0;sbitADDR1= P1A1;sbitADDR2= P1A2;sbitADDR3= P1A3;sbitENLED= P1A4;unsigned char code LedChar = /用数组来表示数码管真值表0 xC0,0 xF9,0 xA4,0 xB0,0 x99,0 x92,0 x82,0 xF8,0 x80,0 x90,0 x88,0
16、 x83,0 xC6,0 xA1,0 x86,0 x8e,;void main() unsigned int counter = 0;unsigned char j = 0;unsigned long stopwatch = 0;unsigned char LedNumber6 = 0;ENLED = 0; ADDR3 = 1;P0 = 0XFF;74HC138和P0初始化部分TMOD = 0 x01; / 设置定时器0 为模式 1TH0= 0 xFC;TL0= 0 x67; / 定时值初值, 定时 1msTR0 = 1;/ 打开定时器0while(1) if(1 = TF0) TF0 = 0
17、;TH0 = 0 xFC;TL0 = 0 x67; counter+;if(1000 = counter) 达到 50 次counter = 0; stopwatch+;/ 秒表数值一秒加 1LedNumber0LedNumber1LedNumber2LedNumber3 管显示值计算LedNumber4LedNumber5 if (0=j)/ 判断定时器0 是否溢出/ 一旦溢出后,重新赋值/ 判断定时器0 溢出是否/stopwatch%10;stopwatch/10%10;stopwatch/100%10;stopwatch/1000%10; / 数码stopwatch/10000%10;s
18、topwatch/100000%10; ADDR0=0; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber0; else if (1=j) ADDR0=1; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber1; else if (2=j) ADDR0=0; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber2; else if (3=j) ADDR0=1; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber3; else if (4=j) ADDR0=0; ADDR1=0
19、; ADDR2=1; j+;P0=LedCharLedNumber4; else if (5=j) ADDR0=1; ADDR1=0; ADDR2=1; j=0;P0=LedCharLedNumber5; / 数码管动态刷新部分这程序,大伙自己抄到 Keil 中,然后边抄边理解,最终下载到实验板上实验一下效果。其中下边的if.else 语句确实是每1ms快速的刷新一个数码管,如此 6个数码管整体刷新一遍的时间确实是 6ms,视觉上确实是6个数码管无闪烁的 同时亮起来了。另外一个简单知识点那个地方也提一下, 事实上属于小学三年级知识, 然而许多同学刚接触C语言,可能遇到了也会发懵。确实是在数码管
20、显示值计算那个地方,相信小学我们没学小数之前,除法运算里边有“被除数”、“除数”、“商”、“余数”这四个概念年。而在我们 C语言中,“ / ”等同于数学里的除法运算,而“ %”等同于我们小学学的求余数运算。假如是123456 那个数字,我们要正常显示在数码管上, 个位显示, 确实是直截了当对10 取余数, 那个“ 6” 就出来了,十位数字确实是先除以10,然后再对10 取余数,以此类推,就把6 个数字全部显示出来了。关于多项选择一的动态刷新数码管的方式, 我们假如用 switch 会有更好的效果,大伙来看一下我们用 switch 语句完成的情况。#include / 包含寄存器的库文件sbit
21、ADDR0 = P1A0;sbitADDR1 = Pil;sbitADDR2 = P1A2;sbitADDR3 = P1A3;sbitENLED = P1A4;unsigned char code LedChar = /用数组来表示数码管真值表0 xC0,0 xF9,0 xA4,0 xB0,0 x99,0 x92,0 x82,0 xF8,0 x80,0 x90,0 x88,0 x83,0 xC6,0 xA1,0 x86,0 x8e,;void main() unsigned int counter = 0;unsigned char j = 0;unsigned long stopwatch
22、=0;unsigned char LedNumber6=0;ENLED = 0; ADDR3 = 1;P0 = 0XFF; /74HC138 和 P0初始化部分TMOD = 0 x01; / 设置定时器0 为模式 1TH0= 0 xFC;TL0= 0 x67; / 定时值初值, 定时 1msTR0 = 1; / 打开定时器0 while(1)if(1 = TF0)TF0 = 0;TH0 = 0 xFC;TL0 = 0 x67;counter+;if(1000 = counter)达到 1000 次counter = 0;stopwatch+;/ 秒表数值一秒加 1LedNumber0LedNu
23、mber1LedNumber2LedNumber3 管显示值计算LedNumber4/ 判断定时器0 是否溢出/ 一旦溢出后,重新赋值/ 判断定时器0 溢出是否/stopwatch%10;stopwatch/10%10;stopwatch/100%10;stopwatch/1000%10; / 数码stopwatch/10000%10;stopwatch/100000%10;LedNumber5 switch(j)case 0: ADDR0=0; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber0;break;ADDR0=1; ADDR1=0; ADDR2=0;
24、 j+;P0=LedCharLedNumber1;break;ADDR0=0; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber2;break;ADDR0=1; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber3;break;ADDR0=0; ADDR1=0; ADDR2=1; j+;P0=LedCharLedNumber4;break;ADDR0=1; ADDR1=0; ADDR2=1; j=0;P0=LedCharLedNumber5;break;default: break;/ 数码管动态刷新部分大伙是否能感受到 switc
25、h 语句比if.else语句显得要整齐的多?6.4.2 数码管消隐处理不明白细心的同学能否发明, 我们的两次数码管动态刷新显示的时候大概并不是那么完美,第一个小问题,大伙认真看,数码管的不应该显示的段,大概有微微的发亮,这种现象叫做“鬼影”,那个“鬼影”严峻妨碍了我们的视觉效果,我 们该如何解决呢? 同 学们今后可能会遇到各种各样的问题,可能有许多我是没有讲过的问题,遇 到问题如何办呢?大伙要相信, 你作为初学者, 遇到的问题确信不是第一个遇到 的, 确信 有前辈会遇到同类问题, 他们一般会在网上发表各种帖子, 各种讨论, 因此大伙遇到问题, 首先解决方法就应该形成一个到网上搜索的条件反射,
26、那个 问题大伙能够 到网上搜:“数码管消隐”或者“数码管鬼影解决”,多找相关 关键词搜索,会搜索也是一种能力。大伙在网 上搜了一下会发明, 解决这类问题的普遍两个方法, 其中之一是延时,延时之后我们肉眼就可能看不到那个 “鬼影” 了。 然而延时是一个特别拙劣的手段,且不说延 时多久能让我们看不到“鬼影”,延时后,我们的数码管亮度会普遍降低。我们解决问题呢,不能只知其然,不知其因此然,因此我们首先要弄懂什么原因会出现“鬼影”。“鬼影” 的出现, 要紧是因为我们数码管位选和段选产生的瞬态所造成的。 举个简单例子, 我们在数码管动态刷新的那部分程序中, 实际上每一个数码管点亮的持续时间是1ms的时间
27、,1ms后进行下个数码管的切换。在进行数码管切换的时候,比如我们从case 5 要切换到 case 0 的时候, case 5 的位选用的是ADDR0=1;ADDR1=0; ADDR2如此刻case5也确实是最高位数码管对应的值是 0。我们 要切换成的case 0的数码管位选是 ADDR0=0; ADDR1=0; ADDR2=0;对应的数码 管的值假如是1。因为我们的C语言程序是一句一句顺序往下执行的,每一条语句都会占用一定的时间, 即使那个时间特别特别短暂。 然而当我们把“ ADDR0=” 1 改变成“ADDR0=”0的时候,那个瞬间存在了一个中间状态ADDR0=0; ADDR1=0; AD
28、DR2=那个瞬问上,我们就给case 4对应的数码管DS5瞬间赋值了 0。当我们全部写完了 ADDR0=0; ADDR1=0; ADDR2=0;,那个时候,我们的 P0还没有正式赋值,而 P0 此刻却保持了前一次的值,也确实是在那个瞬间,我们又给case 0 对应的数码管DS1赋值了一个00直到我们把case 0后边的语句全部完成后,我们的刷新 才正式完成。 而在那个刷新过程中, 有 2 次瞬间我们给了错误的数码管赋值, 尽 管很弱因为亮的时间很短,然而我们依旧能够发明。那 弄懂了原理后,解决起来就不是困难的情况了,我们只要避开那个瞬态就能够了。 不产生瞬态的方法是, 我们在进行刷新的赋值语句
29、期间, 幸免一切数码管的赋值即 可。方法有两个,一个方法是刷新之前关闭所有的段,改变好了位选后,再打开段即可;第二个方法是关闭数码管的位,赋值过程都做好后,再重新打开即可。那个 不是很难,答案我都公布一下。关闭段:在switch(j)这句程序之前,加一句P0=0XFF如此就把数码管所有的 段都关闭了,当把“ ADDR的值全部搞定后,再给P0赋对应的值即可。关闭位:在switch(j) 这句程序之前,加上一句ENLED=1等至IJ把“ADDR=0ADDR1=0;ADDR2=0;P0=LedCharLedNumber0; 这几条刷新程序全部写完后, 再加上一句ENLED=0然后再进行break操作
30、即可。那个地方略微有点逻辑思路在里边, 大伙一定要理解深刻, 深刻理解, 完全弄明白, 把那个瞬态弄明白, 后边许多牵扯到此类情况的问题, 我们都能够一并搞定。上边的数码管程序还有第二个问题, 大伙认真看, 我们的数码管上的数字每一秒变化一次, 变化的时候, 不参加变化的数码管可能出现一次抖动, 那个抖动没有什么专业的名字, 我们就称之为数码管抖动吧。 这种数码管抖动是什么缘故造成的呢?为何在数据改变的时候才抖动呢?我们来看我们的程序。 我们的程序在定时到 1 秒的时候, 执行了 “数码管显示值计算”那个过程,一个32 位的除法运算,实际上是比较耗费时间的,至于这一段程序占用了多少时间,大伙能
31、够通过第四章讲的Debug进入看看这段程序运行一共占据了多少时间。 由于达到 1 秒的时候, 程序多运行了这么一段, 导致了某个数码管的点亮时间比其他情况下要长一些,时间是1ms程序消耗时间,于此同时,其它的数码管就熄灭了5ms程序消耗时间,假如那个程序消耗时间特别短,那么能够忽略不计,但很明显,现在这段程序差不多比较长了,严峻妨碍我们的视觉效果了,因此我们要采取另外一种思路去解决那个问题。6.5 中断的学习 6.5.1 中断的产生背景比如此刻我正在厨房用煤气烧一壶水,烧开一壶水刚好需要10 分钟。我是一个主体,烧水是一个目的,而且我只能时 时刻刻在那个地方烧水,因为一旦水开了,溢出来浇灭煤气
32、的话,有可能引发一场灾难。而那个时候呢,我听到了电视里传来天龙八部的主题歌,马上就要开演了, 我真想夺门而出,去看我最喜爱的电视剧。然而,听到那个水壶发出的“咕嘟”的声音,我清晰:除非水开了,否那么我是无法享受我喜爱的电视剧的。那个地方边主体只有我一个, 而我要做的有两件情况, 一个是看电视, 一个是烧水,而电视和烧水是两个独立的客体,他们是同时进行的。其中烧水需要10 分钟, 但不需要了解烧水的过程的, 只需要得到水烧开的如此一个结果就行了, 提下水壶和关闭煤气只需要几秒的时间而已。 因此我们采取的方法确实是: 烧水的时候,定上一个闹钟,定时10 分钟,然后我就能够安心看电视了。当 10 分
33、钟时间到了,闹钟响了,此刻水也烧开了,我就过去把煤气灭掉,然后接着回来看电视就能够了。那个场景和单片机有什么关系呢?在单片机的程序处理过程中也有许多类似的场景, 当单片机正在用心致志的做一件情况的时候( 如看电视 ) , 总会有一件或者多件紧迫或者不紧迫的情况发生, 需要我们去关注, 有一些需要我们停下手头的工作去马上完成( 比如水开了 ) , 只有处理完, 才能回头接着完成刚才的工作( 看电视 ) 。 假如在那个地方用上了单片机的中断机制, 不仅仅我拥有了处理意外情况的能力, 而且假如我能够充分发挥那个机制的妙用,就能够“同时”完成多个任务了。假如依旧一知半解关于中断更6.5.2 定时器中断
34、应用方法在第五章我们学过定时器,而实际上定时器一般用法基本上采取中断方式来做的,我是有意在第五章用查询法,确实是使用 if(TR0 =0) 这 样的语句先讲定时器, 目的是明确告诉同学们, 定时器和中断不是一回事, 定时器是单片机模块的一个资源,确真的实存在的一个模块,而中断,是单片机的一种运行机制。尤其是初学者们, 许多人会误以为定时器和中断是一个东西, 只有定时器才会触发中断,但实际上许多事件都会触发中断的,除了“烧水”,还有“有人按门铃”,“来标准51 中与中断相关的寄存器,一共有2 个,其中 1 个是中断使能寄存器, 另外 1 个是中断优先级寄存器, 那个地方先介绍中断使能寄存器。 随
35、着一些增强型51 单片机的问世,可能会有增加的寄存器,大伙这些理解了那个地 方所讲的,其他的通过自己研读数据手册全部能够理解明白同时使用起来。可位寻址;复位值:0 x00;复位源:任何复位位76543210符号 EA - ET2 ES ET1 EX1 ET0 EX0表 6-2 IE- 中断使能寄存器的位描述位 符号描述7 EA 总中断使能位,相当于总开关6-5ET24ES3ET12EX11ET00EX0定时器 2 中断使能串口中断使能定时器 1 溢出中断使能外部中断 1 使能 定时器 0 中断使能外部中断 0 使能中断使能寄存器IE 操纵了 6 个中断使能,其中第 6 位临时不用,第七位是总开
36、关, 相当于我们家里或者学生宿舍里的那个电源总闸门。 而 0 到 5 位这 6 个相当于每个分开关。那么也确实是说,我们只要用到中断,就要写 EA = 1 这一句,打开中断总开关,然后用到哪个分中断,再打开相对应的位就能够了。我们现在就把第五章学的定时器的程序进行改写, 使用中断实现出来, 把数码管 的抖动问题也同时一并处理掉。/ 用数组来表示数码管真值表/ 包含寄存器的库文#include 件sbitADDR0 = P1A0;sbitADDR1 = Pil;sbitADDR2 = P1A2;sbitADDR3 = P1A3;sbitENLED = P1A4;unsigned char cod
37、e LedChar = 0 xC0,0 xF9,0 xA4,0 xB0,0 x99,0 x92,0 x82,0 xF8,0 x80,0 x90,0 x88,0 x83,0 xC6,0 xA1,0 x86,0 x8e, ;unsigned char LedNumber6 = 0; / 定义全局变量unsigned char j = 0;unsigned int counter = 0;void main()unsigned long stopwatch =0;ENLED = 0; ADDR3 = 1; P0 = 0XFF;74HC138 和 P0初始化部分TMOD = 0 x01;/ 设置定时器
38、0 为模式 1TH0= 0 xFC;TL0= 0 x67;/ 定时值初值, 定时 1msTR0 = 1;/ 打开定时器0EA = 1;/ 打开中中断ET0 = 1;/ 打开定时器0 中断while(1)if(1000 = counter)/ 判断定时器0 溢出是否达到1000次counter = 0;stopwatch+;LedNumber0 = stopwatch%10;LedNumber1 = stopwatch/10%10;LedNumber2 = stopwatch/100%10;LedNumber3 = stopwatch/1000%10;LedNumber4 = stopwatch
39、/10000%10;LedNumber5 = stopwatch/100000%10;void InterruptTimer0() interrupt 1/ 中断函数的特别写法,数字 1为中断入口号 TH0 = 0 xFC; / 溢出后进入中断重新赋值TL0 = 0 x67;counter+;/ 计数值counter 加 1P0 = 0 xFF;/ 消隐switch(j) case 0: ADDR0=0; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNumber0; break;ADDR0=1; ADDR1=0; ADDR2=0; j+;P0=LedCharLedNum
40、ber1; break;ADDR0=0; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber2; break;ADDR0=1; ADDR1=1; ADDR2=0; j+;P0=LedCharLedNumber3; break;ADDR0=0; ADDR1=0; ADDR2=1; j+;P0=LedCharLedNumber4; break;ADDR0=1; ADDR1=0; ADDR2=1; j=0;P0=LedCharLedNumber5; break;default: break;/ 动态刷新大伙能够先把那个程序了解明白,下载到单片机里边实验一下,看看实际效果
41、。是否能够看出来, 近乎完美的显示效果通过我们的努力终于做成功了。 那下面我们还要来解析一下我们的那个程序。在我们那个程序中,有两个函数,一个是主函数, 一个是中断函数。 主函数 main()我们就不用说了, 重点强调一下中断函数, 中断函数的格式是固定的, 首先中断函数前边void 表示函数返回空,即中断函数不返回任何值,函数名字是InterruptTimer0(),那个函数名字只要符合函数命名规那么的前提下我们就能够随便起, 我如此起名字是为了方便区分和经历, 而后是 interrupt 那个关键字不能错,那个是中断特有的关键字,另外后边还有个数字1,那个数字1 如何来的呢?我们先来看一个
42、表格。表 6-3 中断查询序列描述中断标志中断使能默认优先级外部中断0IE00003HEX01( 最高 )T0 中断TF0000BHET02外部中断1IE10013HEX13T1 中断TF1001BHET14UART 断TI/RI0023HES5T2 中断TF2/EXF2002BHET26那个表格同样不需要大伙记住, 需要的时候过来查就能够了。 我们现在看第二行T0中断,它的中断标志是TF0,也确实是当TF0变成1的时候,就会触发中断。而在interrupt 后边的数字x的计算方法是x*8+3=向量地址,T0的向量地址是 000BH那么我们能够求得x的值是1。如此那个中断函数名字我们就完全明白
43、 了。中断函数和一般函数有个不一样的地方, 一般函数一般是在程序中调用, 而中断函数因为有了中断入口, 达到中断条件后, 他会自动进入程序执行。 比如咱那个程序,平时一直在主程序 while(1) 的循环中运行,假如程序有100行,当运行到了 50行的时候,定时器溢出了,那么CPLM会赶忙跑到中断函数中执行中断程序, 中断程序运行完毕后再自动返回到刚才的第 50 行处接着运行下面的程序,如此就保证了动态刷新是固定的1ms时间,可不能因为程序运行时间不一致的缘 故导致数码管的抖动了。6.5.3 中断的优先级中断优先级的内容, 大伙先通过我的介绍大概了解一下即可, 后边真正实际应用的时候我们再详细
44、理解。在讲中断产生背景的时候, 我们仅仅讲了看电视和烧水的例子, 然而实际生活话的“中断” 程序当中去, 就在接电话的同时, 听到了水开的声音, 水开的 “中断”也发生了,我们要放下手上的电话,先把煤气关掉,然后再回来听电话,最后听完了电话再看电视,那个地方就产生了一个优先级的问题。还有一种情况, 我们在看电视的时候, 那个时候听到水开的声音, 水开的 “中断”发生了,我们要进入关煤气的“中断”程序当中,而在关煤气的同时,电话声音响了,而那个时候,我们的处理方式是先把煤气关闭,再去接听电话,最后再看电视。从这两个过程中, 我们能够得到一个结论, 确实是最最紧急的情况, 一旦发生后,我们不管当时处在哪个“程序”当中,我们必须先去解决最最
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 小额汽车贷款合同范例
- 2024年企业租车合同协议样本
- 标准版市政道路工程合同
- 上门服务协议合同范本2024年
- 小型货车销售合同
- 网络广告合作协议
- 2024年度网络安全防护服务合同
- 办公租赁合同模板
- (2024版)人工智能医疗诊断系统开发合同
- 2024年度医疗器械独家代理合同
- 跨境数据流动的全球治理进展、趋势与中国路径
- 【多旋翼无人机的组装与调试5600字(论文)】
- 2023年辽阳市宏伟区事业单位考试真题
- 环境工程专业英语 课件
- 继电保护动作分析报告课件
- 五年级数学上册8解方程课件
- 教学工作中存在问题及整改措施
- 内部项目跟投协议书(正)
- 钢管静压桩质量监理细则
- 5000头奶牛养殖场新建项目环境评估报告书
- 16飞机颠簸教学课件
评论
0/150
提交评论