LM3S8962有两个UART模块,UART0和UART1。模块图如下
我们可以看到UART模块的寄存器主要包括五部分:
1)控制/状态寄存器
2)数据寄存器
3)波特率寄存器
4)中断控制寄存器
5)标识寄存器(Identification Registers)
1、控制/状态寄存器控制状态寄存器主要功能是控制UART工作模式,跟踪UART的工作状态,定义UART的数据格式以及使能禁能UART。
2、数据寄存器发送和接收数据,有两个16字节的FIFO,发送FIFO和接收FIFO。当FIFO使能时写数据寄存器操作会将数据放入发送FIFO尾,读数据寄存器操作会将数据从接收FIFO中读取出来。如果没有使能FIFO,可以认为FIFO深度为1字节。
3、波特率寄存器用来设置UART波特率。
4、中断控制寄存器用来配置UART中断。
5、标识寄存器只读,用于标识器件。
使用UART的操作基本步骤有四步:1)使能UART模块,使能与UART相关的GPIO模块,将相应的TX和RX引脚设置为UART模式;
2)配置和使能UART,主要包括设置UART的波特率,是否使用FIFO,数据帧格式;
3)配置UART中断(可选);
4)读写数据;
UART使用中最常用到的API:1、
UARTConfigSetExpClk(unsigned long ulBase, unsigned long ulUARTClk,unsigned long ulBaud, unsigned long ulConfig)带时钟参数的UART配置函数,参数分别是UART模块基地址,系统主频,波特率,数据帧格式配置。
这个函数功能非常强大,可以说一句话就完成了第二步工作。
这个函数的执行结果是:设置波特率为ulBaud,将数据帧格式设置为ulConfig,使能FIFO,使能UART。
数据帧格式配置参数ulConfig是由三个参数进行或运算得来的,这三个参数是数据字长(WordLENgth),奇偶校验(PARity),停止位长度(STOP)。
2、
UARTEnable(unsigned long ulBase),UARTDisable(unsigned long ulBase)使能和禁能UART
3、
UARTFIFOEnable(unsigned long ulBase),UARTFIFODisable(unsigned long ulBase)使能和禁能FIFO
4、
void UARTCharPut(unsigned long ulBase, unsigned char ucData),tBoolean UARTCharPutNonBlocking(unsigned long ulBase, unsigned char ucData)发送一个字符,区别是:
使用UARTCharPut函数如果发送FIFO满,函数会等待发送FIFO变成非满状态再将要发送字符放入发送FIFO。
使用UARTCharPutNonBlocking函数如果发送FIFO满,函数会放弃发送字符并返回false。
5、
void UARTCharGet(unsigned long ulBase),tBoolean UARTCharGetNonBlocking(unsigned long ulBase)接收一个字符,区别是:
使用UARTCharGet函数如果接收FIFO空,函数会等待接收FIFO变成非空再获取字符。
使用UARTCharGetNonBlocking函数如果接收FIFO空,函数会放弃接收并返回false。
6、
tBoolean UARTCharsAvail(unsigned long ulBase),tBoolean UARTSpaceAvail(unsigned long ulBase)查看接收FIFO是否有数据,查看发送寄存器是否满。
下面是一个非常简单的程序,演示UART的基本使用。
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/uart.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "drivers/rit128x96x4.h"
int main()
{
char cLoop = 0;
//各种初始化工作....... SysCtlClockSet(SYSCTL_OSC_MAIN|SYSCTL_XTAL_8MHZ|SYSCTL_USE_OSC|SYSCTL_SYSDIV_1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0|GPIO_PIN_1);
RIT128x96x4Init(1000000);
RIT128x96x4StringDraw("UART0test...",20,12,15);
RIT128x96x4StringDraw("Baudrate: 9600",10,24,15);
RIT128x96x4StringDraw("WordLength: 8",10,36,15);
RIT128x96x4StringDraw("Parity None",10,48,15);
RIT128x96x4StringDraw("Stop One",10,60,15);
//UART初始化,设置波特率为9600,数据字长8bit,无校验,1位停止位,使能FIFO,使能UART。 UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),9600,UART_CONFIG_WLEN_8|UART_CONFIG_PAR_NONE|UART_CONFIG_STOP_ONE); while(1) { //打印‘a’到‘z’; for(cLoop = 'a';cLoop<='z';cLoop++) { UARTCharPut(UART0_BASE,cLoop); } //换行 UARTCharPut(UART0_BASE,13); UARTCharPut(UART0_BASE,10); //如果接收FIFO不为空,则打印字符到Oled while(UARTCharsAvail(UART0_BASE)) { cLoop = UARTCharGet(UART0_BASE); RIT128x96x4StringDraw(&cLoop,60,72,15); } SysCtlDelay(SysCtlClockGet()/3);//延时1s }}
需要注意的是在调用UARTConfigSetExpClk这个函数时会使能FIFO和UART,FIFO是很有用的东西,它可以显著减少UART产生的CPU中断,提高程序运行效率,所以FIFO一般不必Disable。
如果只想配置UART而不想使能UART,那就需要在UARTConfigSetExpClk函数后紧接着UARTDisable了。
UART中断UART一共有如下几种中断
溢出错误(Overrun error):接收FIFO满时有新的数据到来,导致数据丢失产生溢出错误;帧错误(Frame error):接收数据停止位为‘0’;奇偶校验错误(parity error):就是奇偶校验错误.....;中止错误(break error):RX在一个帧周期内一直为低电平。当发送FIFO和接收FIFO中数据数量超过一定限度时可以产生Transmit或Receive中断,这个限度可以通过
UARTFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel,unsigned long ulRxLevel)
函数设置。这个限度可以是FIFO深度的1/8,2/8,4/8,6/8,7/8
接收中断(Receive):当接收FIFO中数据超过设置限度时产生中断。发送中断(Receive):当发送FIFO中数据超过设置限度时产生中断。由于只有当接收FIFO数据达到设置限度时才会产生接收中断,这有可能导致FIFO中有少量数据却由于没有产生中断而长时间没有被处理,所以设这一个接收超时中断。
接收超时(Receive Timeout):当接收FIFO中有数据且在32bit周期内没有接收到其他数据,则产生接收超时中断。
下面这个程序简单演示了RX中断,RT中断,Break中断。
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/uart.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "drivers/rit128x96x4.h"
#include "driverlib/interrupt.h"
#include "inc/hw_ints.h"
void UART0IntHandler(void);
int main()
{
//各种初始化。。。。。。 SysCtlClockSet(SYSCTL_OSC_MAIN|SYSCTL_XTAL_8MHZ|SYSCTL_USE_OSC|SYSCTL_SYSDIV_1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
GPIOPinTypeUART(GPIO_PORTA_BASE,GPIO_PIN_0|GPIO_PIN_1);
RIT128x96x4Init(1000000);
RIT128x96x4StringDraw("UART0Inttest...",20,12,15);
//初始化UART0 UARTConfigSetExpClk(UART0_BASE,SysCtlClockGet(),9600,UART_CONFIG_WLEN_8|UART_CONFIG_PAR_NONE|UART_CONFIG_STOP_ONE); //设置FIFO中断条件,当TX或RX6/8满时产生TX或RX中断 UARTFIFOLevelSet(UART0_BASE,UART_FIFO_TX6_8,UART_FIFO_RX6_8); UARTIntEnable(UART0_BASE,UART_INT_RX|UART_INT_BE|UART_INT_RT);//使能RX,BE,RT中断 IntEnable(INT_UART0);
//使能UART0中断 IntMasterEnable();
//使能全局中断 while(1);
}
//各种中断进行逻辑或后传给中断控制器,在中断服务程序中应该先判断中断源
void UART0IntHandler(void)
{
unsigned long ulStatus;
IntMasterDisable();
ulStatus = UARTIntStatus(UART0_BASE,true);//保存屏蔽后中断状态 UARTIntClear(UART0_BASE,UART_INT_RX|UART_INT_RT|UART_INT_BE);//清除中断标志 //根据不同的中断标志执行不同的中断服务 if(
ulStatus&UART_INT_RX)
{
RIT128x96x4StringDraw("UART0_RX_INT",4,24,15);
RIT128x96x4UnsignedLongBinaryDraw(ulStatus,12,4,36,15);
while(UARTCharGetNonBlocking(UART0_BASE));
//将接收FIFO中字符读出 }
if(ulStatus&UART_INT_RT)
{
RIT128x96x4StringDraw("UART0_RT_INT",4,24,15);
RIT128x96x4UnsignedLongBinaryDraw(ulStatus,12,4,36,15);
}
if(ulStatus&UART_INT_BE)
{
RIT128x96x4StringDraw("UART0_BE_INT",4,24,15);
RIT128x96x4UnsignedLongBinaryDraw(ulStatus,12,4,36,15);
}
IntMasterEnable();
}
通过串口调试工具发送一个字符可以产生RT中断,发送一个字符串(大于12个)可以产生RX中断,将RX端口接地可以产生BE中断。