您现在的位置: USB开发网 > USB技术文档 > USB MASS STORAGE
- USB MASS STORAGE

用51单片机的串口读写优盘(U盘)的C语言源码

------分隔线----------------------------

 一、简介

  点评:此文来源于网络,不过仔细研读后发现,这并不是真正意义上的用单片机直接读写优盘的例子,我刚开始看到这个标题也觉得纳闷,我们都知道要读写优盘,必须要单片机系统做成主机模式,由于主机端协议和代码远比设备端复杂,最好在嵌入式系统上跑OS来实现,51单片机由于资源和速度限制,可能做不了这样的事,果不其然,作者其实是用了一块嵌入式模块(基于ARM的嵌入式系统)实现主机功能,再用51与此系统通过串口来通信来实现读写优盘的目的。

  文章原文:

  目前,基于USB接口的移动存储设备已经被广泛使用,尤其是采用USB-FLASH技术的U盘产品几乎完全取代了软盘。

  U盘的使用通常是作为计算机的外部存储设备,能否脱离计算机直接向U盘读写数据呢?答案是肯定的。嵌入式U盘读写模块提供了通过串口读写U盘的简单途径,由此结合单片机的串口就可以实现U盘的文件读写。

  嵌入式U盘读写模块可以嵌入用户的数据采集系统中,从而实现数据的海量存储。在工控领域,军工产品、石油、交通、水文等野外数据采集系统中可以广泛使用。

