webee210 开发板的串口裸板驱动

webee210开发板使用的是串口0作为log的输出口,如图所示:


1.RXD0和TXD0 分别是GPA0_0以及GPA0_1,首先先使能2个GPIO为串口功能。GPA0CON(0xE020_0000)



2.其次看时钟

串口的典型的结构图是:


可以看到UART部分分为了2个时钟信号,一个是由外部的时钟经过分频得到SCLK_UART,一个是PCLK的时钟,而这个时钟是66M


假如前面经历过时钟配置那一节的话,我们已经将基本的几个时钟都配置成为了三星推荐的时钟频率。我们采用PCLK的时钟。

UCON0, R/W, Address = 0xE290_0004


3.常用参数的初始化

波特率,数据位,停止位,奇偶校验位的配置,我们选择的是8bit数据位,1bit停止位,无奇偶校验。

ULCON0, R/W, Address = 0xE290_0000


4.数据fifo控制器

UFCON0, R/W, Address = 0xE290_0008


我们只需要关闭fifo就可以了。其他的采用默认的参数。关于有无fifo的区别可以参考http://blog.csdn.net/u013256018/article/details/50410840这个文章。

5.UTXH0, W, Address = 0xE290_0020 发送数据寄存器


6.URXH0, R, Address = 0xE290_0024,接收数据寄存器


7.波特率配置

有两个相关的寄存器

UBRDIV0, R/W, Address = 0xE290_0028,UDIVSLOT0, R/W, Address = 0xE290_002C



有公式计算:

DIV_VAL = UBRDIVn + (num of 1's in UDIVSLOTn)/16
DIV_VAL = (PCLK / (bps x 16)) −1或者是DIV_VAL = (SCLK_UART / (bps x 16)) −1,这个取决于选择哪个时钟源作为UART的时钟

三星提供了我们一个表格关于UDIVSLOTn中1的个数以及对应写的值


三星给了我们一个例子:

For example, if the baud-rate is 115200 bps and SCLK_UART is 40 MHz, UBRDIVn and UDIVSLOTn are:
DIV_VAL = (40000000 / (115200 x 16)) -1
= 21.7 -1
= 20.7
UBRDIVn = 20 ( integer part of DIV_VAL )
(num of 1's in UDIVSLOTn)/16 = 0.7
then, (num of 1's in UDIVSLOTn) = 11
so, UDIVSLOTn can be 16'b1110_1110_1110_1010 or 16’b0111_0111_0111_0101, etc.

整体的串口程序就是这些了。

看代码:

start.s

.text
.global  _start
_start:
		ldr	sp, =0xD0037D80	  @设置栈,以便调用c函数				
		bl main				  @调用main函数	
halt_loop:
		bl  halt_loop
main.c

#include "led.h"
#include "clock.h"
#include "uart.h"

int main()
{	
	unsigned char c;
	led_init();        //LED初始化
	sys_clock_init();  //系统时钟初始化
	uart_init();       //串口初始化

	while(1)
	{
		c = uart0_getbyte();       //等待键盘输入
		uart0_sendbyte(c-32);      //将a~z小写字母转换为A~Z大写字母
		if((c == 'F')||(c == 'f')) //当按下F或者f时,闪灯
		{
			led_flash();
		}
	}
	return 0;
}
uart.c
#include"uart.h"

void uart_init()
{
	/*  配置引脚
	 *	GPA0CON[1] = UART_0_TXD
	 *	GPA0CON[0] = UART_0_RXD
	 */
	GPA0CON = (0x2 << 4)|(0x2 << 0);

	/*
	 *	设置UART0的数据格式为:8个数据位,
	 *	一个停止位,无奇偶校验
	 */
	ULCON0 = (0 << 3)|(0 << 2)|(0x3 << 0);

	/*
	 *	设置UART0的时钟源为PCLK_PSYS = 66.7MHz,由时钟分频器产生
	 *	发送、接收均采用查询方式
	 */
	UCON0 = (0 << 10)|(0x1 << 2)|(0x1 << 0);

	/*  禁止UART0  FIFO!!!!!!!!!!!
	 *  这里如果使能的话实验效果差别相当大,
	 *  读者可以尝试修改为UFCON0 = (1 << 0);
     *	思考为什么效果会这样?
	 */
	UFCON0 = (0 << 0);

	/* 无流控 */
	UMCON0 = (0 << 4);

	/*
	 *	波特率 = 115200bps
	 *	分频系数 = ( PCLK_PSYS / (Baud * 16)) - 1;
	 *	分频系数 = UBRDIVn寄存器的值 + (UDIVSLOTn寄存器中1的个数) / 16;
	 *	For example:
	 *		PCLKP =66.7MHz,波特率设为115200
	 *		分频系数 = ( 66700000 / (115200 * 16)) - 1 = 35.2;
	 *		所以:UBRDIVn寄存器的值 = 35;
	 *		所以UDIVSLOTn寄存器的值的1的个数为2,
	 *		根据S5PV210手册p880可知 UDIVSLOTn= 0x808;
	 */

	UBRDIV0 = 0x23;
	UDIVSLOT0 = 0x808;
}

void uart0_sendbyte(unsigned char c)
{
	/*直到发送缓存为空,不为空时一直等待*/
	while(!(UTRSTAT0 & (1 << 2)));

	/*向UTXH0 寄存器中写入数据,UART会自动将它发送出去*/
	UTXH0 = c;
}

unsigned char uart0_getbyte()
{
	/*直到发送缓存不为空,为空时一直等待*/
	while(!(UTRSTAT0 & (1 << 0)));
	
	/*直接读取URXH0 寄存器,即可获得接收到的数据*/
	return URXH0;
}

其实使能和失能FIFO的区别就是一个可以保存多个串口的数据,一个只能保存一个数据。

上面的例子假如在使能fifo的时候,我们连续按多次的F(频率很快),但是基本上灯闪烁的次数是F的次数的2倍,但是关闭fifo时,连续F多次,只能闪烁4次,原因是在第一个F后,我们读取了URXH0,进入闪烁。但是很快第二个F来时,硬件赋值给了URXH0,但是此时的led闪烁还没有结束,当继续按第3个F时,此时之前的URXH0还没有被读取,造成第3个数据就丢失了。当使能FIFO时,这些数据先会写到FIFO中,数据不会丢失。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值