1. 8155芯片概述
做嵌入式这么多年,8155这个芯片我接触得真不少。它虽然不是什么高大上的新器件,但在很多经典系统里都能看到它的身影。今天咱们就来聊聊这颗芯片,从里到外把它看透。
1.1 8155芯片简介
8155,全称是Intel 8155,一颗可编程的RAM/IO扩展芯片。说白了,它就是给单片机"扩容"用的。你想想看,早期的8051单片机,内部RAM才128字节,IO口也就那么几个,想做点复杂的事情根本不够用。这时候8155就派上用场了。
我个人习惯把它叫做"三合一"芯片。为什么?因为它集成了三样东西:
- 256字节的静态RAM — 给系统增加存储空间
- 22个可编程IO口 — 扩展输入输出能力
- 一个14位可编程定时器/计数器 — 处理定时和计数任务
我记得刚入行那会儿,带我的老工程师就跟我说:"8155这芯片,你玩透了,单片机系统的IO扩展和存储管理基本就通了。"现在想想,这话一点不假。
核心特点:8155是Intel公司为MCS-51系列单片机配套设计的接口芯片,采用40引脚DIP封装,单一+5V供电。它通过地址/数据复用总线与单片机连接,大大简化了系统设计。
1.2 8155芯片内部结构
咱们来看看8155内部到底长什么样。我习惯把它分成几个功能模块来理解:
| 模块名称 | 功能描述 | 寄存器地址 |
|---|---|---|
| 256×8位静态RAM | 数据存储,掉电丢失 | 00H~FFH |
| 命令/状态寄存器 | 控制芯片工作模式,读取状态 | 命令寄存器:写入;状态寄存器:读出 |
| PA口(8位) | 可编程输入/输出端口A | 01H |
| PB口(8位) | 可编程输入/输出端口B | 02H |
| PC口(6位) | 可编程输入/输出/控制端口C | 03H |
| 定时器/计数器 | 14位减法计数器,可编程输出波形 | 04H(低8位)、05H(高6位+模式) |
嗯,这里要注意一点:命令寄存器和状态寄存器共用同一个地址,但一个是只写,一个是只读。写操作时写入的是命令字,读操作时读出的是状态字。这个细节我在项目中吃过亏,后面会讲到。
1.3 8155芯片引脚功能
8155有40个引脚,咱们挑关键的来说。我把它分成几组:
电源与复位
- VCC(引脚40):+5V电源
- VSS(引脚20):地
- RESET(引脚4):复位信号,高电平有效。复位后IO口全部变为输入模式
地址/数据总线
- AD0~AD7(引脚12~19):地址/数据复用总线,和8051的P0口直接相连
- ALE(引脚11):地址锁存使能,下降沿锁存地址
- IO/M(引脚7):IO/存储器选择。高电平选IO口,低电平选RAM
- CE(引脚8):片选信号,低电平有效
读写控制
- RD(引脚9):读选通,低电平有效
- WR(引脚10):写选通,低电平有效
IO端口
- PA0~PA7(引脚21~28):A端口,8位
- PB0~PB7(引脚29~36):B端口,8位
- PC0~PC5(引脚37~39、1~3):C端口,6位
定时器
- TIMER IN(引脚6):定时器时钟输入
- TIMER OUT(引脚5):定时器输出
实战小技巧:我曾经在一个项目中,因为IO/M引脚的电平没处理好,导致读写RAM时老是出错。后来查了半天才发现,原来是IO/M信号和地址线有毛刺。解决办法是在IO/M引脚上加一个10kΩ上拉电阻,同时用施密特触发器整形一下。嗯,这种小坑,遇到了才知道疼。
1.4 8155芯片工作原理
8155的工作原理,说白了就是通过总线与单片机通信,然后根据命令字配置各个模块的工作模式。
咱们来看一个典型的读写时序:
// 8155初始化示例代码(C51)
#include <reg51.h>
#define CMD_PORT 0xFF00 // 命令寄存器地址
#define PA_PORT 0xFF01 // PA口地址
#define PB_PORT 0xFF02 // PB口地址
#define PC_PORT 0xFF03 // PC口地址
#define TIMER_L 0xFF04 // 定时器低8位
#define TIMER_H 0xFF05 // 定时器高6位+模式
void Init_8155(void)
{
// 设置命令字:PA输出,PB输出,PC输出,禁止定时器
// 命令字格式:D7 D6 D5 D4 D3 D2 D1 D0
// D0: PA口模式(0=输入,1=输出)
// D1: PB口模式(0=输入,1=输出)
// D2,D3: PC口模式(00=输入,11=输出)
// D4,D5: 定时器控制(00=禁止,01=停止,10=启动,11=启动并输出)
// D6,D7: 未使用
XBYTE[CMD_PORT] = 0x07; // 0000 0111:PA、PB、PC全部输出
}
void Write_RAM_8155(unsigned char addr, unsigned char data)
{
// 写RAM时,IO/M必须为低电平
// 这里假设IO/M由地址线A8控制
XBYTE[addr] = data; // addr < 0x100 时自动选中RAM
}
unsigned char Read_RAM_8155(unsigned char addr)
{
return XBYTE[addr];
}
为什么会这样设计?因为8155内部有地址译码逻辑。当CE为低电平时,芯片被选中。然后根据IO/M的电平,决定是访问RAM还是IO口。ALE下降沿时锁存地址,之后RD或WR信号控制数据的读写方向。
我刚开始做8155驱动时,总觉得时序很复杂。后来画了个时序图,一步一步分析,发现其实就三步:
- 送地址:通过AD0~AD7送出地址,ALE下降沿锁存
- 选方向:根据IO/M和CE确定访问对象
- 传数据:RD或WR有效时,数据在AD0~AD7上传输
避坑指南:我曾经在一个项目中,因为忽略了8155的复位状态,导致系统上电后IO口输出乱电平。8155复位后,所有IO口默认是输入模式,内部寄存器清零。如果你需要输出高电平,必须在初始化时先配置好方向,再写数据。否则,嘿嘿,你的外设可能会"抽风"。
关于定时器,我再多说两句。8155的定时器是14位的,可以产生方波、连续方波、单脉冲等多种波形。它的工作模式通过定时器高字节的高两位来设置:
| M2 M1 | 输出模式 | 说明 |
|---|---|---|
| 00 | 单次方波 | 计数到0时输出高电平,然后停止 |
| 01 | 连续方波 | 自动重装,持续输出方波 |
| 10 | 单脉冲 | 计数到0时输出一个正脉冲 |
| 11 | 连续脉冲 | 自动重装,持续输出脉冲 |
嗯,这里要注意:定时器的计数初值要写入低8位和高6位(高两位是模式控制)。写入顺序是先写低8位,再写高6位+模式。这个顺序搞反了,定时器可能不工作。
好了,关于8155的概述就聊到这儿。这颗芯片虽然老,但它的设计思想——地址/数据复用、可编程IO、片内集成RAM——至今还在很多现代芯片中沿用。理解了8155,你就理解了单片机系统扩展的基本套路。