找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13262|回复: 19
打印 上一主题 下一主题
收起左侧

51单片机+CH375读写U盘例程+电路原理图

  [复制链接]
跳转到指定楼层
楼主
运行环境:STC51 1T单片机 22.1184M晶振 (建议使用STC12C5A60S2 或 STC89C58)
代码介绍:

一:此程序首先将CH375程序库及CH375芯片进行初始化,随后开始检测U盘是否已经插入,U盘插入后,读取U盘的物理总容量,单位为扇区,即一共有多少个扇区。然后获取U盘的格式化容量、剩余容量及文件系统类型。

二:此程序进行一些初始化的操作及基本参数的获取。后面在根目录下创建一个TEST.TXT文件,创建成功后,获取此文件的相关信息并输出。

三:此程序进行一些初始化的操作及基本参数的获取。后面对根目录下的所有文件进行列举。然后更改test.txt的一些信息,如创建时间,文件属性等。

四:此程序进行一些初始化的操作及基本参数的获取。后面先定位文件的偏移量,然后读取根目录下的test.txt的从偏移量开始的40个字节(如果实际长度小于40,就读取实际长度),最后向文件中写入数据。

五:CH375对U盘的扇区级文件操作。

电路原理图如下:


单片机源程序如下:
  1. #include "ch375.h"
  2. #include "myfun.h"

  3. /***********************************************************
  4.         +-----------------------------------------------+
  5.         | 振南电子 高级外设程序模块 CH375 部分 [IO方式] |
  6.                 | 【此程序与视频教程中有出入,主要是为了程序兼容|
  7.                 |     性与稳定性,有些代码借鉴沁恒官方源码】        |
  8.         +-----------------------------------------------+
  9.   此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
  10.         严禁随意用于商业目的
  11.          振南电子
  12.                             WW:yzn07
  13.   注:本程序为IO方式,即使用单片机的IO模拟时序来驱动CH375
  14.       IO方式便于移植。其实IO在模拟外部总线的时序,对于没有
  15.           外部总线的单片机,可以参考此程序。模拟时序,在速度上
  16.           不及硬件的外部总线。在操作U盘的时候,对操作速度有一定
  17.           要求。
  18.           这是振南在长期对CH375的研究中,得到的经验,请借鉴!!                                  
  19. ***********************************************************/

  20. /******************************************************************
  21. - 功能描述:向CH375写入命令
  22. - 隶属模块:CH375模块
  23. - 函数属性:内部
  24. - 参数说明:cmd:要写入的命令码
  25. - 返回说明:无返回
  26. ******************************************************************/

  27. void CH375_Write_Cmd(unsigned char cmd)        //写命令
  28. {
  29. delay(DELAYTIME); //稍作延时
  30. CH375_CS=0; //打开片选
  31. CH375_A0=1; //命令模式
  32. DATA_PORT=cmd;        //输出命令码
  33. CH375_WR=0; //打开写使能
  34. delay(DELAYTIME); //稍作延时
  35. CH375_WR=1; //关闭写使能
  36. CH375_CS=1; //关闭片选
  37. CH375_A0=1; //恢复A0为高电平
  38. delay(DELAYTIME); //稍作延时
  39. }

  40. /******************************************************************
  41. - 功能描述:向CH375写入数据
  42. - 隶属模块:CH375模块
  43. - 函数属性:内部
  44. - 参数说明:dat:是要写入到CH375中的一个字节的数据
  45. - 返回说明:无返回
  46. ******************************************************************/

  47. void CH375_Write_Dat(unsigned char dat)        //写数据
  48. {
  49. delay(DELAYTIME); //稍作延时
  50. CH375_CS=0; //打开片选
  51. CH375_A0=0; //数据模式
  52. DATA_PORT=dat;        //输出数据
  53. CH375_WR=0; //打开写使能
  54. delay(DELAYTIME); //稍作延时
  55. CH375_WR=1; //关闭写使能
  56. CH375_CS=1; //关闭片选
  57. CH375_A0=1; //恢复A0为高电平
  58. delay(DELAYTIME);  //稍作延时
  59. }

  60. /******************************************************************
  61. - 功能描述:从CH375读取一个字节
  62. - 隶属模块:CH375模块
  63. - 函数属性:内部
  64. - 参数说明:无
  65. - 返回说明:读到的字节
  66. ******************************************************************/

  67. unsigned char CH375_Read_Dat() //读数据
  68. {
  69. unsigned char temp;
  70. CH375_CS=0; //打开片选
  71. CH375_A0=0; //数据模式
  72. CH375_RD=0; //打开读使能
  73. DATA_PORT=0xff; //51单片机IO作输入,先置高
  74. delay(DELAYTIME); //稍作延时
  75. temp=DATA_PORT; //读取端口上的数据
  76. CH375_RD=1;  //关闭读使能
  77. CH375_CS=1;  //关闭片选
  78. CH375_A0=1;  //恢复A0为高电平
  79. return temp; //返回读到的值
  80. }

  81. /******************************************************************
  82. - 功能描述:等待CH375的中断,并获取中断状态
  83. - 隶属模块:CH375模块
  84. - 函数属性:内部
  85. - 参数说明:无
  86. - 返回说明:中断状态码 返回0说明操作成功
  87. ******************************************************************/

  88. unsigned char CH375_Wait_Int() //等待中断信号,即INT引脚上产生低电平,并获取中断状态码,获取后INT恢复高电平,以产生下一次中断信号
  89. {
  90. CH375_INT=1;  //IO作输入先置高
  91. while(CH375_INT); //等待中断
  92. CH375_Write_Cmd(CMD_GET_STATUS); //产生操作完成中断,获取中断状态
  93. return CH375_Read_Dat();
  94. }

  95. /******************************************************************
  96. - 功能描述:初始化CH375芯片
  97. - 隶属模块:CH375模块
  98. - 函数属性:外部,供用户调用
  99. - 参数说明:无
  100. - 返回说明:执行结果
  101. ******************************************************************/

  102. unsigned char CH375_Init()
  103. {
  104. unsigned char i=0;
  105. CH375_Write_Cmd(CMD_GET_IC_VER);  /* 获取芯片及固件版本 */
  106. i=CH375_Read_Dat();  /* 版本 */
  107. if(i<0xA2) return 1;  /* 不支持该芯片 */

  108. CH375_Write_Cmd(CMD_SET_USB_MODE);  /* 设置USB工作模式 */
  109. CH375_Write_Dat(6);  /* 模式代码,自动检测USB设备连接 */

  110. for(i=0;i<250;i++)
  111. {  /* 等待操作成功,通常需要等待10uS-20uS */
  112.   delay(10);
  113.   if(CH375_Read_Dat()==CMD_RET_SUCCESS )
  114.    return 0;  /* 操作成功 */
  115. }

  116. return 1;  /* CH375出错,例如芯片型号错或者处于串口方式或者不支持 */
  117. }


  118. /******************************************************************
  119. - 功能描述:初始化磁盘
  120. - 隶属模块:CH375模块
  121. - 函数属性:外部,供用户调用
  122. - 参数说明:无
  123. - 返回说明:操作结果,0表示初始化磁盘成功
  124.                        1表示初始化磁盘失败
  125. - 注:在使用U盘之前,先要调用此函数,此函数将进行判断
  126.             磁盘是否连接,初始化是否成功等操作
  127. ******************************************************************/

  128. unsigned char CH375_InitDisk()
  129. {
  130. unsigned char status,i,j=0;

  131. status=CH375_Wait_Int();
  132. if(status==USB_INT_DISCONNECT) return 1;  /* USB设备断开 */

  133. while(1)
  134. {
  135.   CH375_Write_Cmd(CMD_DISK_INIT);  /* 初始化USB存储器 */
  136.   status=CH375_Wait_Int();             /* 等待中断并获取状态 */
  137.   if(status==USB_INT_SUCCESS)
  138.    break;
  139. }

  140. while(1)         //以下代码均源自沁恒的官方U盘初始化函数,借用它可以提高对U盘的兼容性!
  141. {   
  142.   j++;
  143.   CH375_Write_Cmd(CMD_DISK_SIZE);  /* 获取USB存储器的容量 */
  144.   status=CH375_Wait_Int();             /* 等待中断并获取状态 */
  145.   if(status==USB_INT_SUCCESS)
  146.    break;
  147.   else
  148.   {
  149.    delay(1000);
  150.    CH375_Write_Cmd(CMD_DISK_R_SENSE); /* 获取USB存储器的容量 */
  151.    status=CH375_Wait_Int();                 /* 等待中断并获取状态 */
  152.    if(status==USB_INT_SUCCESS)            /* 出现错误 */
  153.         continue;
  154.    else
  155.     return 1;
  156.   }
  157.   if(j==5)
  158.    return 1;
  159. }
  160. for(i=0;i!=5;i++)
  161. {
  162.   CH375_Write_Cmd( CMD_DISK_READY );     /* 获取USB存储器的容量 */
  163.   status=CH375_Wait_Int();                 /* 等待中断并获取状态 */
  164.   if(status==USB_INT_SUCCESS)
  165.    return 0;                           /* U盘已经成功初始化 */
  166. }
  167. return 1;
  168. }

  169. /******************************************************************
  170. - 功能描述:读取U盘的扇区
  171. - 隶属模块:CH375模块
  172. - 函数属性:外部,供用户调用
  173. - 参数说明:addr:扇区地址
  174.              pbuf:指向数据缓冲区的指针
  175. - 返回说明:返回操作结果,如果为0说明操作成功,
  176.                            如果为1说明操作失败
  177. ******************************************************************/

  178. unsigned char CH375_Read_Sector(unsigned long addr,unsigned char *pBuf)
  179. {
  180. unsigned char i=0,j=0,k=0;
  181. unsigned char status,len;
  182. unsigned int counter=0;
  183. for(k=0;k<4;k++)
  184. {
  185.   counter=0;
  186.   CH375_Write_Cmd(CMD_DISK_READ);//磁盘读取命令
  187.   CH375_Write_Dat(addr);
  188.   CH375_Write_Dat(addr>>8);
  189.   CH375_Write_Dat(addr>>16);
  190.   CH375_Write_Dat(addr>>24); //送入32位扇区地址
  191.   CH375_Write_Dat(1); //送入扇区数

  192.   for(i=0;i<8;i++)         //CH375的数据缓冲区为64字节,所以读取一个扇区要读8次
  193.   {
  194.    status=CH375_Wait_Int();        //等待CH375中断信号,读取状态码
  195.    if(status==USB_INT_DISK_READ)        //如果状态码是USB_INT_DISK_READ,就开始读取数据,否则发生错误
  196.    {
  197.     CH375_Write_Cmd(CMD_RD_USB_DATA); //送入读数据的命令
  198.     delay(4);
  199.     len=CH375_Read_Dat(); //先读到的是数据的长度
  200.     do         //把随后CH375送过来的数据放入pBuf中
  201.     {
  202.      pBuf[counter++]=CH375_Read_Dat();
  203.     }while(--len);
  204.     CH375_Write_Cmd(CMD_DISK_RD_GO);        //送入继续读数据的命令,CH375会将下面64个字节放入缓冲区,等待单片机来读
  205.    }
  206.    else
  207.    {
  208.     return 1; //发生错误,返回状态码
  209.    }
  210.   }

  211.   status=CH375_Wait_Int(); //读取8次以后,最后一次送入继续读数据的命令,等待CH375产生中断信号,并读取状态
  212.   if(status==USB_INT_SUCCESS) //如果状态码为USB_INT_SUCCESS,说明读取扇区成功,返回0
  213.   {
  214.    return 0;
  215.   }
  216.   else
  217.    if(status==USB_INT_DISK_ERR )
  218.    {
  219.     delay(1000);
  220.     CH375_Write_Cmd(CMD_DISK_R_SENSE); /* 获取USB存储器的容量 */
  221.     status=CH375_Wait_Int();                 /* 等待中断并获取状态 */
  222.     if(status!=USB_INT_SUCCESS)            /* 出现错误 */
  223.     return 1;
  224.    }
  225. }
  226. }

  227. /******************************************************************
  228. - 功能描述:写U盘的扇区
  229. - 隶属模块:CH375模块
  230. - 函数属性:外部,供用户调用
  231. - 参数说明:addr:扇区地址
  232.              pbuf:指向数据缓冲区的指针
  233. - 返回说明:返回操作结果,如果为0说明操作成功,
  234.                            如果为1说明操作失败
  235. ******************************************************************/

  236. unsigned char CH375_Write_Sector(unsigned long addr,unsigned char *pBuf)
  237. {
  238. unsigned char i=0;
  239. unsigned char status,len;
  240. CH375_Write_Cmd(CMD_DISK_WRITE);//磁盘写 命令
  241. CH375_Write_Dat(addr);
  242. CH375_Write_Dat(addr>>8);
  243. CH375_Write_Dat(addr>>16);
  244. CH375_Write_Dat(addr>>24);        //写入32位的扇区地址,先送低字节
  245. CH375_Write_Dat(1); //送入扇区数

  246. for(i=0;i<8;i++)
  247. {
  248.   status=CH375_Wait_Int();
  249.   if(status==USB_INT_DISK_WRITE)
  250.   {
  251.    CH375_Write_Cmd(CMD_WR_USB_DATA7);
  252.    len=64;
  253.    CH375_Write_Dat(len);
  254.    do
  255.    {
  256.     CH375_Write_Dat(*pBuf);
  257.         pBuf++;
  258.    }while(--len);
  259.    CH375_Write_Cmd(CMD_DISK_WR_GO);
  260.   }
  261.   else
  262.   {
  263.    return 1;
  264.   }
  265. }
  266. status=CH375_Wait_Int();
  267. if(status==USB_INT_SUCCESS) //如果状态码为USB_INT_SUCCESS,说明写扇区成功,返回0
  268. {
  269.   return 0;
  270. }
  271. else
  272. {
  273.   return 1;  
  274. }
  275. }
