新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > S3C2440之UART操作(FIFO模式)

S3C2440之UART操作(FIFO模式)

作者:时间:2016-11-19来源:网络收藏
背景知识:

<1>

本文引用地址:http://www.eepw.com.cn/article/201611/318139.htm

由于UART的波特率设置与时钟有关,此文设置FCLK:HCLK:PCLK=1 : 2 : 4,FCLK=200MHZ,遂先介绍时钟的设置。

通常认为上电复位后PLL是不稳定的。因此在软件重新配置PLLCON之前Fin代替MPLL直接供给Fclk。即便用户不希望复位之后改变PLLCON的数值,用户还是要用软件写入相同的数值到PLLCON寄存器中。

按照MDK4.22中启动代码的设置来说明以下设置。


MPLL,UPLL根据公式即可算出,这里的MPS最后算出的Fclk=200Mhz。PCLK也就是50Mhz了。

注意到HDIVN这里设置为0x01,不为0,那么Fclk != Hclk,要将fast mode转为异步模式,不然的话,Fclk相当于Pclk了。

由于MDK自带的启动代码没有这部分代码,所以自己加以修改了这部分。


FAST_TO_ASYN如果勾选的话,会选中

IFASYN_SETUP <> 0
MRCp15, 0, r1, c1, c0, 0
ORRr1, r1, #0xc0000000
MCRp15, 0, r1, c1, c0, 0
ENDIF

这样就可以配置成自己想要设置的时钟了。

关于串口的知识

3个独立的串口,每一个都可以利用DMA和中断方式操作。每个包含2个64字节FIFO,一个接,一个发。

FIFO模式相当于FIFO模式的一个寄存器缓冲模式。

每一个UART有7种状态,overrun错误,校验错误,帧错误,断点,接收缓冲区准备好,发送缓冲区为空,发送移位寄存器为空。钱4个被认为是接收错误状态,每一个都可以引起接收错误状态中断请求,前提是UCONn中设置了receive-error-status-interrupt-request=1。

当接收移位寄存器中的数据传给FIFO的时候,且接收的数据触发了Rx FIFO的阀值,Rx中断产生了。

发送器中FIFO的还未发得数据到达Tx FIFO阀值的时候,Tx中断产生了。

程序要点:

本程序首先完成基本的UART0的配置,比如TXO RXO的管脚配置,这可以在启动文件里配置完成,接着ULCON0配置,UCON0配置,UFCON0配置,UMCON0配置,UBRDIV0配置,INTSUBMSK打开相应位,INTMSK打开相应位。

中断程序里,接收和发都会引起UART0中断,在里面要加以区分,是接还是发引起。接设置FIFO16字节触发,脉冲模式;发为0字节触发,电平模式。

注意到一上电,UART0配置完成后,就会触发发中断,因为发设置为0电平模式触发,所以为了避免无缘无故的触发,需要在某些时机下,禁止中断。

功能:在串口上输入16字节,包括回车,然后会把输入的字符回显在串口终端上。

程序代码:

uart.c

/**   PC<----->2440UART0*/#include "S3C2440.h"#include "uart.h"static u8 string[512]  = {0,0};static u8 data_is_ready = 0;void init_uart0(void){rULCON0 = 0x03;  rUCON0 = (0x05) | (1<<9);//15---12   	11-10		9		8		7				6						5		 4			3-2				1-0//not pclk/n	pclk		Tlevel	Rpulse	timeout disable	rx error int disable   loop dis  break dis	int or poll		int or pollrUFCON0 = (0x0<<6) | (0x02<<4) | (0x01<<0);//0		0		1		1		0		0		0		1//Tx trigger level = 0	Rx trigger level = 16bytes	FIFO enable=1rUMCON0 = 0x0;rUBRDIV0 = UART_BRDIV;rINTSUBMSK &= ~BIT_SUB_RXD0;rINTMSK &= ~BIT_UART0;pHandleUART0 = UART0_Handle;}void __irq UART0_Handle(void){u8* ps = string;if(rSUBSRCPND&0x01){rINTSUBMSK |= BIT_SUB_RXD0;while(((rUFSTAT0&0x1f)>0))*ps++ = RdURXH0_L;data_is_ready = 1;		rSUBSRCPND = BIT_SUB_RXD0;}else if(rSUBSRCPND&0x02){int i;rINTSUBMSK |= BIT_SUB_TXD0;	 while((!(rUFSTAT0&(1<<14))) && (*ps != r)){WrUTXH0_L(*ps++);        for(i=0; i<100;i++);}	data_is_ready = 0;rSUBSRCPND = BIT_SUB_TXD0;	 }rSRCPND = BIT_UART0;rINTPND = BIT_UART0;if(data_is_ready)rINTSUBMSK &= ~(BIT_SUB_TXD0);   elserINTSUBMSK &= ~(BIT_SUB_RXD0);	}

main.c

#include "S3C2440.h"#include "uart.h"int main(void){	rGPBDAT |= (0xf<<5);init_uart0();while(1);}

经测试可以完成功能。


评论


技术专区

关闭