嵌入式学习——硬件(s3c2440外部中断、定时器中断)——day54

  1. start.s
cpp 复制代码
	preserve8
	area reset, code, readonly
	code32
	entry

	ldr pc, =start
	nop
	nop
	nop
	nop
	nop						   
	ldr pc, =interrupt_handler
	nop
		
start
	ldr sp, =0x40001000

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x12;IRQ
	bic r0, r0, #(1 << 7);打开IRQ中断允许
	msr cpsr_c, r0
	ldr sp, =0x40001000
	sub sp, sp, #1024

	mrs r0, cpsr
	bic r0, r0, #0x1F
	orr r0, r0, #0x10 ;User
	msr	cpsr_c, r0
	ldr sp, =0x40001000
	sub sp, sp, #2048

	import main
	b main

interrupt_handler
	sub lr, lr, #4	
	stmfd sp!, {r0-r12, lr}
	import do_interrupt
	bl do_interrupt
	ldmfd sp!, {r0-r12, pc}^

finished
	b finished

	end
  1. main.c------timer4是一个纯粹的定时器
cpp 复制代码
#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频率大约为400Mhz
	CLKDIVN |= ((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=2MHz
	TCFG1 &= ~(0x0f << 16);// 选择 PWM 定时器 4 的选通输入1/2 2/2=1MHz

	TCNTB4 = 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);//启动定时器4

	register_irq(IRQ_INT_TIMER4, timer4_handler);//注册定时器中断处理函数				 
}

int main(void)
{
	init_wdt();
	init_led();
	init_key();
	init_clk();
	init_timer4();
	while (1)
	{
//		ledAllNor();
//		delay(0xffff);
	}
}
  1. led.h
cpp 复制代码
#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
  1. led.c
cpp 复制代码
#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));
}
  1. key.h
cpp 复制代码
#ifndef _KEY_H_
#define _KEY_H_

extern void init_key(void);
extern void key_handler(void);

#endif
  1. key.c
cpp 复制代码
#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;
}
  1. interrupt.h
cpp 复制代码
#ifndef _INTERRUPT_H_
#define _INTERRUPT_H_

typedef void (*irq_handler)(void);
#define IRQ_EINT8_23 5
#define IRQ_INT_TIMER4 14

extern void do_interrupt(void);
extern void register_irq(int irq_num, irq_handler handler);


#endif
  1. interrupt.c
cpp 复制代码
#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;//先清src
	INTPND = INTPND;//置位																							  
}

void register_irq(int irq_num, irq_handler handler)
{
	handler_vector[irq_num]	= handler;
}
  1. 中断执行流程

  2. 中断源发出中断请求

  3. CPU查询中断是否被运行、以及中断是否被屏蔽

  4. CPU考察中断优先级

  5. CPU保护现场

  6. 执行中断服务函数

  7. 恢复现场

  8. 外部中断是带有sub寄存器的子请求源

  9. 对pend寄存器写1是清零

pend寄存器0未请求 1请求,但写1清零

  1. 串口中断带sub子寄存器

  2. 判断中断源

pend 给1是0 给0是1

srcpnd

intpnd

  1. s3c2440是递减寄存器

  2. 定时器没有子中断源

PLL锁相环:倍频,使频率升高

MPLL:给主板倍频(不要修改MPLL)

UPLL:给USB倍频

分频器:分频,将频率升高

FCLK分频器

重点

p

m

s

7-20

相关推荐
代码游侠13 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
CODECOLLECT17 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen17 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠20 小时前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_20 小时前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件
深圳市九鼎创展科技1 天前
瑞芯微 RK3399 开发板 X3399 评测:高性能 ARM 平台的多面手
linux·arm开发·人工智能·单片机·嵌入式硬件·边缘计算
辰哥单片机设计1 天前
STM32项目分享:车辆防盗报警系统
stm32·单片机·嵌入式硬件
小龙报1 天前
【51单片机】从 0 到 1 玩转 51 蜂鸣器:分清有源无源,轻松驱动它奏响新年旋律
c语言·数据结构·c++·stm32·单片机·嵌入式硬件·51单片机
范纹杉想快点毕业1 天前
嵌入式与单片机开发核心学习指南——从思维转变到第一性原理的深度实践
单片机·嵌入式硬件
Industio_触觉智能1 天前
瑞芯微RK3566开发板规格书,详细参数配置,型号EVB3566-V1,基于RK3566核心板SOM3566邮票孔封装
嵌入式硬件·开发板·rk3568·rk3566·核心板·瑞芯微