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

一.串口基本知识

1.串口角色

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

2.串口通讯

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

起始位:当线路空闲时候,电平为高。一旦检测到一个下降沿,则视为一个起始位。然后接收方按照约定好的格式,接收这一帧数据。
数据位:一帧中实际有效数据的位数。
停止位:表示这帧数据的结束。
校验位:用于检测数据传输是否正确的位。

3.串口硬件引脚

嵌入式学习-uboot-lesson13-串口相关_第2张图片
我们通常使用的RS232的9帧串口,其中最为重要的是2,3,5脚
2 :RXD:接收数据
3 :TXD:发送数据
5 :GND:接地

二、串口驱动程序设计

1).串口初始化

  • 1.配置引脚功能

嵌入式学习-uboot-lesson13-串口相关_第3张图片
配置GPIO为串口接收发送模式,看上面的图可知为GPA0,GPA1.

#define GPACON      (*((volatile unsigned short *)0x7F008000)) //端口A配置寄存器
    GPACON &= ~0xff;
    GPACON |= 0x22;
  • 2.1 设置数据格式

嵌入式学习-uboot-lesson13-串口相关_第4张图片
设置为8位数据位,1位停止位,不使用校验位,

#define ULCON0      (*((volatile unsigned long *)0x7F005000))  //UART0通道行控制寄存器
ULCON0 = 0b11;
  • 2.2 设置工作模式

设置收发模式
嵌入式学习-uboot-lesson13-串口相关_第5张图片
嵌入式学习-uboot-lesson13-串口相关_第6张图片
设置其为轮询模式

#define UCON0       (*((volatile unsigned long *)0x7F005004))
    UCON0 = 0b0101; 
  • 3设置波特率

嵌入式学习-uboot-lesson13-串口相关_第7张图片

根据上图,可以得知波特率的计算公式,并且计算结果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();  //结束转换
  1. 打印字符串到串口
    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;
}


菜鸟一枚,如有错误,多多指教。。。

你可能感兴趣的:(串口,uboot,UART,OK6410)