复制代码

全部资料51hei下载地址:
U盘例程+电路图.rar (2.05 MB, 下载次数: 397)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏16 分享淘帖 顶1 踩
回复

使用道具 举报

来自 2#
ID:709781 发表于 2020-9-18 20:21 | 只看该作者
大家好,在CH375写数据到U盘,如何实现将字符串和变化的时间值写入U盘中,比如说字符串是“当前时间值为:”,变化的时间为小时、分钟和秒,即写入U盘例子为:  当前时间值为:  12:30:15,请指点下,在此先谢谢了
回复

使用道具 举报

板凳
ID:497810 发表于 2019-9-5 12:38 | 只看该作者
下载下来 学习一下!
回复

使用道具 举报

地板
ID:72951 发表于 2019-9-18 11:06 | 只看该作者
谢谢分享,学习USB了
回复

使用道具 举报

5#
ID:138119 发表于 2019-9-18 21:59 | 只看该作者
不错,学习好资料!
回复

使用道具 举报

6#
ID:111376 发表于 2019-9-19 08:46 | 只看该作者
谢谢分享,学习了!
回复

使用道具 举报

7#
ID:511456 发表于 2019-10-10 10:09 | 只看该作者
这个例程非常好,可以用于对设备数据的读写中,实用性强
回复

