文档库 最新最全的文档下载
当前位置:文档库 › Nios II按键中断调试程序及经验

Nios II按键中断调试程序及经验

Nios II按键中断调试程序及经验
Nios II按键中断调试程序及经验

软件:Quatus II 6.1,Nios II 6.1

硬件:EP1C3T144 FPGA开发板

实验目的:熟悉nios II开发,掌握中断程序调试

系统配置:CPU+OnChipRam(4K)+LED_PIO+BUTTON_PIO

功能描述:按键实现中断,使led亮或灭

led配置成开发板上的led0,led1,led2,led3

按键采用简单按钮B17,B18,19,B20

不给过多注释了(其实注释够多了)

#include

#include

#include "sys/alt_irq.h"

#include "altera_avalon_pio_regs.h"

#include "system.h"

/* A variable to hold the value of the button pio edge capture register. */ volatile int edge_capture;

#ifdef BUTTON_PIO_BASE

/* 按键中断服务程序*/

static void handle_button_interrupts(void* context, alt_u32 id)

{

/* Cast context to edge_capture's type. It is important that this be

* declared volatile to avoid unwanted compiler optimization.

*/

volatile int* edge_capture_ptr = (volatile int*) context;

/* Store the value in the Button's edge capture register in *context. */

*edge_capture_ptr =

IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);

/* Reset the Button's edge capture register. */

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0); }

/* Initialize the button_pio. */

static void init_button_pio()

{

/* Recast the edge_capture pointer to match the alt_irq_register() function

* prototype. */

void* edge_capture_ptr = (void*) &edge_capture;

/* Enable all 4 button interrupts. */从硬件角度,允许硬件中断

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf);

/* Reset the edge capture register. */

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0x0);

/* Register the interrupt handler. */注册后开中断

alt_irq_register( BUTTON_PIO_IRQ, edge_capture_ptr,

handle_button_interrupts );

}

#endif

int main (void) __attribute__ ((weak, alias ("alt_main")));

int alt_main(void)

{

alt_irq_init(ALT_IRQ_BASE); //necessary,enable interrupts

alt_sys_init(); //unnecessary

alt_io_redirect(ALT_STDOUT,ALT_STDIN,ALT_STDERR);//unnecessary init_button_pio();

while(1)

{

switch(edge_capture)

{

case 0x01:

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,0xFF);

break;

case 0x02:

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,0x00);

break;

case 0x04:

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,0xFF);

break;

case 0x08:

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,0x00);

break;

default:

IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,0x0A);

break;

}

}

return 0;

}

1 因为使用的是片上RAM,容量有限,故得重载alt_main(), 否则空间不够

2 系统默认的alt_main()是干了很多活的...比如系统中断,IO设备驱动等,改写的时候得注意,哪些用户程序用到了.比如本例用到中断,故alt_irq_init(ALT_IRQ_BASE);函数是必须的.开始没有调试成功就是因为没有开总中断

中断的调试过程可以依次看以下:

status:最低位PIE(使能),为0禁止,为1允许中断

ienable:3232位,每位对应一个外部中断,为1则对应使能

ipending:表示处理器正在处理的中断

全局变量:alt_irq.若注册成功的话就会向向量表写入ISR和Context.注册完后返回0则成功,为负则失败

按键中断

#include /* common defines and macros */ #include "derivative.h" /* derivative-specific definitions */ #define LED PORTB #define LED_dir DDRB #define KEY1 PTIH_PTIH3 #define KEY2 PTIH_PTIH2 #define KEY3 PTIH_PTIH1 #define KEY4 PTIH_PTIH0 #define KEY1_dir DDRH_DDRH3 #define KEY2_dir DDRH_DDRH2 #define KEY3_dir DDRH_DDRH1 #define KEY4_dir DDRH_DDRH0 unsigned char data=0x01; unsigned char direction=1; //设置灯亮的方向,0向左,1向右。unsigned char time=5; //设置灯闪的速度。 /*************************************************************/ /* 延时函数*/ /*************************************************************/ void delay(unsigned int n) { unsigned int i,j; for(j=0;j

单片机_C语言函数_中断函数(中断服务程序)

