我要成为嵌入式高手之4月12日ARM第七天!!
————————————————————————————
2440GPIO
GPIO:通用目的输入输出
LED
要把GPBCON初始化
地址是固定的,可以当做无符号int型
控制所有灯就需要初始化GPBCON5.6.7.8
#include "led.h"
void led_init(void)
{
unsigned int t = 0;
t = GPBCON;
t &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
t |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
GPBCON = t;
}
void ledAllOn(void)
{
GPBDAT &= ~(0x0F << 5);
//低电平打开
}
void ledAllOff(void)
{
GPBDAT |= (0x0F << 5);
//高电平关闭
}
void ledAllNor(void)
{
GPBDAT ^= (0x0F << 5);
}
void delay(unsigned int n)
{
while (n--);
}
//关闭看门狗定时器
void wdt_init(void)
{
WTCON &= ~(1 << 5);
}
void ledOn(unsigned char n)
{
unsigned int t = 0;
n &= 0x0F;
t = GPBDAT;
t &= ~(0x0F << 5);
t |= n << 5;
GPBDAT = t;
}
main.c
#include "led.h"
int main(void)
{
wdt_init();
led_init();
ledAllOff();
while (1)
{
ledAllNor();
delay(0x3FFF);
ledOn(8);
delay(0x3FFF);
}
}
按键
首先初始化GPEGCON
K1与K6有上拉电阻,故应将附加上拉电阻功能禁止
GPGUP |= (1 << 0);
#include "key.h"
void key_init(void)
{
GPGCON &= ~((3 << 0) | (3 << 6) |(3 << 10) | (3 << 12) | (3 << 14) | (3 << 22));
GPGUP |= (1 << 0);//第一个按键和最后一个按键有物理上拉电阻,故在此将附加上拉功能禁止
}
int key_press(void)
{
if ((GPGDAT & (1 << 0)) == 0)
{
return 1;
}
else if ((GPGDAT & (1 << 3)) == 0)
{
return 2;
}
else if ((GPGDAT & (1 << 5)) == 0)
{
return 4;
}
else if ((GPGDAT & (1 << 6)) == 0)
{
return 8;
}
else if ((GPGDAT & (1 << 7)) == 0)
{
return 9;
}
else if ((GPGDAT & (1 << 11)) == 0)
{
return 10;
}
return 0;
}
main.c
int main(void)
{
wdt_init();
led_init();
key_init();
ledAllOff();
while (1)
{
//ledOn(key_press());
}
}
2440中断
中断处理流程
1、中断源发出中断请求
2、CPU查询是否允许中断和该终端是否被屏蔽
3、CPU查询中断优先级
4、保护现场(和栈有关)
5、执行中断函数
6、恢复现场
外部中断的60个中断源最后经过筛选,比较,最终将中断请求交给920T内核;然后920T内核通过FIQ异常或者IRQ异常来采取措施最终实现中断。(由于我写的startup.s用的是IRQ异常,故将中断处理为IRQ异常)
要初始化的寄存器
中断模式(INTMOD)寄存器
需要置0改为IRQ模式
中断屏蔽(INTMSK)寄存器
需要置0改为可服务模式
此外,还需要设置GPIO,改为中断模式
GPGCON寄存器
EXTINTn(外部中断控制寄存器 n)
控制中断如何发生(上升沿、下降沿……)
EINTMASK(外部中断屏蔽寄存器)
至此初始化流程完成
———————————————————————————————————————————
中断服务函数
进入中断服务函数后要查询中断源的寄存器:
中断偏移(INTOFFSET)寄存器
写在中断处理函数中(interrupt_handle)
中断偏移寄存器中的值表明了是哪个 IRQ 模式的中断请求在 INTPND 寄存器中。此位可以通过清楚 SRCPND 和 INTPND 自动清除。
判断完之后读GPIO中的寄存器确定到底是哪个中断源
EINTPEND(外部中断挂起寄存器)
写在中断详细处理方案函数中(eint_handle)
用来查询是哪个中断源,且需要软件写“1”清零
1:发生中断 0:不发生中断
源挂起(SRCPND)寄存器
写在中断处理函数中(interrupt_handle)
中断处理完成后需要清除那些数据中被设置为 1 的相应 位置的 SRCPND 位。
中断挂起(INTPND)寄存器
写在中断处理函数中(interrupt_handle)
必须在中断服务程序中清除了 SRCPND 寄存器后清除此寄存器。
//中断初始化
void eint_init(void)
{
//设置中断
INTMOD &= ~(1 << 5);
INTMSK &= ~(1 << 5);
//设置GPIO
GPGCON |= (2 << 0);
//设置外部中断触发方式
EXTINT1 |= (2 << 0);
//设置外部中断使能
EINTMASK &= ~(1 << 8);
}
//中断处理函数
void eint_handle(void)
{
if ((EINTPEND & (1 << 8)) != 0)
{
key = 1;
}
EINTPEND = EINTPEND;//指定位写1,用来清零
}
//中断服务函数
void interrupt_handle(void)
{
switch(INTOFFSET)
{
case 5:
eint_handle();
break;
default:
break;
}
SRCPND = SRCPND;
INTPND = INTPND;
}
2440时钟
注意是时钟,不是实时时钟
这里的时钟指的是处理器运算时的主频(即程序运行一条指令所需要的时间)
实时时钟是一个表,可以记录 年 月 日 时 分 秒
PLL(phase lock loop)锁相环电路:
作用:倍频作用
时钟发生模块框图
时钟发生模块框图
step1:配置PLL(MPLL)
1、先清零MDIV . PDIV . SDIV
2、后填数设置倍频为400M
step2:配置时钟分频控制(CLKDIVN)寄存器
配置之前要查询摄像头时钟分频(CAMDIVN)寄存器