数据位 D7 D6-D3 D2 D1 D0
定义 COS 0 DB FFULL/RXRDY TXRDY
复位 0 0 0 0 0
UART 最多可允许产生 4 个中断请求:1 个来自于发送器,3 个来自于接收器。UART 中断状态寄存器(UISR)提供这 4 个中断请求的标志。其中最常用的是接收中断。
D7—COS,状态改变(Change-Of-State)中断标志。CTS 引脚上任何电平的转变会使 得该中断标志位被置位。通过读取 UART 输入端口改变寄存器(UIPCR)中的值来得到 CTS 状态。读 UIPCR 将自动取消 COS 中断标志位。
D2—DB,Break 信号的中断标志。只要接收器检测到 Break 字,该标志即被置位。
接收器在收到的字符为全零且没有检测到停止位时,断言为 Break 条件。写 UART 命令寄 存器 MISC 位域的值为“101”,可将 DB 标志清零。
D1—FFULL/RXRDY,FIFO 满/接收就绪中断标志(也称接收中断标志)。当接收器 的 RB 中有数据,该标志置位。用户可以选择 RXRDY 或 FIFO 满作为中断请求源,该选 择是通过 UART 模式寄存器 1(UMRl)中的接收中断选择控制位(RXIRQ/FFULL)来实 现的。当 CPU 读 RB 时,RXRDY 中断标志将自动清零。
D0—TXRDY,发送器准备完毕中断标志。当发送缓冲寄存器空时 UART 发送器置位 该标志。
83
4.4 基于构件方法的UART编程
4.4.1 UART构件的函数原型设计
UART 具有初始化、接收和发送三种基本操作。按照构件的思想,可将它们封装成三 个独立的功能函数,初始化函数完成对 UART 模块的工作属性的设定,接收和发送功能 函数则完成实际的通信任务。对 UART 模块进行编程,实际上已经涉及到对硬件底层寄 存器的直接操作,因此,可将初始化、接收和发送三种基本操作所对应的功能函数共同放 置在命名为 UART.c 的文件中,并按照相对严格的构件设计原则对其进行封装,同时配以 命名为 UART.h 的头文件,用来定义模块的基本信息和对外接口。
按照模块所具有的基本操作来确定构件中应该具有哪些功能集合,是很自然也很重要 的事情。但是,要实现编程的构件化,对具体的函数原型的设计则是重中之重。函数原型 设计的好坏直接体现构件化编程的成败。下面就以 UART 的初始化、接收和发送三种基 本操作为例,来说明实现构件化的全过程。
需要说明的是,实现构件化编程的 UART 软件模块应当具有以下几个特点:
(1)UART 模块是最底层的构件,它主要向上提供三种服务,分别是 UART 模块的 初始化、接收单个字节和发送单个字节,向下则直接访问模块寄存器,实现对硬件的直接 操作。另外,从现实使用角度出发,它还需要封装接收 N 个字节和发送 N 个字节的子功 能函数。
(2)UART 模块在软件上对应 1 个 UART.c 程序源代码文件和 1 个 UART.h 头文件,
当需要对它进行移植时,大多数情况下只需简单拷贝这两个文件即可,无需对源代码文件 和头文件进行修改,只有当实施不同芯片之间的移植时,才需要修改头文件中与硬件相关 的宏定义。
(3)上层构件或软件在使用该构件时,严格禁止通过全局变量来传递参数,所有的 数据传递都直接通过函数的形式参数来接收。这样做不但使得接口简洁,更加避免了全局 变量可能引发的安全隐患。
UART 模块是最基本最底层的构件,它在满足功能完整性的情况下,具有不可再分的 特性,可以把它叫做“元构件”。下面简要介绍,按照构件化的思想对 UART 模块进行编程 的过程。
通过以上分析,可以设计 UART 构件的 5 个基本功能函数。
(1)初始化
void UartInit(uint8 uartNo, int32 sysclk, int32 baud, uint8 intStatusInit)
(2)发送单个字节
void UartSend1(uint8 uartNo, uint8 ch)
(3)接收单个字节
uint8 UartRe1 (uint8 uartNo, uint8 *p)
(4)发送 N 个字节
第 4 章 异步串行通信与直接存储器访问 DMA
84
void UartSendN(uint8 uartNo, uint8 n, uint8 ch[])
(5)接收 N 个字节
uint8 UartReN(uint8 uartNo, uint8 n, uint8 ch[])
4.4.2 UART构件的头文件
与 UART 通信子函数相关的文件有头文件 UART.h,以及包含 UART 初始化和收发子 函数的程序文件 UART.c。
头文件 UART.h 中的内容可分为两个主要的部分,它们分别是 5 个函数原型的声明和 外设模块寄存器相关信息的定义。前者给出了本 UART 构件对上层构件或软件所提供的 接口函数,而后者则指明了本“元构件”与具体硬件相关的信息。
串行通信头文件 UART.h 含有串行通信寄存器和标志位定义,以及串行通信相关函数 声明,下表简要给出了它的主要内容。以初始化函数 UartInit 为例,通道号、当前的系统 时钟、希望实现的通信波特率以及初始化时是否使能中断,都被设计为函数参数。这样的 话,应用程序和上层构件在使用(调用)它时,将具有极大的灵活性。文件还给出了必要 的硬件相关信息,当要把该构件移植到其他芯片时,就必须检查并修改这些信息。
//---*
//Uart.h串行通信头文件 * //---*
#ifndef UART_H
#define UART_H //1.对外引用
#include "type.h" //类型定义头文件 extern uint8 __IPSBAR[]; //引用外部标号 //2.外用UART通信函数声明
//---*
//函数名: UartInit * //功 能: 初始化UARTx模块。x代表0,1,2 * //参 数: uint8 uartNo: 第uartNo个UART模块。其中uartNo取值为0,1,2 * // 如果uartNo大于2,则认为是2 * // int32 sysclk: 系统总线时钟,以MHz为单位 * // int32 baud: 波特率,如 4800,9600,19200,38400,57600,115200 * // 其他的波特率在MCF52233的评估板上没有测试过,若要使 * // 用该函数,请自行测试,一般来说,速度慢一点,通信会 * // 更稳定 * // uint8 intStatusInit: 初始化中断的状态 1表示开中断 其他表示不开 * //返 回: 无 * //说 明: uartNo=0表示使用UART0模块,依此类推。 * //---*
void UartInit(uint8 uartNo, int32 sysclk, int32 baud, uint8 intStatusInit);
//---*
//函数名: UartSend1 * //功 能: 串行发送1个字节 *
85
void UartSend1(uint8 uartNo, uint8 ch);
//---*
void UartSendN(uint8 uartNo, uint8 n, uint8 ch[]);
//---*
uint8 UartRe1 (uint8 uartNo, uint8 *p);
//---*
uint8 UartReN(uint8 uartNo, uint8 n, uint8 ch[]);
//---*
第 4 章 异步串行通信与直接存储器访问 DMA
86
//---*
void UartSendString(uint8 uartNo,char *p);
//3.模块相关的宏定义
#define MCF_UART_NONE_PARITY (0x10) //UART模式寄存器无奇偶校验掩码
#define MCF_UART_BIT_8 (0x03) //UART模式寄存器8位传输掩码
#define MCF_UART_CM_NORMAL (0x00) //UART模式寄存器正常通道模式掩码
#define MCF_UART_STOP_BITS_1 (0x07) //UART模式寄存器1位停止位掩码
#define MCF_UART_RCS_SYSCLK (0xD0) //UART时钟选择寄存器接收时钟选择掩码
#define MCF_UART_TCS_SYSCLK (0x0D) //UART时钟选择寄存器接收时钟选择掩码
#define MCF_UART_RX_ENABLED (0x01) //UART命令寄存器使能接收器掩码
#define MCF_UART_TX_ENABLED (0x04) //UART命令寄存器使能发送器掩码 //ColdFire的UART模块相关寄存器的定义
//x=0表示UART0模块 x=1表示UART1模块 x=2表示UART2模块
//UART的IO端口功能分配寄存器定义,其中x=0表示UART0端口,依此类推
#define MCF_GPIO_PUPAR(x) (*(vuint8 *)(&__IPSBAR[0x100071+ (x)])) //UART模式寄存器
#define MCF_UART_UMR(x) (*(vuint8 *)(&__IPSBAR[0x000200+((x)*0x040)])) //UART状态寄存器
#define MCF_UART_USR(x) (*(vuint8 *)(&__IPSBAR[0x000204+((x)*0x040)])) //UART时钟选择寄存器
#define MCF_UART_UCSR(x) (*(vuint8 *)(&__IPSBAR[0x000204+((x)*0x040)])) //UART命令寄存器
#define MCF_UART_UCR(x) (*(vuint8 *)(&__IPSBAR[0x000208+((x)*0x040)])) //UART接收数据寄存器
#define MCF_UART_URB(x) (*(vuint8 *)(&__IPSBAR[0x00020C+((x)*0x040)])) //UART发送数据寄存器,接收和发送数据寄存器使用同一个地址
#define MCF_UART_UTB(x) (*(vuint8 *)(&__IPSBAR[0x00020C+((x)*0x040)])) //UART中断状态/掩码寄存器
#define MCF_UART_UIMR(x) (*(vuint8 *)(&__IPSBAR[0x000214+((x)*0x040)])) //UART波特率寄存器1(高位)
#define MCF_UART_UBG1(x) (*(vuint8 *)(&__IPSBAR[0x000218+((x)*0x040)])) //UART波特率寄存器2(低位) Baud=fsys/(32*divider)
#define MCF_UART_UBG2(x) (*(vuint8 *)(&__IPSBAR[0x00021C+((x)*0x040)])) //定义UART中断相关的寄存器
//UART的中断控制器寄存器
#define MCF_UART_ICR_LEVEL(x) (*(vuint8 *)(&__IPSBAR[0x000C4D+(x)])) //中断掩码控制器
#define MCF_UART_IMRL (*(vuint32*)(&__IPSBAR[0x000C0C]))
87 //中断掩码控制器中UART掩码设置(13,14,15位)
#define MCF_UART_IMRL_MASK(x) (0x00002000<<x)
#endif