第六课JZ2440裸板开发之UART

一、协议简介

1.1原理图

UART的全称是Universal Asynchronous Receiver and Transmitter,即异步发送和接收。
原理图如下:
在这里插入图片描述
通过TxD->RxD把ARM开发板要发送的信息发送给PC机。
通过RxD->TxD线把PC机要发送的信息发送给ARM开发板。
最下面的地线统一参考地。

1.2 参数

波特率:一般选波特率都会有9600,19200,115200等选项。其实意思就是每秒传输这么多个比特位数(bit)。
起始位:先发出一个逻辑”0”的信号,表示传输数据的开始。
数据位:可以是5~8位逻辑”0”或”1”。如ASCII码(7位),扩展BCD码(8位)。小端传输。
校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验),以此来校验数据传送的正确性。
停止位:它是一个字符数据的结束标志。

1.3怎么发送一字节的数据

A 的ASCII值是0x41,二进制就是01000001,怎样把这8位数据发送给PC机呢?

双方约定好波特率(每一位占据的时间);
规定传输协议

a. 原来是高电平,ARM拉低电平,保持1bit时间;

b. PC在低电平开始处计时;

c. ARM根据数据依次驱动TxD的电平,同时PC依次读取RxD引脚电平,获得数据;

前面图中提及到了逻辑电平,也就是说代表信号1的引脚电平是人为规定的。
如图是TTL/CMOS逻辑电平下,传输‘A’时的波形:在xV至5V之间,就认为是逻辑1,在0V至yV之间就为逻辑0。
在这里插入图片描述
如图是RS-232逻辑电平下,传输‘A’时的波形:
在这里插入图片描述
在-12V至-3V之间,就认为是逻辑1,在+3V至+12V之间就为逻辑0。
RS-232的电平比TTL/CMOS高,能传输更远的距离,在工业上用得比较多。
市面上大多数ARM芯片都不止一个串口,一般使用串口0来调试,其它串口来外接模块。
ARM芯片上得串口都是TTL电平的,通过板子上或者外接的电平转换芯片,转成RS232接口,连接到电脑的RS232串口上,实现两者的数据传输。

现在的电脑越来越少有RS232串口的接口,当USB是几乎都有的。因此使用USB串口芯片将ARM芯片上的TTL电平转换成USB串口协议,即可通过USB与电脑数据传输。
在这里插入图片描述

二、芯片手册及原理图

2.1原理图

查看原理图,找到uart部分,如下:
在这里插入图片描述

2.2芯片手册

这里先分享一个2440uart控制器的原理图:
在这里插入图片描述
由上图可知,uart的时钟是由PCLK、FCLK/n,UEXTCLK三种的一种提供,整个控制器分为发送与接收两部分,2440有两个buffer register,一个是发送,一个是接收用,都是64个字节的长度,当使用FIFO模式的时候,64字节全部使用,当不使用FIFO模式的时候,只会使用一个字节,即:Holding Register

uart的红外模式,loop-back模式、自动流控制(AFC)这里就先不做介绍了,等以后遇到了再细说。

我们先介绍一下uart涉及到的寄存器:
①:线控制寄存器ULCONn
在这里插入图片描述
第一节我们分析了uart的几个参数,这里这个寄存器会设置数据位 word length,停止位 Number of Stop ,效验位 Parity Mode,至于该寄存器第【6】位,我们设为0,正常模式。

②:控制寄存器UCON
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
由于这里我们打算使用中断/查询模式,上面这些位采用默认的设置就行,这里说一下中断/查询模式的意思,这里就是我们可以通过中断函数,来进行数据发送的控制,比如non -FIFO模式下,如果发送缓存区没有数据了,就会产生一个中断,我们需要在中断处理函数中给缓冲区写入数据,如果接受缓存区有数据了,就会产生一个中断,在中断处理函数中读取数据。这就是中断模式,查询模式我们在后面介绍uart 发送/接受状态寄存器的时候说。
在这里插入图片描述

③FIFO控制寄存器
在这里插入图片描述
这个寄存器是FIFO模式下需要配置的一些设置:
第【0】位为开启或者关闭FIFO
第【1】、【2】位为reset的时候是否清楚buff缓冲器里的数据,一般我们都让它自动清除掉;
第【5:4】位是用来设置接收缓冲区触发中断的条件,即如果配置为00=1-byte,当接收buff有一个字节的数据时,就会发生中断。(查询也是一个道理)
第【7:6】位是用来设置发送缓冲区出发中断的条件,即如果设置为01=16-byte,当发送buff中少于16字节的数据是,就会发生中断。(查询也是一个道理)
由于我不打算使用FIFO,所以这里【0】配置成0就行,所以采用默认就行,不需要修改该寄存器配置。

