您的位置:首页 > 其它

嵌入式学习-uboot-lesson13-串口相关

2016-07-06 16:04 399 查看

一.串口基本知识

1.串口角色

数据传输、充当控制台(即uboot启动的时候,通过串口输入输出数据进行控制)

2.串口通讯



串口通讯,分为同步通讯和异步通讯,我们通常使用的都是异步串口。通讯时,双方先约定好数据帧的格式,即波特率,数据位,停止位,奇偶校验位等。这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。常用的波特率有38400,115200。

起始位:当线路空闲时候,电平为高。一旦检测到一个下降沿,则视为一个起始位。然后接收方按照约定好的格式,接收这一帧数据。

数据位:一帧中实际有效数据的位数。

停止位:表示这帧数据的结束。

校验位:用于检测数据传输是否正确的位。

3.串口硬件引脚



我们通常使用的RS232的9帧串口,其中最为重要的是2,3,5脚

2 :RXD:接收数据

3 :TXD:发送数据

5 :GND:接地

二、串口驱动程序设计

1).串口初始化

1.配置引脚功能



配置GPIO为串口接收发送模式,看上面的图可知为GPA0,GPA1.



#define GPACON      (*((volatile unsigned short *)0x7F008000)) //端口A配置寄存器
GPACON &= ~0xff;
GPACON |= 0x22;


2.1 设置数据格式



设置为8位数据位,1位停止位,不使用校验位,

#define ULCON0      (*((volatile unsigned long *)0x7F005000))  //UART0通道行控制寄存器
ULCON0 = 0b11;


2.2 设置工作模式

设置收发模式





设置其为轮询模式

#define UCON0       (*((volatile unsigned long *)0x7F005004))
UCON0 = 0b0101;


3设置波特率



根据上图,可以得知波特率的计算公式,并且计算结果UBRDIVn保留整数位,UDIVSLOTn保留小数位,

#define UBRDIV0     (*((volatile unsigned short *)0x7F005028))  //波特率分频寄存器
#define UTRSTAT0   (*((volatile unsigned long *)0x7F005010))   //UART 通道0 发送/接收状态寄存器
#define PCLK 66500000
#define BAUD 115200
UBRDIV0 =(int)(PCLK/(BAUD*16)-1);  //UBRDIV0保存该公式计算后的整数部分
UDIVSLOT0 = 0x0;   //UDISLOT0=保存该公式计算后的小数部分*16


2).数据发送





#define UTXH0          (*((volatile unsigned char *)0x7F005020))   //UART 通道0 发送缓冲寄存器
#define UTRSTAT0    (*((volatile unsigned long *)0x7F005010))
void putc(unsigned char ch)
{
while (!(UTRSTAT0 & (1<<2)));
UTXH0 = ch;
}


buff空了,说明以前的数据发送走了,然后将要发送的数据送入寄存器

3).数据接收



根据上图可以得知,如果第0位为0,则说明没有数据,因此需要等待

而接收到的数据会放到URXH0这个寄存器里面,因此需要从这个寄存器里面取出数据

unsigned char getc(void)
{
unsigned char ret;

while (!(UTRSTAT0 & (1<<0)));
// 取数据
ret = URXH0;

return ret;
}


三.printf和scanf实现

实现了上面的puts和gets函数,接下来就要实现大家常用的printf和scanf函数。

1)printf

1.将变参转化为字符串

va_start(args,fmt);  //利用fmt得到变参的个数,然后把变参放到args里面

vsprintf((char *)outbuf, fmt, args);   //将变参转换为字符串

va_end();  //结束转换


打印字符串到串口

for(i=0;i< strlen((char *)outbuf); i++)  //一个字符一个字符输出
{
putc(outbuf[i]);
}


2)scanf

1. 获取输入的字符串


while (1)
{

c = getc();
if ((c==0x0d) || (c==0x0a))
{
inbuf[i] = '\n';
break;
}
else
{
inbuf[i++] = c;
}
}


2. 格式转化


va_start(args, fmt);
vsscanf((char *)inbuf,fmt,args);
va_end(args);


贴上代码:

uart.c

/********************************************
*file name: uart.c
*author   : stone
*date     : 2016.7.5
*function : 串口相关
*********************************************/
#define GPACON      (*((volatile unsigned short *)0x7F008000))  //端口A配置寄存器
#define ULCON0      (*((volatile unsigned long *)0x7F005000))   //UART0通道行控制寄存器
#define UCON0       (*((volatile unsigned long *)0x7F005004))   //UART0通道控制器
#define UBRDIV0     (*((volatile unsigned short *)0x7F005028))  //波特率分频寄存器
#define UTRSTAT0    (*((volatile unsigned long *)0x7F005010))   //UART 通道0 发送/接收状态寄存器
#define UTXH0       (*((volatile unsigned char *)0x7F005020))   //UART 通道0 发送缓冲寄存器
#define URXH0       (*((volatile unsigned char *)0x7F005024))   //UART 通道0 接收缓冲寄存器
#define UDIVSLOT0   (*((volatile unsigned short *)0x7F00502C))  //UART 通道0 分频插槽寄存器

#define PCLK 66500000
#define BAUD 115200

void uart_init()
{
//配置引脚功能
GPACON &= ~0xff;
GPACON |= 0x22;

//设置数据格式  停止位、校验位、数据位
ULCON0 = 0b11;

//设置工作模式 工作在轮询模式(简单)
UCON0 = 0b0101;

//设置波特率
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))); //UTRSTAT0为1时表明里面有数据  等待
// 取数据
ret = URXH0;

if ( (ret == 0x0d) || (ret == 0x0a) )
{
putc(0x0d);
putc(0x0a);
}
else
putc(ret);

return ret;
}


printf.c

/********************************************
*file name: printf.c
*author : stone
*date : 2016.7.5
*function : 实现数据的收发
*********************************************/
#include "vsprintf.h"

unsigned char outbuf[1024];
unsigned char inbuf[1024];

int printf(const char* fmt, ...)
{
va_list args;
int i;

//1.将变参转化为字符串
va_start(args,fmt); //利用fmt得到变参的个数,然后把变参放到args里面

vsprintf((char *)outbuf, fmt, args); //将变参转换为字符串

va_end(); //结束转换

//2. 打印字符串到串口
for(i=0;i< strlen((char *)outbuf); i++)
{
putc(outbuf[i]);
}

return i;
}

int scanf(const char* fmt, ...)
{
unsigned char c;
int i = 0;
va_list args;

//1. 获取输入的字符串while (1)
{

c = getc();
if ((c==0x0d) || (c==0x0a))
{
inbuf[i] = '\n';
break;
}
else
{
inbuf[i++] = c;
}
}

//2. 格式转化va_start(args, fmt);
vsscanf((char *)inbuf,fmt,args);
va_end(args);

return i;
}



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