×
嵌入式 > 嵌入式开发 > 详情

FL2440 UART的用法

发布时间:2020-08-26 发布时间:
|
UART原理说明:

通用异步收发器简称UART,即“Universal Asynchronous Receiver Transmitter”,它用来传输串行数据:发送数据时,CPU将并行数据写入UART,UART按照一定格式在一根电线上串行发出;接收数据时,UART检测另一根电线上的信号,将串行数据放在缓冲区中,CPU即可读取UART获得的数据。UART之间以全双工方式传输数据,最精简的连线方式只有三根电线:TxD用于发送数据,RxD用于接收数据,Gnd用于给双方提供参考电平。连线如下图所示:

为了增强数据的抗干扰能力、提高数据传输长度,通常将TTL/CMOS逻辑电平转换为RS-232逻辑电平,3~12V表示0,-3~-12V表示1。S3C2440有3个独立的UART通道,每个通道都可以工作于中断、查询或者DMA模式。
S3C2440UART的使用:
UART使用之前需要设置波特率、数据传输格式,配置相关管脚为UART功能,选择工作模式是中断、查询还是DMA.。另外,S3C2440中每个UART都有一个深度为64字节的接收FIFO和发送FIFO。我们采用的配置方式不使用FIFO模式。
1. 将涉及的UART通道管脚设为UART功能
比如,UART通道0中,GPH2、GPH3分别用作TXD0、RXD0,即要使用UART通道0时,必须先将GPHCON寄存器中GPH2/3配置为TXD0/RXD0。
2. UBRDIVn寄存器:设置波特率
S3C2440的时钟源有PCLK 、UEXTCLK、FCLK/n,其中n值是通过UCON0~UCON2联合设置。
根据给定的波特率、所选择的时钟源频率,可以通过以下公式计算UBRDIVn寄存器。
UBRDIVn=(int)(UART CLOCK /(BUAD RATE * 16)) - 1
时钟源选择PCLK为50MHz,波特率设置为115200赫兹,所以计算出的值为26.13,取整之后为26,即把26存到寄存器UBRDIV0即可。
3. ULCONn:设置传输格式
设置数据宽度、停止位宽度、检验模式、红外模式。
4. UCONn寄存器
通过该寄存器来设置S3C2440中UART的接收模式、发送模式、接收中断方式、发送中断方式、时钟选择、FCLK分频系数(FCLK/n中n的值)等等。
5.UTRSTATn寄存器
UTRSTATn寄存器用来表明数据是否发送完毕,是否已经接受到数据。第0位可以用来判断接受缓存器内是否有可接收的数据,接收到数据自动设置为1;第1位和第2位可以用来判断发送缓存器中是否为空,为空时可以发送数据。寄存器格式如下:
接收到的数据是放到接收缓存器URXHn中,要发送数据时,是把数据放入发送缓存器UTXHn中。由于UART是通过字节方式传输数据的,因此要区分是大端模式还是小端模式,也就是说这两个寄存器在这两种模式下,所在的地址是不同。
现在来看一段代码,这段代码采用的查询的方式来使用UART的。每次完成一个字节的传输。

#include "2440addr.h"

void Main(void)

{

char ch;

rGPBCON = 0x155551;

rGPBUP = 0x7ff;

rGPBDAT = 0x560;

rGPHCON = 0x00faaa; /*使用UART0功能 0000 0000 1111 1010 1010 1010 管脚使能*/

rGPHUP = 0x7ff;

rULCON0 = 0x3; /*设置UART0无奇偶校验,一位停止位,8位数据 设定数据传输格式*/

rUCON0 = 0x245; /*PCLK为时钟源,接收和发送数据为查询或中断方式[4]没有break信号[7]禁止fifo*/

rUFCON0 = 0;

rUMCON0 = 0;

rUBRDIV0 = 26; /*设置波特率,PCLK为50MHz,波特率为115.2kHz*/

while(!(rUTRSTAT0 & 0x2)); /*等待并判断发送缓存是否为空*/

rUTXH0 = 0xaa; /*是空,则发送0xAA字节*/

while(1)

{

while(!(rUTRSTAT0 & 0x1)); /*等待并判断接收缓存是否准备好*/

ch = rURXH0; /*接收一个字节数据*/

while(!(rUTRSTAT0 & 0x2)); /*等待并判断发送缓存是否为空*/

rUTXH0 = ch; /*发送一个字节数据*/

switch(ch) /*根据所接收数据的不同,执行不同的程序*/

{

case 0x11: /*灭LED*/

rGPBDAT |= 0x560;
break;

case 0x22: /*亮LED*/

rGPBDAT &= 0x1f;
break;

case 0x33: /*蜂鸣器不响*/

rGPBDAT &= 0x560;
break;

case 0x44: /*蜂鸣器响*/

rGPBDAT |= 0x1;
break;
default: /*LED灭,蜂鸣器不响*/

rGPBDAT = 0x560;
break;

}

}

}

中断处理方式,UART有子中断,要注意子中断屏蔽的打开,由于UART中断涉及到SUBSRCPND寄存器,因此在中断处理程序中不仅要清SRCPND寄存器,还要清SUBSRCPND寄存器,它们的顺序一定是先清SUBSRCPND寄存器,再清SRCPND寄存器,否则就会引起一个中断两次响应的问题。因为是否中断由SRCPND寄存器决定,而SRCPND寄存器的相关状态位由SUBSRCPND寄存器决定,如果先清SRCPND寄存器,而还没有清SUBSRCPND寄存器的话,SRCPND寄存器的相关位还是会被置1,而一旦被置1,则一定还会引起中断。

#include "2440addr.h"

#define U32 unsigned int

void __irq uartISP(void)

{

char ch;

rSUBSRCPND |= 0x3;

rSRCPND = 0x1<<28;

rINTPND = 0x1<<28;

if(rUTRSTAT0 & 1) /*接收数据处理部分*/

{

ch = rURXH0; /*接收字节数据*/

if(ch==0x55)

rGPBDAT = ~0x60; /*亮两个LED,蜂鸣器响*/

else

rUTXH0 = ch; /*发送字节数据*/

}

else /*发送数据处理部分*/

{

rGPBDAT = ~0x561; /*亮4个LED*/

}

}

void Main(void)

{

rGPBCON = 0x155555;

rGPBUP = 0x7ff;

rGPBDAT = 0x560;

rGPHCON = 0x00faaa;

rGPHUP = 0x7ff;

rULCON0 = 0x3;

rUCON0 = 0x5;

rUFCON0 = 0;

rUMCON0 = 0;

rUBRDIV0 = 26;

rSRCPND = 0x1<<28;

rSUBSRCPND = 0x3;

rINTPND = 0x1<<28;

rINTSUBMSK = ~(0x3); /*打开UART0发送和接收中断屏蔽*/

rINTMSK = ~(0x1<<28); /*打开UART0中断屏蔽*/

pISR_UART0 = (U32)uartISP;

while(1)

{

}

}

在"2440addr.h"里面的关于rUTXH0/rURXH0的定义。arm指令默认小端模式初始化,所以地址是这个。




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
RIOS实验室联手Imagination.共同助力RISC-V生态发展