受到linux对一切设备的控制都当成文件对待的启发
于是便有了这个将GPIO映射到U盘中的想法,这样一来便可以在任何支持U盘的设备中扩展系统的硬件功能了
我的QQ是243786753,这属于原创作品,作为一个对单片机一窍不通的人从设想到实现成功付出了巨大的努力,
最初的设想是通过openwrt路由器远程控制一个开关,然而找遍整个网络都没有这样的东西,
所以只好花了两百元巨款买了整套的单片机实验套件,从51逐步调试成功,转载请注明出处,举手之劳,本文首发于CSDN和数码之家,20160809
在openwrt路由器中可以用这样的方法来控制路由器的led
echo 1 > /sys/devices/platform/leds-gpio/leds/tp-link:green:lan1/brightness   //亮
echo 0 > /sys/devices/platform/leds-gpio/leds/tp-link:green:lan1/brightness   //灭

遗憾的是,由于系统的原因,并不是所有led灯都能得到控制

实验环境:
win7 32位、Keil uVision4、Putty、FlyMcu
硬件:stm32f103c8t6 8M晶振、PL2303 USB转串口
代码修改:
参考资料: 5分钟用STM32的内置Flash做一个超小U盘  http://blog.sina.com.cn/s/blog_ae3f6c0f01017nyf.html
ST的官方网站的UM0424中有一个关于使用STM32做Mass Storage的例子,实现的第一步自然是要先实现利用内置Flash做一个超小U盘
之后的U盘GPIO正是在此基础上修改而来的
从ST官网下载UM0424 ,en.stsw-stm32121.zip解压后是STM32_USB-FS-Device_Lib_V4.0.0

这个库中没有任何关于文件系统的代码,(QQ:243786753原创作品,转载请注明出处)即文件系统的实现都是由操作系统完成的,这个库中只需要对操作系统发过来的读取与写入命令负责即可。
库中的mass_mal.c为文件系统与存储介质的访问接口(Medium Access Layer interface),负责将文件存储在实际的介质上,如NAND-Flash,SD卡等
我们需要把文件存储在STM32的内部Flash中,因此更改这里的接口即可
mass_mal提供了四个函数
u16 MAL_Init (u8 lun);  //初始化介质,由于是内部Flash,为了能写入,只需Unlock FLASH

u16 MAL_GetStatus (u8 lun);  //读取介质的参数,页大小,总页数,以及总大小,这个视STM32的内Flash情况而定,为文件系统format介质提供依据

u16 MAL_Read(u8 lun, u32 Memory_Offset, u32 *Readbuff, u16 Transfer_Length);  //读取介质上的一块区域

u16 MAL_Write(u8 lun, u32 Memory_Offset, u32 *Writebuff, u16 Transfer_Length); // 写入介质上的一块区域

读写操作的Memory_Offset是从零偏移开始的,用作U盘的STM32内部Flash需要从代码之后开始

原作都说编译结束后代码在0x0800252B,取mini U盘开始地址为0x08003000
STM32F103C8T6,Flash为64K,还剩余52K即0xD000,每一页为1K
根据以上信息,(QQ:243786753原创作品,转载请注明出处)打开STM32_USB-FS-Device_Lib_V4.0.0\Projects\Mass_Storage\src\mass_mal.c

添加FLASH的定义:

#define     FLASH_START_ADDR        0x08008800    // Flash起始地址,为了保留更多的代码空间,这个地址比原文更靠后
#define     FLASH_SIZE              30*1024       // 30K 大小,因为起始地址改了,所以这里也相应的改了
#define     FLASH_PAGE_SIZE         1024          // 1K per page
#define     FLASH_WAIT_TIMEOUT      100000

