L12D14 YART实验

一、UART帧格式

(一)UART概念

1、通信协议,也就是串口,主控与其他芯片通信。

2、双数据线,双工。

3、UART总线接口在嵌入式领域仍然占比很大。

4、并行和串行

一次可以发送多位。总线多,布线困难,数据线之间有干扰,因此串行通信在Linux开发中应用更广泛。

一位一位发送。

5、单工和双工

 IIC是半双工,串口、SPI是全双工

6、波特率

串口传送的速率,每秒传送bit的个数。

9、UART帧格式

起始位:高低电平变换,区分空闲和发送状态。

校验位:校验数据是否出现错误。

停止位:高电平1。

10、串口规定,每次可以发送1字节数据(5-8位),先发低位,后发高位。

 11、偶校验:偶数个1,校验位为1,奇数个1,校验位为0,只能校验不能修改。

 12、发送多个字节的数据,重复帧格式过程。防止累计误差。

13、异步和同步

串口是异步通信。通信双方看的是自己的时钟,因此为了防止累计误差,串口一次只能发送一个字节。IIC是同步传送,因此不存在时间上的误差(双方时钟有快慢),所以一次可以发送多个字节。

14、硬件连接

自己的发送接对方的接收,对方的发送接自己的接收,不能平行相接。

 15、UART控制器

二、Exynos4412下的UART控制器

(一)串口的硬件原理

1、 串口控制器控制数据的发送和接收。

2、串口是用低电平表示0,高电平表示1。

3、USB转串口线:电脑和开发板通信。电脑USB接口信号转换为串口信号。三个端口,只有中间端口可以下载文件。

4、串口接到了一个叫SP3232EEA的芯片上,因为串口通过高低电平发送的信号比较弱,发送距离有限,通过芯片增强抗干扰能力,延长通信距离。

 5、引脚功能设置

 引脚不属于任何一个模块。设置引脚功能本质是让引脚在芯片内部连接到摸一个对应的控制器上。

我们将要发送的数据写入缓冲区,遵循先进先出原则,先写入的串口通过TXD发出。接收器接收到数据也放入缓冲区。我们只需要考虑将要发送的数据按照顺序写入缓冲区。

波特率可以修改,UNRT也可以通过红外线发送和接收。需要具备相应的硬件。

不同硬件速度不同,频率不同。

6、移位器的功能

发送数据时,数据从缓冲区要先到移位器,然后移位器移位1,1bit数据被放入引脚TXD。

接收数据时,数据从发送队列移到移位器,移位器移到缓冲区FIFO,再从FIFO中读取数据。

 7、4412下串口发送器UART的主要包括发送器、接收器、波特率产生器以及控制逻辑。

8、CPU可以通过数据总线发送数据和接收数据,也可以通过控制总线,控制UART控制器。

三、UART寄存器详解

(一)串口寄存器

1、4412中共有5套串口寄存器,所以对应有5个基地址。

ULCONn:帧格式

UCONn:发送接收模式,控制寄存器

UFCONn:控制队列

UTRSTATn:接收和发送状态

UERSTATn:出错信息

UFSTATn:队列状态

UMSTATn:流控制

UTXHn:存放串口发送器发送的数据

URXHn:存放串口接收器接受的数据

URACvALn:设置波特率

UINTPn:中断相关

UINTSPn:中断相关

UINTMn:中断相关

2、CPU从串口读取数据的方式

1)轮询

2)中断

3)DMA

接收到的数据直接到内存,不需要CPU拿

3、轮询

/*用串口实现简单的数据发送和传输,需要设置4个寄存器*/

/*将GPA1_0,GPA1_1分别设置成UART2的接收引脚和发送引脚 GPA1CON[7:0]*/
/*设置UART的帧格式ULCON2/8位数据为 1位停止位 无校验位 正常模式*/
/*设置UART2的接收和发送模式位轮询模式UCON2[3:0]*/
/*设置URT2的波特率位115200 UBRDIV2/UFRACVAL2*/

 波特率设置公式:

如果乘16之后还有小数直接四舍五入。每次发送1字节,不会有很大误差。

裸机程序都需要写循环,因为程序结束后,防止CPU跑飞。

四、UART编程

(一)波特率的计算公式

(二)CPU发送的速率和波特率不相同的问题

按照此顺序发送,但是发送器发送速度慢,有些数据被吞没。发送的数据不定。

(三)发送器状态寄存器

通过访问该寄存器,解决CPU速度过快,数据被吞没的问题。如果发送器为空,则发送,否则等待。

/*判断发送器是否为空,满则循环*/
while(!(UART2.UTRSTAT2 & (1 << 1)));
UART2.UTXH2 = 'A';

 效果:

 

五、输入输出重定向

(一)puts

(二)printf

1、在这里的printf和之前的区别

之前printf是Linux系统中的C库提供,现在的printf是自己写的(不能用浮点型)。

2、之前的printf输出到显卡,现在的printf输出到UART,最后显示到电脑屏幕。

printf-puts-putc-UART串口。

#include "exynos_4412.h"

void UART_Init(void)
{
	/*1.将GPA1_0和GPA1_1设置成UART2的接收和发送引脚 GPA1CON[7:0]*/
	GPA1.CON = GPA1.CON & (~(0xFF << 0)) | (0x22 << 0);
	/*2.设置UART2的帧格式 8位数据位 1位停止位 无校验 正常模式 ULCON2[6:0]*/
	UART2.ULCON2 = UART2.ULCON2 & (~(0x7F << 0)) | (0x3 << 0);
	/*3.设置UART2的接收和发送模式为轮询模式 UCON2[3:0]*/
	UART2.UCON2 = UART2.UCON2 & (~(0xF << 0)) | (0x5 << 0);
	/*4.设置UART2的波特率为115200 UBRDIV2/UFRACVAL2*/
	UART2.UBRDIV2 = 53;
	UART2.UFRACVAL2 = 4;
}

void UART_Send_Byte(char Dat)
{
	/*等待发送寄存器为空,即上一个数据已经发送完成 UTRSTAT2[1]*/
	while(!(UART2.UTRSTAT2 & (1 << 1)));
	/*将要发送的数据写入发送寄存器 UTXH2*/
	UART2.UTXH2 = Dat;
}

char UART_Rec_Byte(void)
{
	char Dat = 0;
	/*判断接收寄存器是否接收到了数据 UTRSTAT2[0]*/
	if(UART2.UTRSTAT2 & 1)
	{
		/*从接收寄存器中读取接收到的数据 URXH2*/
		Dat = UART2.URXH2;
		return Dat;
	}
	else
	{
		return 0;
	}
}

void UART_Send_Str(char * pstr)
{
	while(*pstr != '\0')
		UART_Send_Byte(*pstr++);
}

int main()
{
	char RecDat = 0;
	UART_Init();

	while(1)
	{
		/*
		RecDat = UART_Rec_Byte();
		if(RecDat == 0)
		{
			
		}
		else
		{
			RecDat = RecDat + 1;
			UART_Send_Byte(RecDat);
		}
		*/
		
		/*
		UART_Send_Str("Hello World\n");
		*/

		printf("Hello World\n");
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值