1. 项目背景与需求分析
公交IC卡系统作为城市公共交通的重要组成部分,已经在全国范围内得到广泛应用。传统公交收费系统存在找零麻烦、效率低下等问题,而基于51单片机的IC卡系统能够有效解决这些痛点。这个项目主要实现乘客刷卡消费、余额显示、数据存储等核心功能。
我曾在2018年参与过某三线城市公交系统的升级改造,当时就采用了类似的方案。相比商业级的读卡器方案,基于51单片机的设计成本可以控制在30元以内,而商业读卡器单价通常在200元以上,这对于中小城市的公交系统改造具有明显的成本优势。
2. 系统整体设计方案
2.1 硬件架构设计
整个系统由STC89C52RC单片机作为主控芯片,搭配RFID-RC522射频模块作为读卡器,LCD1602液晶屏用于显示,AT24C02芯片用于数据存储,蜂鸣器用于提示音,以及必要的电源模块组成。
硬件选型考虑:
- STC89C52RC:价格低廉(约5元),具有8K Flash存储空间,完全满足需求
- RFID-RC522:支持ISO14443A协议,读取距离2-5cm,单价约15元
- LCD1602:显示余额和提示信息,单价约8元
- AT24C02:存储消费记录,单价约1元
2.2 软件功能模块
系统软件主要包括以下几个模块:
- 射频卡读写模块
- 液晶显示驱动模块
- EEPROM数据存储模块
- 蜂鸣器提示模块
- 主控制逻辑模块
3. 核心硬件电路设计
3.1 单片机最小系统
STC89C52RC最小系统包括:
- 11.0592MHz晶振电路
- 复位电路(10uF电容+10K电阻)
- 电源滤波电路(0.1uF去耦电容)
注意:晶振频率选择11.0592MHz是为了保证串口通信的波特率精度,这是很多新手容易忽略的细节。
3.2 RC522读卡模块接口
RC522通过SPI接口与单片机连接:
- SDA - P2.0
- SCK - P2.1
- MOSI - P2.2
- MISO - P2.3
- RST - P2.4
- NSS - P2.5
3.3 LCD1602显示电路
采用4位数据线连接方式:
- RS - P1.0
- RW - P1.1
- E - P1.2
- D4-D7 - P1.4-P1.7
4. 关键软件实现
4.1 射频卡读写实现
c复制// RC522初始化
void RC522_Init() {
P2 = 0xFF;
RC522_Reset();
RC522_WriteReg(CommandReg, PCD_RESETPHASE);
RC522_WriteReg(TModeReg, 0x8D);
RC522_WriteReg(TPrescalerReg, 0x3E);
RC522_WriteReg(TReloadRegL, 30);
RC522_WriteReg(TReloadRegH, 0);
RC522_WriteReg(TxAutoReg, 0x40);
RC522_WriteReg(ModeReg, 0x3D);
RC522_AntennaOn();
}
// 寻卡函数
uchar RC522_FindCard(uchar *pTagType) {
uchar status;
uint backBits;
status = RC522_Request(PICC_REQIDL, pTagType);
if(status != MI_OK) return status;
status = RC522_Anticoll(pTagType);
if(status != MI_OK) return status;
return MI_OK;
}
4.2 余额处理逻辑
c复制// 扣费处理
void DeductBalance(uchar cardID[4], float amount) {
float balance = ReadBalanceFromCard(cardID);
if(balance >= amount) {
balance -= amount;
WriteBalanceToCard(cardID, balance);
ShowMessage("Deduct OK");
Beep(100);
} else {
ShowMessage("Insufficient");
Beep(300);
}
}
4.3 EEPROM数据存储
c复制// 写入消费记录
void WriteRecord(uchar cardID[4], float amount) {
uchar i;
uchar data[6];
// 组合卡号和金额
for(i=0; i<4; i++) data[i] = cardID[i];
data[4] = (uchar)(amount*100)>>8;
data[5] = (uchar)(amount*100);
// 寻找空闲地址
uchar addr = FindEmptyAddr();
if(addr != 0xFF) {
for(i=0; i<6; i++) {
I2C_Write(addr+i, data[i]);
}
}
}
5. 系统调试与优化
5.1 常见问题排查
-
读卡不灵敏:
- 检查天线匹配电路(通常为50Ω)
- 调整读卡距离在3cm以内
- 确保电源稳定(3.3V)
-
数据显示异常:
- 检查LCD对比度调节电位器
- 确认4位/8位模式设置正确
- 检查初始化时序
-
数据存储失败:
- 检查I2C上拉电阻(通常4.7K)
- 确认AT24C02的A0-A2地址设置
- 注意写周期时间(5ms)
5.2 性能优化技巧
-
射频部分:
- 调整Q值提高读取距离
- 优化防冲突算法
- 增加软件滤波减少误读
-
显示部分:
- 采用局部刷新减少闪烁
- 优化显示缓冲机制
-
存储部分:
- 实现磨损均衡算法
- 增加数据校验机制
6. 实际应用扩展
在实际部署中,我们还可以考虑以下扩展功能:
-
数据同步功能:
- 通过串口与上位机通信
- 定期上传消费记录
- 支持参数配置
-
多卡类型支持:
- 兼容M1卡和CPU卡
- 支持不同协议切换
-
安全增强:
- 增加3DES加密
- 实现双向认证
- 防克隆机制
我在实际项目中发现,增加一个简单的振动传感器可以显著提高系统可靠性。当检测到车辆振动时自动唤醒系统,既能降低功耗,又能避免漏刷情况。这个小技巧可以为系统增加不少实用价值。