东南大学自动化学院实验报告课程名称: MCU(微控制器)综合课程设计第三次实验实验名称:定时中断实验、键盘输入与显示综合实验院(系):自动化专业:自动化姓名:学号:08009000实验室:电工电子MCU 实验组别:同组人员:实验时间:2012年 5 月2 日评定成绩:审阅教师:目录一、实验目的和要求(如合作完成,需注明分工) (3)二、实验原理 (3)三、实验方案与实验步骤 (4)四、实验设备与器材配置 (7)五、实验记录(自行设计记录方式) (7)六、实验总结(包括实验数据处理、实验结果分析讨论等) (9)七、思考题或讨论题(若干) (9)八、附上源代码(注意实验只能采用汇编语言实现) (10)一、实验目的和要求(如合作完成,需注明分工)1. 掌握定时器的使用2. 掌握中断的使用,并能够使用定时器进行定时中断3. 掌握中断程序编写的方法和注意点4. 掌握键盘扫描的实现、编程5. 在上次实验基础上,实现数码管的显示6. 掌握CPLD控制LED灯的方法7. 能够使用汇编语言实现复杂的逻辑功能8. 学习模块化编程分工:定时中断实验(包括扩展部分):****编写代码,共同调试键盘输入与显示综合实验:****编写代码,共同调试二、实验原理1. 定时中断实验利用单片机定时器中断,控制单片机P0.0口输出一50Hz的方波。
结果可采用示波器显示。
提高要求(选做可加分):实现50Hz的PWM波的输出,可以采用某个拨码开关选择不同的PWM占空比(例如某个拨码状态为0时表示占空比为40%,状态为1时表示占空比为80%),拨码开关地址为0F500H,位于LED灯下排。
2. 键盘输入与显示综合实验利用4*4键盘输入,在通过CPLD译码与CPU总线相连的8位LED上显示键码值(实验箱上有两排LED,这里指的是下面一排,无需连线),并在8位数码管上显示输入的数字。
电路如图3-1所示。
键盘矩阵输入电路采用行列扫描法实现。
将行线接输出口,列线接到输入口,采用列扫描法,先将某一行输出为低电平,其它行输出为高电平,用输入口来查询列线上的电平,逐次读入列值,如果行线上的值为0时,列线上的值也为0,则表明有按键按下。
否则,接着读入下一列,直到找到该行有按下的键为止。
如该行没有找到有按键按下,就按此方法逐行找下去,直到扫描完全部的行和列。
4*4键盘示意图与CPU总线相连的8位LED地址为0F600H,数码管段控地址为0F300H,位控地址为0F400H。
4*4键盘地址为0F700H,其中行线对应该地址的低4位数据,只可以写不可以读;而列线对应高4位数据,只可以读不可以写。
键码表如下所示:(由于键盘可能会调整,不一定正确,请按照实际情况自己确定,这里仅键码表中,ExH 表示键码值的高4位为E ,低4位未知,这表示的是选通第1条行线。
xEH 表示低4位为E ,高4位未知,表示的是选通第1条列线。
故而第一条行线和第一条列线交叉处的键C 的键码值为0EEH 。
其它键以此类推。
三、 实验方案与实验步骤1. 定时中断实验简单的实现,无扩展部分扩展部分的流程图:2. 键盘输入与显示综合实验四、实验设备与器材配置1. PC机一台2. 红色仿真盒一个3. 实验平台一个键盘拨码盘下排LED灯数码管五、实验记录(自行设计记录方式)1. 定时中断实验接线方式:使用了拨码盘,由于内部寻址读取不可用,将拨码盘连接I/O口P3,通过P3第四位读取拨码盘的第四位,进行控制。
可变占空比的方波,输出波形:10%30%50%70%90%2. 键盘输入与显示综合实验六、实验总结(包括实验数据处理、实验结果分析讨论等)本次实验,主要针对定时器使用和键盘使用。
编程方面,主要针对中断的使用。
第一个实验,基础部分针对定时器和定时器的中断,需要对定时器进行初始值、控制寄存器设定,还需要将特殊的控制字比如允许中断的控制字等进行相应的设置。
在编程时,还需要在中断向量的地方给出具体的中断向量,编写相应的中断处理程序。
对于中断程序,必须要进行堆栈设置,因为中断产生需要保存断点,将PC的值入栈,待中断结束再将PC值出栈。
第一个程序的扩展部分,需要对程序灵活操作,由于拨码盘的地址无法读入拨码盘,因此将拨码盘通过通用I/O口读入。
键盘综合程序,主要进行了键盘的扫描。
除了键盘扫描,编程中需要将键盘码转换成具体的数字,因此需要查表转换,需要一定的变成灵活性。
程序中还需要使用数码管,使用方法和之前程序相同,而且不需要扫描输出,因此比较简单。
七、思考题或讨论题(若干)1. 数据可以放在哪里?放在哪里合适?为什么?答:数据可以放在除了系统保留、中断向量区、堆栈区以外的地方。
数据最好放在整个程序的最尾部。
我们在调试代码时,需要对某一些语句进行跟踪观察执行结果,因此,我们总希望代码的地址更好地查询,而且能够更快的得到。
但是,数据一般占用较多的地方,如果把数据放在程序的开始部位或者是中间部位,都会使得代码的地址很难确定,因而在调试时会使得查找某条具体语句变得复杂。
当数据放在所有的代码之后,此时就不会过多的影响前面的代码。
2. 设置堆栈有什么用处?答:1. 中断产生时,用于保存断点,即PC的值,以便于中断程序返回时,能够回到原来的需要执行程序。
2. 中断产生时,用于保护中断之前的现场,需要结合push语句使用,需要注意,在中断结束时,也需要相应的pop语句恢复现场,否则会出现堆栈错误。
3. 用于程序中需要临时存储变量的时候。
3. 如何一次性判断是否有按键?答:给行对应的四位都写低,此时,从电路上看,如果有按键按下,那么,肯定会有某一列的输出时低电平,这时,读入列值,将会有一列是低电平,其他列是高电平,那么,列值对应的四位就不是全为1,那么读入的列值四位将小于F。
如果没有按键,那么所有列读入的值都是1,列值就是F,所以,只需要将列值跟F对比,只要不是F,或者说,只要小于F,就有按键,等于或者不小于F时,就没有按键。
对应的代码如下:MOV A,#0F0H ;给行值全部输出为0,即低电平MOV DPTR,#0F700H ;键盘地址MOVX @DPTR,A ;输出到行值MOVX A,@DPTR ;读入列值ANL A,#0F0H ;忽略低位,只看列值读入的值CJNE A,#0F0H,NEW_KEY ;比较,如果有按键,那就有不是高电平的位,则和F不相等,或者说是比F小,那就跳转出去LJMP BEGIN ;没有读到有按键,继续循环4. 如何实现根据拨码盘的输入输出不同的占空比波形?答:我们在中断程序里主要是给定时器新的计时初值,并且将输出反转。
对于不同的占空比,高电平输出时间和低电平输出的时间是不同,因此,我们必须要解决在不同的电平输出时给定时器不同的计数初值。
解决这个问题,可以通过判断原来的输出值,来决定给下一个计数初值。
我们将一个占空比对应的高电平计数初值、低电平计数初值放在一起,共有四字节,当判断要输出高字节,那就取前二字节,否则就取后二字节。
根据读入拨码盘的数值,取计数初值。
但是由于一个占空比的计数初值共有四字节,因此,读入的拨码盘值需要变成四倍。
这样就能够实现变占空比的波形输出。
八、附上源代码(注意实验只能采用汇编语言实现)1. 定时中断实验ORG 0000HLJMP MAIN ;主程序ORG 001BHLJMP INTORG 0100HMAIN:MOV SP,60H ;预设堆栈区MOV TMOD,#01HMOV R7,#0D8HMOV R6,#0F0HMOV TH1,R7 ;计时10 000周期即1101 1000 1111 0000B MOV TL1,R6SETB EA ;开中断SETB ET1 ;定时器1允许中断SETB TR1 ;定时开始HERE: ;CALL DELAY;CPL P0.0SJMP HEREINT:MOV TH1,R7 ;计时10 000周期即1101 1000 1111 0000B MOV TL1,R6CPL P0.0 ;取反RETIEND定时中断实验扩展部分代码:ORG 0000HLJMP MAIN ;主程序ORG 001BH ;LJMP INTORG 0100HPWM:DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0F8H,30H,0B9H,0B0H ;10%DB 0F0H,60H,0C1H,80H ;20%DB 0E8H,90H,0C9H,50H ;30%DB 0E0H,0C0H,0D1H,20H ;40%DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0D1H,20H,0E0H,0C0H ;60%DB 0C9H,50H,0E8H,90H ;70%DB 0C1H,80H,0F0H,60H ;80%DB 0B9H,0B0H,0F8H,30H ;90%DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0D8H,0F0H,0D8H,0F0H ;50%DB 0D8H,0F0H,0D8H,0F0H ;50%;10%:63536,47536,F830H,B9B0H;20%,61536,49536,F060H,C180H;30%,59536,51536,E890H,C950H;40%,57536,53536,E0C0H,D120H;50%,55536,D8F0HMAIN:MOV SP,60H ;预设堆栈区MOV TMOD,#01H ;计数方式1MOV R7,#0D8HMOV R6,#0F0HMOV TH1,R7 ;计时10 000周期即1101 1000 1111 0000BMOV TL1,R6SETB EA ;开中断SETB ET1 ;定时器1允许中断SETB TR1 ;定时开始CLR CBEGIN:;MOV DPTR,#0F500H;MOVX A,@DPTRMOV A,P3ANL A,#0FH ;避免高位扰动MOV R5,AADD A,R5ADD A,R5ADD A,R5 ;给首址;MOV R4,AJMP BEGININT:MOV DPTR,#PWMMOV C,P0.0JC ZEROMOV A,R4MOVC A,@A+DPTRMOV R7,AMOV A,R4INC AMOVC A,@A+DPTRMOV R6,ASJMP OKZERO:MOV A,#02HADD A,R4MOVC A,@A+DPTRMOV R7,AMOV A,R4INC AMOVC A,@A+DPTRMOV R6,AOK:MOV TH1,R7MOV TL1,R6CPL P0.0 ;按位取反RETIEND2. 键盘输入与显示综合实验ORG 0000HLJMP MAINORG 0100HKEY_CODE: DB 7EH,7DH,7BH,77H,0BEH,0BDH,0BBH,0B7H,0DEH,0DDH,0DBH,0D7H,0EEH,0EDH,0EBH,0 E7HTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH ;段码;由于读进来的是一种键盘码的码,需要和代表的数字对应起来,只能是查表;本数据是按照0-F的顺序排列的,位置就是数字值MAIN:MOV SP,#60HBEGIN:MOV A,#0F0HMOV DPTR,#0F700H;键盘地址MOVX @DPTR,AMOVX A,@DPTRANL A,#0F0H ;忽略低位CJNE A,#0F0H,NEW_KEY ;比较,如果有按键,那就有不是高电平的LJMP BEGIN;没有按键,继续循环NEW_KEY:MOV A,#0FEH ;1111 1110MOV R7,#04HKEY_LOOP:PUSH ACCMOV DPTR,#0F700HMOVX @DPTR,AMOVX A,@DPTRANL A,#0F0HCJNE A,#0F0H,NEW_KEY1 ;如果有按键,那么就不是都是高电平,跳转POP ACCRL A ;移位DJNZ R7,KEY_LOOP ;判断,只有四位,循环四次JMP BEGIN ;没找到按键,回到最初NEW_KEY1:MOV R6,A ;找到按键,保存目前的列值POP ACC ;弹出原来保存的行值ANL A,#0FH ;清空高位ADD A,R6;得到键盘码MOV R5,A ;保存起来MOV DPTR,#0F600H ;输出给LED灯CPL AMOVX @DPTR,AMOV DPTR,#KEY_CODE ;开始循环查找键盘码对应的数字MOV R7,#10H ;循环16次MOV R6,#00H ;记录是第几个按键,也可以不用,最后用16-R7也可以,但还得用这个作为偏移量LOOP:MOV DPTR,#KEY_CODEMOV A,R6 ;偏移量MOVC A,@A+DPTR ;取数据MOV R4,A ;MOV A,R5 ;CLR C ;SUBB A,R4 ;JZ KEY_OK ;INC R6DJNZ R7,LOOPJMP BEGINKEY_OK:MOV A,R6MOV DPTR,#TABMOVC A,@A+DPTRMOV DPTR,#0F300HMOVX @DPTR,AMOV A,#00HMOV DPTR,#0F400HMOVX @DPTR,AJMP BEGINEND。