单片机_C语言函数_中断函数(中断服务程序) 在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。 中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。 (1)中断源:中断请求信号的来源。(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效,上面的那个横杠不知道怎么加上去))(2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。期间涉及到CPU响应中断的条件,现场保护,现场恢复。 (3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。优先级是可以编程的,而优先权是固定的。 80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。 80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制 (1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1 (2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP 具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。 在这里我们讲下注意的事项 (1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。 (2)CPU响应中断后,在边沿触发方式下,IE0(外部中断INT0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和IE1。所以在中断返回前必须撤出INT0和INT1引脚的低电平,否则就会出现一次中断被CPU多次响应。 (3)串口中断中,CPU响应中断后,TI(串行口发送中断请求标志位)和RI(接收中断请求标志位)必须由软件清零。 (4)单片机复位后,TCON,SCON给位清零。 C51语言允许用户自己写中断服务子程序(中断函数) 首先来了解程序的格式: void 函数名() interrupt m [using n] {} 关键字 interrupt m [using n] 表示这是一个中断函数 m为中断源的编号,有五个中断源,取值为0,1,2,3,4,中断编号会告诉编译器中断程序的入口地址,执行该程序时,这个地址会传个程序计数器PC,于是CPU开始从这里一条一条的执行程序指令。 n为单片机工作寄存器组(又称通用寄存器组)编号,共四组,取值为0,1,2,3 中断号中断源 0 外部中断0 1 定时器0 2 外部中断1 3 定时器1中断 4 串行口中断 (在上一篇文章中讲到的ROM前43个存储单元就是他们,这5个中断源的中断入口地址为: 这40个地址用来存放中断处理程序的地址单元,每一个类中断的存储单元只有8B,显然不

用51单片机中断编写的4x4键盘程序

用51单片机中断编写的4x4键盘程序 应用查询扫描编写键盘程序,由于要给按键去抖动,程序变得比较复杂和冗长(详见2013年9月29日博文《MSP430和 AT89C51单片机4x4键盘C程序》),如果用中断编写,设置中断响应在下降沿时执行中断,则程序编写不用去抖动判断,所以相比较要简单很多!下面用汇编和C语言两种方式编写4X4键盘程序! 一、汇编程序 ORG 0000H LJMP MAIN ORG 0003h Ljmp ZD0

ORG 000Bh LJMP TZD0 ORG 0013h Ljmp ZD1 ORG 001Bh LJMP TZD1 ORG 0040H MAIN: Mov TMOD,#66h MOV TH0,#0ffh MOV TL0,#0ffh MOV TH1,#0ffh MOV TL1,#0ffh SETB EA SETB ET0 SETB TR0 SETB ET1 SETB TR1 SETB IT0 SETB IT1 SETB EX0 SETB EX1 xh: mov P1,#0feh

Lcall Delay mov P1,#0fdh Lcall Delay mov P1,#0fbh Lcall Delay mov P1,#0f7h Lcall Delay SJMP xh ZD0: JNB P1.0,dat1 JNB P1.1,dat2 JNB P1.2,dat3 JNB P1.3,dat4 dat1: mov P2,#06h ;1 sjmp ZD0R dat2: mov P2,#5bh ;2 sjmp ZD0R dat3: mov P2,#4fh ;3 sjmp ZD0R dat4: mov P2,#66h ;4 ZD0R: reti ZD1: JNB P1.0,dat5

51单片机独立按键程序查询法和外部中断两种

//以下程序都是在VC++6.0 上调试运行过的程序,没有错误,没有警告。 //单片机是STC89C52RC,但是在所有的51 52单片机上都是通用的。51只是一个学习的基础平台,你懂得。 //程序在关键的位置添加了注释。 //用//11111111111111111代表第一个程序。//2222222222222222222222222代表第二个程序,以此类推 //1111111111111111111111111111111111111111111111111111111111111111111 //1111111111111111111111111111111111111111111111111111111111111111111 /****************************************************************************** * * 实验名: 左右流水灯实验 * 使用的IO : LED使用P2,键盘使用P3.1 * 实验效果: 按下K1键, * 注意: ******************************************************************************* / #include #include #define GPIO_LED P2 sbit K1=P3^1; void Delay10ms( ); //延时10ms /****************************************************************************** * * 函数名: main * 函数功能: 主函数 * 输入: 无 * 输出: 无 ******************************************************************************* / void main(void) { unsigned int i,j; j=0xfe; //1111_1110 while(1) { GPIO_LED=j; if(K1==0) //检测按键K1是否按下 { Delay10ms(); //消除抖动 if(K1==0) {

外部中断扫描矩阵键盘

外部中断扫描矩阵键盘 ;将4个7段数码显示器显示的内容放在4个显存中,4个显存空间定义如下 LED0 EQU30H LED1 EQU31H LED2 EQU32H LED3 EQU 33H ORG 0000H LJMP MAIN ORG0003H;转入外部中断0服务程序入口 LJMP INP0 ORG0040H MAIN: MOV SP, #60H SETB EX0 ;开INT0中断 SETB IT0 ;设置中断触发方式 SETB EA ;开总中断 MOV LED0, #0 MOV LED1, #1 MOV LED2, #2 MOV LED3, #3 START: MOV P0, #00H;使显示器不显示 MOV P2, #0FFH;关闭显示器位选择码目的也是使显示器不显示 MOV A, LED0 LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序 CLR P2.0;最后一位七段数码管显示 LCALL DELAY ;少许延时目的是使得数码管更亮 MOV P0, #00H;使显示器不显示 MOV P2, #0FFH ; MOV A, LED1 LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序 CLR P2.1;倒数第二位七段数码管显示 LCALL DELAY MOV P0, #00H;使显示器不显示 MOV P2, #0FFH ; MOV A, LED2 LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序

CLR P2.2 ;倒数第三位七段数码管显示 LCALL DELAY MOV P0, #00H;使显示器不显示 MOV P2, #0FFH ; MOV A, LED3 LCALL DISP0 ;调用将数值转换为显示段码并在P0端口输出的子程序 CLR P2.3;倒数第四位七段数码管显示 LCALL DELAY LJMP START ;跳回初始位置,使程序循环;;;;;;;;;;;;;;;;;;;;;;;;;;;中断程序 INP0: CLR EA PUSH PSW PUSH ACC PUSH B JB P2.3, NP2 ;P2.3口输出低电平,扫描K0,K1,K2,K3 SK0: JB P2.4, SK1 ;P2.4为高电平扫描K0 LCALL OPRK0 ;P2.4为低电平执行K0对应子程序 LCALL DELAY1 ;延时去除抖动 LJMP SKLOOP ;重新循环扫描 SK1: JB P2.5, SK2 LCALL OPRK1 LCALL DELAY1 ;延时去除抖动 LJMP SKLOOP SK2: JB P2.6, SK3 LCALL OPRK2 LCALL DELAY1 ;延时去除抖动 LJMP SKLOOP SK3: JB P2.7, NP2 ;换一次输出位 LCALL OPRK3 LCALL DELAY1 ;延时去除抖动 LJMP SKLOOP

stm32 之 中断按键初始化(注意事项)

stm32 之 中断按键初始化(注意事项) 之前做终端按键的时候都是只做了一个,没有做多个,昨天在把所有按键都设置成中断模式的时候遇到问题,于是乎还跟一个网上的哥们进行了热议,后来还是我发现了问题!最终把问题给解决了! 我的按键的GPIO连接有点奇葩,他不是连续的,这可能就是竞赛板故意设置的难度吧! 首先管脚初始化: [cpp]view plaincopyprint? 1. GPIO_InitTypeDef key; 2. 3. RCC->APB2ENR |= ((1<<0)|(1<<2)|(1<<3)); 4. 5. key.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8; 6. key.GPIO_Mode = GPIO_Mode_IPD; 7. GPIO_Init(GPIOA, &key); 8. 9. key.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;

10. key.GPIO_Mode = GPIO_Mode_IPD; 11. GPIO_Init(GPIOB, &key); 全部设置成输入模式,AFIO再时钟使能的时候不要忘记了!这里我就 不多说了! 然后就是中断组设置: NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC初始化: [cpp]view plaincopyprint? 1. key_nvic.NVIC_IRQChannel = EXTI0_IRQn; 2. key_nvic.NVIC_IRQChannelCmd = ENABLE; 3. key_nvic.NVIC_IRQChannelPreemptionPriority = 0; 4. key_nvic.NVIC_IRQChannelSubPriority = 1; 5. NVIC_Init(&key_nvic); 重点都不在这,值得注意的是下面: 我第一次在配置EXTI Line的时候这样配置! GPIO_EXTILineConfig(GPIO_PortSourceGPIOA|GPIO_PortSourceGPIOB,\ GPIO_PinSource0|GPIO_PinSource1|GPIO_PinSource2|GPIO_PinSource8);大致一看,貌似很正常啊!但是问题就出在这! 我们跳转到GPIO_PinSourcex和GPIO_PortSourceGPIOx哪里看看:[cpp]view plaincopyprint? 1. #define GPIO_PortSourceGPIOA ((uint8_t)0x00) 2. #define GPIO_PortSourceGPIOB ((uint8_t)0x01) 3. #define GPIO_PortSourceGPIOC ((uint8_t)0x02) 4. #define GPIO_PortSourceGPIOD ((uint8_t)0x03) 5. #define GPIO_PortSourceGPIOE ((uint8_t)0x04) 6. #define GPIO_PortSourceGPIOF ((uint8_t)0x05) 7. #define GPIO_PortSourceGPIOG ((uint8_t)0x06) [cpp]view plaincopyprint?

中断服务程序流程图

第一讲: 第六章I/O接口原理-接口、端口、编址 回顾:微机系统的层次结构,CPU、主机、接口电路及外部设备之间的结构关联,输入/输出的一般概念。 重点和纲要:微机系统主机与外部设备之间的数据传送,包括I/O端口的寻址方式,输入/输出的传送控制方式。 讲授内容: 6. 1 输入/输出数据的传输控制方式 一、输入/输出的一般概念 1.引言 输入/输出是微机系统与外部设备进行信息交换的过程。输入/输出设备称为外部设备,与存储器相比,外部设备有其本身的特点,存储器较为标准,而外部设备则比较复杂,性能的离散性比较大,不同的外部设备,其结构方式不同,有机械式、电动式、电子式等;输入/输出的信号类型也不相同,有数字信号,也有模拟信号;有电信号,也有非电信号;输入/输出信息的速率也相差很大。因此,CPU与外部设备之间的信息交换技术比较复杂。 CPU与外设之间的信息交换,是通过它们之间接口电路中的I/O端口来进行的,由于同一个外部设备与CPU之间所要传送的信息类型不同,方向不同,作用也不一样(例如数据信息、状态信息、控制信息、输入/输出等),所以接口电路中可以设置多个端口来分别处理这些不同的信息。 2.输入/输出端口的寻址方式 微机系统采用总线结构形式,即通过一组总线来连接组成系统的各个功能部件(包括CPU、内存、I/O端口),CPU、内存、I/O端口之间的信息交换都是通过总线来进行的,如何区分不同的内存单元和I/O端口,是输入/输出寻址方式所要讨论解决的问题。

根据微机系统的不同,输入/输出的寻址方式通常有两种形式:(1).存储器对应的输入、输出寻址方式 这种方式又称为存储器统一编址寻址方式或存储器映象寻址方式。 方法:把外设的一个端口与存储器的一个单元作同等对待,每一个I/O端口都有一个确定的端口地址,CPU与I/O端口之间的信息交换,与存储单元的读写过程一样,内存单元与I/O端口的不同,只在于它们具有不同的的地址。优点: ①CPU对I/O端口的读/写操作可以使用全部存储器的读/写操作指令,也可 以用对存储器的不同寻址方式来对I/O端口中的信息,直接进行算术、逻辑运算及循环、移位等操作。 ②内存与外设地址的分配,可以用统一的分布图。 ③不需要专门的输入、输出操作指令。 缺点: ①内存与I/O端口统一编址时,在地址总线根数一定的情况下,使系统中 实际可以直 接寻址的内存单元数减少。 ②一般情况下,系统中I/O端口数远小于内存单元数,所以在用直接寻址方 式来寻址这些端口时,要表示一个端口地址,必须用与表示内存单元地址相同的字节数,使得指令代码较长,相应地读/写执行时间也较长,这对提高系统的运行速度是不利的。 Mortorola公司的M6800CPU等均采用这种寻址I/O端口的方式。 3. CPU与外设之间所传送的信息类型 CPU与I/O端口之间所交换的信息,可以有下列几种类型: ①数据信息:包括数字量、模拟量、开关量等,可以输入、也可以输出 ②状态信息:这是I/O端口送给CPU的有关本端口所对应的外设当前状态 的信息。供CPU进行分析、判断、决策。 ③控制信息:这是CPU送给I/O端口的控制命令,使相应的外部设备完成 特定的操作。 数据信息、状态信息和控制信息是不同类型的信息,它们所起的作用也不一样。但在8086/8088微机系统中,这三种不同类型的信息的输入、输出过程是相同的。为了加以区分,可以使它们具有不同的端口地址,在端口地址相同的情况下,可以规定操作的顺序,或者在输入/输出的数据中设置特征位。

按键中断程序

* 1个LED指示灯,对应的GPIO为 : PC0输出为1点亮LED 输出为0关闭LED 另外PC1为外部中断触发:按键按下时为低电平,即可设置为低电平触发 /* GPIO配置函数 */ void GPIO_Configuration(void) { /*定义2个结构体变量 */ GPIO_InitTypeDef GPIO_InitStructure; /*开启GPIOB,GPIOC ,复用口时钟的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); /*给GPIOC_Pin_1一个初始值*/ GPIO_ResetBits(GPIOC, GPIO_Pin_0); 配置IO口,初始化IO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; // 将连接LED的GPIO设置为推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为2MHZ的速度,响应时间,没要求越小越好GPIO_Mode_IPU为输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; //初始化GPIOC GPIO_Init(GPIOC, &GPIO_InitStructure); /*给KEY_InitStructure.GPIO_Pin KEY_InitStructure.GPIO_Mode KEY_InitStructure.GPIO_Speed付初始值*/

基于STM32的单个按键中断的例子

#include"stm32f10x.h" //K1点亮LED , K2熄灭LED void RCC_Config(void); void GPIO_Config(void); void NVIC_Config(void); void EXTI_Config(void); int main(void) { RCC_Config(); GPIO_Config(); NVIC_Config(); EXTI_Config(); while(1); } void RCC_Config(void) { SystemInit(); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC|RCC_APB 2Periph_AFIO,ENABLE); } void GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_5; //PC5-K1 PC2-K2 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOC,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; //led1 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOB,&GPIO_InitStructure);

键盘、中断与定时器

一、按键输入 一、按键的分类 键盘分编码键盘和非编码键盘。 键盘上闭合键的识别由专用的硬件编 码器实现,并产生键编码号或键值的 称为编码键盘,如计算机键盘.而靠软 件编程来识别的称为非编码键盘;在 单片机组成的各种系统中,用的最多 的是非编码键盘。也有用到编码键盘 的。 非编码键盘有分为:独立键盘和行列式(又称为矩阵式)键盘。 二、独立按键的检测 当按键没按下时,CPU对应的I/O接口由于内部有上拉电阻,其输入为高电平;当某键被按下后,对应的I/O接口变为低电平。只要在程序中判断I/O接口的状态,即可知 道哪个键处于闭合状态。(如下图所示) 变化与否,得出按键是否被按下,从而做出相 吗? ◎现实并非理想 在我们通过上面的按键检测原理得出上述 的结论的时候,其实忽略了一个重要的问题: 那就是现实中按键按下时候的电平变化状态。 我们的结论是基于理想的情况得出来的,就如 同这幅按键按下时候对应电平变化的波形图一 样。 而实际中,由于按键的弹片接触的时候, 并不是一接触就紧紧的闭合,它还存在一定的 抖动。尽管这个时间非常的短暂,但是对于我 们执行时间以us为计算单位的微控制器来说 ,它太漫长了。于是就会造成上图所示的差

别。 这样便存在这样一个问题。假设我们的系统有这样功能需求:在检测到按键按下的时候,将某个I/O的状态取反。由于这种抖动的存在,使得我们的微控制器误以为是多次按键的按下,从而将某个I/O的状态不断取反,这并不是我们想要的效果。假如该I/O控制着系统中某个重要的执行的部件,那结果更不是我们所期待的。于是乎有人便提出了软件消除抖动的思想,道理很简单,抖动的时间长度是一定的,只要我们避开这段抖动时期,检测稳定的时候的电平不就可以了吗。于是这就产生了一种方法,就是通过延时来跳过这段抖动的时间,而实际上这样的效果还不错。当然,还有其他的消抖方法,同学们请自己思考思考。 由于独立键盘的程序太简单,同学们请自行编写。 三、矩阵键盘 1、为什么使用矩阵键盘 当使用按键过多时,使用独立按键虽然编写程序简单,但是会大量占用IO口资源,为了节省IO资源,通常将键盘按照矩阵方式排列(如下图所示)。 0xfe低电平 2、矩阵键盘检测原理 一般矩阵键盘的检测方法有以下两种: 方法一:逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。 方法二:行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。 下面给出矩阵键盘逐行扫描函数的一部分(只扫描了第一行的四个按键),其余部分请自行添加,如有不懂的地方先查阅C语言课本或者自行百度。

怎么在中断中实现一个按键第一次按键之后,立刻切换到一个循环状态。

问题的提出:怎么在中断中实现一个按键第一次按键之后,立刻切换到一个循环状态,然后同一个按键第二次按下时结束循环,回到中断入口? 疑难点: 1.中断是实时扫描的,但是中断中改变的状态量在主函数中却不能实时读取,这样不能达到立刻切换的目的。 2.如果把循环子函数放在中断中,那么仅仅用一个状态变量的话,是不可能时刻改变它的值的,因为在C中状态变量相当于一个存储器。 例子说明解答方法: 例子:想中断按键按下时,循环执行Led子函数,再次按下时,停止循环,回到主函数继续执行。 很多人是这样写的: void int0(void)interrupt 0 { if (k1==0) { delay_ms(10); if(k1==0) { m=!m; while(!k1); while(m) Led(); } } } 这样写为什么不行呢?因为m状态量改变一次之后,若m==1,则进入while()循环,此后即使中断改变了m的值,但是while(m) Led();一直在进行while(1)循环,所以m即使再怎么改变,按键都不能复位到初始化状态。下面提出这样一串代码: void int0(void)interrupt 0 { if (k1==0) { delay_ms(10); if(k1==0) { m=!m; while(!k1); while(k1&&m) Led(); } } } 这样因为K1按键弹出后立刻变为1,而k1它属于口线,并不是变量,所以实时改变,一旦按键再次按下时,K1变0,即可从while()中挑出,则程序会再次去读出m,此时将m值激活,则可达到再次按键初始化问题,并且反应比起在主函数中扫描要灵敏N倍。

实验二 按键中断实验

实验二按键中断实验 一、实验目的 了解中断的含义 二、实验内容 板子加电后,按动板子上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。通过在软件中断/事件寄存器写“1”,一个中断/事件请求也可以通过软件来产生。 本次实验需要组件的工程文件文档如下: USER--stm32f10x_it.c 为中断服务程序主程序,我们对主程序进行一次详细的注释。 //______________________主程序____________________________________________________________________ int main(void) { unsigned char a=0,b=0,c=0; /*完成对系统时钟的设置,例程中通过系统时钟设置函数,外接晶振采用8Mhz,经过片内频率合成,9倍频,设置为72MHz的时钟。*/ RCC_Configuration(); /*嵌套向量中断控制器

外部按键中断延时控制LED设计

成绩 实训报告 题目:外部按键中断延时控制LED设计课程名称: ARM嵌入式系统实训 学生姓名:徐欣郑亮亮杨康宁 任课教师:权循忠 系别: 电子工程学院 专业:通信工程 年级: 13级 实训时间: 2015年11月13日 电子工程学院

外部按键中断延时控制LED设计 学生:徐欣郑亮亮杨康宁 指导老师:权循忠 电子工程学院通信工程专业 实训目的 1.掌握STM32项目开发流程; 2.学会画出算法流程图; 3.掌握LED的控制编程。 二、实训内容 (1)LED0亮2秒,LED0灭2秒;循环(1)的操作5次; (2)LED1亮3秒,LED1灭3秒;循环(2)的操作5次; (3)然后到(1)循环。 三、实训过程 1.人员分配: 徐欣负责程序部分,利用c语言设计算法,建立工程项目,生成目标文件,并将目标文件编程下载到开发板,验证算法;郑亮亮负责绘制电路图,进行电路设计及分析;杨康宁负责程序流程框图以及完成实验报告。 2.电路设计: (1)要求使用LED0和LED1两个LED,连接图如下: 图1、LED原理图

(2)所用到的硬件只有LED(DS0和DS1)。LED与MCU连接,实现定时控制LED闪烁,其原理图如下: 图2、LED与STM32连接原理图 3.电路分析: 因为用Proteus绘图软件来绘制原理图,Proteus中没有MCU芯片,通过手绘将这些芯片和引脚绘出来,不能进行仿真。 LED0(DS0)与PB5相连;LED1(DS1)与PE5相连。 4.算法设计

算法解释: 通过if 选择语句实现按键选择功能, 按下KEY0时,实现函数 LED0=0; delay_ms(1500); delay_ms(1500); 按下KEY1时,实现函数 LED0=0; delay_ms(1500); delay_ms(1500); 按下WK_UP 时,实现函数 LED0=0; LED1=0; delay_ms(1500); delay_ms(1500); delay_ms(1500); delay_ms(500); 延时3S LED0,1灭 LED0灭 LED0灭 延时5S 延时3S KEY0按下? KEY2按下? KEY1按下? LED0,1亮 LED0亮 LED0亮 开始 初始化I/O 为输入,开启I/O 复用时钟,设置I/O 与中断线的映射关系,初始化线上中断,设置触发条件等,配置中断分组(NVIC ),并使能中断编 写中断服务函数 检测按键

51单片机串行口中断服务程序

51单片机串行口中断服务程序 ---------------------------------------------------------------------------- //串口中断服务程序,仅需做简单调用即可完成串口输入输出的处理 //编程:聂小猛。该资料来自“51单片机世界”https://www.wendangku.net/doc/6a8949365.html,/~dz2000,欢迎访问。 //出入均设有缓冲区,大小可任意设置。 //可供使用的函数名: //char getbyte(void);从接收缓冲区取一个byte,如不想等待则在调用前检测inbufsign是否为1。 //getline(char idata *line, unsigned char n); 获取一行数据回车结束,已处理backspce和delete,必须定义最大输入字符数 //putinbuf(uchar c);模拟接收到一个数据 //putbyte(char c);放入一个字节到发送缓冲区 //putbytes(unsigned char *outplace,j);放一串数据到发送缓冲区,自定义长度 //putstring(unsigned char code *puts);发送一个字符串到串口 //puthex(unsigned char c);发送一个字节的hex码,分成两个字节发。 //putchar(uchar c,uchar j);发送一个字节数据的asc码表达方式,需要定义小数点的位置 //putint(uint ui,uchar j);发送一个整型数据的asc码表达方式,需要定义小数点的位置 //CR;发送一个回车换行 //************************************************************************* #include //该头文件包括了51,52,80320的特殊寄存器,用在51,52上也可 #define uchar unsigned char #define uint unsigned int #define OLEN 64 /* size of serial transmission buffer */ idata unsigned char outbuf[OLEN]; /* storage for transmission buffer */ unsigned char idata *outlast=outbuf; //最后由中断传输出去的字节位置 unsigned char idata *putlast=outbuf; //最后放入发送缓冲区的字节位置 #define ILEN 2 /* size of serial receiving buffer */ idata unsigned char inbuf[ILEN]; unsigned char idata *inlast=inbuf; //最后由中断进入接收缓冲区的字节位置 unsigned char idata *getlast=inbuf; //最后取走的字节位置 bit outbufsign; //输出缓冲区非空标志有=1 bit inbufsign; //接收缓冲区非空标志有=1 bit inbufful; //输入缓冲区满标志满=1 #define CR putstring("\r\n") //CR=回车换行 //***************************** //放入一个字节到发送缓冲区 putbyte(char c) {uchar i,j; ES=0; /*暂停串行中断,以免数据比较时出错? */ if (outlast==putlast ) { i=(0-TH1); do{i--;j=36; do {j--;}while(j!=0);

实验五 键盘中断实验

实验五键盘中断实验 一、实验目的 1.熟练运用CodeWarrior嵌入式开发系统环境、C语言、调试方式。 2.复习串行通信接口(SCI)的内容。 3.加强键盘中断基本原理及编程原理的理解。 4.理解“行扫描”法的原理并能进行键值识别和键值编码。 5.理解键盘接线原理图(如图5-1)。 二、知识要点 本实验采用的是4×4矩阵式键盘(以下简称键盘)。PTG4、PTD2、PTD3、PTD7分别接四根列线,定义为输入且上拉,PTG0~PTG3分别接四根行线,且定义为输出。行扫描法是使键盘的某一行输出为低电平,其余行为高电平,然后读取列值,如果列值中有某位为低电平,则表明该行和列交点处的键被按下;若为全高则再扫描下一行,直至扫描完全部的行线为止。这样就可以确定是哪一行哪一列交点的键被按下。 MCU与键盘接线原理图: 图5-1 4×4键盘与MCU接法示例 键盘的c语言编程: 1)初始化,先按IO口方式初始化,即定义列线为输入且上拉,行线为输出,然后依输入口的键盘功能初始化相应的寄存器。 2)定义键值表 3)扫描一次,读取键值 4)获得键盘定义值 行扫描法是使键盘的某一行输出为低电平,其余行为高电平,然后读取列值,如果列值中有某位为低电平,则表明该行和列交点处的键被按下;若为全高则再扫描下一行,直至扫描完全部的行线为止。这样就可以确定是哪一行哪一列交点的键被按下。

设置键盘中断允许寄存器,当键盘有键被按下时,立即产生中断,中断程序处理按键事件,比如确定哪个键被按下,然后转换为该键的定义值。 键盘的键面标示码(即定义值)与MCU识别的键值对应关系通过列表对应起来,即键盘定义表对应表示。当通过“行扫描”法获得某个键的键值时,通过查表法就可以得到它的定义值。 该键盘中断方式程序的主程序主体是一个死循环,且是一个空循环体,所有处理的过程代码放在中断程序中。 三、演示性实验 在光盘资料中提供读者键盘实例程序文件夹。 编程采用规范要求编写,将键盘独立成一个构件,如C语言中,形成key.h头文件和key.c源文件。头文件对键盘的所用端口寄存器或引脚进行宏定义以及初始化函数和驱动函数声明。源文件对初始化函数和驱动函数进行定义。具体实现代码见光盘。 四、设计性实验 要求按下的一个键的键值和键面定义值(键的ASCII码值)通过串口在PC方软件界面显示。 当键值被按下时,高端虚拟键盘被按下,或者在高端PC机中显示对应按键值。 1、资源使用 键盘的数据线分别接在MCU 口的号引脚、口的号引脚。 2、硬件设计(标识引脚名) 图5-2 4×4键盘按键的信息显示在PC机界面的连线图 3、软件设计 1)MCU端程序流程图 2)编程 (1)下面填写主程序main。 (填写主程序main.c) 键盘中断程序 (填写C语言编写的键盘中断程序)

定时中断T0服务程序参考框图

软件程序: ORG 0000H LJMP MAIN ORG 000BH LJMP PIT0 ORG 001BH LJMP PIT1 ORG 0100H MAIN: MOV SP,#FH ;设堆栈指针 MOV SCON,#00H ;设置串行口为方式0 MOV TMOD,#11H ;T0和T1初始化为方式1 MOV TH0, #3CH ;置时间常数,T0和T1定时100ms MOV TL0, #OB0H MOV TH1, #3CH MOV TL1, #0B0H MOV 50H, #96H ;T0中断次数计数单元 MOV 51H,#14H ;T1中断次数计数单元 MOV R1, #00H MOV R2, #00H MOV R0, #40H ;显示缓冲单元起始地址 DISP0:MOV @R0, #00H ;显示缓冲单元清零 INC R0 CJNE R0, #4CH,DISP0 MOV 44H,#01H ;设置通道号的显示缓冲单元 MOV 48H,#02H MOV R7,#40H ;置当前通道显示缓冲单元首址 MOV 53H,#40H SETB ETO ;开中断 SETB ET1 SETB EA SETB TR0 ;启动定时器 SETB TR1 LP: MOV R7, 53H ;调显示子程序 ACALL DISP AJMP JP 定时器TO中断服务程序 PIT0: MOV TH0, #3CH ;重置时间常数 MOV TL0, #OBOH DJNZ 50H,#96H PUSH ACC PUSH 03H ACALL WDXJ ;调温度巡检子程序 POP 03H POP ACC

DH0: RET1 定时器T1中断服务程序 PIT1: MOV TH1,#3CH ;重置时间常数 MOV TL0, #OBOH DJNZ 51H,DH1 ;计数20次即定时2S MOV 51H,#14H INC R2 CJNE R2,#03H,CNL0 ;根据R2中的内容确定显示缓冲区首址 MOV R2,#00H CNL0: CJNE R2,#00H,CNL1 MOV 53H,#40H SJMP DH1 CNL1: CJNE R2,#01H,CNL2 MOV 53H,#40H SJMP DH1 CNL2: MOV 53H,#48H DH1: RETI 显示子程序 DISP: CLR P3.7 ;输出锁存 MOV R3,#01H ;置显示字位码 MOV DPTR,#TAB DISP1:MOV A,R3 MOV SBUF,A ;字位码送串行口 JNB T1,$ ;等待串行转送结束 CLR T1 ;清串行中断标志 MOV A,R7 MOV R0,A MOV A,@RO ;取代显示的数据 MOVC A,@R0 ;查表求字段码 MOV SBUF, A ;字段码送串行口, JNB T1,$ ;等待串行中断标志 SETB P3.7 ;允许输出显示 ACALL DEL ;调延时子程序 MOV A,R3 JB ACC.3,DISP2 ;4位显示完否 RL A MOV R3,A INC R7 CLR P3.7 ;输出锁存 AJNP DISP1 DISP2:RET TAB : DB 3FH,06H,5BH,4FH,66H DB 6DH,7DH,07H,7FH,6FH DEL: PUSH 07H ;延时子程序

相关文档
相关文档 最新文档