二、源码

 

  1. /*                                 C51读写优盘程序 
  2. /*                                                                
  3. /************************************************************************************************ 
  4. * 
  5. *  U盘文件读写模块 以字节为单位进行U盘文件读写。10条精简命令完成所有读写过程 
  6. *  MCS-51单片机C语言示例程序  
  7. *  硬件连接方式: 4线制串口(电源,地,输入,输出)  
  8. */ 
  9. #include <REG51RD2.h> 
  10. #include <stdio.h> 
  11. #define uchar unsigned char 
  12. #define uint unsigned int 
  13. //检测u盘命令 
  14. uchar code Detect[66]={0xaa,0xbb, 
  15.                        0x01,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  16.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  17.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  18.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};   
  19. //建立TEST.TXT文件命令 
  20. uchar code Create[66]={0xaa,0xbb, 
  21.                        0x07,0x54,0x45,0x53,0x54,0x20,0x20,0x20,0x20,0x54,0x58,0x54,0x20,0x00,0x00,0x00, 
  22.                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x4F,0xFD,0x32,0x00,0x00,0x00,0x00,0x00, 
  23.                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  24.                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
  25. //打开文件命令 
  26. uchar code  Open[66] ={0xaa,0xbb, 
  27.                        0x06,0x54,0x45,0x53,0x54,0x20,0x20,0x20,0x20,0x54,0x58,0x54,0x00,0x00,0x00,0x00, 
  28.                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  29.                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 
  30.                        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
  31. //写文件命令  
  32. uchar code  Write[66]={0xaa,0xbb, 
  33.                        0x09,0x00,74,0x01,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  34.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  35.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  36.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; 
  37. //读文件命令 
  38. uchar code  Read[66]={0xaa,0xbb, 
  39.                       0x08,0x08,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  40.                       0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  41.                       0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  42.                       0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; 
  43. //设置文件指针命令 
  44. uchar code SetFilePointer[66]=           
  45.                       {0xaa,0xbb, 
  46.                        0x15,0x00,74,0x01,0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  47.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  48.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, 
  49.                        0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}; 
  50. //数据1 
  51. uchar code  Date1[66]={0x30,0x31, 
  52.                        0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32, 
  53.                        0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32,0x33, 
  54.                        0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32,0x33,0x34, 
  55.                        0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32,0x33,0x0d,0x0a}; 
  56. //数据2 
  57. uchar code  Date2[66]={0x30,0x31, 
  58.                        0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32, 
  59.                        0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32,0x33, 
  60.                        0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32,0x33,0x34, 
  61.                        0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x30,0x31,0x32,0x33,0x34,0x35}; 
  62. uchar data num; 
  63. void delay_xms(unsigned int);               //延时函数 
  64. void init_com(void);                        //初始化串口函数 
  65. void test(void);                            //系统测试函数 
  66. void Send_Data(uchar Serial_data);          //发送一个字节函数 
  67. void TXD_Int(uchar *s);                     //发送数据函数 
  68. bit Receive_Data(uchar,uint );              //接收数据函数 
  69. uchar Receive_One(void);                    //接收一个字节函数           
  70. void main() 
  71.     int i,j; 
  72.     SP = 0x60;                              //设置堆栈指针 
  73.     P3 = 0xff; 
  74.     init_com();                             //初始化串口 
  75.     test();                                 //系统测试并延时 
  76.  
  77. det:                                        //检测U盘 
  78.     TXD_Int(Detect); 
  79.  
  80.     if(Receive_Data(0x04,0)==0)         //命令是否成功执行,是则继续执行 
  81.     {                                       //否则重新执行 
  82.         delay_xms(1000); 
  83.         goto det; 
  84.     } 
  85.  
  86.     num=0x41; 
  87. for(j=0;j<20;j++) 
  88. {    
  89.         delay_xms(50); 
  90. crt:                                        //建立文件 
  91.     TXD_Int(Create); 
  92.     if(Receive_Data(0x0a,0)==0)             //命令是否成功执行,是则继续执行 
  93.     {                                       //否则重新执行 
  94.         delay_xms(1000); 
  95.         goto crt; 
  96.     } 
  97.      
  98.  
  99.     delay_xms(100); 
  100. wrt:                                        //写文件 
  101.     TXD_Int(Write); 
  102.     for(i=0;i<5;i++) 
  103.         TXD_Int(Date1); 
  104.      
  105.     if(Receive_Data(0x0c,0)==0)             //命令是否成功执行,是则继续执行 
  106.     {                                       //否则重新执行 
  107.         delay_xms(1000); 
  108.         goto wrt; 
  109.     } 
  110.  
  111.     num++; 
  112.  
  113.     delay_xms(500); 
  114. op:                                         //打开文件 
  115.     TXD_Int(Open); 
  116.     if(Receive_Data(0x0d,0)==0)             //命令是否成功执行,是则继续执行 
  117.     {                                       //否则重新执行 
  118.         delay_xms(1000); 
  119.         goto op; 
  120.     } 
  121. /* 
  122.     delay_xms(500); 
  123.                                             //读文件 
  124.     TXD_Int(Read); 
  125.  
  126.     if(Receive_Data(0x0b,8)==0)             //命令是否成功执行,是则继续执行 
  127.     {                                       //否则重新执行 
  128.         delay_xms(1000); 
  129.         goto op; 
  130.     } 
  131. */ 
  132. /* 
  133.     delay_xms(500); 
  134.                                             //删除文件 
  135. del:TXD_Int(Remove); 
  136.  
  137.     if(Receive_Data(0x21,0)==0)             //命令是否成功执行,是则继续执行 
  138.     {                                       //否则重新执行 
  139.         delay_xms(1000); 
  140.         goto del; 
  141.     } 
  142. */ 
  143.  
  144. sfp: 
  145.     TXD_Int(SetFilePointer);                //移动文件指针 
  146.  
  147.     if(Receive_Data(0x25,0)==0)             //命令是否成功执行,是则继续执行 
  148.     {                                       //否则重新执行 
  149.         delay_xms(1000); 
  150.         goto sfp; 
  151.     } 
  152.     delay_xms(500); 
  153.  
  154. wrt2:                                       //二次写文件 
  155.     TXD_Int(Write); 
  156.     for(i=0;i<5;i++) 
  157.         TXD_Int(Date2); 
  158.      
  159.     if(Receive_Data(0x0c,0)==0)             //命令是否成功执行,是则继续执行 
  160.     {                                       //否则重新执行 
  161.         delay_xms(1000); 
  162.         goto wrt2; 
  163.     } 
  164.  
  165.     P0=0; 
  166.     while(1);                               //循环等待 
  167. /******************************************************************** 
  168.                 CoM口波特率初始化函数  
  169. 原型:init_com();  
  170. 功能:初始化com口 
  171. 入口参数:无  
  172. 出口参数:无  
  173. ********************************************************************/  
  174. void init_com( ) 
  175.          
  176.     TMOD = 0x20;                        //计数1工作在方式2 
  177.     TH1 = 0xfa;                         //晶振频率11.0592mhz,9600时为FAH 
  178.     TH1 = 0xfa;                         //19200时为FDH,57600为FFH 
  179.     PCON = 0x80;                        //SMOD为1 
  180.     SCON = 0x40;                        //串行口工作在方式一  
  181.     TI=1; 
  182.     TR1 = 1;                            //启动计数 
  183.  
  184.  
  185. /******************************************************************** 
  186.                          测试系统 
  187. 功能:使发光二极管闪烁 
  188. 入口参数:无 
  189. 出口参数: 无 
  190. ********************************************************************/ 
  191. void test( ) 
  192.     int a=0; 
  193.     P0 = 0xff;                          //P3口初始化,使发光二极管熄灭    
  194.     while(a<10) 
  195.     {    
  196.         P0 = ~P0;                       //P3.3取反 
  197.         delay_xms(500);                 //延时0.5秒 
  198.         a++; 
  199.     } 
  200.     P3 = 0xff; 
  201.  
  202. /******************************************************************** 
  203.                         延时函数 
  204. 功能:共延时1ms乘以delay_time 
  205. 入口参数:延时delay_time ms 
  206. 出口参数:无 
  207. ********************************************************************/ 
  208. void delay_xms(unsigned int delay_time) 
  209.     unsigned int i,j; 
  210.  
  211.     for(i = 0; i < delay_time; i++) 
  212.     { 
  213.         for(j = 0; j < 250; j++);  
  214.     } 
  215. /******************************************************************** 
  216.                        发送一帧数据函数 
  217. 功能:发送一帧数据 
  218. 入口参数:命令帧首地址,数据个数 
  219. 出口参数:无 
  220. ********************************************************************/ 
  221. void TXD_Int(uchar *s) 
  222.          char i;          
  223.          TI = 0;          
  224.          for(i=0; i<66; i++)           //发送64个参数   
  225.          { 
  226.             if(i==7) 
  227.                 Send_Data(num);  
  228.             else 
  229.                Send_Data(*(s+i));  
  230.          } 
  231.          RI = 0; 
  232.          TI = 0;                      //一帧发送完毕 
  233.  
  234. /******************************************************************** 
  235.                       串口发送一个字节 
  236. 功能:发送一个字节数据 
  237. 入口参数:发送数据 
  238. 出口参数:无 
  239. ********************************************************************/ 
  240. void Send_Data(uchar Serial_data) 
  241.     SBUF = Serial_data;             //发送一个字节 
  242.     while(!TI);                     //等待发送 
  243.     TI = 0;                          
  244. /******************************************************************** 
  245.                          接收应答信号和数据函数 
  246. 功能:接收一个字节通讯 
  247. 入口参数:无 
  248. 出口参数:返回接收值 
  249. ********************************************************************/ 
  250. bit Receive_Data(uchar  rxd,uint num) 
  251.     int i; 
  252.     REN = 1;                        //接收位打开 
  253.     P3_3 = 1; 
  254.     P3_5 = 1; 
  255.     if(Receive_One()== rxd)         //接收的是否是应答码 
  256.     { 
  257.         if(Receive_One() == 0x01)   //是应答码,是否是成功执行 
  258.         { 
  259.          
  260.             for(i=0;i<62;i++)       //成功执行,接收62个保留位 
  261.             { 
  262.                 Receive_One(); 
  263.             } 
  264.             P3_3 = 0;               //指示灯亮 
  265.             P3_5 = 0; 
  266.             if(num!=0)              //是否有数据,有则跳接收部分 
  267.                 goto rev; 
  268.             else return(1);         //无,返回1 
  269.          } 
  270.          else                       //未成功执行 
  271.          { 
  272.             for(i=0;i<62;i++)       //接收62个保留位 
  273.             { 
  274.                 Receive_One(); 
  275.             } 
  276.             P3_3 = 1; 
  277.             P3_5 = 0; 
  278.             return(0);              //返回0 
  279.           } 
  280.     } 
  281.     else                            //收到的不是应答码 
  282.     { 
  283.         for(i=0;i<63;i++)           //接收剩下的63个字节 
  284.         { 
  285.             Receive_One(); 
  286.         } 
  287.         P3_3 = 1; 
  288.         P3_5 = 0; 
  289.         return(0);                  //返回0 
  290.      } 
  291.  
  292. rev: 
  293.     if(num>0)                       //应答信号后有数据 
  294.     { 
  295.         for(i=0;i<num;i++)          //接收数据 
  296.             Receive_One(); 
  297.     } 
  298.     REN = 0;                        //关闭接收位 
  299.     return(1);                      //返回1 
  300. /******************************************************************** 
  301.                          接收一个字节通讯函数 
  302. 功能:接收一个字节通讯 
  303. 入口参数:无 
  304. 出口参数:返回接收值 
  305. ********************************************************************/ 
  306. uchar Receive_One(void
  307.     while(!RI) 
  308.     { 
  309.         P0=0x00;                    //等待接收 
  310.      } 
  311.      P0=0xff; 
  312.     RI = 0; 
  313.     return(SBUF);               //将接收数据返回 
------分隔线----------------------------
联系我们
  • Q Q: 1148374829 点击这里给我发消息
  • 旺旺:jhoneqhsieh 点击这里给我发消息
  • 电话:(0)15923141204
  • 淘宝网店
USB开源项目