51单片机介绍
一、51单片机基本概念
51单片机 是指基于 Intel MCS-51架构 的8位微控制器系列,由Intel在1980年推出,后由多家厂商(如Atmel、STC、NXP等)生产兼容型号。因其结构简单、成本低廉、生态完善,成为嵌入式开发的经典入门选择。
二、核心特点
特性 | 说明 |
---|---|
CPU架构 | 8位CISC内核,12时钟周期/机器周期(增强型1T架构为1时钟周期) |
存储器 | - 4KB~64KB Flash ROM(程序存储) - 128B~1KB RAM(数据存储) |
I/O端口 | 4组8位双向I/O口(P0-P3),部分引脚复用为外设功能(如串口、中断等) |
定时器 | 2~3个16位定时器/计数器(TIM0/TIM1/TIM2) |
串口通信 | 1个全双工UART(支持异步串行通信) |
中断系统 | 5~7个中断源(2外部+2定时器+1串口,增强型扩展更多) |
工作频率 | 典型12MHz(标准型),增强型可达35MHz(如STC12系列) |
三、常见型号对比
型号 | 厂商 | Flash | RAM | 特殊功能 |
---|---|---|---|---|
AT89C51 | Atmel | 4KB | 128B | 经典基础型号 |
STC89C52 | STC | 8KB | 512B | 支持ISP下载 |
STC12C5A60S2 | STC | 60KB | 1KB | 1T架构、ADC、PWM |
P89V51RD2 | NXP | 64KB | 1KB | 双DPTR指针 |
四、硬件架构详解
存储器结构
哈佛架构:程序存储器(ROM)与数据存储器(RAM)独立编址。
特殊功能寄存器(SFR):通过直接寻址访问(地址80H~FFH),控制外设功能。
I/O端口特性
P0口:开漏输出,需外接上拉电阻;复用为数据/地址总线。
P1口:准双向口,无复用功能。
P2/P3口:部分引脚复用(如P3.0=RXD,P3.1=TXD)。
中断优先级
2级可编程优先级(IP寄存器配置)。
默认优先级顺序:外部0 > 定时器0 > 外部1 > 定时器1 > 串口。
五、开发工具链
编程环境
Keil μVision:主流IDE,支持C51汇编和C语言开发。
SDCC:开源跨平台编译器(Linux/macOS适用)。
烧录工具
STC-ISP:STC单片机专用下载软件(通过串口烧录)。
USB-TTL模块:连接电脑与单片机的UART引脚。
仿真调试
Proteus ISIS:电路设计与代码协同仿真。
硬件调试器:如J-Link(需芯片支持)
PCF8575介绍
PCF8575 是 NXP(原飞利浦半导体)生产的一款通用 I²C 总线 I/O 扩展器芯片,主要用于微控制器(如 Arduino、STM32 等)的 I/O 端口扩展。
主要特性
16位并行 I/O 端口:可以配置为输入或输出
I²C 总线接口:
兼容 Fast-mode I²C (400 kHz)
支持 3.3V 和 5V 系统
中断输出:当输入状态改变时可触发中断
低待机电流消耗:适合电池供电设备
宽工作电压范围:2.5V 至 6V
工业温度范围:-40°C 至 +85°C
引脚配置
PCF8575 通常采用 24 引脚 SO 或 TSSOP 封装,主要引脚包括:
SDA, SCL:I²C 总线接口
A0-A2:地址选择引脚
INT:中断输出
P00-P17:16个可编程 I/O 引脚
VCC, GND:电源和地
应用场景
LED 控制
按键/开关输入检测
继电器控制
需要额外 I/O 端口的嵌入式系统
工业控制和自动化
与 PCF8574 的区别
PCF8575 是 PCF8574 的升级版本,主要区别在于:
PCF8575 提供 16 位 I/O (PCF8574 只有 8 位)
PCF8575 的中断功能更完善
编程接口
通过 I²C 接口通信,典型操作包括:
写入输出状态
读取输入状态
配置 I/O 方向(通过写入特定模式)
典型电路连接
PCF8575 通常与微控制器通过 I²C 总线连接,地址由 A0-A2 引脚决定,允许同一总线上连接最多 8 个 PCF8575 设备。
proteus 51单片机 连接PCF8575
代码实现
#include <reg51.h>
#include <intrins.h>
#define u8 unsigned char
#define u16 unsigned int
// 定义I2C引脚
sbit SDA = P2^1;
sbit SCL = P2^0;
// PCF8575地址(根据A0,A1,A2引脚配置)
#define PCF8575_ADDR 0x40
// 延时函数
void delay_us(u8 t) {
while(t--);
}
void delay_ms(u16 t) {
u16 i, j;
for(i=0; i<t; i++)
for(j=0; j<120; j++);
}
// I2C起始信号
void I2C_Start() {
SDA = 1;
SCL = 1;
delay_us(5);
SDA = 0;
delay_us(5);
SCL = 0;
}
// I2C停止信号
void I2C_Stop() {
SDA = 0;
SCL = 1;
delay_us(5);
SDA = 1;
delay_us(5);
}
// I2C发送应答
void I2C_Ack(u8 ack) {
SDA = ack;
SCL = 1;
delay_us(5);
SCL = 0;
SDA = 1;
}
// I2C接收应答
u8 I2C_Wait_Ack() {
u8 ack;
SDA = 1;
SCL = 1;
delay_us(5);
ack = SDA;
SCL = 0;
return ack;
}
// I2C发送一个字节
void I2C_SendByte(u8 dat) {
u8 i;
for(i=0; i<8; i++) {
SDA = (dat & 0x80) ? 1 : 0;
SCL = 1;
delay_us(5);
SCL = 0;
dat <<= 1;
}
}
// I2C接收一个字节
u8 I2C_RecvByte() {
u8 i, dat = 0;
SDA = 1;
for(i=0; i<8; i++) {
SCL = 1;
delay_us(5);
dat <<= 1;
dat |= SDA;
SCL = 0;
delay_us(5);
}
return dat;
}
// 向PCF8575写入16位数据
void PCF8575_Write(u16 dat) {
I2C_Start();
I2C_SendByte(PCF8575_ADDR); // 发送设备地址+写命令
I2C_Wait_Ack();
I2C_SendByte(dat >> 8); // 发送高字节
I2C_Wait_Ack();
I2C_SendByte(dat & 0xFF); // 发送低字节
I2C_Wait_Ack();
I2C_Stop();
}
// 从PCF8575读取16位数据
u16 PCF8575_Read() {
u16 dat;
I2C_Start();
I2C_SendByte(PCF8575_ADDR | 0x01); // 发送设备地址+读命令
I2C_Wait_Ack();
dat = I2C_RecvByte() << 8; // 读取高字节
I2C_Ack(0); // 发送应答
dat |= I2C_RecvByte(); // 读取低字节
I2C_Ack(1); // 发送非应答
I2C_Stop();
return dat;
}
// 主函数
void main() {
u16 output_data = 0x5555; // 示例输出数据(0101 0101 0101 0101)
u16 input_data;
// 初始化I2C引脚
SDA = 1;
SCL = 1;
while(1) {
// 写入数据到PCF8575
PCF8575_Write(output_data);
delay_ms(1000);
// 从PCF8575读取数据
input_data = PCF8575_Read();
delay_ms(1000);
// // 改变输出数据
output_data = ~output_data;
}
}