使用道具 举报

8#
ID:611525 发表于 2019-11-5 15:25 | 只看该作者

这个例程非常好,可以用于对设备数据的读写中,实用性强
回复

使用道具 举报

9#
ID:321614 发表于 2019-11-6 20:43 | 只看该作者
可以,学习中,这个例程很好
回复

使用道具 举报

10#
ID:279058 发表于 2019-11-19 15:04 | 只看该作者
这个可以用znfat操作U盘吗?
回复

使用道具 举报

11#
ID:130230 发表于 2019-12-2 11:40 | 只看该作者
666有视频讲解不
回复

使用道具 举报

12#
ID:527324 发表于 2020-3-29 10:23 来自手机 | 只看该作者
今天下载不少好东西了。没黑币了赶紧去赚点
回复

使用道具 举报

13#
ID:240901 发表于 2020-6-3 16:09 | 只看该作者

谢谢分享,学习USB了
回复

使用道具 举报

14#
ID:858595 发表于 2020-12-11 11:29 来自手机 | 只看该作者
这个用连接单片机实验箱
回复

使用道具 举报

15#
ID:907595 发表于 2021-4-17 22:29 来自手机 | 只看该作者
滴,请问这个能制作出来实物吗
回复

使用道具 举报

16#
ID:749848 发表于 2021-4-20 00:34 | 只看该作者
i不知道如何制作成品
回复

使用道具 举报

17#
ID:927526 发表于 2021-5-26 20:22 | 只看该作者
谢谢分享,学习USB了
回复

使用道具 举报

18#
ID:967573 发表于 2021-9-22 20:17 | 只看该作者
谢谢分享,学习USB了
回复

使用道具 举报

19#
ID:983266 发表于 2021-12-6 10:30 | 只看该作者
这个确实是好东西,有时间,多研究看看,现在我是用TF卡的SPI模式写数据的,后面用这个方法试试
回复

使用道具 举报

20#
ID:804869 发表于 2022-3-4 10:57 | 只看该作者
用我们这边的说法就是,大佬
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表