LPC2478中断控制器以及串口详解
LPC2478的中断系统
LPC2478使用的是ARM PrimeCell向量中断控制器,一共支持32个中断向量,处于AHB空间便于系统快速访问,在中断向量的硬件优先级上还有一层可以用户自己设计的软件优先级,
由于是ARM7内核,所以,2478的中断有两种,分别是FIQ中断和IRQ中断,IRQ有多个中断通道,FIQ的中断通道却只有一个,中断系统框图如下
当FIQ中断进入时,会经历多个中断想或的过程,得到的中断状态不管是不是使能了中断,都会存放至RAWINT里面,然后判断中断使能,被使能的中断写入到FIQSTATUS,并向系统发出快速中断请求,系统响应中断的模式则是自动读取FIQSTATUS判断哪个中断发生,并直接跳转到FIQ处理程序,我们可以看到,FIQ是没有中断优先级的,他只需要判断最高位为1是哪一位就能快速跳转到FIQ处理程序了
当IRQ中断发生的时候,首先会有一个优先级鉴别,只有软件优先级最高的才能进入系统,当有多个中断进入系统的时候,这多个中断优先级相同,则会经过一次硬件优先级鉴别,选出优先级最高的那个进入系统,系统直接到相应的中断处理程序处理
相关寄存器如下
在实际的硬件中断没发生的情况下又想调用对应的中断处理程序,这需要用这个软件中断
移除有软件中断引发的中断
这个应该叫做中断事件标志位,当有中断发生不管是什么中断不管是否使能对应位都要写1
中断使能
清除中断使能
选择中断的模式,可以看到,初始化的时候都是IRQ中断
IRQ中断状态,并不是说这是中断标志,只是一种状态表示
FIQ的中断状态, 并不是说这是中断标志,只是一种状态表示
有32个这样的寄存器,指定中断的服务程序的地址,系统发生中断之后,会自动调用
中断的优先级,四位优先级,有16个优先级,一共有32个寄存器和中断向量一一映射
当前正在响应的中断优先级的地址
将VIC中断寄存器保护起来,防止用户在用户模式下修改,只能在特权模式下修改
使用VIC向量中断寄存器一般分为以下几步
1. 关闭对应中断使能以及对应的软件中断
2. 清除中断状态
3. 选择中断模式,设置中断级别,设置中断地址,使能中断
4. 注意将相应的中断优先级屏蔽进行处理
中断处理时
1. 清除中断标志
2. 中断处理
3. 完成之后将当前处理函数指针清零
具体代码如下
#ifndef __VIC_H_
#define __VIC_H_
#include "common.h"
#include "lpc24xx.h" void InitVic(void); #endif
#include "vic.h" void InitVic(void)
{
//禁止所有中断
VICIntEnClr = 0xffffffff;
//设置当前中断指向为0
VICVectAddr = 0;
//所有中断都是IRQ模式
VICIntSelect = 0;
//软件中断全部清除
VICSoftIntClr = 0xffffffff;
}
LPC2478串口使用
Lpc2478有三个串口,是通用的异步串口,分别是串口0 2 3,都带有FIFO,深度可控制,1 2 4 8 均可触发,同时内置波特率发生器,并有小数波特率分频器用于实现自动波特率
一般而言,对于串口的控制分为设置格式,设置fifo,设置波特率,配置中断,打开串口
主要有以下寄存器
分别用来接收数据,发送数据,选择波特率分频,其中,波特率分频系数的计算需要小数波特率的参与,如下
计算公式如下
自动波特率一般用于测量基于AT指令的协议,用的不多,
配置串口的过程如下
选择格式,数据位长度,停止位,校验位,同时,里面的除数访问锁关闭,否则无法计算波特率
配置相应的中断使能,
配置串口的FIFO
配置波特率,除数寄存器前面已经描述
设置发送使能
具体查看代码
#ifndef __DEBUGSERIAL_H_
#define __DEBUGSERIAL_H_
#include "lpc24xx.h"
#include "common.h"
#include "clock.h"
#include "stdio.h" #define SERIALS_BUFFER_MAX_LENGTH 0X3FF
#define SERIAL_RECV_PACKAGE (1<<15)
#define SERIAL_RECV_LENGTH (serialRecvStatus&0X3FF)
#define SERIAL_RECV_CLEAR (serialRecvStatus = 0)
#define SERIAL_RECV_LF (1<<14) void DebugSerialInit(u32 baud);
void DebugSerialSendChar(u8 value);
void UartSendBuffer(u8* bufferStart,u8 length); extern u8 serialsBuffer[SERIALS_BUFFER_MAX_LENGTH];
extern u16 serialRecvStatus; #endif
#include "debugSerial.h" u8 serialsBuffer[SERIALS_BUFFER_MAX_LENGTH];
u16 serialRecvStatus = 0; void __irq UART0_IRQHandler(void)
{
u8 Res;
Res = U0RBR; //读取接收数据
IENABLE; /* handles nested interrupt */
if(serialRecvStatus & SERIAL_RECV_PACKAGE) //已经收到完整的一包未处理
{
//丢弃
}
else if(serialRecvStatus & SERIAL_RECV_LF) //已经收到0X0D
{
if('\n' == Res)//收到0X0A
{
serialRecvStatus |= SERIAL_RECV_PACKAGE;
}
else //没收到,包错误,丢弃
{
SERIAL_RECV_CLEAR;
}
}
else
{
if('\r' == Res) //收到0X0D
{
serialRecvStatus |= SERIAL_RECV_LF;
}
else //正常数据
{
if(SERIAL_RECV_LENGTH >= SERIALS_BUFFER_MAX_LENGTH)
{
//已经到最大包长度,数据错误
SERIAL_RECV_CLEAR;
}
else
{
serialsBuffer[serialRecvStatus] = Res;
serialRecvStatus++;
}
}
}
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
} //加入printf支持
#if 1
#pragma import(__use_no_semihosting)
struct __FILE
{
int handle;
/* Whatever you require here. If the only file you are using is */
/* standard output using printf() for debugging, no file handling */
/* is required. */
};
FILE __stdout;
_sys_exit(int x)
{
x = x;
}
int fputc(int ch, FILE *f)
{
while(!((U0LSR) & 0x20)); //等待判断LSR[5](即THRE)是否是1,1时表示THR中为空
U0THR = (u8)ch; //发送数据
return ch;
}
void _ttywrch(int ch)
{
while(!((U0LSR) & 0x20)); //等待判断LSR[5](即THRE)是否是1,1时表示THR中为空
U0THR = (u8)ch; //发送数据
}
#endif void DebugSerialInit(u32 baud)
{
PCLKSEL0 &= ~(0x03<<6); //选择外设时钟 pclk = sysclock
PCLKSEL0 |= (0x01<<6);
PCONP |= (1<<3); //打开UART0功率、时钟控制位 PINSEL0 &= ~(0x03<<4);//配置uart0对应io口功能 p02 p03
PINSEL0 |= (0x01<<4);//p02 tx0
PINSEL0 &= ~(0x03<<6);
PINSEL0 |= (0x01<<6);//p03 rx0 U0TER &= ~(1<<7);//禁止发送
U0IER = 0x00; //关闭所有中断
U0LCR = 0x83; //设置串口数据格式,8位字符长度,1个停止位,无校验,使能访问除数锁存器 ,设定波特率
U0FDR = 0x10; //小数波特率不工作
U0DLM = ((SystemCoreClock/16)/baud) / 256; //除数高八位 , 没有小数情况
U0DLL = ((SystemCoreClock/16)/baud) % 256; //除数低八位
U0LCR &= ~(1<<7); //禁止访问除数锁存器,锁定波特率
U0FCR &= ~(1<<0); //禁止FIFO
U0IER |= (1<<0); //使能接收中断 //中断向量配置
VICSoftIntClr |= (1<<6);//清除软件中断,uart0中断源为6 0开始
VICIntEnClr |= (1<<6);//禁止中断
VICIntSelect &= (1<<6);//选择为IRQ中断
VICVectAddr6 = (unsigned)UART0_IRQHandler;//连接中断向量
VICVectPriority6 = 0x01;//中断优先级寄存器
VICIntEnable |= (1<<6);//中断向量使能有效 //启动串口发送
U0TER |= (1<<7); } void DebugSerialSendChar(u8 value)
{
//当检测到UARTn THR已空时,THRE就会立即被设置。写UnTHR会清零THRE
//0 - UnTHR包含有效字符
//1 - UnTHR为空
while(!((U0LSR) & 0x20)); //等待判断LSR[5](即THRE)是否是1,1时表示THR中为空
U0THR = value; //发送数据
} //串口发送数组
void UartSendBuffer(u8* bufferStart,u8 length)
{
u8 i = 0;
for(i = 0; i < length; i++)
{
DebugSerialSendChar(*(bufferStart+i));
}
}
LPC2478中断控制器以及串口详解的更多相关文章
- iOS 视图控制器转场详解
iOS 视图控制器转场详解 前言的前言 唐巧前辈在微信公众号「iOSDevTips」以及其博客上推送了我的文章后,我的 Github 各项指标有了大幅度的增长,多谢唐巧前辈的推荐.有些人问我相关的问题 ...
- “全栈2019”Java多线程第六章:中断线程interrupt()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- Spring MVC 学习)——控制器与@RequestMapping详解
Spring MVC 学习总结(二)——控制器定义与@RequestMapping详解 一.控制器定义 控制器提供访问应用程序的行为,通常通过服务接口定义或注解定义两种方法实现. 控制器解析用户的请求 ...
- s3c2440串口详解
一.UART原理说明 通用异步收发器简称UART(Universal Asynchronous Receiver/Transmitter),它用来传输串行数据:发送数据时,CPU将并行数据写入UART ...
- ios控制器生命周期详解
#import "MyOneViewController.h" @interface MyOneViewController () @property (nonatomic, st ...
- 笔记-iOS 视图控制器转场详解(上)
这是一篇长文,详细讲解了视图控制器转场的方方面面,配有详细的示意图和代码,为了使得文章在微信公众号中易于阅读,seedante 辛苦将大量长篇代码用截图的方式呈现,另外作者也在 Github 上附上了 ...
- 转:WCF传送二进制流数据基本实现步骤详解
来自:http://developer.51cto.com/art/201002/185444.htm WCF传送二进制流数据基本实现步骤详解 2010-02-26 16:10 佚名 CSDN W ...
- “全栈2019”Java多线程第五章:线程睡眠sleep()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 基于STM32之UART串口通信协议(一)详解
一.前言 1.简介 写的这篇博客,是为了简单讲解一下UART通信协议,以及UART能够实现的一些功能,还有有关使用STM32CubeMX来配置芯片的一些操作,在后面我会以我使用的STM32F429开发 ...
随机推荐
- CenOS配置VSFTP服务器
1 Linux FTP服务器分类: wu-ftp proftp=profession ftp vsftp=very security ftp 2 安装vsftp yum install vsftp 3 ...
- POJ - 3062 Borg Maze
题目链接:http://poj.org/problem?id=3026 Svenskt Masterskap我程序员/ Norgesmesterskapet 2001 Description The ...
- 最短路径算法专题2----Dijkstra
这个算法适用于求单源最短路径,从一点出发,到其余个点的最短路径. 算法要点: 1.用二维数组存放点到点的距离-----不能相互到达的点用MAX代替距离 2.用dis数组存放源点到任意其他一点的距离-- ...
- HTML DOCTYPE文档类型举例说明
HTML DOCTYPE文档类型举例说明 HTML4.01文档过渡定义类型,此类型定义的文档可以使用HTML中的标签与元素包括一些不被W3C推荐的标签(例如:font.b等),不可以使用框架 < ...
- StretchAnimation伸缩动画.
原理是继承animation 然后改变他的margintop 和marginbottom 形成2个效果 ExpandTopAnimation public class ExpandTopAnim ...
- PAT (Advanced Level) 1075. PAT Judge (25)
简单模拟题. 注意一点:如果一个人所有提交的代码都没编译通过,那么这个人不计排名. 如果一个人提交过的代码中有编译不通过的,也有通过的,那么那份编译不通过的记为0分. #include<cstd ...
- shell中break 与 continue
在学习中我看到不单单有break和continue的存在,还有break -n 和 continue -n 的存在 那么它们有什么区别呢. 这时可以写出测设代码: for i in a b c ...
- Python3基础 当函数中的局部变量与全局变量同名了,各管各的
镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...
- web容器启动顺序
web容器启动顺序: 第一:context-param 第二:Listerer 第三:Filter 第四:servlet
- Android WifiDisplay分析一:相关Service的启动
网址:http://www.2cto.com/kf/201404/290996.html 最近在学习Android 4.4上面的WifiDisplay(Miracast)相关的模块,这里先从WifiD ...