STC8单片机I/O端口原理及驱动

STC8系列单片机的I/O驱动原理


STC8系列有四种驱动模式

  • 准双向输出
  • 强推挽输出
  • 仅为输入(高阻)
  • 开漏输出

准双向输出配置

说明:准双向输出可以用作输出和输入功能,而不需要重新配置I/O口输出状态。如下图所示:当端口锁存数据置为逻辑高时,驱动能力很弱,允许外部设备将其拉低(要尽量避免这种情况);当引脚输出为低时,驱动能力很强,可吸收很大的电流。
准双向输出配置
注:(1)STC 1T系列单片机的供电电压(VCC)为3.3V,建议不要在准双向口模式下直接施加5V电压到管脚上。
(2)在准双向口模式下读取外部设备状态前,要先将相应的端口位置1,才可以读到外部正确的状态。

强推挽输出配置

说明:此种模式提供持续的强上拉,推挽模式一般用于需要更大驱动电流的情况。
强推挽输出配置

仅为输入(高阻)配置

仅为输入(高阻)配置
注:仅为输入(高阻)配置,不提供吸收20mA电流的能力

开漏输出配置

说明:在开漏模式下,单片机可以读取引脚的外部状态;(在外接上拉电阻的情况下)可以正确对外部输出高电平;否则,只要对外部输出低电平的情况下是正确的。
开漏输出配置
注:(1)由于8051CPU始终速度较高,因此当软件执行由低变高的指令后,一般需要加入1-2个空操作延迟指令,再读取外部状态。
(2)在STC单片机中,通过I/O端口模式寄存器,可以切换这些引脚的工作模式


I/O端口控制寄存器组


总说明:

(1)对于LQFP 64脚封装的STC8系列单片机才有P6组端口和P7组端口
(2)STC8系列单片机STC8A8K64S4A12的P4组端口只有5位有效,即P5.0~P5.5,而端口P0,P1,P2,P3,P6,P7都是8位有效


端口模式控制寄存器

说明:含义以P0端口举例,其余类似。
P0M0/P0M1寄存器
组合配置含义
端口模式寄存器含义和复位值


端口寄存器

说明:通过端口寄存器,STC单片机可以读取端口状态,或者像端口写数据,以P0为例。
P0端口寄存器
补充说明:P0端口地址为80H,复位值为0xFFH
其余端口情况见下图
其余端口寄存器情况


端口上拉电阻控制寄存器

说明:(1)在STC8系列单片机中,每个端口集成了可供用户选择使用的上拉电阻。
(2)当给端口上拉寄存器相应的位写0时,禁止端口内部的3.7kΩ的上拉电阻;当给每个端口上拉寄存器相应的位写0时,使能端口内部3.7kΩ上拉电阻;默认复位后不使能。
端口上拉电阻控制寄存器


端口施密特触发控制寄存器

说明:(1)在STC8系列单片机中,为每个端口提供了可供选择使用的施密特触发器(使用施密特触发器,可以进一步提高端口的抗干扰能力)
(2)当给每个端口施密特触发控制寄存器相应位写0时,使能施密特触发功能(上电复位后默认使能);当给每个端口施密特触发控制寄存器相应位写1时,禁止端口的施密特触发功能。
端口施密特触发控制寄存器
在供电电压为5V时和供电电压为3.3V时,使能和禁止施密特触发功能的允许输入电平特性见下图
(说明:STC8系列是宽电压范围供电,2.0~5.5V)
供电电压为5V的情况下
供电电压为3.3V的情况下


代码驱动GPIO端口的实现


汇编代码版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
说明:此例程基于松果派增强版STC51单片机所写
效果:流水灯闪烁
单片机型号:STC8A8K64S4A12
吐槽:松果派抄袭小脚丫FPGA外形,设计小缺陷很多,不管是电路还是给的例程资料,但是出于是高中生所作,也在可以理解范围之内
*/

P5 DATA 0C8H //定义P5的SFR地址
CSEG AT 0x0000 //定义代码段起始地址
LJMP main //无条件跳转到main标号的位置
my_prog SEGMENT CODE //声明代码段
RSEG my_prog //引用代码段
ORG 0x100 //偏移地址0x100
main:
USING 0 //使用0组R0-R7
CLR P5.5 //使能PNP三极管SS8550,见下面电路图
LOOP2:
MOV A,#0FEH //赋值0xFE给累加器A
LOOP1:
MOV P1,A //复位启动后,亮最左边第一个LED
ACALL DELAY1S //延时1s
RL A //循环左移
CJNE A,#0FEH,LOOP1 //如果没有恢复初态(也就是亮左一LED),跳转循环1,依次点亮LED1-LED8
JMP LOOP2 //当A=0xFE时,重新大循环LOOP2,完成流水灯循环
/*
名称:延时子程序
说明:由单片机小精灵自动生成,晶振24M,指令周期STC1T
*/
DELAY1S: ;误差 -0.000000000056us
MOV R7,#8EH
DL1:
MOV R6,#0A8H
DL0:
MOV R5,#0FAH
DJNZ R5,$
DJNZ R6,DL0
DJNZ R7,DL1
MOV R5,#02H
DJNZ R5,$
NOP
RET

END //说明程序到这里结束

C语言代码版本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "reg51.h"
#include "intrins.h"

#define LED P1 //用LED代替P1口名字,增加程序的通用性,实际上由电路图可知P1的八个管脚分别对应着八个LED
sfr P5=0xC8; //因为传统51只在reg51.h中定义了P0~P3管脚的SFR地址,所以P5得单独声明
sbit PNP_T=P5^5;//由电路图可知PNP三极管控制管脚接的是P5.5管脚,当P5.5=0时,PNP三极管导通

/*
说明:延时1s,由单片机小精灵生成
参数:晶振24M,指令周期STC1T
*/
void delay1s(void) //误差 -0.000000000056us
{
unsigned char a,b,c,n;
for(c=142;c>0;c--)
for(b=168;b>0;b--)
for(a=250;a>0;a--);
for(n=2;n>0;n--);
_nop_(); //if Keil,require use intrins.h
}

void main()
{

unsigned char temp=0xFE;//仅亮最右边一个灯,由电路图可知,P1相应管脚为低电平时点亮
PNP_T=0; //当P5.5=0时,PNP三极管导通
while(1)
{
LED=temp;
delay1s();
/*
这里你得好好理解一下C语言下的左移操作,参见文章https://www.aye.ink/posts/175b9a61/
1111 1110- 1111 1100|0000 0001=1111 1101-...-1111 1111
当为1111 1111时恢复1111 1110 完成流水灯的循环
*/
temp=(temp<<1)|1;
if(temp==0xFF)
{
temp=0xFE;
}
}
}

电路原理图:

LED周围电路


实物运行效果如下:

附件下载:

Keil51汇编程序及电路图压缩包:

Keil51C语言程序压缩包: