51单片机(二)—— GPIO&Uart

一、GPIO

1.1 内部上拉电路

51单片机的I/O口都可以同时作为输入和输出之用。除了P0口以外,其他的I/O口都有内部上拉电阻。

3个内部上拉电阻都有不同的功用,要理解这个电路需要一定的模拟电路的知识。

内部上拉电阻示意图
51单片机(二)—— GPIO&Uart_第1张图片

由于相关的硬件配置,在编程时有以下需要注意的地方:

  • 当I/O口被用作输入用途时,读取输入前要保证锁存器状态为1。
  • 当将I/O口由低拉高时,指令执行后需要1~2个机器周期才能使实际的输出变成高电平。

在外围电路上需要注意的地方:

  • P0口做普通I/O使用时,要加上拉电路,因为其没有内部上拉。
  • 为防止电流过大,必要时外加限流电阻。

1.2 编程示例

51单片机的I/O口在使用时,并不需要对其进行初始化。

可以直接位寻址读/写单个GPIO状态,也可以直接访问sfr来读/写一组GPIO的状态。

/* byte */
unsigned char temp; 
P0 = 0xff;
temp = P0;

/* bit */
P0_1 = 1;
}

假设需要读取一个I/O口的输入状态,而该I/O口目前被锁存为0,则需要先将锁存器置1,再延时2个时钟周期。

#define INPUT P2_6
#define NOP __asm nop __endasm

INPUT = 1;
NOP;
if (INPUT == 0) {
....
}

二、串口

2.1 串口概要

  • 51单片机有一个内部集成的全双工串口。

  • 引脚为P3.0(Rx)和P3.1(Tx)。

  • 波特率由定时器产生。

  • 发送缓冲器和接收缓冲器共用一个地址(99H),发送缓冲器只写,接收缓冲器只读。

2.2 相关寄存器

与串口直接相关的寄存器如下(从sdcc头文件<8051.h>中拷贝):

#ifndef REG8051_H
#define REG8051_H

/* sfr */
__sfr __at (0x98) SCON ;
__sfr __at (0x99) SBUF ;
__sfr __at (0x87) PCON ;

/*  SCON  */
__sbit __at (0x98) RI   ;
__sbit __at (0x99) TI   ;
__sbit __at (0x9A) RB8  ;
__sbit __at (0x9B) TB8  ;
__sbit __at (0x9C) REN  ;
__sbit __at (0x9D) SM2  ;
__sbit __at (0x9E) SM1  ;
__sbit __at (0x9F) SM0  ;

/* BIT definitions for bits that are not directly accessible */
/* PCON bits */
#define IDL             0x01
#define PD              0x02
#define GF0             0x04
#define GF1             0x08
#define SMOD            0x80

在头文件里也描述得很清楚,PCON寄存器不允许位寻址。

2.3 SCON寄存器

bit B7 B6 B5 B4 B3 B2 B1 B0
name SM0/FE SM1 SM2 REN TB8 RB8 TI RI

SM0&SM1指定串口工作模式、SM2为多机通信控制位、REN为接收允许位、TB8和RB8为要发送的第9位数据、TI和RI为收发中断。

SM0、SM1:
SM0在PCON.6位为1时,做错误检测只用,这点在PCON叙述。当PCON.6位为0时,两个寄存器共同指定串口工作模式。

SM0 SM1 工作模式 说明 波特率
0 0 方式0 同步移位串行方式 SYSClock/12
0 1 方式1 8位uart,波特率可变 (2^SMOD/32)*(TIMER1溢出率)
1 0 方式2 9位uart (2^SMOD/64)* SYSClock
1 1 方式3 9位uart,波特率可变 (2^SMOD/32)*(TIMER1溢出率)

方式0用于外扩I/O,串转并等需要快速响应I/O跳变的场合。

方式1采用8位传输。

方式2和方式3采用9位传输,第九位通常被用来当做校验位,或者多机通信中的地址位。方式2和方式3的区别主要是波特率产生方式不同。

SM2:
多机通信控制位,开启后,从机只有接收到RB8为1,才开始响应串口中断。51单片机还提供两个从机地址寄存器来支持多机通信的硬件自动化控制。

REN:
REN位为接收允许位,只有该位置1,才允许从串口接收数据。

TB8:
该位是在方式2和方式3下要发送的第9位,需要由软件置位或者清0。比如在进行奇偶校验时,自己用软件计算出该字节的奇偶,然后写该位。

或者在多机通信时,假设在总线上接了一群从机。主机在发送数据时,先发送1帧地址帧并将该位置1。这样所有收到地址帧的从机都开始判断是否是与自己匹配的地址,而只是判断是自身地址的从机才会处理后续数据。

RB8:
该位是在方式2和方式3下接受到的第9位。而在方式1中,该位是接收到的停止位。

TI、RI:
接收和发送中断位。

注意:

  • 两者共用一个系统中断,进入中断后,要自行判断是TI还是RI引发的中断。
  • 需要软件清0,否则会重复进入中断。

2.4 PCON寄存器

bit B7 B6 B5 B4 B3 B2 B1 B0
name SMOD SMOD0

SMOD:
SMOD为1时,波特率加倍,参考上面的公式。

SMOD0:
SMOD0为0时,SCON里的M0和M1共同指定串口工作方式。SMOD0为1时,M0作为帧错误检测使用。

2.5 SBUF寄存器

SBUF寄存器是收发缓冲器,当发送和接受收,缓冲器里存的事收发的8位数据。如果在方式2和方式3,收发的第9位数据在SCON中的RB8和TB8中保存。

虽然收发共用一个sfr的地址,但实际上是两个不同的存储区域,可以独立使用。

2.6 编程示例

不考虑波特率的设置、中断、多机通信,uart的初始代码可以这么写。

#include <8051.h>

#define USE_UART
#define UART_MODE_1
#define UART_REN

#ifdef USE_UART

void uart_init(void)
{

/* enable receive */
#ifdef UART_REN
    REN = 1;
#endif

/* set uart mode */
    PCON = PCON | SMOD;
#ifdef UART_MODE_0
    SM0 = 0;
    SM1 = 0;

#elif defined(UART_MODE_1)
    SM0 = 0;
    SM1 = 1;

#elif defined(UART_MODE_2)
    SM0 = 1;
    SM1 = 0;

#elif defined(UART_MODE_3)
    SM0 = 1;
    SM1 = 1;
#endif
}

#endif

你可能感兴趣的:(嵌入式)