7244|3

63

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

菜鸟学习笔记6---UART [复制链接]

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中断。

最新回复

好强大  详情 回复 发表于 2014-8-13 23:20

赞赏

1

查看全部赞赏

 
点赞 关注(1)

回复
举报

32

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
支持。。。。。。。。。。。。。
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
~厉害,我刚刚开始学呢 膜拜一下
 
 
 

回复

3

帖子

1

TA的资源

一粒金砂(初级)

4
 
好强大
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表