1-14 串口在S3C2440上的原理、配置与驱动实现
(本节笔记的具体实验代码,在这里:https://github.com/elvinsys/arm_tq2440/tree/master/1_uboot/1-14.serial)
一、 基本概念
1. 作用:作为数据传输的途径,或者作为控制台来提供用户对设备的控制方式
2. 通讯格式的几个概念
2.1 波特率:每秒传输bit的个数,常用的波特率有38400/115200
2.2 常用的参数:
起始位:当线路空闲时,电平为高,一旦检测到一个下降沿,则视为一个起始位
数据位:一帧中实际有效的数据的位数
校验位:用于检测数据传输的正确性
停止位:表示这帧数据的结束
3. 引脚:
RS232——9针引脚串口
2 : RXD : 接收脚
3 : TXD : 发送脚
5 : GND : 接地脚
二、 串口驱动程序设计
1. 串口初始化—— void uart_init()
(先touch uart.c,把uart.o加入到Makefile中)
查看底板原理图和核心板原理图可得知:
TXD0 : TXD0 / GPH2
RXD0: RXD0 / GPH3
1.1 配置引脚功能:GPHCON 0x5600 0070
GPH2 [5:4] 10 : TXD[0]
GPH3 [7:6] 10 : RXD[0]
1.2 设置串口数据格式:ULCON0 0x5000 0000
Word Length | [1:0] | 11 | 设定为8bit |
Number of stop | [2] | 0 | one stop bit 1位停止位 |
Parity Mode | [5:3] | 0XX | No Parity 无校验 |
1.3 设置串口工作模式:UCON0 0x5000 0004
(若在操作系统的支持下,可选择使用中断或DMA模式,但在bootloader中,一般采用轮询的工作模式)
Receive Mode | [3:2] | 01 | polling mode |
Transmit Mode | [1:0] | 01 | polling mode |
1.4 设置UART波特率(UART BAUD RATE DIVISOR REGISTER)
公式是:UBRDIVn = (int)(UART clock / (buad rate x 16) -1)
UBRDIV0 R/W 0x5000 0028
UART clock = PCLK = 50MHZ
(#define PCLK 500 0000)
(#define BAUD 115200)
UBRDIV0 = (int)(PCLK / (BAUD X 16)-1);
2. 发送数据——void putc (unsigned char ch)
2.1 检查UTRSTAT0 R 0x5000 0010
Transmitter empty | [2] | 0 | Not empty 等待 |
同上 | 同上 | 1 | empty 发送 |
2.2 发送到UTXH0 W 0x5000 0020 (UART TRANSMIT BUFFER REGISTER)
UTXH0 = ch;
3. 接收数据——unsigned char getc(void)
3.1 检查UTRSTAT0 R 0x5000 0010
Receive buffer data ready | [0] | 0 | Empty 等待 |
1 | has data 接收 |
3.2 从URXH0 R 0x5000 0024 (UART RECEIVE BUFF REGISTER)
return URXH0;
4. 把uart_init()加入到main.c中,并加入如下代码进行测试:
/* 加入回车换行符的ASCII码 */
putc(0x0d);
putc(0x0a);
/* 加入输出一个大写字母“H” */
putc('H');
5. 添加控制台回显功能
5.1 在main.c中删除以上三行测试代码,在while(1)中加入getc(),让程序不断检测自PC断输入的字符。
5.2 修改usrt.c中的接受收据的函数,代码如下:
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;
}
6. 发送一个字符串的函数,在uart.c中加入如下代码:
void uart_send_string(char * str)
{
while(*str)
{
putc(&str++);
}
putc(0x0d);
putc(0x0a);
}
7. 整个uart.c的实验代码如下:
#define ULCON0 (*(volatile unsigned char *)0x50000000)
#define UCON0 (*(volatile unsigned char *)0x50000004)
#define UTRSTAT0 (*(volatile unsigned char *)0x50000010)
#define UTXH0 (*(volatile unsigned char *)0x50000020)
#define URXH0 (*(volatile unsigned char *)0x50000024)
#define UBRDIV0 (*(volatile unsigned long *)0x50000028)
#define GPHCON (*(volatile unsigned long *)0x56000070)
#define PCLK 50000000
#define BUAD 115200
void uart_init(void) /* 初始化串口 */
{
//配置GPIO口,查表得TXD0=GPH2,RXD0=GPH3
GPHCON &= ~((0x3<<4)|(0x3<<6));
GPHCON |= ((0x2<<4)|(0x2<<6));
//配置ULCON0
ULCON0 = 0x03;
//配置UCON0
UCON0 = 0x09; /* 这里必须设置为0x09,也就是0b1001,否则后面DMA实验会出错 */
//设置波特率
UBRDIV0 = (int)(PCLK/(BUAD*16)-1);
}
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;
}
void uart_send_string(char * str) /* 发送一个字符串用作测试 */
{
while(*str)
{
putc(&str++);
}
putc(0x0d);
putc(0x0a);
}
三、 建立S3C2440开发板基于串口的控制台
1. 大建控制台框架,在main.c中加入如下while(1)代码:
while(1)
{
printf("\n****************************************\n\r");
printf("\n*****************GBOOT******************\n\r");
printf("1:Download Linux Kernel from TFTP Server!\n\r");
printf("2:Boot Linux from RAM !\n\r");
printf("3:Boot Linux from Nand Flash !\n\r");
printf("\nPlease Select : ");
scanf("%d", &num);
switch (num)
{
case 1:
printf("selected 1 !\n\r");
break;
case 2:
printf("selected 2 !\n\r");
break;
case 3:
printf("selected 3 !\n\r");
break;
default:
printf("Error : This is a wrong slection !\n\r");
break;
}
}
2. printf / scanf 函数的移植和实现
2.1 touch printf.c ,并把printf.o丢到Makefile里
2.1.1 unsigned char outbuf[1024];
2.1.2 man 3 printf,函数原型为 int printf(const char * fmt, ...),讲变参转化为字符串,
va_list args; /* 变参列表 */
va_start(args, fmt); /* 把原型中的fmt格式传递给变量列表 */
vsprint( (char *)outbuf, fmt, args ); /* 把变参转化字符串放进outbuf中 */
va_end();
2.1.3 打印字符串到串口
for ( i = 0; i < strlen( (char *) outbuf); i++)
{
putc(outbuf[i]);
}
return i;
2.2 然而,va_start, vsprintf, va_end 在gboot并木有定义,必须先从Lib中移植
2.2.1 修改顶层Makefile
OBJS := start.o main.o dev/dev.o lib/lib.o
2.2.2 编译后,出现错误,ctype.c 符号没定义,分析其原因为:ctype.h 没被预编译时包含,arm-linux-gcc路径应包含本地include文件夹,于是在顶层Makefile中添加如下代码:
CFLAGS := -I$(shell pwd)/include
export CFLAGS
编译后,报错,va_list'没声明,解决方法为,在printf.c中添加:#include “vsprintf.h”
编译后,报错,main.c中的“puts”没定义,原因为,出现了内联函数(inline funtion),解决办法未,修改顶层Makefile中的CFLAGS
CFLAGS := -fno-builtin -I$(shell pwd)/include
export CFLAGS
......
%.o : %.c
arm-linux-gcc $(CFLAGS) -c $^
2.3 移植scanf
2.3.1 unsigned char inbuf[1024];
2.3.2 man 3 scanf, 原型为:int scanf (const char * fmt, ....);
2.3.3 在printf.c中加入如下代码:
int scanf(const char *fmt, ...)
{
int i = 0;
unsigned char ch;
va_list args;
while(1)
{ /* 获取输入的字符串 */
ch = getc();
if((ch==0x0d) || (ch==0x0a))
{
putc('\n');
break;
}
else
{
inbuf[i++] = ch;
}
} /* 格式转换 */
va_start(args, fmt);
vsscanf((char *)inbuf, fmt, args); /* 此处和vsprintf不大一样 */
va_end();
return i;
}
3. 程序代码结构优化
3.1 建立dev文件夹,把button.c interrupt.c led.c mmu.c uart.c 等文件丢进去
3.2 在dev中,复制lib中的makefile进行修改
objs := mmu.o led.o button.o interrupt.o nandflash.o uart.o dma.o
3.3 xiugai dingceng Makefile
OBJS := start.o main.o dev/dev.o lib/lib.o
1-14 串口在S3C2440上的原理、配置与驱动实现相关推荐
- SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)
由于工作的原因,对SPI的理解最为深刻,也和SPI最有感情了,之前工作都是基于OSEK操作系统上进行实现,也在US/OS3上实现过SPI驱动的实现和测试,但是都是基于基本的寄存器操作,没有一个系统软件 ...
- SPI在linux3.14.78 FS_S5PC100(Cortex A8)和S3C2440上驱动移植(deep dive)_0
由于工作的原因,对SPI的理解最为深刻,也和SPI最有感情了,之前工作都是基于OSEK操作系统上进行实现,也在US/OS3上实现过SPI驱动的实现和测试,但是都是基于基本的寄存器操作,没有一个系统软件 ...
- S3C2440上LCD驱动 (FrameBuffer)实例开发讲解
1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其中的代码也可直接参考:drivers/video/s3c2410fb.c 以下为转载文章,文章原地址:http://blog. ...
- 转:S3C2440上LCD驱动(FrameBuffer)实例开发详解
1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其中的代码也可直接参考:drivers/video/s3c2410fb.c 以下为转载文章,文章原地址:http://blog. ...
- cubemx stm32 陶晶驰 串口屏 基于YXY通信原理的串口屏驱动代码
陶晶驰串口屏 资料 陶晶驰串口屏是本质是一个MCU,屏幕是MCU的模块,一般是一块TFT屏幕.在串口屏厂商提供的软件上面编写界面,然后通过串口直接烧到串口屏的MCU上,然后在屏幕上展示出来. 串口屏资 ...
- sever串口wifi拓展板_串口Wifi模块的工作原理和详细功能介绍
在无线网络领域里面,无线wifi是最火的名词.对于串口wifi模块的工作原理是什么呢?串口wifi模块又有什么功能呢?wifi方案设计远嘉科技给大家讲解有关串口wifi模块的工作原理,以及详细功能介绍 ...
- S3C2440上MMC/SD卡驱动分析(二)
下面的文章主要是转载的,先记录下自己的经验. MMC/SD驱动有两种模式:FIFO和DMA.在代码中两种方式都予以了实现,在make menuconfig时候,可以选择是使用fifo方式还是DMA方式 ...
- STM32串口接收不定长数据原理与源程序
**STM32串口接收不定长数据原理与源程序**CSDN上有很多关于STM32串口接收不定长数据的文章,但实际使用后发现照搬他们的代码,程序根本就不能正确接收数据,其中最关键的一句有问题.其余内容完全 ...
- 在Ubuntu 14.04.5 64bit上安装git GUI客户端GitKraken
git的图像化管理工具很多,有两个是比较推荐用的,sourceTree以及GitKraken.个人比较喜欢GitKraken.下面是我在Ubuntu 14.04.5 64bit上的安装过程. 从官网下 ...
最新文章
- 2020年人工神经网络第二次作业-参考答案第六题
- html隐藏二级导航的制作代码,HTML+CSS实现二级导航
- 梦幻西游物价稳定的服务器,梦幻西游:三界功绩对服务器点卡比例的影响,鬼区比例比火区高...
- 关于PHP页面显示乱码问题的解决
- 更改mysql数据库存储引擎_MySQL更改数据库表的存储引擎
- 21世纪IT人才需要具有的5个鲜明特点
- windows下载和安装gcc编译器(MinGW)及其环境配置(C语言编译环境配置)
- Linux运维04:vmstat命令详解
- 百度网盘破解版Pandownload开发者被抓
- 安卓手机屏幕投射电脑能同步声音
- multiprocessing.Pool(pool.map pool.apply pool.apply_async poo.map_async)
- ST-LINKV2仿真器接线、配置、仿真方法
- 服务器固态硬盘连接,技术支招:服务器中固态硬盘如何选?
- windows服务器ssl证书安装及配置
- 天正自定义填充图案怎么添加_天正填充图案 图层管理 文件
- Android应用全屏显示
- 如何设置windows防火墙的出入规则
- 谁偷走了小男孩的初吻?
- AI视频插帧 附带『视频插帧』工具
- Photoshop中如何把多张图片快速变为PDF文档
热门文章
- 20190221 beautiful soup 入门
- Android CompressImage图片压缩工具类介绍
- 【网络通信协议】OSI七层模型
- WiFi、WiMAX、WBMA与3G的比较
- 长尾分布之DECOUPLING REPRESENTATION AND CLASSIFIER FOR LONG-TAILED RECOGNITION
- 您的企业已经准备好使用专线了吗?——Vecloud
- OM | 运筹学在医疗运营管理中的应用
- 这个村子并不富裕,每个人都年复一年,日复一日地在田里劳作
- win8系统下载 mysql 64位 win8_win8系统64位iso镜像
- css中英文自动换行问题