串口通讯
串口充当的角色有两个,一个是数据传输,还有一个就是充当控制台。串口通讯分为同步和异步,我们通常使用的是异步串口。通讯时,双方先约定好数据帧的格式,即波特率,数据位,停止位,奇偶校验位等。我们通常使用的是RS232的9帧串口,其中,最重要的是2,3,5脚。
2:RXD接收数据
3:TXD发送数据
5:GND接地
接下来,我们开始进行串口的初始化。在此使用的开发板是飞凌S3C6410。初始化内容主要分为以下四个方面,引脚设置,帧格式设置,工作模式设置,波特率设置。
引脚设置
由核心板原理图上可找到RXD和TXD是通过GPA这个寄存器控制的,所以,在芯片手册中找到GPACON这个寄存器。
由芯片手册可得,只要设置GPACON的0到3位和4到7位来分别设置RXD和TXD即可。这里很简单,只要如下设置
GPACON &= ~0xff; /*先将低八位清零*/
GPACON |= 0x22;
设置数据格式
引入一个寄存器ULCON0,线控制寄存器,主要是设置数据格式。
ULCON0寄存器低两位主要设置数据位个数,第二位设置停止位个数,校验位暂时不需要使用,其他位使用默认的值。
ULCON0 = 0b11;
设置工作模式
引用UCON0寄存器,只要设置这个寄存器中的0:3位,其中0:1位设置收模式,2:3位设置发模式,在这里都设置为polling mode,即轮询模式,也就是查询等待模式。
UCON0 = 0b0101;
设置波特率
这里引入两个寄存器UBRDIV0和UDIVDLOT0,可以从芯片手册中得到两个寄存器的值,串口的时钟是由PCLK来提供的,在时钟体系那节中明确写出PCLK被设置成66MHZ,波特率一般设置为115200,故UBRDIV0=PCLK/(BAUD*16)-1取整,而UDIVDLOT0则是对小数部分乘上16,取整后查表得出UDIVDLOT0的值,由于PCLK等于66MHZ,BAUD为115200,(66000000/(115200*16))-1=34.8,故UBRDIV0=34,0.8*16=12.8,12查表得UDIVDLOT0为0xDDDD。
至此,串口初始化程序已经完成,但是如何测试串口正常工作呢,这里需要加两个函数,接收字符和发送字符。
发送数据
引入UTRSTAT寄存器
主要检查这个寄存器第1位是否为0,如果为0,表明前一次数据还没有发送完,如果等于1,则可以进行发送数据,在程序中用while循环,将字符送给UTXH0寄存器即可。
void putc(unsigned char ch)
{
while (!(UTRSTAT0 & (1<<2)));
UTXH0 = ch;
}
接收数据
这里还是使用UTRSTAT寄存器,使用第0位,第0位若为0,表明还没有接收到数据,为1表明接收到数据,当接收到数据的时候送到URXH0寄存器中进行返回。
unsigned char getc(void)
{
unsigned char ret;
while (!(UTRSTAT0 & (1<<0)));
// 取数据
ret = URXH0;
if ( (ret == 0x0d) || (ret == 0x0a) ) /*增加回显的功能,0x0d表示回车,0x0a表示换行*/
{
putc(0x0d);
putc(0x0a);
}
else
putc(ret);
return ret;
}
附上整体程序
#define GPACON (*((volatile unsigned short *)0x7F008000))
#define ULCON0 (*((volatile unsigned long *)0x7F005000))
#define UCON0 (*((volatile unsigned long *)0x7F005004))
#define UTRSTAT0 (*((volatile unsigned long *)0x7F005010))
#define UBRDIV0 (*((volatile unsigned short *)0x7F005028))
#define UTXH0 (*((volatile unsigned char *)0x7F005020))
#define URXH0 (*((volatile unsigned char *)0x7F005024))
#define UDIVSLOT0 (*((volatile unsigned short *)0x7F00502C))
#define PCLK 66500000
#define BAUD 115200
void uart_init()
{
//1.配置引脚功能
GPACON &= ~0xff;
GPACON |= 0x22;
//2.1 设置数据格式
ULCON0 = 0b11;
//2.2 设置工作模式
UCON0 = 0b0101;
//3. 设置波特率
UBRDIV0 =(int)(PCLK/(BAUD*16)-1); //UBRDIV0保存该公式计算后的整数部分
UDIVSLOT0 = 0x0; //UDISLOT0=保存该公式计算后的小数部分*16
}
void putc(unsigned char ch)
{
while (!(UTRSTAT0 & (1<<2)));
UTXH0 = ch;
}
unsigned char getc(void)
{
unsigned char ret;
while (!(UTRSTAT0 & (1<<0)));
// 取数据
ret = URXH0;
if ( (ret == 0x0d) || (ret == 0x0a) )
{
putc(0x0d);
putc(0x0a);
}
else
putc(ret);
return ret;
}