【嵌入式】——arm裸机开发 step by step 之 串口通信
2014-03-19 23:19
288 查看
一、在使用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
uart.c
main.c
makefile
二、arm9 TQ2440
这款 arm9 的串口通信跟 上面的 S5PV210相似:
uart.h
uart.c
main.c
uart.lds
Makefile
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 = 3; UCON0 = 5; UFCON0 = 0; UMCON0 = 0; UBRDIV0 = 35; UDIVSLOT0 = 0x0080; GPA0CON = 34; GPA0PUD = ~0xF; } //发送一个字符 void uart0_putc(char c){ //判断状态位 while(!(UTRSTAT0 & (1<<1))); //发送字符 UTXH0 = c; } //接收一个字符 char uart0_getc(void){ while(!(UTRSTAT0 & 1)); 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){ //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 = 0; } //发送一串字符 void uart0_puts(const char *str){ if(str == 0){ return; } while(*str){ uart0_putc(*str); if(*str == '\n'){ uart0_putc('\r'); } str++; } }
main.c
#include "uart.h" void main(void){ char val[30]; uart0_init(); while(1){ //uart0_gets(val); uart0_puts("\nstart\n"); uart0_gets(val,30); 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 = 3; //数据位 8位 一个停止位 无校检 正常模式 UCON0 = 5; //查询方式 UFCON0 = 0; //禁止FIFO UMCON0 = 0; //禁止流量控制 UBRDIV0 = 50000000/(115200*16)-1; //26 } char uart0_getc(void){ char ch; while(!(UTRSTAT0 & 1)); //ch = URXH0; return URXH0; } void uart0_putc(char ch){ while(!(UTRSTAT0 & (1<<2))); 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 == 8){ //在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 = 0; } 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(1){ char ch[30]; uart0_puts("netboy# "); uart0_gets(ch,5); uart0_puts(ch); uart0_puts("\n"); } return 0; } void delay(void){ int i; for(i = 0; 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 之 按键控制 LED 和 蜂鸣器
- ARM芯片学习内容规划及ARM开发环境的搭建 分类: 嵌入式开发学习 2014-06-06 14:17 278人阅读 评论(0) 收藏
- 嵌入式开发环境ARM+linux的搭建 推荐
- ARM嵌入式开发中的GCC内联汇编简介
- 嵌入式开发笔记(三)ARM基础知识
- 【miscellaneous】【ARM-Linux开发】ARM平台基于嵌入式Linux Gstreamer 使用
- ARM嵌入式系统开发指南-设计和优化系统软件(译作连载)
- 嵌入式驱动开发笔记(裸机程序篇)---点亮LED灯
- Step by step——WinX开发入门教程-4
- 2012 ARM嵌入式开发应用研讨会杂谈 推荐
- ARM裸机开发(二)中断编程
- 【GCC-ARM裸机开发随笔】----之lds链接脚本分析
- 嵌入式Linux裸机开发(十四)——ADC
- 【嵌入式开发】 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计)
- 基于ARM 的嵌入式系统程序开发要点--目录
- ARM硬件平台上基于UCOS移植Lwip网络协议栈 分类: 嵌入式开发学习 2015-06-14 10:33 55人阅读 评论(1) 收藏
- 基于ARM的Qt Creator嵌入式开发环境搭建
- 应聘linux/ARM嵌入式开发岗位
- ARM嵌入式常用开发工具介绍及插画开发流程(更新)
- QTCreator + QTEmbedded 在Ubuntu上创建嵌入式ARM开发环境