历史上的今天
今天是:2024年12月23日(星期一)
2020年12月23日 | 天嵌开发板 TQ210 S5PV210 中断方式按键实现
2020-12-23 来源:eefocus
中断在裸机开发中是非常重要的一项学习内容,之前学习过STM32的中断实现,是参考正点原子的代码,通过库函数的方式实现的,为了进一步深度理解其中的道理,此次通过天嵌的TQ210开发板实现中断方式。
具体功能为,LED正常闪烁,当按键被按下的时候,通过串口打印信息,提示按键被按下,此过程不影响LED正常闪烁。中断执行过程具体如下图:

根据示意图,可知道当有中断请求时,首先进行保护现场,然后跳到中断处理函数,执行中断处理函数当中的程序,最后进行恢复现场,程序继续运行。
通过查询开发板原理图得知,按键连接的为外部中断XEINT0,连接的芯片引脚为GPH0,具体细节如下图。


知道了硬件连接就可以进行代码编写了,具体流程如下:
配置GPH0引脚为为外部中断模式
配置中断触发方式(此处设置为下降沿触发)
中断屏蔽配置
使能外部中断
通过以上流程中断基本已经完成初始化准备工作。
其中提到了中断屏蔽,此处引用百度百科进行简单的介绍下:
什么叫屏蔽中断?允许中断?怎样实现?
按照是否可以被屏蔽,可将中断分为两大类:不可屏蔽中断(又叫非屏蔽中断)和可屏蔽中断。不可屏蔽中断源一旦提出请求,CPU必须无条件响应,而对可屏蔽中断源的请求,CPU可以响应,也可以不响应。CPU一般设置两根中断请求输入线:可屏蔽中断请求INTR(Interrupt Require)和不可屏蔽中断请求NMI(NonMaskable Interrupt)。对于可屏蔽中断,除了受本身的屏蔽位控制外,还都要受一个总的控制,即CPU标志寄存器中的中断允许标志位IF(Interrupt Flag)的控制,IF位为1,可以得到CPU的响应,否则,得不到响应。IF位可以由用户控制,指令STI或Turbo c的Enable()函数,将IF位置1(开中断),指令CLI或Turbo_c 的Disable()函数,将IF位清0(关中断)。
此外,还需配置中断向量表、优先级、控制等具体配置过程中涉及的中断控制器如下图所示:

