将一个二进制数转换成十进制数表示,只需按权展开做一次10进制运算即可以完成。将一个十进制数转换成二进制数表示,是数据转换中较复杂的工作。做乘、除运算时,其法则与十进制数也是相同的。它不同于数值运算。二进制数可以进行按位的逻辑运算,每位之间相互独立,位与位之间不存在进位和借位的关系。......
2023-11-07
所谓中断,就是计算机为提高运行效率而采用的一种方式。例如对一个变量,当它发生状态改变时,就要立即进行处理。为此就必须时刻查询这个变量的状态。例如,例4-37中,对定时器T/C0的溢出标志位TF0必须不间断地查询它的状态。但这样做就要浪费计算机大量的运行时间,很显然这是我们不希望的。而采用中断方式,就可以有效地克服这种缺点。当一个变量一旦发生要求的改变时,计算机立即自动触发中断,转向一段服务程序,执行完成后,自动返回主程序的原断点继续运行。这就不必要时刻查询这个变量的状态,在不发生改变时,可以放心让机器做其他工作。这样就解放了计算机的大量能力,提高了运行效率。
1.有关中断的设置
(1)选择中断源
8051系列单片机的中断机制,共设置有5种中断源,见表4-7。
表4-7 5种中断源
(2)设置寄存器
与中断执行有关的SFR有两个,即中断允许寄存器IE和中断优先级寄存器IP。
1)中断允许寄存器IE。
复位后,IE=0x00,禁止一切中断。各位状态的设置如下:
①EA为总允许位。若EA=0,禁止一切中断;EA=1,允许中断。
②×表示无效,是保留位。
③ET2为定时器2中断允许位。若ET2=0,此位禁止;ET2=1,此位允许有效(EA=1时)。
④ES为串行口中断允许位。若ES=0,此位禁止;ES=1,此位允许有效(EA=1时)。
⑤ET1为定时器1中断允许位。若ET1=0,此位禁止;ET1=1,此位允许有效(EA=1时)。
⑥EX1为外部中断1允许位。若EX1=0,此位禁止;EX1=1,此位允许有效(EA=1时)。
⑦ET0为定时器0中断允许位。若ET0=0,此位禁止;ET0=1,此位允许有效(EA=1时)。
⑧EX0为外部中断0允许位。若EX0=0,此位禁止;EX0=1,此位允许有效(EA=1时)。
2)中断优先级寄存器IP。
复位后,IP=00H,无优先级,各位状态的设置(该位置“1”,表示优先级为高,清“0”表示优先级为低)如下:
①×表示无效,是保留位。
②PT2为定时器2优先级设置位。PT2=1,优先级为高。
③PS为串行口中断优先级设置位。PS=1,优先级为高。
④PT1为定时器1中断优先级设置位。PT1=1,优先级为高。
⑤PX1为外部中断1优先级设置位。PX1=1,优先级为高。
⑥PT0为定时器0中断优先级设置位。PT0=1,优先级为高。
⑦PX0为外部中断0优先级设置位。PX0=1,优先级为高。
所谓优先级设置,即设置计算机对中断响应的选择权。当几个通道同时发生中断时,计算机只能选择一个通道进行响应,即具有高优先级的通道才能被响应。
当多个高优先级中断发生或无优先级设定时,要按照下面自然优先级响应中断:
(3)中断服务函数定义
在C语言中,若应用中断功能,必须先定义中断服务函数。其一般形式如下:
其中,n是中断号,m是选定的工作寄存器组编号,0~3代表4个工作寄存器。
中断服务函数编程中的规则如下
1)中断函数中,不能有任何参数声明。
2)中断函数不能设返回值。应设为void型。
3)中断函数不能直接调用。
如果在中断函数中调用了其他函数,则被调用函数所用的寄存器组必须与中断函数所用寄存器组相同。
2.【例4-41】 利用定时器T/C0控制灯D0闪烁,定时时间为1s,采用中断方式
(1)确定定时器T/C0各SFR
1)确定TMOD值。选用T/C0为定时器,工作方式选mode 1,即16位定时器,TMOD=0000 0001B=0x01。
2)计算定时常数。项目要求定时时间为1s,选T/C0定时时间为T/C0=0.1s,靠软件重复10次,总定时时间T=10×0.1s=1s。
定时常数T0=65536-(100×103/2)
=65536-50000
将T0分解为高8位TH0和低8位TL0,为
TH0=15536/256=60=0x3C
TL0=15536-(256×60)=176=0xB0
3)确定TCON值。TR0在程序中设置,其他位为0,TCON=0x00。
4)确定IE值。EA=1,允许总中断。ET0=1允许T/C0中断。其他位为0,IE=1000 0010=0x82。
5)确定IP值。因只有一个中断,可以不设置优先级,仍保持复位状态IP=0x00。
(2)编辑C语言源程序
(3)编译
(4)执行
1)软仿真。
①进入调试,米黄色标志箭头停在第11语句处。
②调出P1状态窗口。
③调出Timer 0窗口。
④调出变量窗口。
⑤连续单击“跟踪”,在语句18等待中断处,令TF0=1,即在Timer 0窗口的TF0处打“√”。单击“跟踪”,程序即跳转到中断服务子函数。
⑥连续单击“跟踪”,由于a+1,a≠5,所以返回主函数继续等待下一次中断。
⑦中断5次,由于a=5,D0取反,a=0。等待下一个5次中断。
通过调试,证明程序达到要求。
2)下载到实验机。执行程序,灯D0闪烁,间隔时间为0.5s。
(5)程序点评
本例采用用T/C0中断方式控制灯闪烁。变量a应为全局变量。不管在主函数或在中断函数中均有效。在变量a信息栏内,因为它不是局部变量,所以单击F2键,才可以观察a的变化。
3.【例4-42】 乐曲编程《生日快乐歌》
(1)乐曲编程简介
对于一个音符,有两个属性:一是音高,即音符对应的音名(频率);二是时值,即占有的节拍数。对于声音的频率,按定时器T0的工作方式1(16位计数)在P2.7口产生方波,驱动蜂鸣器发声。对于节拍,按延时函数产生,不同的节拍数由不同延时倍率保证。用定时器产生方波,比较准确。对于节拍,准确度要求不高,用延时函数产生是合适的。
要对一首乐曲(主要是歌曲)进行编程,就是将歌曲简谱的每个音符按顺序编辑成两组代码,一组是音符的音高代码,一组是音符的时值代码。节拍按每拍0.5s计算。完成后与程序一齐存入片内存储器。执行程序,即可听到歌曲的演奏声。
也可以将乐曲代码单独存入外部扩展存储器,例如24C02或24C64。开机后立即将乐曲的所有音符代码读入片内RAM,然后执行发音程序。如果片内RAM足够大,也可以开机后直接存入RAM,然后执行。
编程前,第一步将乐曲的简谱写出。第二步将每个音符的音高根据音高表列出编码。第三步按乐曲节拍列出编码。
(2)编辑C语言源程序
1)流程图,如图4-12所示。
图4-12 流程图
2)C语言程序如下:
(www.chuimin.cn)
(3)编译
(4)执行
1)软仿真。
①进入“调试”,调出P2口状态。调出Timer 0。
②连续单击“单步”,执行语句。由于第一个音符≠00,≠15,≠14,直接执行到取TH0/TL0,开Timer 0,取节拍值。在此期间,由T/C0按中断服务函数发音。当节拍延时结束,立即关T/C0,停止发音。完成一个音符,进入下一个音符的提取。如此循环,直到0x14,循环结束。
③若结束符为0x15,则表示继续从头循环发音。若为0x00,则为空拍,不发音,执行空拍后,取下一音符。
2)下载到目标机。执行后,蜂鸣器发出《生日快乐歌》曲调。
(5)程序点评
本例练习乐曲编程。音符的发声由定时器中断产生。中断的定时时间取决于TH0/TL0的数值。即相当于音符的音高。发声的延时时间由节拍决定。本例只列出了两个曲目。有兴趣的读者只需改变tab_1内容(音高),tab_5内容(节拍)即可以练习其他乐曲。
《生日快乐歌》的曲谱及音高节拍编码表分别如图4-13和图4-14所示。
图4-13 《生日快乐歌》曲谱
4.【例4-43】 电子琴练习,
利用目标机的5只键演奏C调“1,2,3,4,5”
(1)编辑C语言源程序
分析电子琴的程序,主要是两部分:5只键的扫描和T/C0中断服务程序。上电即进入键扫描状态,若无键按下,则继续扫描等待。一旦发现有键按下,即进入T/C0初始化。开中断,从对应的键号开始取TH0/TL0,并由中断服务程序发声。当查询到键若未抬起,则继续中断发声。若查询到键已抬起,则返回继续键扫描,等待下次按键。
图4-14 音高/节拍编码表
具体程序如下:
(2)编译
(3)执行
1)软仿真。
①进入“调试”,调出P2口状态。调出Timer 0。
②连续单击”跟踪”,执行语句,由于P2无键按下,key()子函数的返回值c=0x05,进入循环查键。TR=0,T/C0关闭,系统等待。
③若置P2.0=0,连续单击“单步”,执行语句,由于有键按下,key()子函数的返回值c=0x00,相当于按下+1键,i=0x00。
④进入键号取值。TH0=0xFC,TL0=0x46,对应于“do”音。
⑤连续单击“单步”,由于开中断,导致Timer 0中断发音。
⑥到达key_ up(),等待键抬起。当键抬起后,TR0=0,关闭Timer 0发音。进入下一轮查键。
通过调试,证明程序可以满足设计要求。
2)下载到目标机执行程序,依次按下+1、-1、H、AD、WR键,发音1、2、3、4、5(do、re、mi、fa、sol)音。
(4)程序点评
本例在实验机建立一个5键电子琴,可以验证电子琴的编程原理。
5.【例4-44】 频率计
若用T/C0做定时器,用T/C1做计数器,当有脉冲输入时,在一定时间内将计数结果保存并显示,就是频率计。下面我们用T/C0作为定时器,用T/C1做计数器,P3.5(T1)作为外触发输入计数脉冲,并用数码管显示结果。
(1)编程
(2)编译
(3)执行
1)软仿真。
①进入软仿真调试状态。米黄色图标指向main()主函数第1条语句。
②连续单击“单步”向下执行,到if(TF0)停止等待。因为T0未溢出。这时,TH0=0x3C,TL0=0xB0,TH0=0x00,TL0=0x00。调出P3口。
③手动单击P3.5(T1),发下降沿脉冲,即置0,置1,共50次。在T/C1的TL0栏内即显示输入的次数0x32=50,即表示输入50次计数值。
④置TC0的TF0=1,定时器T/C0溢出。程序向下执行,a=TL1=0x32。
⑤单击“单步”,执行send(form[a%10]),因为a=50,a%10=0,传送的实参byte=0xC0。即0的字形码。
⑥单击“单步”,执行send(form[a/10]),因为a=50,a/10=5,传送的实参byte=0x92。即5的字形码。
⑦单击“单步”,向下执行。重置TH0/TL0,开TR0,TR1进入下次测试。
从调试的结果,证明程序正确。
2)下载到目标实验机。若进行硬件部分执行,除主机运行上面程序外,还必须用另一单片机组成一个已知频率的发生器,将计数脉冲输入到主机,然后观察显示结果,应与已知频率相同。
(4)程序点评
本例要求了解定时器既可以做定时器,也可以做计数器。当在一定时间内,计入外部输入的计数脉冲值,就是频率计。此例对理解定时和计数的原理是很合适的。
6.【例4-45】 外部中断练习在外部中断0的输入端P3.2加一个下降沿脉冲,触发外部中断0,控制一个二进制位xbit的状态。xbit的初始状态为0。
(1)外部中断简介
8051单片机本身设有两个外部中断输入端,分别为和。外部中断0的中断服务程序入口的地址为0x0003,外部中断1()的中断服务程序入口的地址为0x0013。在C语言中中断服务函数可以用下列格式进行声明:
其中,extern表示外部,extern_ int0(void)表示外部中断服务函数的名称,(void)表示此函数无返回值,interrupt 0表示中断编号为0,using 0表示函数放于寄存器0区。为了避免与其他数据相互影响,也可以用using 1,表示函数放于寄存器1区。
外部中断的激活方式(不管是或INT1)有两种:一种是电平激活,另一种是脉冲边沿激活。这两种方式可以靠TCON寄存器的外部中断类型控制位IT0和IT1来控制。当为1时,是后沿触发中断。当为0时,是低电平触发中断。
为了可靠地触发中断,对于后沿触发至少高电平要保持1个机器周期,而下降沿也要至少保持1个机器周期。对于6MHz晶振,高电平保持至少2μs,低电平也至少保持2μs。
(2)编辑C语言源程序
(3)编译
(4)执行
1)软仿真。
①调出P1和P3口状态。
②连续单击“跟踪”,当未产生外部中断0时,xbit=0,P1口不产生变化。
③当置P3.2=0,产生一个下降沿中断,程序转入中断服务函数,xbit=1,中断返回后,导致P1+1产生变化。
若继续产生下降沿中断,则xbit=0,P1口停止变化。如此反复。可以检验外部中断0的效果。
2)下载到实验机。进行如下操作:
若总中断被打开,外部中断0被打开,TCON的IT0=1,若未产生外部中断0,则xbit=0,程序继续循环,P1口不产生变化。
当第1次在P3.2产生一个下降沿时,立即触发外部中断0,并执行中断服务函数,导致xbit=1。P1口的状态产生+1变化。直到再次产生中断,xbit=0为止。
当又产生中断时,xbit=1,P1口的状态再次产生+1变化。直到再次产生中断,xbit=0为止。
这样,就验证了外部中断0的机制。
(5)程序点评
本例验证外部中断机制。用位变量xbit作为引导。当INT0产生下降沿外部中断时,导致xbit取反。当xbit=1,P1+1,即表示外部中断的效果。
有关零起点学习单片机多语言编程的文章
将一个二进制数转换成十进制数表示,只需按权展开做一次10进制运算即可以完成。将一个十进制数转换成二进制数表示,是数据转换中较复杂的工作。做乘、除运算时,其法则与十进制数也是相同的。它不同于数值运算。二进制数可以进行按位的逻辑运算,每位之间相互独立,位与位之间不存在进位和借位的关系。......
2023-11-07
if-else条件分支语句是选择结构的一种形式,是最常用的语句之一。这意味着如果if后面的表达式成立(不为0),则执行if下面的语句,否则直接向下执行。......
2023-11-07
程序点评:数据传送指令MOV将一组数据分别传送到P1口,做了输出口的操作。将8位立即数传送给累加器A,再由累加器A将数据传送到I/O接口的P1口,使P1.0灯亮。在I/O接口输出操作时不能将间接寄存器中的地址输出到P1口。......
2023-11-07
尽管单片机有许多特点,但仍然属于计算机的范围。这种特殊的语言就是程序设计语言,也就是由一系列语句组成的程序。程序设计语言从原理上可分为机器语言、汇编语言和高级语言三种类型,单片机也不例外。由于汇编语言指令具有直接对应机器语言指令的特点,因而生成的机器代码效率高,执行速度快,至今在单片机程序设计中仍被采用。在众多高级语言中,只有C语言成了应用于单片机系统的高级语言。......
2023-11-07
对单片机来说,可以用高级语言编程,也可用汇编语言编程,两种语言各有特点。像8051具有MCS51系列单片机的指令集。用助记符指令组成的计算机语言就称为汇编语言。......
2023-11-07
逐一依次循环闪烁:“逐一”表示某时刻仅能有一个发光二极管亮;“依次”表示I/O接口各位的发光二极管按顺序亮;“循环”表示I/O接口各位的灯逐一依次无固定次数的不停闪烁;“闪烁”表示I/O接口各位的发光二极管有亮有灭。方案说明:图2-1中深色的符号表示发光二极管亮,浅色的符号表示发光二极管不亮。3)程序设计(二)。程序点评:在关闭上一对发光二极管1s后,开启下一对,关闭与开启之间有1s的时间间隔。I/O接口位N=00~07。......
2023-11-07
在上述程序段中,当#1=01、#2=50.0时,程序段就相当于G01 X50.0 Y150.0;如果#1=00、#2=100.0,则相当于G00 X100.0 Y200.0等。例如,利用指令#100=#1000,可以读入来自PMC的开关量输入信号G054.0;利用指令#1100=1,可将PMC的信号F054.0直接置为ON状态等。5)变量采用的是计算机小数点输入方式,即123.000可以直接以123表示。6)在不同地址下,变量可根据CNC的输入格式,自动四舍五入,例如,当X的输入单位为0.001mm时,如#1=123.456789,X#1自动成为X123.457。......
2023-06-25
实参的个数、顺序和数据类型必须与形参一致。主调函数被执行后,实参值即被传送到被调函数中执行,完成后返回主调函数的程序中继续向下执行。程序点评本例通过程序执行,验证了函数的传值调用功能。add(5,6)中的数值就是实参。由于c是全局变量,因而可以执行add(),并显示结果。在主函数main中只执行add(),不要加赋值c。......
2023-11-07
相关推荐