一、单片机并行I/O端口基础
1. 端口结构:
P0口:开漏结构,需外接上拉电阻;可用作数据/地址总线或通用I/O。
P1-P3口:内部带上拉电阻的准双向I/O,默认状态为高电平。
驱动能力:P0口吸收电流能力较强,输出高电平需外部上拉;P1-P3口可直接驱动LED(需限流电阻)。
2. 工作模式:
准双向模式(默认):输入时需先写1,输出可直接控制。
推挽输出:高电平由内部上拉驱动,增强输出能力(部分型号支持)。
高阻态:用于总线共享(如P0作输入时)。
二、C51编程核心要点
1. 关键字与寄存器访问:
sfr:定义特殊功能寄存器(如 sfr P1 = 0x90;)。
sbit:定义位变量(如 sbit LED = P1^0;)。
bit类型:声明位变量(如 bit flag;)。
2. 延时函数实现:
void delay_ms(unsigned int ms) {
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 120; j++); // 12MHz晶振近似1ms
}
三、应用实例
1. LED闪烁(P1.0)
#include <reg51.h>
sbit LED = P1^0;
void delay_ms(unsigned int ms) { /* 如上 */ }
void main() {
while(1) {
LED = 0; // 点亮(低电平驱动)
delay_ms(500);
LED = 1; // 熄灭
delay_ms(500);
}
}
2. 按键控制LED(P3.2)
#include <reg51.h>
sbit KEY = P3^2;
sbit LED = P1^0;
void delay_ms(unsigned int ms) { /* 同上 */ }
void main() {
LED = 1; // 初始熄灭
while(1) {
if (KEY == 0) { // 检测按键按下
delay_ms(10); // 去抖动
if (KEY == 0) {
LED = !LED; // 状态翻转
while (!KEY); // 等待释放
delay_ms(10);
}
}
}
}
3. 流水灯效果(P1口)
#include <reg51.h>
#include <intrins.h> // 包含_crol_移位函数
void delay_ms(unsigned int ms) { /* 同上 */ }
void main() {
P1 = 0xFE; // 初始值:11111110
while(1) {
delay_ms(200);
P1 = _crol_(P1, 1); // 循环左移
}
}
四、高级应用——LCD1602驱动
#include <reg51.h>
#define LCD_DATA P0 // 数据总线
sbit RS = P2^0; // 命令/数据选择
sbit RW = P2^1; // 读/写选择
sbit EN = P2^2; // 使能信号
void LCD_Command(unsigned char cmd) {
RS = 0; RW = 0; // 写命令
LCD_DATA = cmd;
EN = 1; // 产生使能脉冲
delay_ms(2);
EN = 0;
}
void LCD_Init() {
LCD_Command(0x38); // 8位数据,两行显示
LCD_Command(0x0C); // 开显示,关光标
LCD_Command(0x06); // 地址递增
}
void main() {
LCD_Init();
LCD_Command(0x80); // 第一行首地址
// 发送显示数据...
}