1-14 串口在S3C2440上的原理、配置与驱动实现
来源:互联网 发布:the zen of python 编辑:程序博客网 时间:2024/05/17 23:31
(本节笔记的具体实验代码,在这里: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设定为8bitNumber of stop[2]0one stop bit 1位停止位Parity Mode[5:3]0XXNo Parity 无校验1.3 设置串口工作模式:UCON0 0x5000 0004
(若在操作系统的支持下,可选择使用中断或DMA模式,但在bootloader中,一般采用轮询的工作模式)
Receive Mode[3:2]01polling modeTransmit Mode[1:0]01polling 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]0Not empty 等待同上同上1empty 发送 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]0Empty 等待 1has 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上的原理、配置与驱动实现
- s3c2440串口驱动原理分析
- DM9000CEP在S3C2440上的裸机驱动
- 在S3C2440上配置UART
- S3C2440 Linux UART 串口驱动-----1
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- S3C2440串口驱动
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- S3C2440 UART串口驱动
- PL2303芯片实现串口转usb,但是要在电脑上装上芯片的驱动
- S3C2440 Windows CE的RTC模块驱动设计与实现
- S3C2440 Windows CE的RTC模块驱动设计与实现
- s3c2440串口通讯的相关配置
- mini2440的串口在Qt上实现
- poj1486Sorting Slides【二分图匹配判断是否是必须】
- 求数组中数的最大值、最小值(C语言)
- 选择排序算法
- Spark Streaming生成RDD并执行Spark Job源码内幕解密
- 一个好的微信运营胜过100个销售人员:微信运营深度剖析
- 1-14 串口在S3C2440上的原理、配置与驱动实现
- HDU 4807 Lunch Time(费用流)★
- 线性时间的哈希排序
- Java 中MD5 和SHA加密算法工具类
- 创建第二个 local network - 每天5分钟玩转 OpenStack(84)
- 指针
- 勾股定理一日一证连载96
- ThinkPHP Where 条件中使用表达式
- html入门