UART0串口编程(二):串口编程的硬件原理;轮训方式的串口编程

UART0串口编程(二)

本节针对的是ARM2200环境下编写串口程序,其中设计轮循方式,中断方式,以及在UC/OS-II操作系统下的串口编程。使用轮循和中断两种方式来实现串口编程。用中断实现串口编程,系统的效率较高,但是难度也较大 ;轮循方式效率较低,但是编程比较简单。

一.串口编程的硬件原理

1.     串口特性:

1>16字节接收FIFO16字节发送FIFO

2>接收FIFO触发点可设置为14814字节。

3>内置波特率发生器。

2.     UART0引脚:

1>RxD0 引脚用于UART0接受数据,接受方式为串行输入。

2>TxD0引脚用于UART0发送数据,发送方式为串行发送数据。

3.     UART0的结构和工作方式

先看图在说明:


1>  VPB总线提供CPUUART0之间得的通信连接

(CPU内核通过VPB接口对UART0的寄存器进行读写访问.)

2>  UART0 接收器模块监视串行输入线RxD0的有效输入。UART0 接收单元的移位寄存器(U0RSR)通过RxD0接收有效的字符。当U0RSR接受到一个有效字符时,它将该字符传送到UART0 接收单元缓冲寄存器FIFO中,等待CPU通过VPB接口进行访问。

3>  UART0发送器模块接收CPU或主机写入的数据并将数据缓存到UART0 FIFOU0THR中,UART0发送模块中的移位寄存器(U0TSR)读取U0THRFIFO中的数据并将数据通过串行输出到引脚TxD0发送。

4>  UART0的接收模块和发送模块的状态信息保存在U0LSR中。

控制信息保存在U0LCR中。

5>  UART0波特率发送器模块产生UART0 发送模块所使用的定时。波特率发生器模块时钟源为VPB时钟(pclk)。主时钟与U0DLLU0DLM寄存器所定义的除数相除得到UART0 发送器模块使用的时钟,该时钟必须为波特率的16倍。

6>  中断接口包含寄存器U0IERU0IIR。中断接口接收UART0发送模块和接收模块发出的单时钟宽度的使能信号。

4.  UART0ARM7 CPU之间的通信过程

1>CPU通过UART0发送模块发送信息给外设

第一:CPU发出信息通过AHB总线到AHB-VPB

第二:通过AHB-VPB桥把信息转换后发送给VPB总线。

第三:UART0接收模块接受来自VPB总线的数据。并将数据缓存到U0THR寄存器中。

第四:UART0接受模块的移位寄存器U0TSR读取U0THR中的数据 并将数据通过输出引脚TxD0发送。


2>外设通过UART0接收模块向ARM7 CPU发送信息

第一:UART0移位寄存器(U0RSR)通过引脚RxD0接收有效字符。

第二:当UART0接收到一个有效字符后,通过读取U0RBR寄存器可以将FIFO中最早接收到的字节读出,当FIFO中不再包含有效数据时,该寄存器反映接收到的最后一个有效字节数据。接收的数据不足8位时,高位用0填充。

第三:VPB总线将缓冲寄存器(U0RBR)中的数据通过AHB-VPB桥传到AHB总线上

第四:AHB总线将数据传送给ARM7 CPU。


二.轮训方式的串口编程

1.     串口程序都有那几部分组成如下图:


1>  串口初速化

A.    串口初始化的流程

第一:设置I/O引脚连接到UART0

第二:设置串口波特率

第三:设置串口工作模式

B.     串口初始化需要设置的寄存器

第一:U0LCR(控制寄存器):设置UART0的通信格式。

第二:U0DLL,U0DLM(寄存器):设置UART0的通信波特率。

C.     具体寄存器的设置

(1) U0LCR(线控制寄存器)