将原有的四个函数清空,改成下面的样子:
uint16_t MAL_Init(uint8_t lun)
{
    FLASH_Unlock();
    return lun == 0 ? MAL_OK : MAL_FAIL;
}
uint16_t MAL_Write(uint8_t lun, uint32_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length)
{
  if(lun == 0){
     uint16_t i;

         for( i=0; i<Transfer_Length;i+=FLASH_PAGE_SIZE){
           if(FLASH_WaitForLastOperation(FLASH_WAIT_TIMEOUT)!=FLASH_TIMEOUT){
             FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
           }
           FLASH_ErasePage(FLASH_START_ADDR + Memory_Offset + i);
         }
         for(i=0;i<Transfer_Length;i+=4){
           if(FLASH_WaitForLastOperation(FLASH_WAIT_TIMEOUT)!=FLASH_TIMEOUT){
             FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
           }
           FLASH_ProgramWord(FLASH_START_ADDR + Memory_Offset + i , Writebuff[i>>2]);
         }
     
     return MAL_OK;
   }
   return MAL_FAIL;
}
uint16_t MAL_Read(uint8_t lun, uint32_t Memory_Offset, uint32_t *Readbuff, uint16_t Transfer_Length)
{
   uint16_t i;
   if(lun == 0){
     for(i=0;i<Transfer_Length;i+=4){
       Readbuff[i>>2] = ((vu32*)(FLASH_START_ADDR + Memory_Offset))[i>>2];
     }
     return MAL_OK;
   }
   return MAL_FAIL;
}
uint16_t MAL_GetStatus (uint8_t lun)
{
  if(lun == 0){
     Mass_Block_Count[0] = FLASH_SIZE/FLASH_PAGE_SIZE;
     Mass_Block_Size[0] =  FLASH_PAGE_SIZE;
     Mass_Memory_Size[0] = FLASH_SIZE;
     return MAL_OK;
   }
   return MAL_FAIL;
}

改好了之后文件的存储目标就变成了STM32的内部Flash

实际还有一个问题,那就是在memory.c中Data_Buffer定义大小为512Bytes,这里我们的Flash是1K一页,要将Data_Buffer重新定义成1KBytes的
第49行uint32_t Data_Buffer[BULK_MAX_PACKET_SIZE * 2]; 改成下面

uint32_t Data_Buffer[BULK_MAX_PACKET_SIZE * 4];

编译好后烧到板子上,电脑会提示格式化磁盘,(QQ:243786753原创作品,转载请注明出处)格式化后就可以像一般的U盘那样使用这个mini U盘了

编译:
用Keil作开发环境,所以直接打开STM32_USB-FS-Device_Lib_V4.0.0\Projects\Mass_Storage\MDK-ARM\MassStorageSimpleBuffer.uvproj
因为是新下载的源码编译前需要配置(Doc/readme.txt有详细说明)
readme.txt中说要打开platform_config.h文件中的一个宏定义
果然有注释掉的宏定义,可是应该打开哪个呢?我用的是stm32f103c8t6芯片,直接搜stm32f103c8t6找不到
整个文件中只有一条stm32f10x.h
观察这里的结果,于是决定将#define USE_STM3210B_EVAL的注释去掉
另外还得:
找到STM32F103C8
修改项目配置生成hex文件,否则我们拿什么下载到芯片上去呢?

此时就可以顺利的编译了,编译结果在STM32_USB-FS-Device_Lib_V4.0.0\Projects\Mass_Storage\MDK-ARM\STM3210B-EVAL

下载到单片机:

这里我用的是ISP下载方式,你也可以用其它方式下载,只要能下载到单片机上就行

选择相应的端口,打开程序文件,点击读器件信息然后按住板子上的ispk再按一下rstk读到信息后松开
最后点击开始编程,编程完毕后就可以连接电脑了,此时一个利用内置FLASH的超小U盘就做成了
这里用的是普中的ARM核心板(STM32F103C8T6)
接单片机的TXD1和RXD1就是PA9和PA10
连接电脑:
原理图(D+D-接在单片机的PA11和PA12上,D+也就是PA12需要接1.5K电阻到3.3V否则电脑无法识别,R1,R2可以取22欧电阻如果没有可以忽略)

STM32F103C8T6是3.3V的单片机,不能接5V的电压,好在核心板上自带了1117进行降压。所以直接这样接就行了

需要飞一个1.5K电阻!(很重要,否则无法工作):

连接电脑,提示格式化,格式化后就会出现一个35K的U盘

为什么单独拿出核心板来用?因为核心板放在普中的主板上接线电脑是无法识别的,主板上的电路是这样的:

到这里,U盘已经实现了,怎么通过文件来控制GPIO呢?
这里给出一个点亮led灯的例子(通过PA0)
还是在mass_mal.c文件中加入
#define RCC_LED   RCC_APB2Periph_GPIOA   
#define GPIO_LED  GPIOA
#define PIN_LED   GPIO_Pin_0
#define LED_ON()    GPIO_SetBits(GPIO_LED, PIN_LED);
#define LED_OFF()   GPIO_ResetBits(GPIO_LED, PIN_LED);
void LED_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = PIN_LED;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    RCC_APB2PeriphClockCmd(RCC_LED, ENABLE);//打开LED使用的GPIO的时钟使能(QQ:243786753原创作品,转载请注明出处)
    GPIO_Init(GPIO_LED, &GPIO_InitStructure);   //初始化相应的GPIO
}

