UART在4412上的裸机开发

百般思念 提交于 2019-12-09 12:46:32

UART(通用异步传输收发器)简介

  1. 串行通信简介

我们的实际生活中,常见的通信方式有很多,例如:蓝牙,WIFI,网线,红外,HDMI

VGA,USB,I2C,SP1,UART等,每种都有自己的特点以及常用的场合。今天,我们就来看看我们的串行通信。通用异步收发器简称UART,即“Universal
Asynchronous Receiver Transmitter”,串行通信是指计算机与I/O
设备之间数据传输的各位是按顺序依次一位接一位进行传送。通常数据在一根数据线上传输。具体情况如下:用来传输串行数据:发送数据时,CPU将并行数据写入UART,UART按照一定的格式在一根电线上串行发出;接收数据时,UART检测另一根电线上的信号,将串行收集放在缓冲区中,CPU即可读取UART获得这些数据。UART之间以全双工方式传输数据,最精简的连线方法只有三根电线:TxD用于发送数据,RxD用于接收数据,Gnd用于给双方提供参考电平,连线如图7.1所示:transmission recvfrom

在这里插入图片描述

我们通俗所使用的串口硬件格式为:
在这里插入图片描述
实质上,大部分我们只是使用了里面的3根线。

UART使用标准的TTL/CMOS逻辑电平(0~5V、0~3.3V、0~2.5V或0~1.8V四种)来表示数据,高电平表示1,低电平表示0。为了增强数据的抗干扰能力、提高传输长度,通常将TTL/CMOS逻辑电平转换为RS-232逻辑电平,3~12V表示0,-3~-12V表示1。

TxD、RxD数据线以“位”为最小单位传输数据。帧(frame)由具有完整意义的、不可分割的若干位组成,它包含开始位、数据位、较验位(需要的话)和停止位。发送数据之前,UART之间要约定好数据的传输速率(即每位所占据的时间,其倒数称为波特率)、数据的传输格式(即有多少个数据位、是否使用较验位、是奇较验还是偶较验、有多少个停止位)。

电脑的电平—RS232 单片机的电平—TTL

发送形式如下:

在这里插入图片描述

上图演示了UART使用7个数据位、偶校验、2个停止位的格式传输字符‘A’(二进制值为0b1000001)时,TTL/COM逻辑电平和RS-232逻辑电平对应的波形。

传输流程如下:’A’===>1bytes=8bit65(614+ 1)= 1000001

(1)平时数据线处于空闲状态(1状态)

(2)当要发送数据时,UART改变TxD数据线的状态(变为0状态)并维持1位的时间,这样接收方检测到开始位后,在等待1.5位的时间就开始一位一位地检测数据线的状态得到所传输的数据。

(3)UART一帧中可以存放有5、6、7或8位的数据,发送方一位一位地改变数据线的状态将他们发送出去,首先发送最低位,这个我们叫做发送数据位。在发送的过程中,我们需要约定好传输的速率,这个速率我们叫做波特率-----每秒传输的数据位数。

(4)如果使用校验功能,UART在发送完数据后,还要发送1位校验位。有两种校验方法:奇校验、偶校验——数据位连同校验位中,1的数据等于奇数或偶数。

(5)最后,发送停止位,数据线恢复到空闲状态(1状态)。停止位的长度有3种:1位、1.5位、2位。

  1. 串行通信简介

要求:使用UART2连接PC板和开发板,输出调试信息。实现数据的收发。

[1]阅读原理图—
<<FS4412-DevBoard-V5.pdf>>,我们开发板上使用的COM2,COM2的左侧面

写着CON7,我们搜索CON7这个标号即可。

在这里插入图片描述
如上图所示,COM2分别与SP232 的13、14 引脚相连,通过SP3232
的BUF_XuTXD2/UART_AUDIO_TXD和BUF_XuRXD2/UART_AUDIO_RXD 引脚实现TTl 3.3V
电平转换,3.3V 电平转换再通过U8 转变为1.8V电平和CPU
通讯。这样对EXYNOS4412就可以实现在PC 串口上显示数据。SP3232 起到变压器的作用。

在这里插入图片描述
再次阅读我们的核心板,通过网络标号-----UART_AUDIO_TXD,找到我们的信息。

在这里插入图片描述
通过阅读原理图,我们知道,我们的COM2收通过转换芯片,然后接到我们的4412芯片的

AC20和AC25接口,我们根据网络标号,我们知道我们要使用GPA1_0和GPA1_1.

[2]阅读芯片手册,查询这个两个寄存器的用途,然后在查看我们关于uart的章节讲解。

在这里插入图片描述

<1>阅读这几个寄存器的信息,我们发现内容如下:

