【嵌入式】——arm裸机开发 step by step 之 串口通信
一、在使用S5PV210的串口发送和接收的时候,首先要对S5PV210的串口进行配置,我们使用轮询方式时的配置有哪些?
1、配置GPIO,使对应管脚作为串口的发送和接收管脚
GPA0 0 1 管脚 2 3 可以配置,但我们没有使用
GPA0CON寄存器[7:4][3:0] 0x22
GPA0PUD寄存器[3:0] 0 禁止上下拉电阻
2、配置串口单元本身寄存器
ULCON0 0xE2900000
数据位:8位
停止位:1位
校验位:无
使用的正模式,非红外。
3、UCON0 0xE2900004
串口的收发模式:轮训
串口的时钟使用的PCLK UFCON0 0xE2900008
禁止FIFO
UMCON0 0xE290000C
禁止Modem
UBRDIV0 0xE2900028
UDIVSLOT0 0xE290002C
UBRDIV0 = PCLK或者SCLK_UART/波特率/16 - 1 的整数部分
UDIVSLOT0 查表,怎么查?
PCLK或者SCLK_UART/波特率/16 - 1 的小数部分 * 16 取整
查表
PCLK=66500000
波特率是115200
UBRDIV0 = 35
UDIVSLOT0 = 0x0080
发送数据流程(轮询方式)
uart0_putc()
判断UTRSTAT0的BIT1,如果BIT1是0等待如果BIT1是1,就把要发送的一个字节数据写到发送寄存器(UTXH0,0xE2900020)
接收数据流程(轮询方式)
uart0_getc
判断UTRSTAT0的BIT0,如果BIT0是0等待如果BIT0是1,从URXH0 0xE2900024读取一个字节的数据。
编程时:
0xE2900000地址单元写3
0xE2900004地址单元写5
0xE2900008地址单元写0
0xE290000C地址单元写0
0xE2900028地址单元写35
0xE290002C地址单元写0x80
uart.h
#ifndef _UART_H_
#define _UART_H_ #define GPA0CON (*(volatile unsigned int *)0xE0200000)
#define GPA0PUD (*(volatile unsigned int *)0xE0200008) #define ULCON0 (*(volatile unsigned int *)0xE2900000)
#define UCON0 (*(volatile unsigned int *)0xE2900004)
#define UFCON0 (*(volatile unsigned int *)0xE2900008)
#define UMCON0 (*(volatile unsigned int *)0xE290000C)
#define UTRSTAT0 (*(volatile unsigned int *)0xE2900010)
#define UTXH0 (*(volatile unsigned int *)0xE2900020)
#define URXH0 (*(volatile unsigned int *)0xE2900024)
#define UBRDIV0 (*(volatile unsigned int *)0xE2900028)
#define UDIVSLOT0 (*(volatile unsigned int *)0xE290002C) #define PCLK (66500000) //函数原型声明
extern void uart0_init(void);
extern void uart0_puts(const char *);
extern void uart0_putc(char);
extern char uart0_getc(void);
extern void uart0_gets(char *,int); #endif // _UART_H_
uart.c
#include "uart.h" //初始化串口寄存器
void uart0_init(void){
//配置GPIO口 根据CPU 手册中设置下面的寄存器
//GPA0CON GPA0PUD
ULCON0 = ;
UCON0 = ;
UFCON0 = ;
UMCON0 = ;
UBRDIV0 = ;
UDIVSLOT0 = 0x0080;
GPA0CON = ;
GPA0PUD = ~0xF;
}
//发送一个字符
void uart0_putc(char c){
//判断状态位
while(!(UTRSTAT0 & (<<)));
//发送字符
UTXH0 = c;
}
//接收一个字符
char uart0_getc(void){
while(!(UTRSTAT0 & )); return URXH0;
} //接收一串字符
void uart0_gets(char *str,int len){
char* tmp = str;
int in = len;
//int i;
while(--len){
*tmp = uart0_getc();
if(*tmp == '\r'){
uart0_putc('\n'); //若此处为 \r 则不会输出,若为 \n 则在下一行跳跃输出字符的长度,然后输出字符串
uart0_putc('\r');
break;
}
if(*tmp == ){ //127 是 ubuntu下 kermit软件中的 BACKSPACE按键 需要实现的效果就是当按下回车键的时候终端的上一个数据会被删掉,
len++; //由于此分支的 127 输入到了 *tmp 中,此时的127是无用的,所以要进行 len++ ,但是有一个问题,我们的退格的目的是删除上一个字母,所以127的上一个字符也没用了,需要对len做两次自加进行还原 但是又出现一个问题,如果已经删到第0个元素就不能再自加两次了,这样会造成 len 越来越大。因此要在下面做一个判断
if(len < in){
len++;
}
if(tmp == str){
continue;
} uart0_putc('\b');
uart0_putc(' ');
uart0_putc('\b');
--tmp;
continue;
}
uart0_putc(*tmp);
tmp++;
}
*tmp = ;
} //发送一串字符
void uart0_puts(const char *str){
if(str == ){
return;
}
while(*str){
uart0_putc(*str);
if(*str == '\n'){
uart0_putc('\r');
}
str++;
}
}
main.c
#include "uart.h"
void main(void){
char val[];
uart0_init();
while(){
//uart0_gets(val);
uart0_puts("\nstart\n");
uart0_gets(val,);
uart0_puts(val);
// uart0_puts(uart0_getc());
}
}
makefile
PROG=uart
OBJS=main.o uart.o AS=arm-linux-as
CC=arm-linux-gcc
LD=arm-linux-ld
OBJCOPY=arm-linux-objcopy
AFLAGS=-march=armv5te
CFLAGS=-march=armv5te -nostdlib
LDFLAGS=-nostartfiles -nostdlib -Ttext=0x20008000 -e main $(PROG): $(OBJS)
$(LD) $(LDFLAGS) -o $(PROG) $(OBJS)
$(OBJCOPY) -O binary $(PROG) $(PROG).bin
cp uart.bin /tftpboot %.o:%.s
$(AS) $(AFLAGS) -o $@ $< %.o:%.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
@rm -vf $(OBJS) $(PROG) $(PROG).bin
二、arm9 TQ2440
这款 arm9 的串口通信跟 上面的 S5PV210相似:
uart.h
#ifndef __UART_H__
#define __UART_H__ //gpio
#define GPHCON (*(volatile unsigned long*)0x56000070)
#define GPHUP (*(volatile unsigned long*)0x56000078) //uart0 register
#define ULCON0 (*(volatile unsigned long*)0x50000000) //设置传输格式
#define UCON0 (*(volatile unsigned long*)0x50000004) //选择时钟源和中断方式
#define UFCON0 (*(volatile unsigned long*)0x50000008) //是否使用FIFO
#define UMCON0 (*(volatile unsigned long*)0x5000000C) //流量控制模式
#define UTRSTAT0 (*(volatile unsigned long*)0x50000010) //设置状态寄存器 [0] 当接收到数据时,此位被自动设为1 [1] 当发送缓冲区中没有数据时,此位被设置为1 [2] 当发送缓冲区中没有数据,并且最后一个数据也已经发送出去时,此位被自动设为1
#define UBRDIV0 (*(volatile unsigned long*)0x50000028) //设置波特率 //收发数据寄存器
#define UTXH0 (*(volatile unsigned long*)0x50000020) //发数据
#define URXH0 (*(volatile unsigned long*)0x50000024) //收数据
#define UTXH0B (*(volatile unsigned long*)0x50000023) //发数据
#define URXH0B (*(volatile unsigned long*)0x50000027) //收数据 //函数声明
extern void uart0_init(void);
extern char uart0_getc(void);
extern void uart0_putc(char);
extern void uart0_gets(char *,int);
extern void uart0_puts(char *); #endif
uart.c
#include "uart.h"
void uart0_init(void){
//配置 gpio 管脚
GPHCON &= ~0xf0;
GPHCON |= 0xa0;
//GPHUP &= 0x0c; //设置 gph2 gph3 内部上拉
GPHUP &= ~0x6; //设置 gph2 gph3 上下拉电阻禁止
ULCON0 = ; //数据位 8位 一个停止位 无校检 正常模式
UCON0 = ; //查询方式
UFCON0 = ; //禁止FIFO
UMCON0 = ; //禁止流量控制
UBRDIV0 = /(*)-; //
}
char uart0_getc(void){
char ch;
while(!(UTRSTAT0 & ));
//ch = URXH0;
return URXH0;
}
void uart0_putc(char ch){
while(!(UTRSTAT0 & (<<)));
UTXH0 = ch;
}
void uart0_gets(char* ch,int len){
int flag = len;
while(--len){
*ch = uart0_getc();
if(*ch == '\r'){
uart0_putc(*ch);
break;
}
if(*ch == ){ //在dnw中 BACK SPACE按键是8 在 kermit下是127
len++; //此次循环接收的是退格符号所以无论如何len都要自加
if(flag == len){ //为了防止回删到开头,所以做个限制
continue;
}
uart0_putc('\b');
uart0_putc(' ');
uart0_putc('\b');
len++;
ch--;
continue;
}
uart0_putc(*ch);
ch++;
}
*ch = ;
}
void uart0_puts(char* ch){
while(*ch){
uart0_putc(*ch);
//如果是在kermit 下需要用到下面代码;
/*
if(*ch == '\n'){
uart0_putc('\r');
}
*/
ch++;
}
}
main.c
#include "uart.h"
void delay(void);
int main(void){
uart0_init();
uart0_puts("ok start:\n");
while(){
char ch[];
uart0_puts("netboy# ");
uart0_gets(ch,);
uart0_puts(ch);
uart0_puts("\n");
}
return ;
}
void delay(void){
int i;
for(i = ; i < 0xf0000; i++){
;
}
}
uart.lds
SECTIONS
{
. = 0x30000000;
.text :{
main.o (.text);
*.o (.text);
}
.data :{
*.o (.data);
}
__bss_start = .;
.bss :{
*.o (.bss);
}
__end = .;
};
Makefile
PROG=uart
OBJS=main.o uart.o CC=arm-linux-gcc
LD=arm-linux-ld
OBJCOPY=arm-linux-objcopy
AFLAGS=-march=armv5te
CFLAGS=-march=armv5te -nostdlib
LDFLAGS=-nostartfiles -nostdlib -Ttext=0x30000000 -e main $(PROG): $(OBJS)
$(LD) $(LDFLAGS) -o $(PROG) $(OBJS)
$(OBJCOPY) -O binary $(PROG) $(PROG).bin
cp uart.bin /mnt/hgfs/linux_share/tq2440/
%.o:%.c
$(CC) $(CFLAGS) -c -o $@ $< clean:
@rm -vf $(PROG) $(OBJS) $(PROG).bin
【嵌入式】——arm裸机开发 step by step 之 串口通信的更多相关文章
- ARM裸机开发中内存管理库RT_HEAP的使用
在使用arm芯片进行裸机开发的时候,很多时候都需要内存管理的功能,我们可以使用自己写的内存管理程序,也可以直接使用标准库,不过我一般比较喜欢标准库,速度快,今天就来说说在C语言环境下怎么样进行内存的动 ...
- 【嵌入式】——arm裸机开发 step by step 之 按键控制 LED 和 蜂鸣器
一.arm-9 TQ2440 key.h #ifndef __KEY_H__ #define __KEY_H__ #define GPFCON (*(volatile unsigned long *) ...
- ARM裸机开发之交叉工具链和MakeFile工程管理
一.交叉工具链 嵌入式Linux开发采用交叉开发,简单来说就是在宿主机(PC机)上面编译出能够在其他硬件平台上面运行的程序.在这个过程中,需要用到许多的交叉工具,这些交叉工具的集合就叫做交叉工具链.下 ...
- 嵌入式ARM系统开发基础
从.net到delplhi 从windows到Linxu 未来有多远? 如何突破自己? 什么是自己? 我从哪里来,要到哪里去? 世界是什么? 是世选择了我,还是我选择了世界? 怎么才能够完成蜕变? 去 ...
- (转载)用vs2010开发基于VC++的MFC 串口通信一*****两台电脑同一个串口号之间的通信
此文章以visual C++数据採集与串口通信測控应用实战为參考教程 此文章适合VC++串口通信入门 一.页面布局及加入控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目com ...
- S3C2440—2.裸机开发步骤及工具使用
文章目录 一.裸机开发步骤简介 1.在X86架构的Windows系统中 2.在X86架构的Ubuntu系统中 3.ARM裸机开发 二.soucre insight使用 1.sourec insight ...
- Step by Step: 基于MFC下的COM组件开发-Helloworld
http://blog.csdn.net/sybifei/article/details/45008745 [这篇文章有问题, 仅供参考] http://blog.csdn.net/define_us ...
- 使用Xamarin开发手机聊天程序 -- 基础篇(大量图文讲解 step by step,附源码下载)
如果是.NET开发人员,想学习手机应用开发(Android和iOS),Xamarin 无疑是最好的选择,编写一次,即可发布到Android和iOS平台,真是利器中的利器啊!而且,Xamarin已经被微 ...
- 精通initramfs构建step by step
(一)hello world 一.initramfs是什么 在2.6版本的linux内核中,都包含一个压缩过的cpio格式 的打包文件.当内核启动时,会从这个打包文件中导出文件到内核的rootfs ...
随机推荐
- HTTP 请求头 详解
转载:https://kb.cnblogs.com/page/92320/ HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议.HTTP协议采用了 ...
- 将多个 docx 文件使用 POI 进行合并,生成单个文档,包含图片
1 添加 maven 依赖,需要使用 poi 的依赖项 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-scratchpad ...
- 批量修改Mysql数据库表Innodb为MyISAN
mysql -uroot -e "SELECT concat('ALTER TABLE ', TABLE_NAME,' ENGINE=MYISAM;') FROM Information_s ...
- MySQL 5.6学习笔记(函数)
1. 数学函数 ABS(x) 返回x的绝对值BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制)CEIL(x)或CEILING(x) 返回大于x的最小整数值EXP(x) ...
- WPF 程序在 Windows XP 下报错:The image format is unrecognized.
最近做的一个 WPF 程序,在 Windows 7 或以上版本的系统中,测试都很正常,在 Windows XP 下运行时一开始就报了个错误: { "ClassName" : ...
- Unity创建一个简易的弹簧(弹动)效果
参考文章:http://www.cnblogs.com/SkyD/archive/2008/09/05/1284778.html 主要依据胡克公式F=-k·x.这里k是倔度系数,可以理解为k值越大弹性 ...
- 【Unity】7.4 游戏外设输入
分类:Unity.C#.VS2015 创建日期:2016-04-21 一.简介 Unity可以处理摇杆.游戏手柄.方向盘等标准游戏外设的输入,使用的方法如下图所示: 虚拟按键需要在输入管理器中配置,把 ...
- 绕过chrome的弹窗拦截机制
在chrome的安全机制里面,非用户触发的window.open方法,是会被拦截的.举个例子: var btn = $('#btn'); btn.click(function () { //不会被拦截 ...
- AsyncContext简介
为了支持异步处理,在Servlet 3.0中,在ServletRequest上提供了startAsync()方法: AsyncContext startAsync() throws Java.lang ...
- (原创)C++11改进我们的程序之简化我们的程序(八)
本次要讲的是如何通过泛型函数来简化我们的程序. 泛型函数除了之前介绍的一些优点外还有两个重要的优点 1.消除重复逻辑,提高程序的内聚性和健壮性 泛型函数在某种程度上用来弥补泛型类型的不足.通过泛型类型 ...