7.串口(UART)

目录

1.什么是串口?

2.通信接口基础知识

3.使用串口需要注意的东西?

 4.串口如何和电脑进行通信

5.编写程序思路

6.编写程序


 

1.什么是串口?

UART(Universal Asynchronous Receiver Transmitter:通用异步收发器), 一对一,以位为单位发送。

  •  串口通讯

    串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。
    串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的协议。

2.通信接口基础知识

2.1处理器与外部有线通信的两种方式

  • 并行通信  

   -传输原理:数据各个位同时传输。

   -优点:速度快    

   -缺点:占用引脚资源多

  • 串行通信  

  -传输原理:数据按位顺序传输。  

  -优点:占用引脚资源少  

  -缺点:速度相对较慢

2.2串行通信分类(按照通信方向)

  • 单工: 数据传输只支持数据在一个方向上传输
  • 半双工:允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
  • 全双工: 允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

2.3串行通信的通信方式

  • 同步通信:带时钟同步信号传输。    例如: -SPI,IIC通信接口
  • 异步通信:不带时钟同步信号。        例如: -UART(通用异步收发器),单总线(DS18B20温度传感器)

一些常见的串口通信接口:

 

补充几个重要的名词:

  • 波特率

波特率就是每秒钟传输的数据位数。
波特率的单位是每秒比特数(bps),常用的单位还有:每秒千比特数Kbps,每秒兆比特数Mbps。
    

  

3.使用串口需要注意的东西?

①   物理层(电气层:接口决定):       通信接口(RS232,RS485,RS422,TTL)

通信两端的接口类型必须匹配,否则无法进行通信,比如单片机和单片机直接,他们的电平全部是TTL电平,可以进行通信,但是电脑和单片机直接,前者是RS232电平,所以没有办法直接通信,需要进行电平的转换,才能进行通信,如下:

情况一:单片机和单片机直接,都是使用TTL电平可以直接通信

情况二:单片机和PC直接,需要进行电平转换

 常见电器接口电平标准

 

②   数据格式(数据层:芯片决定)

③   通信协议(协议层:程序决定)

  •  起始位:1个逻辑0数据位开始
  •  数据位(8位或者9位)
  •  奇偶校验位(第9位)
  •  停止位(1,1.5,2位)
  •  波特率设置

例子:


 4.串口如何和电脑进行通信

简图如下:

补充:

假设波特率为:115200,8位数据位,无校验位,一个停止位,一个开始位(共10位)简写:115200,8n1

则传输一位的时间是:t = 1/115200 (s)  ,而传输一个字节需要10位;

那么传输一个字节的时间是: t(1byte) =  10/115200 (s) 

则一秒能传输的字节数是: 1/t  = 115200/10  = 11520 byte


5.编写程序思路

软件的设计大概可以分为这几步:

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).如何发送和接收数据

  • 发送:直接把内存的数据写入对应的buffer里面(写寄存器)

  • 接收:从buffer里面读取数据(读寄存器)

5).发送和接收标志位

  • 发送:

当发送数据,检测到UTRSTAT0的 第2为1,说明可以发送数据了,就可以往UTXH0寄存器里面写入一个字节的数据 

  • 接收:

当接收数据,检测到UTRSTAT0的 第0为1,说明可以接收数据了,就可以读取URXH0寄存器里面一个字节的数据 


6.编写程序:

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

  • 19
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值