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开发 ...
随机推荐
- 6-SUPER关键字
(1)强行调用父类方法的执行(2)super不一定在重写中使用,也可以表示那些方法是从父类中继承而来的.
- java导读
导读: 我们学习Java大概有3个方向,第一,桌面系统,包括C/S结构:第二,J2ME,面向无限领域,很有潜力的家伙,看看中国的手机用户就知道了.第三,面向企业应用.计算的平台,J2EE. ...
- EM阅读资料
1,从最大似然到EM算法浅解 2,(EM算法)The EM Algorithm 3,数据挖掘十大算法----EM算法(最大期望算法) (番外)最大后验估计(MAP)
- java网络之tcp
简单tcp传输 package pack; /* 演示tcp传输. 1,tcp分客户端和服务端. 2,客户端对应的对象是Socket. 服务端对应的对象是ServerSocket. 客户端, 通过查阅 ...
- 我也谈javascript正则匹配
一.javascript 正则全局匹配 g 慎用test()方法 来个例子: var a = /^[a-z]+/gi; a.test('bb123'); //true a.lastIndex ; // ...
- [转]makefile文件的编写规则及实例
http://xueqi.iteye.com/blog/1567866 1.一个简单的makefile例子 假设一个程序有两个文件file1.c,file2.c,每个文件都包含head.h,生 ...
- Chapter 1 First Sight——1
My mother drove me to the airport with the windows rolled down. 随着窗户渐渐摇下,我妈妈开着车送我去机场. It was seventy ...
- string数组转化成int数组
string idsStr = "1,2,3,4,5"; int[] ids = idsStr.Split(',').Select(Int32.Parse).ToArray();
- 关于struts2的web.xml配置
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "- ...
- mysql基础---日志文件
一 基本日志文件 MYSQL有不同类型的日志文件(各自存储了不同类型的日志),从它们当中可以查询到MYSQL里都做了些什么,对于MYSQL的管理工作,这些日志文件是不可缺少的. 1.错误日志(The ...