在MAL_Init()函数中调用LED_Init()初始化,然后修改MAL_Write()函数如下
/*
查看参数
            lun     不知道什么意思
  Memory_Offset     偏移地址(FLASH的地址)
      Writebuff     写入的内容
Transfer_Length     内容的长度
*/
uint16_t MAL_Write(uint8_t lun, uint32_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length)
{
  if(lun == 0){
     uint16_t i,qq243786753;
     uint32_t data=Writebuff[0]; 
       
     if(data==0x30303030){ //前四个字符0
       LED_OFF();
     }else if(data==0x31313131){//前四个字符1
       LED_ON();
     }else{
         /*
         实际写入FLASH的代码,从中可行看出来首先会将内容清除,是以页的形式清除
         由此可以推断文件系统的最小单位是页(传说中的扇区?),读和写都是一次性操作一页的内容
         然后是写入操作,每次写4个字节,直到全部写完
         */
         for( i=0; i<Transfer_Length;i+=FLASH_PAGE_SIZE){
           if(FLASH_WaitForLastOperation(FLASH_WAIT_TIMEOUT)!=FLASH_TIMEOUT){
             FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
           }
           FLASH_ErasePage(FLASH_START_ADDR + Memory_Offset + i);
         }
         for(i=0;i<Transfer_Length;i+=4){
           if(FLASH_WaitForLastOperation(FLASH_WAIT_TIMEOUT)!=FLASH_TIMEOUT){
             FLASH_ClearFlag(FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
           }
           FLASH_ProgramWord(FLASH_START_ADDR + Memory_Offset + i , Writebuff[i>>2]);
         }
     }
     return MAL_OK;
   }
   return MAL_FAIL;
}

改好之后重新编译,下载,插电脑,格式化。
此时新建一个文件,往文件里写1111,led就会亮起,写0000,led就会熄灭
代码里是以直接判断内容来进行控制的,这样做的好处是不用考虑哪个文件控制哪个io,
对任何一个文件的读写都可以捕捉到,只需要对写入的内容进行处理就可以了,比如控制PA是文件的前几个字节,控制PB是文件的后几个字节。。。
这里给出的只是往单片机发送数据,获取数据的方法是相同的原理
需要注意的地方:
1.因为单片机内部的FLASH是有擦写次数限制的,超过一定次数芯片就会损坏,安卓手机、固态硬盘、U盘等这类使用FLASH的都有一定的擦写次数限制,所以需要以特别的方式在建立好文件系统后彻底关闭对FLASH的写入
2.这种控制IO的方式速度并不高,但是用来控制开关,采集少量数据是完全可以的,这种方式极大的简化了各系统之间的差异。使得在任何支持U盘的系统上能够以非常简单的方式增加硬件功能。如果需要更快的控制速度可以使用串口通信的形式
3.由于操作系统为了提高效率,文件系统是有缓存的,也就是说对文件的读写并不会立即写到物理磁盘上
root@OpenWrt:/mnt# ls
GPIO.txt
root@OpenWrt:/mnt# echo "1111" > ./GPIO.txt            #并不会立即点亮LED
root@OpenWrt:/mnt# sync         #强制写入磁盘,此时对IO的操作就成功了
root@OpenWrt:/mnt# echo "0000" > ./GPIO.txt
root@OpenWrt:/mnt# sync
root@OpenWrt:/mnt# cat GPIO.txt           #被缓存了,按照我们的U盘实现,是不可能写到磁盘里的
0000
root@OpenWrt:/mnt# echo 1 > /proc/sys/vm/drop_caches    #释放页缓存
root@OpenWrt:/mnt# cat GPIO.txt
.....root@OpenWrt:/mnt#       #此时文件已经重新从磁盘里读取了,因为往U盘写入0000和1111会被我们的程序拦截,
                              #内容不会写到FLASH(但是文件的长度、时间这些会写入),所以重新读磁盘不可能读到0000或1111,读到的是FLASH上的默认数据(0xff)
本文的例子程序下载http://download.csdn.net/detail/zengming00/9599328

U盘GPIO文件系统映射-STM32利用内置FLASH做U盘相关推荐

  1. 用STM32的内置DAC制作一个波形生成器(发生器)

    社团作业=_= 任务一:波形生成.1.使用STM32的DAC功能,生成0~10kHz的方波,频率精确到1%以内: 2.能够生成三角波.正弦波: 3.实现频率设置,可以实现一定步进数的调节,最高为100 ...

  2. 【Unity】3.1 利用内置的3D对象创建三维模型

    分类:Unity.C#.VS2015 创建日期:2016-04-02 一.基本概念 Unity已经内置了一些基本的3D对象,利用这些内置的3D对象就可以直接构建出各种3D模型(当然,复杂的三维模型还需 ...

  3. 带内部参考电压(VREFINT)校正的STM32 DMA 内置温度采集

    笔者今天来介绍一下STM32ADC内置温度的采集,重点是通过内置参考电压来避免ADC参考电压VDDA对温度ADC采集的影响. 1.STM32ADC简介   stm32F4系列ADC,逐次趋近型AD.1 ...

  4. BK7256,Wi-Fi6音视频soc-combo芯片,上海博通-内置Flash,支持720P

    BK7256,拥有以下强大的资源及应用,带有低功耗,RGB驱屏-4寸以上,内置FLASH,可保活长连接. BK7258,支持h.264视频压缩格式,mipi显示接口,200w像素,Wi-Fi6音视频s ...

  5. BK7256,上海博通-音视频Wi-Fi6combo-soc,内置Flash,RGB屏驱\720P

    BK7256,拥有以下强大的资源及应用,支持低功耗,RGB驱屏-4寸以上,内置FLASH.8M-PSRAM -可保活长连接,智能门锁.猫眼.门铃- 高度集成音视频外设和接口- › 720p 25fps ...

  6. 版权原因,QQ不再内置flash插件,需安装二个插件

    QQ不再内置flash插件 需安装二个插件

  7. CC2640之OAD固件升级(内置Flash)

    转自:http://blog.csdn.net/zzfenglin/article/details/52336612 什么是OAD OAD是TI在BLE协议栈基础上扩展的一种无线更新技术.OAD使用客 ...

  8. 1x pcie 速度_利用起闲置的PCIe 1x空间:PCIe 1x的SATA扩展卡,内置2.5寸盘位

    拼 命 加 载 中 ... 随着M.2接口逐渐占据主流,很多主流级主板都不会像以前那样给上8个SATA接口了,而且在M.2接口被占用时还可能会关闭掉几个SATA接口,这让有较多SATA存储设备的用户比 ...

  9. 03pe修改计算机名称,[U盘PE教程]玩转PE内置注册表(基于NT6.0)

    玩转PE内置注册表(基于NT6.0) 1.让文件夹显示中等图标 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\_default\So ...

最新文章

  1. 在用安全框架前,我想先让你手撸一个登陆认证
  2. 人工智能到来的时代,你曾经瞧不起的职业,可能会非常吃香!
  3. 北京邮电大学c语言按要求输出_C语言经典100例004-统计各个年龄阶段的人数
  4. 2018.08.09洛谷P3959 宝藏(随机化贪心)
  5. 复现原文(一):Single-cell RNA sequencing of human kidney(step by step)
  6. 80C51汇编语言有哪几条常用伪指令,单片微机原理与接口技术答案(宋跃版)
  7. 你需要知道的基础算法知识——STL和基础数据结构(一)
  8. Vue3动态组件、缓存组件、分发组件
  9. k近邻算法matlab实现_k近邻算法
  10. breakall lisp文件_breakall.lsp下载
  11. Vue3.0中文文档(Vue3 + TS学习资源路线)
  12. “减糖”迫在眉睫,“代糖”或成最佳考量?
  13. 行业步入快速发展期,万亿级“虚拟蛋糕“将被如何瓜分?
  14. python中namedtuple的用法
  15. Nacos 注册中心
  16. 大家在人生低谷时有多惨,怎么熬过来的(五)
  17. 小程序插件接入、开发与注意事项
  18. Flash 与课件制作:加载图片
  19. Java HTML转成PDF
  20. 安装SSL证书遇到困难怎么办?

热门文章

  1. 微信小程序使用高德地图Web服务爬取企业数据
  2. PMP笔记 第9章 项目资源管理
  3. 琅琊领航联盟|TK联盟首期私享会圆满结束
  4. Linux capstone 反汇编引擎使用方法
  5. 拜托,不用记密码真的超酷好吗?
  6. 素描风格图片 彩色转素描python pillow库
  7. CDH6.2.1CM6.2.1版本部署操作文档
  8. Shiro中Session过期页面跳转回登录页面处理问题
  9. 华泰人工智能系列之一人工智能选股框架及经典算法简介
  10. Linux下C++编程基础