由于我们不介绍流控制,所以接下来一个流控制的寄存器我跳过介绍,这里介绍UART 发送/接受状态寄存器:
UART TX/RX STATUS REGISTER:
在这里插入图片描述
中断/查询模式下,我们可以通过该寄存器来进行数据发送与接受,当【0】位被置1的时候,说明接受buff已满(不论是FIFO模式还是non-FIFO模式下,如果是FIFO模式,证明64字节的接受缓冲区已经到达了我们在fifo寄存器里面设置的满状态,如果是non-fifo模式,说明接收到了一个字节数据)我们可以读取数据;【1】位被置1 的时候,说明发送buff空了(不论是FIFO模式还是non-FIFO模式下,如果是FIFO模式,证明64字节的接受缓冲区已经到达了我们在fifo寄存器里面设置的空状态,如果是non-fifo模式,说明上一个字节数据已经被发送完毕,缓存区已经空了),我们就需要向发送buff写入数据。

⑤ 这里我不介绍错误状态寄存器了 有兴趣的可以自己了解一下,下面介绍发送数据寄存器与接受数据寄存器
在这里插入图片描述
当发送buff为空,我们就通过这个寄存器发送要发送的下个字节数据,该寄存器会自动将值保存到发送缓存区
在这里插入图片描述
当接收buff有数据是,出发中断,会将数据复制到该寄存器,我们只用读取该寄存器的值就可以了。

⑥这里还有一个波特率设置的寄存器UART BAUD RATE DIVISOR REGISTER在这里插入图片描述
通过读芯片手册知道UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1

一共八个寄存器,我们跳过了错误寄存器及流控制寄存器的介绍,这里只介绍今天使用到的六个寄存器,下面开始写程序。

三、程序编写

我们的目的是实现开发板串口的功能,我们这里写程序,实现跟PC上串口的数据通信。
这里先说一下思路:
第一步:初始化引脚为uart引脚,我们使用uart0,引脚查看上面原理图中。
第二步:设置uart控制器的相关寄存器,初始化控制器
①:ULCON0 = 0x00000003; /* 8n1: 8个数据位, 无较验位, 1个停止位 /
②:UCON0 = 0x00000005; /
PCLK,中断/查询模式 */
③:设置 UBRDIV0,我们这里规定波特率是115200,通过计算得出UBRDIVn=26,计算公式上面已经给过了,代码里也有
第三步:编写发送/接受函数,通过判断 UTRSTAT0寄存器的值,来进行发送与接受数据。发送接受数据用到的寄存器为UTXH0、 URXH0
第四步:写一个main函数,与pc串口工具通信。

3.1 start.S

start.S文件我们保持上节课不变,这里内容就不在粘出来了。

3.2main.c

新建一个main.c文件:

void uart0_init()
{
	/* 设置引脚用于串口 */
	/* GPH2,3用于TxD0, RxD0 */
	GPHCON &= ~((3<<4) | (3<<6));
	GPHCON |= ((2<<4) | (2<<6));

	GPHUP &= ~((1<<2) | (1<<3));  /* 使能内部上拉 */
	

	/* 设置波特率 */
	/* UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
	 *  UART clock = 50M
	 *  UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
	 */
	UCON0 = 0x00000005; /* PCLK,中断/查询模式 */
	UBRDIV0 = 26;

	/* 设置数据格式 */
	ULCON0 = 0x00000003; /* 8n1: 8个数据位, 无较验位, 1个停止位 */

	/*  */

}

int putchar(int c)
{
	/* UTRSTAT0 */
	/* UTXH0 */

	while (!(UTRSTAT0 & (1<<2)));
	UTXH0 = (unsigned char)c;
	
}

int getchar(void)
{
	while (!(UTRSTAT0 & (1<<0)));
	return URXH0;
}

int puts(const char *s)
{
	while (*s)
	{
		putchar(*s);
		s++;
	}
}


int main(void)
{
	unsigned char c;
	
	uart0_init();
	puts("Hello, world!\n\r");
	
	while(1)
	{
		c = getchar();
		if (c == '\r')
		{
			putchar('\n');
		}

		if (c == '\n')
		{
			putchar('\r');
		}

		putchar(c);
	}
	return 0;
}

四、编译烧写

通过烧写编译后的文件,实现了开发板与PC的数据传出。我主函数实现的功能是接受PC串口工具输入的一个字符,然后再输出。这样我们才能看到自己输入的东西。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值