第一:作用:设置通信格式(通信字符长度,停止位个数,奇偶校验位

第二:长度:8位寄存器

第三:各位寄存器的含义:

[1 ,0]表示字长

00:表示5位字长

01:表示6位字符长度

10:表示7位字符长度

11:表示8位字符长度

2表示停止位选择

01个停止位

12个停止位

3位:表示奇偶使能

0:禁止奇偶产生和校验

1:使能奇偶产生和校验

注:奇偶使能:控制是否进行奇偶校验。如果使能,发送时将添加一位校验位。

[5 4]位:表示奇偶选择位

  00:奇数(数据位+校验位=奇数)

  01:偶数(数据位+校验位=偶数)

 10:校验位强制为1

11:校验位强制为0

注:奇偶选择主要是设置奇偶校验类型。

6位:间隔控制

 0:禁止间隔发送

 1:使能间隔发送

注:当该位为1时,输出引脚(TxD0)强制为逻辑0,可以引起通信对方产生间隔中断。在一些通信方式中,使用间隔中断作为通信的起始信号(eg:LIN Bus)      

 7位:除数锁存访问位

 0:禁止访问除数锁存寄存器

 1:始能访问除数锁存寄存器


(2) U0DLL,U0DLM(除数锁存寄存器)

第一:作用:U0DLLU0DLM寄存器一起构成一个16位除数。

第三:U0DLLU0DLM都为8位寄存器。

第四:U0DLL:存放分频值的低8

第五:U0DLM:存放分频值的高8位。

注意:

(1)使用U0DLLU0DLM配置波特率之前,必须先计算分频值。

Fdiv=Fpclk/(16*baud)

(2)使用U0DLLU0DLM配置波特率之前必须把U0LCR控制寄存器的第8位置为1才能进行配置。配置完后要把U0LCR控制寄存器的第8位置位0

2.串口接收数据

用轮循方式接收数据

1>CPU通过串口接收数据时各个寄存器之间的关系


2>串口接受数据的流程:

第一:循环检测U0RBR是否有未读取的数据。

第二:如果有数据到来,则接收数据。

3>相关寄存器配置

(1) U0LSR(线状态寄存器)

第一:作用,只读寄存器,它提供UART0发送和接收模块的状态信息。

第二:长度:8位寄存器。

第三:各位寄存器的含义:

A0位:表示接收数据就绪

0表示U0RBR为空

1表示U0RBR包含有效数据

注:当U0RBR包含未读的字符时,第0位被置位;当UART0U0RBRFIFO为空时,第0位置零。

B.1位:溢出错误。

0:溢出错误状态未激活

1:溢出错误状态激活

注:溢出错误条件在错误发生后立即设置。对U0LSR读操作将清零第1位。当UART0RSR已经有新的字符就绪,而UART0  RBRFIFO已满时,第一位置1.此时的UART0 RBRFIFO不会被覆盖,UART0 RSR中的字符将丢失。

C.2位:奇偶错误。

0:奇偶错误状态未激活

1:奇偶错误状态激活

注:当接收字符的奇偶位处于错误状态时产生一个奇偶错误。对U0LSR读操作清零该位。奇偶错误检测时间取决于U0FCRbit0。奇偶错误与UART0 RBRFIFO中读出的字符相关。

D.3位:帧错误

0:帧错误状态未激活。

1:帧错误状态激活

 注: 当接收字符的停止位为0,产生帧错误。对读操作U0LSR清零该位。帧错误检测时间取决于U0FCRbit0。帧错误与UART0RBRFIFO中读出的字符相关。当检测到一个帧错误时,Rx将尝试与数据重新同步并假设错误的停止位实际是一个超前的起始位。但即使没有出现帧错误,它也不能假设下一个接收到的字节是正确的。

E.第四位:间隔中断

0:间隔中断状态未激活

1:间隔中断状态状态激活

注: 在发送整个字符(起始位,数据,奇偶位和停止位)过程中RXD0如果都保持逻辑0,则产生间隔中断。当检测到中断条件时,接收器立即进入空闲状态直到RXD0变为全1状态。读操作U0LSR清零该状态位。 间隔检测的时间取决于U0FCRbit0。间隔中断与UART0RBRFIFO中读出的字符相关。

F.第五位:发送保持寄存器空

0:表示U0THR包含有效数据

1:表示U0THR

注:当检测到UART0 THR空时,THRE置位。对U0THR写操作清零该位。

G.6位:表示发送器空

0U0THR和或U0TSR包含有效数据。

1U0THRU0TSR

注:当U0THRU0TSR都为空时,该位置1,当U0TSRU0THR包含有效数据时,该位清零。

H7位:表示Rx FIFO 错误。

0U0RBR中没有UART0 Rx错误,或U0FCRbit0.

1U0RBR包含至少一个UART0 Rx错误。

注: 当一个带有Rx错误(例如帧错误,奇偶错误或间隔中断)的字符装入U0RBR时,该位置1 当读取U0LSR寄存器并且UART0FIFO中不再有错误时,该位置零。

(2) U0RBR(接收器缓冲寄存器)

第一:作用,只读寄存器,是UART0 Rx FIFO的最高字节。它包含了最早接收到的字符,可通过总线接口读出。串口接收数据时低位在先,即U0RBRbit0为最早接收到的数据位。如果接收到的数据小于8位,未使用的MSB填充为0.

第二:长度:8位寄存器。

 

3.串口发送数据

1>  CPU通过串口发送数据时,各寄存器之间的关系


2>  串口发送数据时的流程

第一:将要发送的一字节数据写入U0THR

第二:等待数据发送完毕

3>  相关寄存器配置

1U0THR(发送保持寄存器)

第一:最用:只写寄存器。U0THRUART0 Tx FIFO的最高字节。它包含了Tx FIFO 中最新的字符,可通过总线接口写入。串口发送数据时,低位在先,bit0代表最先发送的位。

长度:8位寄存器

2U0LSR(线状态寄存器)

在上面已经介绍,在此步再涉及。

 4.下面是完整的程序:用轮训方式实现接收上位机数据,并把数据再发送给上位机。

(通过上位机给串口发送8字节数据,ARM2200接收到串口数据后,把数据又发送回上位机)

/******************************************************************************
** Modified by:         TIGER0-JOHN
** Modified date:       2011-1-21
** Version:             1.1  
** Descriptions:        测试成功 ,在上面上发送16进制数时,每个之间用空格隔开
						不加前缀
****************************************************************************/

#include "config.h"

/****************************************************************************
* 名    称:	DelayNS()
* 功    能:	长软件延时
* 入口参数:	dly		延时参数,值越大,延时越久
* 出口参数:	无
****************************************************************************/
void  DelayNS(uint32  dly)
{  
    uint32  i;
    
    for(; dly>0; dly--) 
    {
        for(i=0; i<5000; i++);
    }

}
/**********************************************************
* 名称:		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;                      //清除除数锁存位,并设置工作模式

}

/**********************************************************
* 名    称:            UART0_RcvByte
* 功    能:            用查询方式接收一字节的数据
* 入口参数:            无
* 出口参数:            data              要接收的数据
**********************************************************/
uint8   UART0_RcvByte(void)
{
	uint8 rcv_data ;
	while((U0LSR&0X01)==0);         //等待数据到达
    rcv_data = U0RBR;               //从U0RBR中读出接收到的数据
    return  rcv_data;               //返回接收到的数据

}
/**********************************************************
* 名    称:            UART0_SendByte
* 功    能:            向串口发送字节数据,并等待发送完毕。
* 入口参数:            data              要发送的数据
* 出口参数:            无
**********************************************************/
void   UART0_SendByte(uint8 data)
{
		U0THR = data;                 
		while(0 == (U0LSR & 0x40));
}
/**********************************************************
* 名称:		UART0_RecBuf()
* 功能:		接收串口发送过来的帧数据,			
* 入口参数:	*buffer  存放一帧数据
* 出口参数:	无
**********************************************************/
void UART0_RecBuf (uint8 *buffer)
{
	uint8 *pbuffer;
    uint8  i;
	for(pbuffer = buffer, i = 0;i < 8; i++)
	 {
	 	*(pbuffer++) = UART0_RcvByte();
	 }
}
/**********************************************************
* 名称:		UART0_SendBuf()
* 功能:		通过串口发送一帧数据
* 入口参数:	*buffer  存放一帧数据
* 出口参数:	无
**********************************************************/
void UART0_SendBuf(uint8 *buffer)
{
	uint8 *pbuffer;
    uint8 i;
	for(pbuffer = buffer,i=0;i < 8; i++)
	UART0_SendByte(*(pbuffer++));
}

int main (void)
{ 
    uint8 recver_buffer[8];                                           //定义接收帧缓冲区
    uint8 send_buffer[8] ={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27};  //定义发送帧缓冲区
    UART0_Init(115200);
    while(1)
    {
      UART0_RecBuf(recver_buffer);   
      DelayNS(10);
     if(0x10 ==recver_buffer[0] && 0x11 == recver_buffer[1])
     UART0_SendBuf(recver_buffer);
     else
     UART0_SendBuf(send_buffer);
     }    
     return 0;
}


下一节讲中断方式串口编程



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魏波.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值