嵌入式学习-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;
}
菜鸟一枚,如有错误,多多指教。。。
相关文章推荐
- css中的一些选择器的用法总结
- 在宇宙间不易被风吹散 —— 太阳
- 【高级功能】使用 Ajax
- Jquery属性获取——attr()与prop()
- 在IIS Express中调试时无法读取配置文件 错误
- python 入门笔记
- Cadence基础知识8(3W原则的实质以及20H原则最强整理)
- PHP 常用字符串,数组处理函数整理(一)
- NumPy学习笔记3-线性代数
- Android技术前线 java8之lambda预热
- 【通过代码的方式完成服务的寄宿工作】
- Codeforces Round #360 (Div. 2) E dp 类似01背包
- linux下打开、关闭tomcat,实时查看tomcat运行日志
- Aginx环境的搭建
- Python数据爬虫,爬链家的二手房信息
- remove all provisioning files from xcode 7
- C语言实现程序跳转到绝对地址0x100000处执行
- 今天新开博客,先写一篇试试看
- 华为公司面试题
- MemcacheQ 安装与使用