您的位置:首页 > 其它

webee210 开发板的串口裸板驱动

2015-12-27 18:47 204 查看
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_00043.常用参数的初始化波特率,数据位,停止位,奇偶校验位的配置,我们选择的是8bit数据位,1bit停止位,无奇偶校验。ULCON0, R/W, Address = 0xE290_00004.数据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)/16DIV_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.7UBRDIVn = 20 ( integer part of DIV_VAL )(num of 1's in UDIVSLOTn)/16 = 0.7then, (num of 1's in UDIVSLOTn) = 11so, 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中,数据不会丢失。

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: