在 51 单片机(AT89C52 / STC89C52 / STC12C5A60S2) 上直接读写 U 盘 几乎不可能用原生 USB 协议实现(51 无 USB Host 控制器),唯一可行方案是使用 USB Host 专用芯片。
工业界标准做法:51 + CH375 / CH376(USB Host 芯片)
一、总体方案
┌──────────┐
│ U盘 │
└────┬─────┘
│ USB
┌────▼─────┐
│ CH376 │ ← USB Host 芯片
└────┬─────┘
SPI / 8位并口
┌────▼─────┐
│ 51 MCU │
└──────────┘
二、芯片选型对比
| 芯片 | 接口 | 文件系统 |
|---|---|---|
| CH376 | SPI / 并口 | FAT12/16/32 |
| CH375 | 并口为主 | FAT |
| USB3300 | ULPI | 51 扛不住 |
强烈推荐 CH376(SPI 接 51)
三、硬件连接(STC89C52 + CH376 SPI)
| CH376 | 51 单片机 |
|---|---|
| VCC | 5V |
| GND | GND |
| SCS | P1.0 |
| SDI | P1.1 |
| SDO | P1.2 |
| SCK | P1.3 |
| INT# | P3.2(中断) |
| RST | P1.4 |
U 盘必须 独立 5V 供电(≥500mA)
四、CH376 核心驱动代码(Keil C )
1、 SPI 基本读写
c
sbit SCS = P1^0;
sbit SDI = P1^1;
sbit SDO = P1^2;
sbit SCK = P1^3;
void SPI_WriteByte(uint8_t dat)
{
uint8_t i;
for(i = 0; i < 8; i++)
{
SCK = 0;
SDI = (dat & 0x80) ? 1 : 0;
dat <<= 1;
SCK = 1;
}
}
uint8_t SPI_ReadByte(void)
{
uint8_t i, dat = 0;
for(i = 0; i < 8; i++)
{
SCK = 0;
dat <<= 1;
if(SDO) dat |= 0x01;
SCK = 1;
}
return dat;
}
2、 CH376 写命令 / 写数据
c
void CH376_WriteCmd(uint8_t cmd)
{
SCS = 0;
SPI_WriteByte(cmd);
SCS = 1;
}
void CH376_WriteData(uint8_t dat)
{
SCS = 0;
SPI_WriteByte(0x00);
SPI_WriteByte(dat);
SCS = 1;
}
uint8_t CH376_ReadData(void)
{
uint8_t dat;
SCS = 0;
SPI_WriteByte(0x00);
dat = SPI_ReadByte();
SCS = 1;
return dat;
}
3、 初始化 CH376
c
uint8_t CH376_Init(void)
{
CH376_WriteCmd(0x06); // CMD_RESET
DelayMs(50);
CH376_WriteCmd(0x05); // CMD_CHECK_EXIST
CH376_WriteData(0x55);
if(CH376_ReadData() != 0xAA)
return 0;
CH376_WriteCmd(0x15); // SET_USB_MODE
CH376_WriteData(0x06); // USB Host
return 1;
}
五、U 盘文件读写示例
1、 新建文件并写入
c
void Write_File(void)
{
CH376_WriteCmd(0x34); // FILE_OPEN
CH376_WriteData('T');
CH376_WriteData('E');
CH376_WriteData('S');
CH376_WriteData('T');
CH376_WriteData('.');
CH376_WriteData('T');
CH376_WriteData('X');
CH376_WriteData('T');
CH376_WriteData(0x00);
CH376_WriteCmd(0x3C); // BYTE_WRITE
CH376_WriteData(5); // 写 5 字节
CH376_WriteData('H');
CH376_WriteData('E');
CH376_WriteData('L');
CH376_WriteData('L');
CH376_WriteData('O');
}
2、 读取文件
c
void Read_File(void)
{
CH376_WriteCmd(0x3D); // BYTE_READ
CH376_WriteData(5);
for(uint8_t i = 0; i < 5; i++)
{
CH376_WriteCmd(0x27); // RD_USB_DATA
buffer[i] = CH376_ReadData();
}
}
六、文件系统支持(CH376 内部完成 )
| 功能 | 支持 |
|---|---|
| FAT12 | √ |
| FAT16 | √ |
| FAT32 | √ |
| 长文件名 | √ |
| 目录 | √ |
51 只负责发命令,不解析 FAT 表
参考代码 51单片机读写U盘的源程序_原理图 www.youwenfan.com/contentcst/181979.html
七、常见问题排查
| 问题 | 原因 |
|---|---|
| 检测不到 U 盘 | 供电不足 |
| 初始化失败 | SPI 时序不对 |
| 写文件失败 | U 盘格式非 FAT |
| 经常掉盘 | 接触不良 |
| 只能读不能写 | U 盘写保护 |
调试建议:
- 先用 CH376 测试程序
- 用 FAT32 格式化 U 盘
- 优先使用 2GB~16GB U 盘