一:中断方式的串口编程
1.用中断方式编写串口程序由那几部分组成
2.硬件上的支持
1>UART0 发送FIFO缓冲区
A.UART0含有1个16字节的发送FIFO缓冲区
B.U0THR是UART0发送FIFO的最高字节
C.UART的发送FIFO是一直使能的
2>UART0接收FIFO缓冲区
A. UART0含有一个16字节的接收FIFO缓冲区。
B. 软件设置接收FIFO缓冲区的触发字节。
3> 中断接口:UART0的中断接口包含中断使能寄存器(U0IER)和中断标识寄存器(U0IIR)。
第一:U0IIR:提供状态码用于指示一个挂起中断的中断源和优先级。
第二:U0IER可以控制UART0的4个中断源。
4> UART0有4个中断源:
A. RLS(接收线状态)中断:
(1) 优先级最高
(2) 它在以下条件发生时产生错误
第一:帧错误(FE)
第二:溢出错误(OE)
第三:奇偶错误(PE)
第四:间隔中断(BI)
注:可以通过查看U0LSR[4:1]中的值看到产生该中断的错误条件,读取U0LSR寄存器时清除该中断。
B. RDA(接收数据可用)中断:
(1)与CTI中断并列第二优先级。
(2)在以下情况触发中断:
第一:当接收的有效数据到达接收FIFO设置寄存器(U0FCR)中设置的触发点时,RDA被激活。当接收FIFO中的有效数据少于触发点时,RDA复位。
第二:中断过程:
1> 移位寄存器(U0RSR)从RxD引脚接收串行数据后,送入接收FIFO中
2> 当接收FIFO中的有效数据数量达到预定的触发点时,置位RDA中断。
3> 从U0RBR寄存器中读取FIFO中最早到达的数据,当FIFO中的有效数据小于触发点时,清零RDA中断。
C. CTI(字符超时指示)中断
(1) 优先级为2.
(2) 在以下情况发生中断:
当接收FIFO中的有效数据少于预定的触发点数量时,如果在一定时间内仍没有接收到新的数据,那将触发该中断。
(3) 上面的时间指的是:3.5~4.5个字节所需要的时间。
(4) 对接收FIFO的任何操作都会清零该中断标志。
(5) 中断过程:
第一:移位寄存器(U0RSR)从RxD0引脚接收串行数据后,送入接收FIFO中。
第二:当接收FIFO中的有效数据少于触发个数,但如果长时间没有数据到达,则触发CTI中断。
第三:从U0RBR中读取接收FIFO中的数据,或者有新的数据送入接收FIFO,都将清零CTI中断。
注:3.5~4.5个字节的时间:指在串口当前的波特率下,发送3.5~4.5个字节所需要的时间。
当接收FIFO中存放多个数据,从U0RBR读取数据,但是没有读完所有数据,那么在经过3.5~4.5个字节的时间后触发CTI中断。
D. THRE(发送)中断
(1) 优先级为第三级优先级。
(2) 当FIFO为空并且在以下情况触发中断:
第一:系统启动时,虽然发送FIFO为空,但不会产生THRE中断。
第二:在上一次发生THRE中断后,向发送FIFO中写入1个字节数据,将在一个字节加上一个停止位后发生THRE中断
(because:如果发送移位寄存器为空,那么写入发送FIFO的数据将直接进入发送移位寄存器。此时发送FIFO仍然为空,如果立即产生THRE中断,就会影响紧接着写入发送FIFO的数据。所以在发送完该一个字节以及一个停止位后,才产生THRE中断。)
如果在发送FIFO中有过两个字节以上的数据,但是现在发送FIFO为空时,将立即触发THRE中断。当THRE中断为当前有效的最高优先级中断时,往U0THR写数或者对U0IIR的读操作,将使THRE中断复位
我们来看看这些中断源与存储器之间的关系:
注:由上图可知:UART0有4个中断源:分别是RLS(线状态)中断,RDA(接收数据)中断,CTI(字符超时)中断,THRE(发送数据)中断。4个中断源的优先级如下图所示:
3.串口中断接收初始化
1>串口中断接收初始化流程
l 设置I/O引脚连接到UART0
l 置位除数锁存位,配置UART0帧数据格式
l 根据波特率计算分频值
l 设置波特率
l 清除除数锁存位,并设置工作模式
l 使能FIFO,并设置触发点
l 允许RBR中断
注:我们可以发现与轮训方式相比,中断方式只是增加了使能FIFO,并设置中断触发点和允许RBR中断两步。
2>中断串口初始化需要配置的寄存器
(与轮循方式配置方法相同的寄存器在此处不在涉及)
l U0FCR(FIFO控制寄存器):U0FCR控制UART0 Rx和Tx FIFO的操作。
l U0IER(中断使能寄存器):U0IER用于使能4个UART0中断源。
3>具体寄存器的配置
(1) U0FCR
A作用:控制UART0 Rx和Tx的操作。
B长度:8位寄存器。
C:每一位的含义:
l 第0位:表示FIFO使能
置1:表示使能对UART0 Rx和Tx的FIFO以及U0FCR[7:1]的访问。
置0:表示不能使用Rx和Tx的FIFO以及步能对U0FCR[7:1]的访问。
注:该位的任何变化都将使UART0 FIFO清空。
l 第1位:表示Rx FIFO的复位。
置1:会清零UART0 RxFIFO中的所有字节并复位指针逻辑。该位自动清零。
l 第2位:表示Tx FIFO的复位。
置1:会清零UART0 TxFIFO中的所有字节并复位指针逻辑。改位自动清零。
l 第[5:3]位:保留位,用户不能对其进行操作。从保留位读出的值未被定义。
l 第[7:6]位:表示Rx触发选择
00:触发点为0(默认为1字节)
01:触发点为1(默认为4字节)
10:触发点为2(默认为8字节)
11: 触发点为3(默认为14字节)
注:这两个位决定在激活中断之前,接收UART0 FIFO必须写入个字符。
(2) U0IER(中断使能寄存器)
A 作用:U0IER用于使能4个UART0中断源
B 长度:8位寄存器
C每一位的含义:
l 第0位:表示RBR中断使能
置1:使能RDA中断
置0:禁止RDA中断
注:U0IEER 第零位使能UART0接收数据可用中断。它还控制(CTI)字符接收超时中断。
l 第1位:表示THRE中断使能
置1:使能THRE中断
置0:禁止THRE中断
l 第2位:表示Rx线状态中断使能
置1:使能Rx线状态中断
置0:禁止RX线状态中断
注:U0IER第二位使能UART0 Rx线状态中断。该中断的状态可从U0LSR[4:1]读出
l 第[7:3]位:是保留位
注:用户不能向其写入1.
4>串口初始化程序:void UART0_Init(uint32 bps)
4. 中断初始化
先来看一下UART0和VIC之间的关系:
1>中断初始化流程:
l 选择中断为向量中断或快速中断
l 分配中断通道
l 设置UART0向量地址
l 使能UART0中断
2>关于ARM中断编程方法和寄存器的使用在此不做涉及(如果想知道的话,可以看这篇文章http://blog.csdn.net/tigerjb/archive/2010/11/30/6045409.aspx
3>中断初始化程序:void Interrupt_Init (void)
5.用中断编写接收函数
1> 中断服务函数流程
l 清除串口中断标识寄存器(U0IIR)
l 清除中断标志
l 读取接收FIFO中的数据
2> 中断函数服务函数中需要配置的寄存器
(1) U0IIR中断标识寄存器。
l 第0位:表示中断挂起
置1:表示没有挂起的中断
置0:表示至少有一个中断挂起
l 第[3:1]位:中断标识,这三位表示了对应UART0 Rx FIFO的中断。
001:表示发送中断(THRE)
010: 表示接收数据可用中断(RDA)
011: 表示接收线状态中断(RLS)
110: 表示字符超时中断(CTI)
l 第[7:4]:是保留位
注:
1. U0IIR提供的状态码可用于指示一个挂起中断的中断源和优先级。
2. 在访问U0IIR过程中,中断被冻结
3. 如果在访问U0IIR时,产生了中断,该中断被记录。在下次访问U0IIR时可以读出,避免中断的丢失。
3> 中断服务函数程序:void __irq IRQ_UART0(void)
6.总程序:通过上位机给串口发送8字节数据,ARM2200接收到串口数据后,把数据又发送回上位机。
(在用中断的时候在Startup.S文件中的InitStack子程序中,修改设置系统模式堆栈处的代码为"MSR CPSR_c,#0x5f",
测试成功 ,在上面上发送16进制数时,每个之间用空格隔开不加前缀。)
#include "config.h"
uint8 recver_buffer[8];
uint8 rcv_new;
/**********************************************************
* 名称: UART0_Init()
* 功能: UART0初始化(通讯波特率115200,8位数据位,
1位停止位,无奇偶校验)
* 入口参数: bps 串口波特率
* 出口参数: 无
**********************************************************/
void UART0_Init(uint32 bps)
{
uint16 Fdiv;
PINSEL0 = 0x00000005; //设置串口引脚
U0LCR = 0x83; //置为除数锁存位,进行配置
Fdiv = (Fpclk >> 4) / bps; // 设置波特率
U0DLM = Fdiv >> 8;
U0DLL = Fdiv & 0xff;
U0LCR = 0x03; //清除除数锁存位,并设置工作模式模式
U0FCR = 0x81; // 使能FIFO,并设置触发点为8字节
U0IER = 0x01; // 允许RBR中断,即接收中断
}
/*********************************************************
* 名 称: IRQ_UART0
* 功 能: 串口UART0中断接收8个字节的数据
* 入口参数: 无
* 出口参数: 无
**********************************************************/
void __irq IRQ_UART0(void)
{ uint8 i;
if( 0x04 == (U0IIR&0x0F) )
{
rcv_new = 1; // 设置接收到新的数据标志,并清除中断标志位
for(i=0; i<8; i++)
{
recver_buffer[i] = U0RBR; // 读取FIFO的数据
}
VICVectAddr = 0;
} //清除中断
}
/**********************************************************
* 名称: Interrupt_Init
* 功能: 初始化串口中断,给串口中断选择为向量中断,
* 分配向量通道号1给串口
* 入口参数: 无
* 出口参数: 无
**********************************************************/
void Interrupt_Init (void)
{
VICIntSelect = 0x00000000; // 设置所有通道为IRQ中断
VICVectCntl0 = 0x26; // UART0中断通道分配到IRQ slot 0,即优先级最高
VICVectAddr0 = (int)IRQ_UART0; // 设置UART0向量地址
VICIntEnable = 0x00000040; // 使能UART0中断
}
/**********************************************************
* 名 称: UART0_SendByte
* 功 能: 向串口发送字节数据,并等待发送完毕。
* 入口参数: data 要发送的数据
* 出口参数: 无
**********************************************************/
void UART0_SendByte(uint8 data)
{
U0THR = data;
while(0 == (U0LSR & 0x40));
}
/**********************************************************
* 名称: UART0_SendBuf()
* 功能: 通过串口发送一帧数据
* 入口参数: *buffer 存放一帧数据
* 出口参数: 无
**********************************************************/
void UART0_SendBuf(uint8 *buffer)
{
uint8 *pbuffer;
uint8 i;
for(pbuffer = buffer,i = 0;i < 8; i++)
UART0_SendByte(*(pbuffer++));
}
/**********************************************************
* 名称: main()函数
* 功能: 上位机接收的数据开头两个字符为0x10,0x11,
* 则原样输出,否次输出0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27
* 入口参数: *buffer 存放一帧数据
* 出口参数: 无
**********************************************************/
int main (void)
{
uint8 send_buffer[8] ={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27}; //定义发送帧缓冲区
UART0_Init(115200);
Interrupt_Init();
while(1)
{
if(1 == rcv_new) // 是否已经接收到8 Bytes的数据
{
rcv_new = 0; // 清除标志
if(0x10 ==recver_buffer[0] && 0x11 == recver_buffer[1])
{
UART0_SendBuf(send_buffer);
}
else
{
UART0_SendBuf(recver_buffer);
}
}
}
return 0;
}
二.用中断编写发送函数
1.中断初始化
同上和用中断接收函数时的中断初始化是一样的
2.串口初始化
1>串口初始化流程:
l 设置I/O引脚连接到UART0
l 置位除数锁存位,配置UART0帧格式
l 根据波特率计算分频值
l 设置波特率
l 清除除数锁存位,并设置工作模式
l 使能FIFO,并使TxFIFO复位
l 使能THRE中断
2>串口初始化函数:void UART0_Init(uint32 bps)
3.中断服务函数:
1>中断服务函数流程:
l 清除串口中断标识寄存器
l 清除中断控制标识寄存器
2>中断发送服务函数程序:void __irq IRQ_UART0(void)
4.用串口中断发送函数的总程序:通过上位机给串口发送8字节数据,ARM2200接收到串口数据后,用中断方式把数据又发送回上位机。
#include "config.h"
uint8 recver_buffer[8];
uint8 rcv_new;
/****************************************************************************
* 名称: UART0_Init
* 功能: UART0初始化 通讯波特率115200,8位数据位,1位停止位,无奇偶校验
* 使能TxFIFO,和THRE中断
* 入口参数: bps 串口波特率
* 出口参数: 无
****************************************************************************/
void UART0_Init(uint32 bps)
{
uint16 Fdiv;
PINSEL0 = (PINSEL0 & ~(0xf) | 0x05) ; //设置UART0的引脚
U0LCR = 0x83; //置位除数锁存位,配置UART0帧格式
Fdiv = (Fpclk>>4)/bps; //根据波特率计算分频值
上一篇:嵌入式处理器的体系架构与内核详解
下一篇:UART0串口编程(二):硬件原理;轮训方式的串口编程
推荐阅读
史海拾趣
随着电子行业的快速发展,Comchip Technology不断追求技术创新和产品升级。公司通过大量研发投入,成功开发出了桥式整流器、高效快速整流器等一系列具有市场竞争力的产品。这些产品不仅提高了电子设备的性能,还降低了能耗,赢得了客户的广泛认可。
随着电子行业的快速发展,Comchip Technology不断追求技术创新和产品升级。公司通过大量研发投入,成功开发出了桥式整流器、高效快速整流器等一系列具有市场竞争力的产品。这些产品不仅提高了电子设备的性能,还降低了能耗,赢得了客户的广泛认可。
进入21世纪后,环保和可持续发展成为全球关注的焦点。Hokuriku Electric积极响应这一趋势,将环保理念融入产品研发和生产过程中。公司投入大量资源研发绿色电子产品,减少生产过程中的能源消耗和废弃物排放。同时,Hokuriku Electric还积极参与行业内的环保倡议和合作项目,推动整个电子行业的可持续发展。这一举措不仅赢得了社会各界的广泛赞誉,还为公司带来了更多的商业机会和合作伙伴。
Crystal Semiconductor Corp成立之初,面临着资金短缺、技术难题和市场竞争的多重压力。然而,公司的创始人凭借对半导体技术的深刻理解和敏锐的市场洞察力,成功吸引了一批志同道合的工程师和投资者。他们共同攻克了技术难关,推出了首款具有竞争力的晶体管产品,迅速在市场上占据了一席之地。
服务:Hartmann Codier GmbH深知客户是企业发展的基石。因此,公司始终将客户服务放在首位,致力于为客户提供优质的产品和服务。公司建立了完善的客户服务体系,包括售前咨询、售中支持和售后服务等环节。
成果:通过不断优化客户服务流程和提高服务质量,Hartmann Codier GmbH赢得了广大客户的信赖和支持。公司与客户之间建立了长期稳定的合作关系,共同推动了电子行业的繁荣发展。同时,公司也根据客户的反馈和需求,不断改进产品和服务,以满足市场的不断变化和升级。
进入新世纪,电子行业的技术更新换代速度加快。AB Connectors Ltd意识到,只有不断创新才能在激烈的市场竞争中立足。于是,公司加大了研发投入,组建了一支高素质的研发团队,专注于连接器技术的创新。经过多年的努力,AB Connectors Ltd成功开发出了一系列具有自主知识产权的新型连接器产品,不仅提高了产品的性能和质量,还降低了生产成本。这些创新产品为公司赢得了众多客户的青睐,进一步巩固了市场地位。
Windows Mobile 6.0 SDK环境下,如何用DirectShow 我有如下工具: >(1)Visual Studio 2005 PRO >(2)Windows Mobile 6.0 SDK >(3)DX90bsdk >(4)Windows CE 6.0 我想以Windows Mobile 6.0 Professional SDK为解决方案平台开发MP3播放器. ...… 查看全部问答∨ |
USB activesync 同步,论坛里面谈论的很多,但是查了以前的帖子都没能对应上的。闹腾了好长时间,都没能解决,请各位朋友帮助! 现像有点奇怪。每次镜像烧些后(NOR flash 启动),同步是能连接上的。但是再关闭电源, ...… 查看全部问答∨ |
我在看一个ADS自带的swi的例子时,遇到了这么一个问题: vec = (routine - (unsigned)vector - 8) >> 2; 这句话老师告诉我是为了算出软中断处理程序距软中断向量的相对位置。 然后我问为什么减8,再右移两位。在arm手册中找到了,关于bl: ...… 查看全部问答∨ |
|
原用AVR,因众所周知的原因,我们开始更换成ST8的单片机。 AVR用了几年,我们得到厂家的支持,价格几乎是全国最低了。 今天买加了样片与STLink,准备开工。… 查看全部问答∨ |
我现在急需一本汇编的书或资料,你说你有一本武汉力源的资料,不知道是什么样的资料,叫什么名字,如果方便的话,可不可以告诉我一下,我跟武汉力源联系,顺便问一下,在市面上能不能买到?不胜感谢… 查看全部问答∨ |
1602在PIC16F914单片机上显示问题搞定了,谢谢大家 嘿嘿,搞定了,原来IO口需要这样配置(原先我咨询了Microchip上海技术支持,一女的说不用段式LCD功能,就不用管COMCON0和LCDCON,搞的我.......看来,还是要自己细心才行啊),同志们,不要犯我这样的错误哦,嘿嘿,谢谢各位的指导啊。/*-----------1 ...… 查看全部问答∨ |
书名如下: 《Windows CE 6.0开发者参考》 《Windows CE 嵌入式系统》 《Windows CE 嵌入式高级编程及其实例详解(用C++实现)》 《Windows CE 实用开发技术(第二版)》 《Windows CE 工程实践完全解析》 《Windows ...… 查看全部问答∨ |