在这里插入图片描述

GPA1CON[0] = 0X2 GPA1_0设置为UART_2_RXD

GPA1CON[1] = 0X2 GPA1_1 设置为UART_2_TXD

基本原理讲解:

Exynos4412 中UART,有4 个独立的通道,每个通道都可以工作于中断模式或DMA
模式,即 UART 可以发出中断或 DMA 请求以便在UART 、CPU 间传输数据。UART
由波特率发生器、发送器、接收器和控制逻辑组成。

** 使用系统时钟时,Exynos4412 的 UART 波特率可以达到 4Mbps
。波特率可以通过编程进行 。**

** Exynos4412 UART 的通道 0有 256 字节的发送 FIFO 和 256 字节的接收FIFO
;通道 1、4有 64 字节的发送 FIFO 和 64 字节的接收FIFO;通道 2、3有 16
字节的发送FIFO 和 16 字节 的接收 FIFO 。发送数据时, CPU 先将数据写入发送FIFO
中,然后 UART 会自动将FIFO 中的数据复制到“发送移位器” (Transmit Shifter
)中,发送移位器将数据一位一位地发送到 TxDn 数据线上 (根据设定的格式,插入开始位
、较验和停止)。接收数据时,“移位器” (Receive Shifter )将 RxDn
数据线上的数据一位一位的接收进来,然后复制到FIFO 中, CPU即可从中读取数据。**

** Exynos4412 UART的每个通道支持停止位有 1位、 2位,数据位有 5、6、7或
8位,支持校验功能,另外还有红外发送 /接收功能。**

Exynos4412 UART结构图:

在这里插入图片描述

<2>UART时钟源的设置

在这里插入图片描述

Exynos4412 UART的时钟源有八种选择: XXTI 、XusbXTI 、SCLK_HDMI24M 、SCLK_USBPHY0
、 SCLK_HDMIPHY 、SCLKMPLL_USER_T 、SCLKEPLL 、SCLKVPLL ,由 CLK_SRC_PERIL0
寄存器控制。选择好时钟源后,由于频率太高,需要通过 DIVUART0 ~4设置分频系数
设置分频系数 ,由 CLK_DIV_PERIL0 寄存器控制。 从分频器得到的时钟被称为SCLK UART
。 SCLK UART 经过上图中的“ UCLK Generator”后,得到UCLK ,它的频率就是UART
的波特率。“ Generator UCLK Generator ”通过这 2个寄存器来设置: UBRDIVn
、UFRACVALn (在下面描述)。

我们这里最终得到的SCLK_UART的大小为100MHZ.----(在uboot.bin启动的时候可以看到)。

我们使用的是COM2,即UART2,所以关于波特率所涉及到的寄存器是UBRDEV2和UFRACVAL2。

在这里插入图片描述

在这里插入图片描述
关于波特率和这两个寄存器之间的计算关系,datasheet写的很明白:

根据给定的波特率、所选择时钟源频率,可以通过以下公式计算 UBRDIVn 寄存器 (n 为
0~4,对应 5个 UART 通道 )的值。

**  UBRDIVn = (int)( UART clock / ( buad rate x 16) ) – 1**

 上式计算出来的 UBRDIVn 寄存器值不一定是整数, UBRDIVn

寄存器取其整数部分,小部分由 UFRACVALn 寄存器设置, UFRACVALn
寄存器的引入,使产生波特率更加精确。

我们这里 UART clock为100MHz,要求波特率为115200 bps,则:

100000000/(115200 x 16) – 1 = 54.25 – 1 = 53.25

UBRDIVn = 整数部分 = 53

UFRACVALn/16 = 小数部分 = 0.25

UFRACVALn = 4

所以设置寄存器 UBRDIV2 = 53 ,UFRACVAL2 = 4

<3>设置uart相关参数

在这里插入图片描述
ULCON2[6] 红外线模式还是普通模式 ,我们选择普通模式 0

ULCON2[1:0] 数据位数 这里我们设置为8bit ,0x3

ULCON2[2] 停止位位数, 我们设置为1bit,0x0

ULCON2[5::3] 校验位 我们设置为无 0x0

综上,ULCON2 = 0b11 = 0x03

  1. 设置uart 收发模式 UCONn

在这里插入图片描述
在这里插入图片描述
UCON2 [1:0] = 01, 接收 poll模式

UCON2[3:2] = 01, 发送 poll模式

  1. 关闭发送接收FIFO

在这里插入图片描述

在这里插入图片描述

UFCON2 [0] = 0 关闭发送接收FIFO

  1. 实现发送数据
    在这里插入图片描述

发送数据

