1. start.s
preserve8area reset, code, readonlycode32entryldr pc, =startnopnopnopnopnop ldr pc, =interrupt_handlernopstartldr sp, =0x40001000mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x12;IRQbic r0, r0, #(1 << 7);打開IRQ中斷允許msr cpsr_c, r0ldr sp, =0x40001000sub sp, sp, #1024mrs r0, cpsrbic r0, r0, #0x1Forr r0, r0, #0x10 ;Usermsr cpsr_c, r0ldr sp, =0x40001000sub sp, sp, #2048import mainb maininterrupt_handlersub lr, lr, #4 stmfd sp!, {r0-r12, lr}import do_interruptbl do_interruptldmfd sp!, {r0-r12, pc}^finishedb finishedend
2. main.c——timer4是一個純粹的定時器
#include <s3c2440.h>
#include "led.h"
#include "key.h"
#include "interrupt.h"void init_wdt(void) //初始化看門狗,禁止啟動,關閉看門狗
{WTCON &= ~(1 << 0);
}void delay(unsigned int n)
{while (n--);
}void init_clk(void)
{unsigned int t = MPLLCON; //將PCLK頻率存入變量設置好再進行修改,防止頻率修改中途器件因為頻率過高而短路t &= ~((0xff << 12) | (0x3f << 4) | (3 << 0)); //利用鎖相環將12MHz倍頻t |= ((127 << 12) | (2 << 4) | (1 << 0)); //配置fclk頻率大約為400MhzCLKDIVN |= ((2 << 1) | (1 << 0));//分頻,配置HCLK為100MHz,HCLK為50MHz MPLLCON = t;//將所有頻率配置好再進行設置,防止器件被燒壞
}void timer4_handler(void)
{static unsigned int n = 0;++n; if (n > 1000) //定時器中斷觸發次數次數{ledAllNor();n = 0;}
}void init_timer4(void)
{TCFG0 |= (24 << 8); //配置定時器 4 預分頻值25 50/25=2MHzTCFG1 &= ~(0x0f << 16);// 選擇 PWM 定時器 4 的選通輸入1/2 2/2=1MHzTCNTB4 = 1000;//設置定時器 4 的計數緩沖器的值為1000 ,1000減到0觸發一次定時器中斷 TCON |= (1 << 22); //自動重載TCON |= (1 << 21); // 定時器 4 的手動更新TCON &= ~(1 << 21);// 定時器 4 的手動更新復位INTMOD &= ~(1 << IRQ_INT_TIMER4);//配置定時器4中斷為IRQ模式INTMSK &= ~(1 << IRQ_INT_TIMER4);//讓定時器中斷處于可服務模式TCON |= (1 << 20);//啟動定時器4register_irq(IRQ_INT_TIMER4, timer4_handler);//注冊定時器中斷處理函數
}int main(void)
{init_wdt();init_led();init_key();init_clk();init_timer4();while (1){
// ledAllNor();
// delay(0xffff);}
}
3. led.h
#ifndef _LED_H_
#define _LED_H_extern void init_led(void);
extern void ledon(unsigned int n);
extern void ledAllOn(void);
extern void ledAllOff(void);
extern void ledAllNor(void);
extern void ledoff(unsigned int n);#endif
4. led.c
#include <s3c2440.h>
#include "led.h"
#include "key.h"
#include "interrupt.h"void init_led(void) //初始化led ,輸出模式
{GPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));GPBCON |= ((1 << 10) | (1 << 12) | (1 << 14) | (1 << 16));ledAllOff();
}void ledon(unsigned int n)
{if (n < 1 || n > 4){return;}GPBDAT &= ~(1 << (n + 4));
}void ledAllOn(void)
{GPBDAT &= ~(0x0f << 5);
}void ledAllOff(void)
{GPBDAT |= (0x0f << 5);
}void ledAllNor(void)
{GPBDAT ^= (0x0f << 5);
}void ledoff(unsigned int n)
{if (n < 1 || n > 4){return;}GPBDAT |= (1 << (n + 4));
}
5. key.h
#ifndef _KEY_H_
#define _KEY_H_extern void init_key(void);
extern void key_handler(void);#endif
6. key.c
#include <s3c2440.h>
#include "led.h"
#include "key.h"
#include "interrupt.h"void init_key(void) //按鍵中斷EINT 8 11 13 14 15 19
{INTMOD &= ~(1 << IRQ_EINT8_23);//EINT8_23設置為IRQ 中斷模式 (INTMOD ) 寄存器INTMSK &= ~(1 << IRQ_EINT8_23);//EINT8_23設置為可服務 中斷屏蔽 (INTMSK ) 寄存器GPGCON &= ~((3 << 0) | (3 << 6) | (3 << 10) | (3 << 12) | (3 << 14) | (3 << 22));GPGCON |= ((1 << 1) | (1 << 7) | (1 << 11) | (1 << 13) | (1 << 15) | (1 << 23));//按鍵改為觸發外部中斷模式GPGUP |= ((1 << 0) | (1 << 11));//禁止附加上拉電阻EXTINT1 |= ((2 << 0) | (2 << 12) | (2 << 20) | (2 << 28)); //為外部中斷配置信號觸發方式EXTINT1 |= ((1 << 3) | (1 << 15) | (1 << 23) | (1 << 27) | ((unsigned int)1 << 31));//下降沿觸發+信號濾波 EXTINT2 |= ((2 << 12) | (1 << 15));EINTMASK &= ~((1 << 8) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19)); register_irq(IRQ_EINT8_23, key_handler);//注冊由enit8_23導致產生的中斷函數
}void key_handler(void)
{if (EINTPEND & (1 << 8))//判斷具體是哪個子中斷源引發中斷{ledAllNor();}else if (EINTPEND & (1 << 11)){ledAllNor(); }else if (EINTPEND & (1 << 13)){ledon(1); }else if (EINTPEND & (1 << 14)){ledon(2); }else if (EINTPEND & (1 << 15)){ledon(3); }else if (EINTPEND & (1 << 19)){ledon(4); }EINTPEND = EINTPEND;
}
7. interrupt.h
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_typedef void (*irq_handler)(void);
#define IRQ_EINT8_23 5
#define IRQ_INT_TIMER4 14extern void do_interrupt(void);
extern void register_irq(int irq_num, irq_handler handler);#endif
8. interrupt.c
#include <s3c2440.h>
#include "led.h"
#include "key.h"
#include "interrupt.h"static irq_handler handler_vector[60];//static防止別人去修改,只能在本interrupt.c文件中使用void do_interrupt(void)
{int n = INTOFFSET;handler_vector[n]();SRCPND = SRCPND;//先清srcINTPND = INTPND;//置位
}void register_irq(int irq_num, irq_handler handler)
{handler_vector[irq_num] = handler;
}
1.?中斷執行流程
? ? ? ? 1. 中斷源發出中斷請求
? ? ? ? 2. CPU查詢中斷是否被運行、以及中斷是否被屏蔽
? ? ? ? 3. CPU考察中斷優先級
? ? ? ? 4. CPU保護現場
? ? ? ? 5. 執行中斷服務函數
? ? ? ? 6. 恢復現場?
2. 外部中斷是帶有sub寄存器的子請求源
3. 對pend寄存器寫1是清零
pend寄存器0未請求 1請求,但寫1清零
4. 串口中斷帶sub子寄存器
5. 判斷中斷源
pend? 給1是0? ?給0是1
srcpnd
intpnd
6. s3c2440是遞減寄存器
7. 定時器沒有子中斷源
PLL鎖相環:倍頻,使頻率升高
MPLL:給主板倍頻(不要修改MPLL)
UPLL:給USB倍頻
分頻器:分頻,將頻率升高
FCLK分頻器
????????????????????????重點
p
m
s
7-20