目录
1.什么是串口?
2.通信接口基础知识
3.使用串口需要注意的东西?
4.串口如何和电脑进行通信
5.编写程序思路
6.编写程序
UART(Universal Asynchronous Receiver Transmitter:通用异步收发器), 一对一,以位为单位发送。
串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。
串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。
2.1处理器与外部有线通信的两种方式
-传输原理:数据各个位同时传输。
-优点:速度快
-缺点:占用引脚资源多
-传输原理:数据按位顺序传输。
-优点:占用引脚资源少
-缺点:速度相对较慢
2.2串行通信分类(按照通信方向)
2.3串行通信的通信方式
一些常见的串口通信接口:
补充几个重要的名词:
- 波特率
波特率就是每秒钟传输的数据位数。
波特率的单位是每秒比特数(bps),常用的单位还有:每秒千比特数Kbps,每秒兆比特数Mbps。
① 物理层(电气层:接口决定): 通信接口(RS232,RS485,RS422,TTL)
通信两端的接口类型必须匹配,否则无法进行通信,比如单片机和单片机直接,他们的电平全部是TTL电平,可以进行通信,但是电脑和单片机直接,前者是RS232电平,所以没有办法直接通信,需要进行电平的转换,才能进行通信,如下:
情况一:单片机和单片机直接,都是使用TTL电平可以直接通信
情况二:单片机和PC直接,需要进行电平转换
常见电器接口电平标准
② 数据格式(数据层:芯片决定)
③ 通信协议(协议层:程序决定)
例子:
简图如下:
补充:
假设波特率为:115200,8位数据位,无校验位,一个停止位,一个开始位(共10位)简写:115200,8n1
则传输一位的时间是:t = 1/115200 (s) ,而传输一个字节需要10位;
那么传输一个字节的时间是: t(1byte) = 10/115200 (s)
则一秒能传输的字节数是: 1/t = 115200/10 = 11520 byte
软件的设计大概可以分为这几步:
1).设置IO的模式为串口模式
查看原理图,可以看到GPH3/4 分别是串口0的 RXD和TXD
查看S3C2400的芯片手册对上面两个引脚的定义:
设置引脚为串口功能:
设置引脚上拉:
2).设置波特率
此时设置Pclk = 50MHz,设置波特率为:115200,那么 UBRDIVn = ?
由公式:UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1
则:UBRDIVn = (int)( 50000000 / ( 115200 x 16) ) –1 = 26
这些寄存器的内容是什么?
此处时钟源为:50Mhz
在程序中使能串口的发送和接收功能: 设置为:0b01
那么设置这个寄存器的值为:0x00000005
设置波特率为:115200,设置UBRDIV的值为26
3).设置数据格式
即:往寄存器ULCON0写入值:0x00000003
4).如何发送和接收数据
5).发送和接收标志位
当发送数据,检测到UTRSTAT0的 第2为1,说明可以发送数据了,就可以往UTXH0寄存器里面写入一个字节的数据
当接收数据,检测到UTRSTAT0的 第0为1,说明可以接收数据了,就可以读取URXH0寄存器里面一个字节的数据
6.1.串口初始化函数
按照上边的编程思路写一个串口初始化函数,如下:
其中还包含三个函数:
1、putchar() //发送一个字节数据
2、getchar() //接收几个字节数据
3、putSring() //发送字符串
#include "s3c2440_soc.h"
void uart0_init(void)
{
/*IO引脚设置*/
/*GPH2/3 设置为Txd0,Rxd0*/
GPHCON &= ~((3<<4)|(3<<6)); //先对位进行清零
GPHCON |= ((2<<4)|(2<<6)); //设置GPHCON[8:4]=0b1010
/*设置上拉功能,设置GPHUP[3:2]=0b00*/
GPHUP &= ~((1<<2)|(1<<3));
/*设置波特率*/
/*======================================
*1.设置 UCON0 寄存器设置 串口0的时钟源是 PLCK
*2.使能串口的发送和接收,设置为中断或者查询模式*/
UCON0 = 0x00000005;
UBRDIV0=26; //设置波特率为:115200
/*设置数据格式:一位起始位,8位数据位,1位停止位,无校验位*/
ULCON0 = 0X00000003;
}
/*发送一个字节的数据*/
int putchar(int c)
{
while(!(UTRSTAT0 & (1<<2)));
UTXH0 = (unsigned char)c;
}
/*读取一个字节的数据*/
int getchar(void)
{
while(!(UTRSTAT0 & (1<<0)));
return URXH0;
}
/*发送一个字符串*/
int putString(const char *s)
{
while(*s)
{
putchar(*s);
s++;
}
}
6.2.编写启动文件 start.S
1.设置堆栈指针sp
2.设置系统时钟
3.设置函数从main函数开始执行
.text
.global _start
_start:
/*关闭看门狗*/
ldr r0 ,=0x53000000
ldr r1 ,=0
str r1 ,[r0]
/*设置MPLL=400Mhz*/
/*LOCKTIME(0x4C000000) = 0xFFFFFFFF*/
ldr r0 ,=0x4C000000
ldr r1 ,=0xFFFFFFFF
str r1 ,[r0]
/*设置CLKDIVN(0x4C000014)=0x5*/
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0]
/*使CPU总线工作与异步模式*/
mrc p15,0,r0,c1,c0,0
orr r0,r0,#0xc0000000
mcr p15,0,r0,c1,c0,0
/*往寄存器MPLLCON(0x4C000004)?的MPLLCON[19:12]=92(0x5c) ,MPLLCON[9:4]=1,MPLLCON[1:0]=1.*/
ldr r0, =0x4C000004
ldr r1, =(0x5c<<12)|(1<<4)|(1<<0)
str r1, [r0]
/*设置内存:sp 栈*/
/*自动分辨是nand/nor启动方式*/
/*思路:因为nand是支持直接读取的,不需要什么
格式,而nor可以任意写,但是读取需要特定的
格式,若一开始往0地址写入一个值,然后读出来
如果读取的值和写入的值是一致的,说明是nand启动
否则是nor启动*/
mov r1 ,#0 //r1赋值为0
ldr r0 ,[r1] //读取0地址的值,以便后面恢复
str r1 ,[r1] //把0写入0地址里面
ldr r2 ,[r1] //从0地址读取值到r2
cmp r1 ,r2 //判断r1和r2是否相等,相等为nand启动
ldr sp ,=0x40000000+4096 //假设为nor启动
moveq sp, #4096 //相当为nand启动,重新设置sp
streq r0,[r1] //恢复nand中0地址的值
bl main
halt:
b halt
6.3编写主函数 main.c
1.调用串口初始化函数
2.调用串口函数进行数据的发送和接收
#include "s3c2440_soc.h"
#include "uart.h"
int main()
{
unsigned char c;
uart0_init();
putString(
"Hello world!\r\n");
while(1)
{
c =getchar();
if(c== '\r')
{
putString("\n");
}
putchar(c);
}
return 0;
}
6.4.编写Makefile文件,对以上文件进行编译
内容如下:
all:
arm-linux-gcc -c -o led.o led.c
arm-linux-gcc -c -o uart.o uart.c
arm-linux-gcc -c -o main.o main.c
arm-linux-gcc -c -o start.o start.S
arm-linux-ld -Ttext 0 start.o led.o uart.o main.o -o uart.elf
arm-linux-objcopy -O binary -S uart.elf uart.bin
arm-linux-objdump -D uart.elf > uart.dis
clean:
rm *.bin *.o *.elf *.dis
6.5.上传到Linux系统进行编译
在Linux上使用make命令:
6.6传回window系统,使用oflash进行烧录,使用串口调试助手
系统复位,输出 Hello world ! 回车进入下一行
从键盘输入字母,ARM芯片收到后,发送回去给电脑,并打印输出在屏幕上
这样一个简单的串口实验就玩成了。
代码:https://download.csdn.net/download/qq_36243942/10886092