具体程序文件由key.h、key.c main.c start.S等文件组成,具体目录结构如下图:
gpio.h 内容如下图
#ifndef _ASM_ARCH_GPIO_H
#define _ASM_ARCH_GPIO_H
struct s5pc1xx_gpio_bank{
unsigned int con;
unsigned int dat;
unsigned int pull;
unsigned int drv;
unsigned int pdn_con;
unsigned int pdn_pull;
unsigned char res1[8];
};
struct s5pv210_gpio{
struct s5pc1xx_gpio_bank gpio_a0;
struct s5pc1xx_gpio_bank gpio_a1;
struct s5pc1xx_gpio_bank gpio_b;
struct s5pc1xx_gpio_bank gpio_c0;
struct s5pc1xx_gpio_bank gpio_c1;
struct s5pc1xx_gpio_bank gpio_d0;
struct s5pc1xx_gpio_bank gpio_d1;
struct s5pc1xx_gpio_bank gpio_e0;
struct s5pc1xx_gpio_bank gpio_e1;
struct s5pc1xx_gpio_bank gpio_f0;
struct s5pc1xx_gpio_bank gpio_f1;
struct s5pc1xx_gpio_bank gpio_f2;
struct s5pc1xx_gpio_bank gpio_f3;
struct s5pc1xx_gpio_bank gpio_g0;
struct s5pc1xx_gpio_bank gpio_g1;
struct s5pc1xx_gpio_bank gpio_g2;
struct s5pc1xx_gpio_bank gpio_g3;
struct s5pc1xx_gpio_bank gpio_i;
struct s5pc1xx_gpio_bank gpio_j0;
struct s5pc1xx_gpio_bank gpio_j1;
struct s5pc1xx_gpio_bank gpio_j2;
struct s5pc1xx_gpio_bank gpio_j3;
struct s5pc1xx_gpio_bank gpio_j4;
};
#define S5PV210_GPIO_BASE (0xE0200000)
struct s5pv210_gph_bank{
unsigned int con;
unsigned int dat;
unsigned int pull;
unsigned int drv;
};
#define S5PV210_GPH0_BASE (0xE0200C00) //GPH0 基地址
#endif
uart.h内容如下图
#ifndef UART_H
#define UART_H
struct s5pv2xx_uart
{
unsigned int ulcon;
unsigned int ucon;
unsigned int ufcon;
unsigned int umcon;
unsigned int utrstat;
unsigned int uerstat;
unsigned int ufstat;
unsigned int umstat;
unsigned char utxh;
unsigned char resl[3];
unsigned char urxh;
unsigned char res2[3];
unsigned int ubrdiv;
unsigned short udivslot;
unsigned char res3[2];
unsigned char res4[0x3d0];
};
#define S5PV210_UART_BASE (0xE2900000)
void uart_init(void);
void myputc(char c);
void myputs(const char *str);
#endif
关键的是key.h 其中的地址一定要正确
#ifndef KEY_H
#define KEY_H
#define pEXECPTION_IRQ (*(volatile unsigned int*)(0xD0037400+0X18))
#define EXT_INT_0_CON (*(volatile unsigned int*)(0xE0200E00)) //外部中断0 控制寄存器
#define EXT_INT_0_MASK (*(volatile unsigned int*)(0xE0200F00)) //外部中断0 mask(屏蔽控制)寄存器
#define EXT_INT_0_PEND (*(volatile unsigned int*)(0xE0200F40)) //外部中断0 pend 阻塞 挂起控制器
#define VIC0INTENABLE (*(volatile unsigned int*)(0xF2000010))//VICO 中断使能控制器
#define VIC0ADDRESS (*(volatile unsigned int*)(0xF2000F00))//VICO 中断地址控制器
#define VIC0VECTADDR0 (*(volatile unsigned int*)(0xF2000100))//VICO 地址O清除寄存器
void key_init(void);
void irq_init(void);
void key1_handler(void);
void irp_c_handler(void);
#endif
key.c文件内容如下图:
#include "cpu_io.h"
#include "gpio.h"
#include "key.h"
#include "uart.h"
extern void asm_irq(void);
void irq_init()
{
pEXECPTION_IRQ=(unsigned int )asm_irq;
}
void irq_c_handler(void)
{
void (*handler)(void)=0x0;
myputs("in irq c handler....n");
handler =(void (*) (void)) VIC0ADDRESS;
if(handler) handler();
}
void key1_handler(void)
{
myputs("key1 down!!!n");
EXT_INT_0_PEND |= (0x1<<0);
VIC0ADDRESS=0X0;
}
void key_init(void)
{
struct s5pv210_gph_bank *gph0_base=(struct s5pv210_gph_bank*) S5PV210_GPH0_BASE;
unsigned int var;
/**外部引脚进行功能选择,EINT***/
var =readl(&gph0_base->con);
var|=0xf<<0; //功能选择 0xf 表示配置GPHO引脚为外部中断0
writel(var,&gph0_base->con);
/****配置ENIT功能***************/
EXT_INT_0_CON &= ~(0X7<<0); //低三位清零 为以后配置中断触发方式做准备
EXT_INT_0_CON |=(0x2<<0); //低三位配置为010 即为下降沿触发方式
EXT_INT_0_MASK &= ~(0x1<<0);//使能中断屏蔽
/*****配置主中断控制器**********/
VIC0INTENABLE |= (0X1<<0); //使能中断
VIC0VECTADDR0=(unsigned int)key1_handler;
}
uart.c 文件内容如下图:
#include "cpu_io.h"
#include "uart.h"
#include "gpio.h"
void uart_init(void)
{
struct s5pv210_gpio *gpio_base=(struct s5pv210_gpio *)S5PV210_GPIO_BASE;
struct s5pv2xx_uart *uart_base=(struct s5pv2xx_uart *)S5PV210_UART_BASE;
unsigned int var;
var=readl(&gpio_base->gpio_a0.con);
var &= ~(0xff<<0);
var |= (0x22<<0);
writel(var,&gpio_base->gpio_a0.con);
_REG(&uart_base->ulcon)=0x3; //8 bit 1stop non-even
_REG(&uart_base->ucon) =0x5; //
_REG(&uart_base->ubrdiv)=35;
_REG(&uart_base->udivslot)=0x80;
}
void myputc(char c)
{
struct s5pv2xx_uart *uart_base=(struct s5pv2xx_uart *)S5PV210_UART_BASE;
//判断缓冲区是否为空,再发送数据
while(!(_REG(&uart_base->utrstat)&(0x1<<2)));
_REG(&uart_base->utxh)=c;
}
void myputs(const char *str)
{
while(*str)
{
myputc(*str);
str++;
}
}
main.c函数内容比较少 ,完成闪烁LED和初始化工作:
//main.c
#include "led.h"
#include "cpu_io.h"
#include "uart.h"
#include "key.h"
static void mydelay()
{
volatile unsigned int i=0xfffff;
while(i--);
}
void led_test()
{
led_init();
while(1)
{
led_blink(1);
mydelay();
led_blink(0);
mydelay();
}
}
int main()
{
irq_init();
uart_init();
key_init();
myputs("hello world!n");
led_test();
return 0;
}
start.S内容如下 ,主要完成中断跳转和保护现场等;
.global _start
.global main
.global irq_c_handler
.global asm_irq
_start :
bl main
loop:
b loop
irq_handler:
stmfd sp!,{r0-r3,lr}
bl irq_c_handler
ldmfd sp!,{r0-r3,lr}
subs pc,lr,#4
asm_irq:
b irq_handler
.end
最后还需要注意的是,下载的时候应该选择SD卡下载,不要选择Dram下载。以上内容仅供参考,如有问题还请指出。
史海拾趣
|
用MSP430P315 单片机的A/D 转换器,实现阻性温度传感器的电阻检测;用查表和线性插值结合的方法,简化标度变换的算法结构。对电池电压的降低进行补偿的同时分析补偿电阻的精度对温度检测的影响。 … 查看全部问答> |
|
/************************************************ *技术直接转销售还是先转技术支持再转销售好呢? ************************************************/ 我是09年毕业的,毕业的时候,是在一家医疗器材公司工作。 最近换了一家公司,是搞 ...… 查看全部问答> |
|
老师让做一个dsp和pc通过并口epp通信的东西,在xp下对并口操作是不是要写个驱动?老板让我用WinDriver,我想问问关于并口开发要怎样调试呢?以前没有做过关于并口通信东西,所以想请问各位老大,希望能给指点一下… 查看全部问答> |
|
在Wince中添加一个较大的位图,设想有一个相对较小的取景框,当这个框快速移动时,我想显示屏幕上位图移动的动画效果。我在evc中代码如下: CBitmap m_bitmap; BITMAP bm; ...… 查看全部问答> |
|
4月21日(周六)东方标准特邀请嵌入式软件仿真开源(SkyEye)项目核心成员、AKA 嵌入式小组成员康烁,为大家做《利用SkyEye进行操作系统分析及SkyEye的最新进展》的讲座。 康烁--作为自由软件爱好者,精通嵌入式系统移植,驱动开发,多年嵌入式开发 ...… 查看全部问答> |




