按键中断显示
- 格式:ppt
- 大小:837.50 KB
- 文档页数:22
实验二按键中断实验一、实验目的了解中断的含义二、实验内容板子加电后,按动板子上K1-K3按键,可控制对应的LED1-LED3的亮灭,该实验学习了外部中断(EXTI)程序的编制及控制流程。
三、实验仪器、设备计算机、开发板、keil软件四、硬件设计在开发板上V6、V7、V8分别与MCU的PB5、PD6、PD3相连,如下图所示键盘部分如下图所示:例程所用到的列扫描线:PC5,PC2,PC3。
例程所用到的行扫描线(EXTI中断线):PE2。
五、实验要求和步骤开发板上有3个蓝色状态指示灯V6(LED1),V7(LED2),V8(LED3),通过对应的按键K1-K3,控制LED的亮灭,将PE2引脚配置为外部中断,当其上出现下降沿时产生一个中断,根据扫描PC5,PC2,PC3来判别是哪个按键按下。
首先我们了解一下什么是外部中断/事件控制器(EXTI)。
外部中断/事件控制器由19个产生事件/中断要求的边沿检测器组成。
每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。
每个输入线都可以被独立的屏蔽。
挂起寄存器保持着状态线的中断要求。
EXTI控制器的主要特性如下:每个中断/事件都有独立的触发和屏蔽每个中断线都有专用的状态位支持多达19 个中断/事件请求检测脉冲宽度低于APB2 时种宽度的外部信号如要产生中断,中断线必须事先配置好并被激活。
这是根据需要的边沿检测通过设置2个触发寄存器,和在中断屏蔽寄存器的相应位写“1”到来允许中断请求。
当需要的边沿在外部中断线上发生时,将产生一个中断请求,对应的挂起位也随之被置1。
通过写“1”到挂起寄存器,可以清除该中断请求。
为产生事件触发,事件连接线必须事先配置好并被激活。
这是根据需要的边沿检测通过设置2个触发寄存器,和在事件屏蔽寄存器的相应位写“1”到来允许事件请求。
当需要的边沿在事件连线上发生时,将产生一个事件请求脉冲,对应的挂起位不被置1。
单⽚机实验:外部中断按键实验内容:实验⼤致上就是说:按键不按的时候,灯⼀直亮,按键按下的时候,灯不亮,报警器响。
现在给了汇编语⾔,要改成c语⾔,并在proteus⾥⾯仿真。
思考与总结:响应中断请求的条件:1.总中断允许开关EA=1。
2.中断源的中断允许位为1。
3.中断源发出中断请求。
4.⽆同级或更⾼级中断正在被服务。
结合实验,就知道,这⾥跑到中断⼦程序的条件,⾸先总开关打开。
然后选择中断请求源,对这个实验来说,也就是选择I N T 0 ‾\overline{INT0}INT0外部中断请求0,它的中断允许控制位是E X 0 EX0EX0,我们置1后,就说明允许了外部中断0中断。
我们如果选⽤跳沿触发,⼀个机器周期采样到外部中断输⼊为⾼,下⼀个为低,那么中断请求触发器置⼀,这个时候进⼊中断⼦程序。
这个实验是电平触发。
cpu查询到中断请求时,就会进⾏中断响应(这⾥假设只是单⼀中断,如果有不同优先级的中断,那么cpu还要进⾏判断)。
硬件⽣成⼀个长调⽤指令并执⾏,程序转向中断⼊⼝地址,两个中断⼊⼝相隔8字节,难以放下中断⼦程序,此时需要⼀个跳转指令,转向在其他地址下的⼦程序中。
实验结果:汇编语⾔实现:ORG 0000hLJMP MAIN//主程序ORG 0003hLJMP INT0s//中断⼊⼝ORG 0100hMAIN: CLR IT0//外部中断请求0为电平触发SETB EA//总中断允许SETB EX0 //允许外部中断0LOOP: CLR P0.0//p0.0是低电平,此时灯亮SETB P2.3//p2.3是⾼电平,此时警报不响SJMP LOOP//短转移指令,程序跳到loop函数循环ORG 0200h//伪指令INT0s: SETB P0.0//p0.0是⾼电平,此时灯灭CLR P2.3//p2.3是低电平,此时警报响Delay: MOV R0,#200//延时函数D1: MOV R1,#254D2: DJNZ R1,D2DJNZ R0,D1RETIEND改成c51语⾔:#include<reg51.h>#define uchar unsigned charsbit key = P3^2;void delay(unsigned int i)//延时函数{unsigned int j;for(;i>0;i--)for(j=0;j<333;j++){}}void main()//主函数{EA=1;//总中断允许EX0=1;//允许外部中断0IT0=0;//选择外部中断0为电平触发⽅式while(1)//循环{P0=0xfe;}//P0.0⼝的Led亮}void key_scan() interrupt 0//外部中断0的中断服务函数{if(key==0)//判断是否有按键按下{delay(10);//延时去抖if(key==0){P2=0xf7;P0=0xff;while(!key);//等待按键松开P2=0xff;P0=0xfe; }}}proteus仿真:。
实验三键盘及LED显示实验一、实验内容利用8255可编程并行接口控制键盘及显示器,当有按键按下时向单片机发送外部中断请求(INT0,INT1),单片机扫描键盘,并把按键输入的键码一位LED 显示器显示出来。
二、实验目的及要求(一)实验目的通过该综合性实验,使学生掌握8255扩展键盘和显示器的接口方法及C51语言的编程方法,进一步掌握键盘扫描和LED显示器的工作原理;培养学生一定的动手能力。
(二)实验要求1.学生在实验课前必须认真预习教科书与指导书中的相关内容,绘制流程图,编写C51语言源程序,为实验做好充分准备。
2.该实验要求学生综合利用前期课程及本门课程中所学的相关知识点,充分发挥自己的个性及创造力,独立操作完成实验内容,并写出实验报告。
三、实验条件及要求计算机,C51语言编辑、调试仿真软件及实验箱50台套。
四、实验相关知识点1.C51编程、调试。
2.扩展8255芯片的原理及应用。
3.键盘扫描原理及应用。
4.LED显示器原理及应用。
5.外部中断的应用。
五、实验说明本实验仪提供了8位8段LED显示器,学生可选用任一位LED显示器,只要按地址输出相应的数据,就可以显示所需数码。
六、实验原理图P1口桥接。
八、实验参考流程图1.主程序流程图2.外中断服务程序流程图外部中断0 外部中断1定时器0中断程序,用于消抖动:3.LED显示程序流程图九、C51语言参考源程序#include "reg52.h"unsigned char KeyResult; //存放键值unsigned char buffer[8]; //显示缓冲区bit bKey; //是否有键按下xdata unsigned char P_8255 _at_ 0xf003; //8255的控制口xdata unsigned char PA_8255 _at_ 0xf000; //8255的PA口xdata unsigned char PB_8255 _at_ 0xf001; //8255的PB口xdata unsigned char PC_8255 _at_ 0xf002; //8255的PC口code unsigned char SEG_TAB[] = { //段码0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0xee,0x3e,0x9c,0x7a,0x9e,0x8e,0x0};sbit bLine0 = P3^2;sbit bLine1 = P3^3;//延时1msvoid Delay1ms(){unsigned char i;i = 0;while (--i);}//显示void Display(){unsigned char i = 0x7f;unsigned char j;for (j = 0; j < 8; j++){PA_8255 = i; //扫描PB_8255 = SEG_TAB[buffer[j]]; //段数据i = i / 2 + 0x80;Delay1ms();}}//更新显示缓冲区数据void RefurbishData(){char i;for (i = 7; i >0; i--)buffer[i] = buffer[i-1];buffer[0] = KeyResult;}void Int0Int() interrupt 0{unsigned char i = 0x80;unsigned char KeyResult0 = 0x0;EX0 = 0; //关外部中断0P_8255 = 0x89; //PC口输入bLine0 = 0; //P3.2作行输出while (i){if ((PC_8255 & i) == 0)break;KeyResult0++;i >>= 1;}P_8255 = 0x80; //8255的PA、PB、PC口全作输出口PC_8255 = 0;bLine0 = 1;if (i){TH0 = 60; //定时中断计数器初值TL0 = 176; //定时50msTR0 = 1;KeyResult = KeyResult0;}IE0 = 0; //清除中断EX0 = 1; //开外部中断0}void Int1Int() interrupt 2{unsigned char i = 0x80;unsigned char KeyResult0 = 8;EX1 = 0; //关外部中断0P_8255 = 0x89; //PC口输入bLine1 = 0; //P3.2作行输出while (i){if ((PC_8255 & i) == 0)break;KeyResult0++;i >>= 1;}P_8255 = 0x80; //8255的PA、PB、PC口全作输出口PC_8255 = 0;bLine1 = 1;if (i){TH0 = 60; //定时中断计数器初值TL0 = 176; //定时50msTR0 = 1;KeyResult = KeyResult0;}IE1 = 0; //清除中断EX1 = 1; //开外部中断0}//50ms中断服务程序void INT_Timer0(void) interrupt 1{if (((KeyResult < 8) && !bLine0) ||((KeyResult >= 8) && !bLine1)){bKey = 1; //有键按下,键值在KeyResult中}TR0 = 0;}void main(){char i;bKey = 0; //没有键按下TMOD = 1; //定时器0:方式一P_8255 = 0x80; //8255的PA、PB、PC口全作输出口PC_8255 = 0x0;ET0 = 1; //开定时器0中断EX0 = 1; //开外部中断0EX1 = 1; //开外部中断1IT0 = 1; //边沿触发IT1 = 1; //边沿触发EA = 1; //允许中断for (i = 0; i < 8; i++)buffer[i] = 0x10;// TR0 = 1; //开定时器T0// bRefurbish = 1;while (1){if (bKey){bKey = 0;RefurbishData();}Display(); //调用显示}}十、实验实施步骤1.仔细阅读实验内容及要求,编写C51源程序。
总结按键输入外部中断请求信号存在的问题与解决方法外部中断是嵌入式系统中常见的一种事件响应机制,可以通过外部设备发出的中断信号来触发处理器执行相应的中断服务程序。
在实际的应用中,按键输入作为一种常见的外部中断源,经常被应用于用户交互和控制系统中。
然而,按键输入外部中断请求信号也会带来一些问题,包括抖动、冲突以及消隐等,并且需要针对这些问题采取相应的解决方法。
按键输入外部中断请求信号存在的问题主要包括抖动、冲突和消隐,下面将逐一介绍这些问题及解决方法。
一、抖动问题按键抖动是指在按下或释放按键的瞬间,由于机械结构的弹性特性或者接触点的不良接触,会导致按键信号在短时间内多次震动,造成中断信号的多次触发,使得系统产生误操作或者多次中断的情况。
解决按键抖动问题的方法主要包括软件滤波和硬件滤波。
1、软件滤波软件滤波是通过在中断服务程序中增加延时、状态检测等手段来解决按键抖动问题的方法。
通过在中断服务程序中增加延时等操作,可以排除由于按键抖动造成的多次中断信号的干扰,确保系统的稳定性和可靠性。
然而,软件滤波需要占用处理器的执行时间和资源,容易影响系统的实时性和响应速度。
2、硬件滤波硬件滤波是采用电路设计来解决按键抖动问题的方法。
通过在按键输入信号的引脚上接入RC滤波电路、反嵌二极管等元件,可以有效地减少按键抖动造成的中断信号的干扰,确保系统对按键输入信号的正确响应。
相比于软件滤波,硬件滤波可以减轻处理器的负担,提高系统的实时性和响应速度。
二、冲突问题按键冲突是指在多个按键同时按下或释放的情况下,会产生错误的中断信号或者无法正确识别所触发的按键,导致系统的误操作或功能执行异常。
解决按键冲突问题的方法主要包括硬件防抖和编码解码电路。
1、硬件防抖硬件防抖是通过在按键输入信号的引脚上接入双稳态触发器或者滤波电路等元件来解决按键冲突问题的方法。
通过这些电路设计,可以确保在多个按键同时按下或释放的情况下,系统可以正确识别并执行相应的中断服务程序,确保系统的稳定性和可靠性。
实验8-2 键盘中断驱动实验【实验目的】掌握键盘原理。
熟悉驱动的中断机制。
【实验步骤】第一步:利用vi编辑器,编写一个Keypad.c驱动代码;1、增加驱动所需的头文件和变量#include<linux/module.h>#include<linux/kernel.h>#include<linux/init.h>#include<linux/delay.h>#include<linux/poll.h>#include<linux/spinlock.h>#include<asm/hardware.h>#include<asm/arch-pxa/pxa-regs.h>MODULE_LICENSE("GPL");#define DEVICE_NAME "emdoor_kbd"#define KEYVALUE_HAVE 1#define KEYVALUE_NO 0#define KPC_DIR 1<<5#define KPC_MAT 1<<22static int Emdoor_kbd_fasync(int, struct file* ,int); typedef unsigned char KBD_RET;struct fasync_struct * fasync;//键盘结构体定义typedef struct {KBD_RET kbd_buff; /* protect against overrun */ unsigned int kbd_status;wait_queue_head_t wq;spinlock_t lock;} KBD_DEV;2、实现键盘驱动读操作函数static ssize_t Emdoor_kbd_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){KBD_DEV * kbd=filp->private_data;KBD_RET kbd_ret;while(1){if(kbd->kbd_status==KEYVALUE_HAVE){kbd_ret = kbd->kbd_buff;copy_to_user(buffer, &kbd_ret, sizeof(KBD_RET));kbd->kbd_status=KEYVALUE_NO;return sizeof(KBD_RET);}else{if (filp->f_flags & O_NONBLOCK)return -EAGAIN;interruptible_sleep_on(&(kbd->wq));if (signal_pending(current))return -ERESTARTSYS;}}return sizeof(KBD_RET);}3、实现键盘驱动中断服务例程static void Emdoor_isr_kbd(int irq, void *dev_id, struct pt_regs *reg){printk(KERN_EMERG"Emdoor_isr_kbd,Interrupt\n");int kpc_value;KBD_DEV * kbd = (KBD_DEV *) dev_id;spin_lock_irq(&(kbd->lock));kpc_value=KPC;if(kpc_value&KPC_MAT) {kbd->kbd_buff=KPAS&0xFF;if(kbd->kbd_buff!=0xFF){switch(kbd->kbd_buff){case 0x0: kbd->kbd_buff=5; break;case 0x1: kbd->kbd_buff=6; break;case 0x2: kbd->kbd_buff=7; break;case 0x5: kbd->kbd_buff=8; break;case 0x10: kbd->kbd_buff=9; break;case 0x11: kbd->kbd_buff=10; break;case 0x12: kbd->kbd_buff=11; break;case 0x15: kbd->kbd_buff=12; break;case 0x20: kbd->kbd_buff=13; break;case 0x21: kbd->kbd_buff=14; break;case 0x22: kbd->kbd_buff=15; break;case 0x25: kbd->kbd_buff=16; break;default: break;}kbd->kbd_status=KEYVALUE_HAVE;}}else if(kpc_value&KPC_DIR){kbd->kbd_buff=KPDK&0xFF;if(kbd->kbd_buff!=0x0){switch(kbd->kbd_buff){case 0x40: kbd->kbd_buff=1; break;case 0x2: kbd->kbd_buff=2; break;case 0x4: kbd->kbd_buff=3; break;case 0x20: kbd->kbd_buff=4; break;default: break;}kbd->kbd_status=KEYVALUE_HAVE;}}if ( fasync )kill_fasync( &(fasync), SIGIO, POLL_IN );wake_up_interruptible(&(kbd->wq));spin_unlock_irq(&(kbd->lock));}4、实现键盘驱动设备打开操作函数static int Emdoor_kbd_open(struct inode *inode, struct file *filp) {int ret;printk(KERN_EMERG " Emdoor_kbd_open!\n");KBD_DEV * kbd;kbd =(KBD_DEV *) kmalloc(sizeof(KBD_DEV ), GFP_KERNEL);KPC=KPC_ASACT | (3<<26) | (7<<23 ) | KPC_IMKP | KPC_MS6 |KPC_MS5 |KPC_MS4 | KPC_MS3 | KPC_MS2 | KPC_MS1 | KPC_MS0 | KPC_ME |KPC_MIE | (7<<6) | KPC_DE | KPC_DIE;init_waitqueue_head(&(kbd->wq));pxa_gpio_mode(94 | GPIO_ALT_FN_1_IN);//KP_DKIN<1>pxa_gpio_mode(95 | GPIO_ALT_FN_1_IN);//KP_DKIN<2>pxa_gpio_mode(98 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(99 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(100 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(101 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(102 | GPIO_ALT_FN_1_IN);pxa_gpio_mode(103 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<0>pxa_gpio_mode(104 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<1>pxa_gpio_mode(105 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<2>pxa_gpio_mode(108 | GPIO_ALT_FN_2_OUT);//KP_MKOUT<5>kbd->kbd_status=KEYVALUE_NO;filp->private_data=kbd;ret = request_irq(IRQ_KEYPAD, Emdoor_isr_kbd, SA_INTERRUPT, DEVICE_NAME, kbd);if (ret){printk(KERN_EMERG " Interrupt init=%x!!!!\n",ret);return ret;}return 0;}5、实现键盘驱动select和poll操作函数static unsigned int Emdoor_kbd_poll(struct file *filp,struct poll_table_struct *wait){printk(KERN_EMERG " Emdoor_kbd_poll!\n");KBD_DEV * kbd=filp->private_data;poll_wait(filp,&(kbd->wq),wait);return (kbd->kbd_status==KEYVALUE_HAVE) ? (POLLIN|POLLRDNORM): 0 ;}static int Emdoor_kbd_release(struct inode *inode, struct file *filp){printk(KERN_EMERG " Emdoor_kbd_release!\n");KBD_DEV * kbd = filp->private_data;KPC=0x0;Emdoor_kbd_fasync(-1, filp, 0);kfree(kbd );free_irq(IRQ_KEYPAD, kbd);return 0;}6、实现键盘驱动非阻塞访问操作函数static int Emdoor_kbd_fasync(int fd, struct file * file, int mode) {return fasync_helper(fd, file, mode, &(fasync) );}7、键盘驱动文件结构体定义static struct file_operations Keypad_fops = {open: Emdoor_kbd_open,read: Emdoor_kbd_read,release: Emdoor_kbd_release,poll: Emdoor_kbd_poll,fasync: Emdoor_kbd_fasync,owner: THIS_MODULE,};8、键盘驱动初始化函数定义static int __init Emdoor_kbd_init(void){printk(KERN_EMERG " Emdoor_kpd initialized\n");int ret;ret = register_chrdev(62, DEVICE_NAME, &Keypad_fops);if (ret < 0) {printk(DEVICE_NAME " can't get major number\n");return ret;}free_irq(IRQ_KEYPAD,NULL);udelay(10);return 0;}9、键盘驱动退出函数定义static void __exit Emdoor_kbd_exit(void){printk(KERN_EMERG " Emdoor_kpd exit\n");unregister_chrdev(62, DEVICE_NAME);}module_init(Emdoor_kbd_init);module_exit(Emdoor_kbd_exit);MODULE_AUTHOR("Ben.li@");MODULE_DESCRIPTION("This is a Keypad driver demo");第二步: 利用vi编辑器,编写一个用于编译Keypad驱动的Makefile# Makefile for the Keypad. #CFLAGS +=$(DEBFLAGS) -Wallifneq ($(KERNELRELEASE),)obj-m :=Keypad.oelseKERNELDIR ?=/root/work/linux-2.6.9PWD :=$(shell pwd)ALL:$(MAKE) $(CFLAGS) -C $(KERNELDIR) M=$(PWD) modulesendifclean:rm -fr *.o *.ko *~ core .depend .*.cmd *.mod.c .tmp_versions第三步:运行make编译命令,用ls命令查看编译后的结果,在该目录中应生成Keypad.ko模块文件,利用file命令查看Keypad.ko文件的格式,应为ARM 格式的ELF文件。
单片机中断实现按键一、引言在嵌入式系统中,往往需要通过外部输入设备如按键来与系统进行交互。
为了能够及时响应按键操作,避免忙等的情况发生,通常会使用中断技术来实现按键的检测和处理。
本文将介绍如何使用中断来实现按键检测,并具体以8051单片机作为示例进行说明。
二、中断基础知识在单片机中,中断是一种由硬件触发的特殊事件,当一些中断条件满足时,单片机会暂停当前任务,跳转到中断服务程序中执行对应的处理代码,待中断处理结束后再返回到原来的任务中。
中断的触发方式一般有两种:外部触发中断和内部触发中断。
对于按键这种外部输入设备,一般通过外部触发中断来实现。
三、实现原理1、按键电路:按键通常由一个导电片和两个触点组成,平时靠两个触点之间的弹簧将导电片与触点隔开,当按下按键时,弹簧压缩,导电片与触点接触形成通路。
为了能够检测按键操作,需要将按键引脚连接到单片机的外部中断引脚上。
2、中断设置:在单片机的程序中,需要设置好相应的中断向量表和中断服务程序。
中断向量表是一个存放中断服务程序地址的表格,当中断触发时,单片机会根据中断号从中断向量表中找到相应的中断服务程序地址并跳转到该地址执行对应代码。
3、中断触发条件:在按键电路中,按键的两个触点状态变化(从断开到接通或从接通到断开)时会产生干扰信号,为了避免干扰,通常会使用软件消抖技术。
当按键被按下,并经过一段时间的消抖后,会产生一个稳定的按键信号,此时可以检测到按键变化,并触发相应的中断。
四、实现步骤1、硬件连接:将按键引脚连接到单片机的外部中断引脚上。
2、中断设置:在单片机的程序中,需要设置中断的相关寄存器,包括中断向量表和中断控制寄存器。
中断向量表保存中断服务程序的入口地址,中断控制寄存器用于设置中断触发条件和中断优先级等参数。
3、中断服务程序:编写中断服务程序,在按键中断触发时执行对应的处理代码。
中断服务程序一般需要包括中断触发条件的判断和处理代码的执行。
4、主程序:在主程序中调用中断服务程序,并添加相应的处理代码,实现按键操作的具体功能。
硬件电路参考如下:程序参考如下:#pragma sfr#pragma interrupt INTP0 LED_INTP0 /* 定义使用INTP0中断,中断函数名LED_INTP0*/ #pragma di /*禁止使用中断功能声明*/#pragma ei /*允许使用中断功能声明*//*数码管编码数组*/unsigned char LED_light[10]={0x30,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x3F}; unsigned char j=0; /*按键次数变量*/void hdinit() /*硬件初始化*/{PM1=0; /*P1口输出数码管字型码,所以设置为输出*/PU1=0XFF; /*由于P1口直接驱动数码管显示,为增大驱动,设置为内部上拉*/PM12.0=0; /*P12.0口线要作为中断多功能,设置为输出和内部上拉 */PU12.0=1;PIF0=0; /*中断请求标志,没有中断请求*/PMK0=0; /*中断屏蔽标志,允许中断*/PPR0=1; /*中断优先级,低优先级*/EGP.0=1; /*与EGN组合,上升沿有效*/EGN.0=0;}void main (void){DI(); /*首先做准备,禁止中断*/IMS=0XCC;IXS=0X00;hdinit();EI(); /*准备完成,允许中断*/while(1){ /*啥也不干,就等待中断,仅是在这个实验中使用中断,实际不是这样/*}}__interrupt void LED_INTP0() /*中断函数*/{ P1= LED_light[j]; /*P1赋值,数码管显示相应数值*/j++; /*按键次数加一*/if(j==10) /*如果按键次数达到十次,按键计数归0*/{j=0;} }思考: 如果用两位数码管,从0—99循环计数又该怎样设计硬件和软件呢?。
按键的中断编程实验
一.实验目的
1.掌握用C51对外不中断设置的方法
2.掌握按键用C51进行识别的方法
二.实验要求
1.基本要求
(1)能够对有关中断的各个寄存器进行设置
(2)能够用C51编写中断服务程序,当每按一下按键,在中断服务程序中实现数码管上显示数据从0以步进为1的步调增加。
2.扩展要求
(1)用实验板上的上下左右按键做一个秒表,其中做按键作为启动按键,上按键作为清零按键,右按键作为停止按键。
三.实验电路原理图
电路图如下图(1)
四.实验原理简介
(1)每进入中断一次实现数码管上显示数据加1,且按按键时蜂鸣器发声。
(2) 配合上下左右按键做一秒表,要求按左键的话秒表启动,按右键的
话秒表停止,按上键的话秒表清零。
C8
C9
(移)(加)(移)(减)
IN4148X4
图(1)。
一、实验目的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灯灭。
STM32按键中断(HAL库版)
本文将介绍如何使用STM32F4的IO口作为中断触发源,通过串口显示按键被按下的日志。
一、运用到的资源、工具:
1.1开发板芯片STM32F407,PI9作为外部中断源、USART3串口向屏幕传输信息
1.2编译工具:MDK-ARM V5(keil5)
1.3辅助工具:STM32CubeMX
二、硬件设计
2.1原理图:
三、软件设计
3.1STM32cubeMX配置工程文件
选择Key1作为外部中断源、选择中断触发方式为下降沿触发、并设置中断优先级分组选择优先级
使能USART3串口配置为异步通信
最后生成工程文件
3.2串口输出重定向(重写fputc函数)
int fputc(int ch, FILE *p)
{
while(!(USART3->SR & (1 << 7)));USART3->DR = ch;
return ch;
}
3.3在中断回调函数中,打印KEY1 DOWN\n
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_9)
{
HAL_Delay(40);
if(HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_9) == 0)
{
printf("KEY1 DOWN\n");
}
}
}
四、代码及运行结果
4.1运行结果按下KEY1、打印一次KEY1 DOWN。
KeilC51学习4按键外部中断主板介绍:P3^2~P^5为四个按键;P1^0~P1^7为8个LED灯#include "reg52.h"//此⽂件中定义了单⽚机的⼀些特殊功能寄存器typedef unsigned int uint; //对数据类型进⾏声明定义typedef unsigned char u8;sbit k1=P3^5; //定义P31⼝是k1sbit led=P1^0; //定义P10⼝是led/******************************************************************************** 函数名 : delay* 函数功能 : 晶振11.0592M延时函数*******************************************************************************/void delay(uint z){uint i,j;for(j=z;j>0;j--)for(i=112;i>0;i--);}/******************************************************************************** 函数名 : keypros* 函数功能 : 按键处理函数,判断按键K1是否按下*******************************************************************************/void keypros(){if(k1==0){delay(50);if(k1==0) //再次判断按键是否按下led=~led; //led状态取反}while(!k1); //检测按键是否松开}/******************************************************************************** 函数名 : main* 函数功能 : 主函数* 输⼊ : ⽆* 输出 : ⽆*******************************************************************************/void main(){while(1){keypros(); //按键处理函数}}按键取反灯亮或灭计数器(计数器0⽤P3^4按钮,计数器1⽤P3^5按钮,不懂)/*-----------------------------------------------名称:计数器0论坛:编写:shifang⽇期:2009.5修改:⽆内容:通过外部按键计数进⼊中断执⾏LED取反------------------------------------------------*/#include<reg52.h> //包含头⽂件,⼀般情况不需要改动,头⽂件包含特殊功能寄存器的定义sbit LED=P1^0; //定义LED端⼝/*------------------------------------------------定时器初始化⼦程序(按钮P3^4控制,不知为什么)------------------------------------------------*/void Init_Timer0(void){TMOD |= 0x01 | 0x04; //使⽤模式1,16位计数器,使⽤"|"符号可以在使⽤多个定时器时不受影响TH0=0xFF; //给定初值TL0=245; //从245计数到255EA=1; //总中断打开ET0=1; //定时器中断打开}/*------------------------------------------------主程序------------------------------------------------*/main(){Init_Timer0();while(1);}/*------------------------------------------------定时器中断⼦程序------------------------------------------------*/void Timer0_isr(void) interrupt 1using1{TH0=0xFF; //重新给定初值TL0=245;LED=~LED; //指⽰灯反相,可以看到闪烁}计数器0/*-----------------------------------------------名称:计数器1论坛:编写:shifang⽇期:2009.5修改:⽆内容:通过外部按键计数进⼊中断执⾏LED取反------------------------------------------------*/#include<reg52.h> //包含头⽂件,⼀般情况不需要改动,头⽂件包含特殊功能寄存器的定义sbit LED=P1^0; //定义LED端⼝/*------------------------------------------------定时器初始化⼦程序------------------------------------------------*/void Init_Timer1(void){TMOD |= 0x10 | 0x40; //使⽤模式1,16位计数器,使⽤"|"符号可以在使⽤多个定时器时不受影响TH1=0xFF; //给定初值TL1=245; //从245计数到255EA=1; //总中断打开ET1=1; //定时器中断打开TR1=1; //定时器开关打开}/*------------------------------------------------主程序------------------------------------------------*/main(){Init_Timer1();while(1);}/*------------------------------------------------定时器中断⼦程序------------------------------------------------*/void Timer1_isr(void) interrupt 3{TH1=0xFF; //重新给定初值TL1=245;LED=~LED; //指⽰灯反相,可以看到闪烁}计数器1中断定义:当机器正在执⾏程序的过程中,⼀旦遇到⼀些异常或者特殊请求时,停⽌正在执⾏的程序转⼊必要的处理,处理完毕后,⽴即返回断点继续执⾏。
《嵌入式系统》课程实验报告学生姓名:所在班级:指导教师:记分及评价:一、实验名称按键中断实验二、实验目的通过实验掌握S3C2410X的中断控制寄存器的使用;通过实验掌握S3C2410X处理器的中断响应过程;通过实验掌握ARM处理器的中断方式和中断处理过程;通过实验掌握ARM处理器中断处理的软件编程方法。
三、实验内容编写程序,当用户在实验箱按下KEY1键或KEY2键时在中断服务子程序中将相关信息打印到串口中,显示在超级终端上。
四、实验原理在本实验平台的主板上设计了两个外部按键,电路原理图如下:EXINT0和EXINT1信号作为CPLD芯片的输入信号。
CPLD内部逻辑图:五、实验结果超级终端上显示以下信息:按下KEY1键或KEY2键,超级终端上显示以下信息。
六、练习题编写程序实现:按下KEY1或KEY2后点亮实验系统的LEDs一段时间后熄灭。
任务:按下KEY1键后LED1点亮一段时间后熄灭;按下KEY2键后点亮LED2一段时间后熄灭。
#define rCPLDIntControl (*(volatile unsigned char*)0x22600000)#define rCPLDIntStatus (*(volatile unsigned char*)0x22200000)#define rCPLDLEDADDR (*(volatile unsigned char*)0x21180000)void __irq int_int(void){unsigned char Status;int i;Status = rCPLDIntStatus;Status = ~(Status & 0x6);if(Status & 0x2){uart_printf(" Eint0 interrupt occurred.\n");rCPLDLEDADDR = (rCPLDLEDADDR | 0xFF )& 0xFE;for(i = 0; i < 100000; i++);rCPLDLEDADDR = rCPLDLEDADDR | 0xFF ;}else if(Status & 0x4){uart_printf(" EINT1 interrupt occurred.\n");rCPLDLEDADDR =(rCPLDLEDADDR | 0xFF) & 0xFD;for(i = 0; i < 100000; i++);rCPLDLEDADDR = rCPLDLEDADDR | 0xFF ;}rEINTPEND=(1<<9);ClearPending(BIT_EINT8_23);}。
南通大学实验报告院系:计算机科学与技术姓名:课程名称:接口技术成绩:学号:1213022013指导教师:李跃华同组实验者:实验日期:2014-5-7实验名称:键盘中断实验一.实验目的1.熟练运用CodeWarrior 嵌入式开发系统环境、C 语言、调试方式。
2.复习串行通信接口(SCI)的内容。
3.加强键盘中断基本原理及编程原理的理解。
4.理解“行扫描”法的原理并能进行键值识别和键值编码二.实验内容键盘的c 语言编程:1)初始化,先按IO 口方式初始化,即定义列线为输入且上拉,行线为输出,然后依输入口的键盘功能初始化相应的寄存器。
2)定义键值表3)扫描一次,读取键值4)获得键盘定义值行扫描法是使键盘的某一行输出为低电平,其余行为高电平,然后读取列值,如果列值中有某位为低电平,则表明该行和列交点处的键被按下;若为全高则再扫描下一行,直至扫描完全部的行线为止。
这样就可以确定是哪一行哪一列交点的键被按下。
2. 软件设计三程序流程图四编程1.内核定时器中断void tpm0_isr(void){static uint_32 TPMCounter = 0; //计时器uint_8 value; //键盘变量static uint_8 LEDindex=0; //位选口声明uint_8 LEDDataBuffer[4]; //LED显示缓冲区uint_8 i;//LED缓冲区赋值LEDDataBuffer[0]='0';LEDDataBuffer[1]='2';LEDDataBuffer[2]='3';LEDDataBuffer[3]='5';//LCD显示缓冲区,其中.表示按下的数字uint_8 kbv[32]="The keyboard you just input is .";if((TPM_SC_REG(TPM0_BASE_PTR) & TPM_SC_TOF_MASK) == TPM_SC_TOF_MASK) {TPMCounter++;}BSET(TPM_SC_TOF_SHIFT,TPM_SC_REG(TPM0_BASE_P TR)); //中断置标志位写1清0//处理LED部分LEDindex++;//位选位+1if (LEDindex>=4) LEDindex=0; //大于4位选口置0i=LEDchangeCode(LEDDataBuffer[LEDindex]-'0');//转码LEDshow1(LEDindex,i);//显示LEDif(TPMCounter>100){TPMCounter = 0;//键盘得到扫描值value = KBScanN(2);//扫描键值,存于value中if(KBDef(value) != 0xff) //发送键值{//修改.成为按键值kbv[31] = KBDef(value);//通过LCD显示出来LCDShow(kbv);uart_send_string(UART_2,kbv);//键盘发送信息}}}2.程序的入口int main(void){//1.声明主函数使用的局部变量uint_8 * g_DispalyInit;//2.关总中断enter_critical();//3.初始化底层模块uart_init (UART_1,BUSCLK, 9600); //串口1初始化, 总线时钟24000Khz,波特率9600LEDInit();//LED初始化LCDInit();//LCD初始化KBInit(); //键盘初始化tpm_init(TPM0,TPM_CLKSRC_PLL,1000);//初始化TPM模块,1ms中断一次//4.缓冲区赋值g_DispalyInit = (uint_8 *)"Wait Receiving..Soochow 2013.01.";//5.开中断tpm_enable_int(0);init_critical();//6.lcd显示初始字符LCDShow(g_DispalyInit);//================================= ================================== ========for(;;){}//============================================return 0;}四.实验小结在这次实验中主要让我们熟悉掌握gpio口通信的知识,在熟悉代码的前提下在主函数里初始化波特率何在中断函数里添加一个接收函数就可以。
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;}}}。
实验四 I/O操作及按键中断一、实验目的1、掌握DSP的I/O操作。
2、掌握DSP的中断控制功能。
二、实验设备计算机、ZY13DSP2BD实验箱、5402EVM板。
三、实验原理数码管的驱动采用了74LS244,其中数码管的段信号和位信号都是由FPGA来控制,在做DSP实验的时候需要知道数码管相对于DSP的I/O口地址为:0x10、0x11、0x12、0x13、0x14、0x15、0x16、0x17就可以完成实验项目了。
在编写LED段码的时候DSP的数据线D7—D0分别代表数码管的A、B、C、D、E、F、G、Dp段,由于DSP的数据是16位的而LED的数据是8位的,所以在使用FPGA接口时做了相应的处理,在使用时只需要在编写好的8位段码前面加上80H就可以了,例如:数据0,1,2,3,4,5,6,7对应的段码分别为:80FCH、8060H、80DAh、80F2h、8066H、80B6H、80BEH、80E0H。
此模块共有两种按键,KEY1—KEY4是轻触按键,在按键未按下时为高电平输入FPGA,当按键按下后对FPGA输入低电平,松开按键后恢复高电平输入,KEY5—KEY8是带自锁的双刀双掷开关,在按键未按下时是低电平,按键按下时为高电平并且保持高电平不变,只有再次按下此按键时才恢复低电平输入。
每当按下一个按键时,FPGA就会对此按键进行编码,KEY1—KEY8分别对应的是01H、02H、03H、04H、05H、06H、07H、08H。
在编码的同时对DSP产生中断INT1,这个时候DSP就会读取按键的值。
四、实验步骤一、I/O操作:1、将5402EVM上的J4同主板上的J4用排线相接,注意方向;2、打开主板上的电源和5402EVM上的电源开关;3、装栽DSP程序LED.PJT并运行,可以观察到数码管上显示的数据;4、修改DSP的实验原程序,观察数码管显示效果的变换,适当修改程序,使数码管显示不同的数据,并记录。
键控计数值显示一、实验目的(1)熟悉Nios II系统构建,并选择简单、合适的系统(2)学习按键中断的控制方法(3)用HDL文本输入方法建立顶层模块、flash编程(4)能够自行改写程序二、实验设备与器件Quartus II 软件、EP4CE115F29实验箱三、实验方案设计实验可实现的功能本实验要求实时显示计数器输出的0~7F计数值,显示终端为八位LED、七段数码管和LCD显示器。
由KEY1~KEY3三个按键选择显示器件。
长按KEY1键时,只在八位LED上进行显示;长按KEY2键时,只在LCD显示器上进行显示;长按KEY3键时,只在七段数码管上进行显示;无键按下时则不显示, 但计数功能保持;KEY0按下时清零。
硬件系统(HDL文本)//=================================================== ====// This code is generated by Terasic System Builder//=================================================== ====module Test_1(//////// CLOCK //////////CLOCK_50,//////// LED //////////LEDG,//////// KEY //////////KEY,CLR,////////COUNT////////////COUNT,//////// SEG7 //////////HEX0,HEX1,//////// LCD ////////// LCD_BLON,LCD_DATA,LCD_EN,LCD_ON,LCD_RS,LCD_RW,//////// SDRAM ////////// DRAM_ADDR, DRAM_BA,DRAM_CAS_N, DRAM_CKE, DRAM_CLK, DRAM_CS_N, DRAM_DQ,DRAM_DQM, DRAM_RAS_N, DRAM_WE_N,//////// Flash //////////FL_ADDR,FL_CE_N,FL_DQ,FL_OE_N,FL_RST_N,FL_RY,FL_WE_N,FL_WP_N,);//=================================================== ====// PARAMETER declarations//=================================================== ====//=================================================== ====// PORT declarations//=======================================================//////////// CLOCK //////////input CLOCK_50;//////////// LED //////////output [7:0] LEDG;//////////// KEY //////////input [2:0] KEY;input CLR;////////////COUNT/////////////input [7:0] COUNT//////////// SEG7 //////////output [6:0] HEX0;output [6:0] HEX1;//////////// LCD //////////output LCD_BLON; inout [7:0] LCD_DATA;output LCD_ON; output LCD_RS; output LCD_RW;//////////// SDRAM //////////output [12:0] DRAM_ADDR; output [1:0] DRAM_BA; output DRAM_CAS_N; output DRAM_CKE; output DRAM_CLK; output DRAM_CS_N; inout [31:0] DRAM_DQ; output [3:0] DRAM_DQM; output DRAM_RAS_N; output DRAM_WE_N;//////////// Flash //////////output [22:0] FL_ADDR;output FL_CE_N; inout [7:0] FL_DQ; output FL_OE_N;input FL_RY;output FL_WE_N;output FL_WP_N;//=================================================== ====// REG/WIRE declarations//=================================================== ====//////// 7-SEG ////////////////wire[2:0] norkey;wire[7:0] count_in;wire[7:0] data;//=================================================== ====// Structural coding//=======================================================wire reset_n;assign reset_n = 1'b1;kernel kernel_inst(// 1) global signals:.clk_50(CLOCK_50),.reset_n(reset_n),.sdram_clk(DRAM_CLK),.sys_clk(clk_sys), ///////////////////////// the_key.in_port_to_the_key(~KEY),//the_count.in_port_to_the_count(count_in[7:0]),// the_lcd.LCD_E_from_the_lcd(LCD_EN),.LCD_RS_from_the_lcd(LCD_RS),.LCD_RW_from_the_lcd(LCD_RW),.LCD_data_to_and_from_the_lcd(LCD_DA TA),// the_led.out_port_from_the_led(LEDG),// the_sdram.zs_addr_from_the_sdram(DRAM_ADDR),.zs_ba_from_the_sdram(DRAM_BA),.zs_cas_n_from_the_sdram(DRAM_CAS_N ),.zs_cke_from_the_sdram(DRAM_CKE),.zs_cs_n_from_the_sdram(DRAM_CS_N),.zs_dq_to_and_from_the_sdram(DRAM_D Q),.zs_dqm_from_the_sdram(DRAM_DQM),.zs_ras_n_from_the_sdram(DRAM_RAS_N ),.zs_we_n_from_the_sdram(DRAM_WE_N),// the_seg7.out_port_from_the_seg7(data),.out_port_from_the_en_seg(en),// the_tri_state_bridge_flash_avalon_slave.address_to_the_cfi_flash(FL_ADDR),.read_n_to_the_cfi_flash(FL_OE_N),.select_n_to_the_cfi_flash(FL_CE_N),.tri_state_bridge_data(FL_DQ),.write_n_to_the_cfi_flash(FL_WE_N),);clk_div clk_div(.clkin(clk_sys),.clk_1KHz(clk_1KHz),.clk_1Hz(clk_1Hz));mydecoder_7seg yima(.clk(clk_1KHz),.segmenth(HEX1),.segmentl(HEX0),.data(data),.en(en));// .lowdata(data[3:0])); counter couter(.clk(clk_1Hz),.clr(CLR),//anjian qingling.count(count_in[7:0]));// Flash Configassign FL_RST_N = reset_n;assign FL_WP_N = 1'b1;///////////////////////////////////////////// LCD configassign LCD_BLON = 0; // not supportedassign LCD_ON = 1'b1; // alwasy onendmodule系统框图实验程序#include"count.h" //关于LCD的相关定义,控制LCD 的输出格式#include <unistd.h>#include <stdio.h>#include"system.h"#include"altera_avalon_pio_regs.h"#include"alt_types.h"#include"sys/alt_irq.h"volatile int a=0;volatile char b;unsigned char count1,count2,count3;static void KeyDown_interrupts(void* context,alt_32 id) //中断函数{IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE,0);//响应中断后,将中断响应位复位;b=IORD_ALTERA_AVALON_PIO_DATA(KEY_BASE); //读取中断响应值switch(b){case 0x1: //七段数码管显示IOWR_ALTERA_AVALON_PIO_DATA(EN_SEG_BASE,1);//IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,0x00);count1=IORD_ALTERA_AVALON_PIO_DATA(COUNT_BASE);IOWR_ALTERA_AVALON_PIO_DATA(SEG7_BASE,count1);break;case 0x2: //LCD显示count2=IORD_ALTERA_AVALON_PIO_DATA(COUNT_BASE); printf("%02x", count2);//直接用标准输出函数表示break;case 0x4://LED灯显示IOWR_ALTERA_AVALON_PIO_DATA(EN_SEG_BASE,0);count3=IORD_ALTERA_AVALON_PIO_DATA(COUNT_BASE);IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE,count3);break;default: //无按键时,正常计数,但无显示break;}}void InitPIO(void)//中断初始化{IOWR_ALTERA_AVALON_PIO_IRQ_MASK(KEY_BASE,0x7);//开中断,允许后三位开中断IOWR_ALTERA_AVALON_PIO_EDGE_CAP(KEY_BASE,0x0);//中断响应后复位,防止中断一直响应。
#include "def.h"#include "option.h"#include "2440addr.h"#include "2440lib.h"#include "mmu.h"#include "2440slib.h"U32 key;/*static void __irq EINT11_ISR(void){ //清中断必须按一下三个的顺序rEINTPEND |=( 1<< 11);//外部中断悬挂寄存器,清0无请求,1时有中断请求rSRCPND |= (1<<5);//指示中断源状态,0无中断源请求,1时有中断源请求rINTPND |=(1<<5);//指示中断状态,0无中断请求,1时有中断请求Uart_Printf("EINT11 is occurred.\n");}static void __irq EINT8_ISR(void){ //清中断必须按一下三个的顺序rEINTPEND |=( 1<< 8);//外部中断悬挂寄存器,清0无请求,1时有中断请求rSRCPND |= (1<<5);//指示中断源状态,0无中断源请求,1时有中断源请求rINTPND |=(1<<5);//指示中断状态,0无中断请求,1时有中断请求Uart_Printf("EINT8 is occurred.\n");}*/U8 Key_Scan( void ){Delay( 8000 ) ;if( (rGPGDA T&(1<< 0)) == 0 )return 1 ;else if( (rGPGDA T&(1<< 3)) == 0 )return 2;else if( (rGPGDA T&(1<< 5)) == 0 )return 3 ;else if( (rGPGDA T&(1<< 6)) == 0 )return 4 ;else if( (rGPGDA T&(1<< 7)) == 0 )return 5 ;else if( (rGPGDA T&(1<<11)) == 0 )return 6 ;elsereturn 0xff;}static void __irq Key_ISR(void)//U32 r;//EnterCritical(&r);if(rINTPND==BIT_EINT8_23) {ClearPending(BIT_EINT8_23);if(rEINTPEND&(1<<8)) {//Uart_Printf("eint11\n");rEINTPEND |= 1<< 8;}if(rEINTPEND&(1<<11)) {//Uart_Printf("eint11\n");rEINTPEND |= 1<< 11;}if(rEINTPEND&(1<<13)) {//Uart_Printf("eint11\n");rEINTPEND |= 1<< 13;}if(rEINTPEND&(1<<14)) {//Uart_Printf("eint11\n");rEINTPEND |= 1<< 14;}if(rEINTPEND&(1<<15)) {//Uart_Printf("eint11\n");rEINTPEND |= 1<< 15;}if(rEINTPEND&(1<<19)) {// Uart_Printf("eint19\n");rEINTPEND |= 1<< 19;}}key=Key_Scan();if( key == 0xff )Uart_Printf( "Interrupt occur... Key is released!\n") ;elseUart_Printf( "Interrupt occur... K%d is pressed!\n", key) ; //ExitCritical(&r);}void xmain(void){ChangeClockDivider(3,1);ChangeMPllV alue(127,2,1); //405MHZMMU_Init();Isr_Init();Uart_Init(0, 115200);Uart_Select(0);Uart_Printf("the main is running.\n");//-----------------中断初始化----------------////选择功能管脚//rGPGCON = rGPGCON & (~(3<<0) |(2<<0) );//rGPGCON &(0x82);//当GPG0取10时,表示EINT8,即K1 p144rGPGCON =rGPGCON & (~((3<<22)|(3<<6)|(3<<0)|(3<<10)|(3<<12)|(3<<14))) |((2<<22)|(2<<6)|(2<<0)|(2<<10)|(2<<12)|(2<<14));//中断模式rINTMOD = rINTMOD & ( ~(1<<5) );//EINT8-23:外部中断8~23 p154//触发方式//rEXTINT1 = ( rEXTINT1 | (7<<0) ) & ( ~(4<<0) );//EINT8 falling edge triggeredrEXTINT1 &= ~(7|(7<<0));rEXTINT1 |= (0|(0<<0)); //EXTINT1用于设置EINT15~EINT8触发信号的类型p146 rEXTINT1 &= ~(7|(7<<12));rEXTINT1 |= (0|(0x0<<12)); //EXTINT1用于设置EINT15~EINT8触发信号的类型p146rEXTINT1 &= ~(7<<20);rEXTINT1 |= (0<<20); //set eint13 falling edge intrEXTINT1 &= ~(7<<24);rEXTINT1 |= (0<<24); //set eint14 falling edge intrEXTINT1 &= ~(7<<28);rEXTINT1 |= (0<<28); //set eint15 falling edge intrEXTINT2 &= ~(0xf<<12);rEXTINT2 |= (0<<12); //set eint19 falling edge int//使能中断rINTMSK = rINTMSK & ( ~(1<<5) );//设定被中断屏蔽,0为中断服务有效,1为中断服务屏蔽p154//清中断//rSRCPND |= (1<<8);//to clear EINT8//rEINTPEND |= ~(1<<8); //clear eint 8rEINTMASK &= ~((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19)); //p148 外部中断掩码寄存器,[3:0]保留取值0,[23:4]控制相应的EINT[23:4],清零使能相应的中断,置1时屏蔽中断// rEINTMASK &= ~((1<<11)); //enable eint11//中断向量//pISR_EINT0 = (U32)EINT0_ISR;//EINT0//ExitCritical(&r);while(1){Uart_Printf("the main is running.\n");Delay(50000000);pISR_EINT8_23 = (U32)Key_ISR;}}1、MMU 一定要在主函数里面开启。
中断的理解和以I/O口为例说明如何实现中断一、中断的理解没有中断的单片机就是残次品,当然也不会被人所器重,因此在激烈的市场竞争中就被淘汰了。
可见,中断对单片机而言是多么重要。
所谓中断就是暂停CPU正在运行的程序,转去执行相应的中断服务程序,完毕后返回被中断的程序继续运行的现象和技术。
下面给大家举个例子来帮助大家理解中断。
假设你自己就是CPU,正处于假期模式,在家“休养生息”,每天的生活就是睡觉、起床、看看书和看看电影。
比如你现在正在看书,突然你妈妈叫你帮忙收拾一下碗筷,你就会把当前读到的位置折一下做个标记,并暂停当前的读书动作,然后乖乖地去收拾碗筷。
那么,你妈妈“叫你”的这个动作对你来说就是请求了一次中断;你把当前读书的位置折一下,做个标记的这个过程就是“保存现场”,方便你忙完妈妈的任务之后再接着看;而你去“收拾碗筷”这个过程其实就相当于执行了一次中断程序。
很快你就完成了碗筷的收拾,继续去看书,并且从你之前做标记的地方开始,这其实就算完成了“中断返回”。
例如你正在看电影,你爸爸叫你去忙别的事情,也是请求了一次中断,你会把电脑先暂停,等你忙完你爸爸的任务后,回来再接着看。
我们来看看如果没有中断功能会是什么情况。
没有“中断功能”的你其实就是聋哑人,别人说话你听不到。
你爸妈脾气都不好,为了防止挨骂,你只能全天候的待在爸妈身边,看到你爸妈使颜色,你就心领神会的立马去帮忙。
所以,你自己的事情就无法做了,你能做的事情就少了很多。
当然了,你也是一个独立的个体,你可以选择是否接受被人的指使。
如果你告诉自己,今天我只做自己的事情,任何人都不能打断,即使有人叫你,你也会选择左耳朵进,右耳朵出,继续忙你自己当前的工作。
这就可以通过寄存器配置,使单片机不允许中断的功能。
当然你可以选择你在做什么事情时不听别人的指使,做什么事情时停别人指使。
比如说你正在“刷牙”,你妈叫你吃饭,你肯定是要拒绝的(一嘴沫子怎么吃),等刷好了再吃;但是,你在“看电影”时,你妈让你收拾碗筷你就去做。