将要发送的8bit数据放入UTXHn寄存器低8位

UTXH2 = txdata

检测数据是否发出完成

在这里插入图片描述
在这里插入图片描述

检测是否发送完毕,检测寄存器UTRSTAT2的bit 1是否置1,置1表示发送完成。

发送代码:

// write fifo

UTXH[0:7] = data;

// wait finish

while (!(UTRSTAT[1] == 0b1));

8.接收数据

将寄存器URXHn的低8位数据取出来。

但是要等到receive buffer data
ready,也即是有数据可读。查看是否有数据可读可以查看寄存器UTRSTAT2的bit
0,置1表示有数据可读。

接收代码:

// wait for data

while (!(UTRSTAT[0] == 0b1));

// read fifo

data = URXH[0:7];

代码如下:

Uart.c

#define GPA1CON 0x11400020

#define UBRDIV 0x13820028

#define UFRACVAL 0x1382002C

#define ULCON 0x13820000

#define UCON 0x13820004

#define UFCON 0x13820008

#define UTRSTAT 0x13820010

#define UTXH 0x13820020 //发送数据

#define URXH 0x13820024 //接收数据

//==============LED3=

#define GPX1CON 0x11000C20 //[3:0] 0001

#define GPX1DAT 0x11000C24 // [0]—1表示高电平,0表示低电平

//把改地址里面存储的数据,返回来。

#define reg_read(addr) (*(unsigned int *)(addr))

//把var这个值,写到addr这个地址对应的内单元中

#define reg_write(addr,var) (*(unsigned int *)(addr)=(var))

void delay_ms(int time)

{

int i, j;

while(time–)

{

for (i = 0; i < 5; i++)

for (j = 0; j < 514; j++);

}

}

void uart_init()

{

//1.配置功能寄存器–收发功能GPA1.CON [0-7]为设置为0x22

unsigned int con = reg_read(GPA1CON);

reg_write(GPA1CON,(con &~(0xff))|(0x22)); //设置为UART_2_RXD

//2.配置波特率。通过UBRDIV2配置整数,通过UFRACVAL2配置小数

//100M晶振

reg_write(UBRDIV,53) ; //设置波特率

reg_write(UFRACVAL,4) ;

//3.关闭校验位,1bit停止位,8bit数据位

con = reg_read(ULCON);

reg_write(ULCON,(con & ~(0xff)) | 0x3);

//3.选择发送和接收为轮询或则中断模式

con = reg_read(UCON);

reg_write(UCON,(con &(~0Xf))|0X5);

//4.关闭FIFO队列

con = reg_read(UFCON);

reg_write(UFCON,con&(~1));

}

void uart_send(unsigned char data)

{

//1.先写数据,在判断上一次是否发送

//完毕,若是发送完毕,就发送该次

reg_write(UTXH,data);

//若是没有发送完毕,一直等待发送。

while((reg_read(UTRSTAT) & 0x2) == 0);

return ;

}

unsigned char uart_recv()

{

unsigned char data;

//若是没有接受到数据,一直等待接收

while(((reg_read(UTRSTAT)&0x1)==0));

//由于是低8bit有效,我们只取一个字节的大小.

data= (unsigned char )(reg_read(URXH)&0xff);

return data;

}

//=======================================

void led3_init()

{

unsigned int con ;

//LED3;

con = *((unsigned int *)GPX1CON);

//先清0,在 把对应的4位设置为0001 [31:28]全部变成0

con = con & ~0xf;

con = con | 0x1;

*(unsigned int *)GPX1CON = con;

}

void led3_on()

{

unsigned int con = 0;

con = *((unsigned int *)GPX1DAT);

con = con | (0x1);

*((unsigned int *)GPX1DAT) = con;

return ;

}

void led3_off()

{

unsigned int con = 0;

con = *((unsigned int *)GPX1DAT);

con = con & ~(0x1);

*((unsigned int *)GPX1DAT) = con;

return ;

}

int main()

{

uart_init();

led3_init();

unsigned char ch;

while(1)

{

ch = uart_recv();

switch(ch)

{

case ‘0’:

led3_off();

break;

case ‘1’:

led3_on();

break;

}

uart_send(ch);

delay_ms(5);

}

}

Makfile文件如下:
all:start.s uart.c

arm-none-linux-gnueabi-gcc -g -c -O0 start.s -o start.o

arm-none-linux-gnueabi-gcc -g -c -O0 uart.c -o uart.o

arm-none-linux-gnueabi-ld start.o uart.o -Ttext 0x40008000 -o test.elf

arm-none-linux-gnueabi-objcopy -O binary test.elf uart.bin

clean:

rm *.elf *.o *.bin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!