STM32F429的外接nandflash当作U盘实现数据记录功能
2017-06-06 10:34
459 查看
目录
目录功能需求
主要功能
485数据采集
NANDFlash模拟成U盘
读写Fatfs
具体实现
遇到的问题
功能需求
实现数据采集记录的功能。需要每一秒将数据记录一次,并且实现24小时循环记录的功能。如果电脑插上USB_SLAVE口,就可以直接将采集到的数据拷贝出来。在上位机上进行数据的管理。主要功能
1.485数据采集
项目主要利用485进行数据采集,每接收到一个完整的一帧数据,就可以解包并进行CRC校验,只要校验通过即可认为这一条数据是有效的。可以进行数据记录。2.NANDFlash模拟成U盘
这里需要利用fatfs+ftl将NANDFlash映射成Windows系统可直接识别的FAT32模式,该模式下文件系统可直接被识别,FTL可以很好的对NANDFlash进行管理,实现坏区标记等功能。最后再通过移植USB,这样就可以直接被电脑所识别。3.读写Fatfs
由于前面两个功能网上都有大量的例子,本人就不必赘言。这里主要叙述开发过程中对Fatfs操作过程中遇到的种种错误以及自己思考的解决办法。具体实现
其实在操作Fatfs过程中,刚开始一直没有弄清楚究竟操作的是什么,其实这里直接可以将操作的对象当成一个文件即可。操作过程中,先打开文件void ProcessBuffer485(u8* bInbuff) { //memset(databuffer, 0, sizeof(databuffer)); switch(bInbuff[0]) { case DATPKG: //如果满足07 数据 bInbuff++; memcpy((u8 *)&statePkg, bInbuff, sizeof(STAT_PKG)); //如果两个时间一致,就跳出执行,将这一帧数据丢弃 if(statePkg.timesec==lastsec) { return; } lastsec=statePkg.timesec; //时间 year = statePkg.YMDHM >> 20; month = (statePkg.YMDHM >> 16) &0x0F; day = (statePkg.YMDHM >>11) & 0x1F; hour = (statePkg.YMDHM >> 6) & 0x1F; minute = statePkg.YMDHM & 0x3F; if(reload==0) { z=0; lastfilelen=0; firststate=0; reload=1; } //如果文件刚开始,写完一条数据 if((z==0)&&(lastfilelen==0)&&(firststate==0)) { firststate=1; p = sprintf( databuffer, "id\t YMDHM\t lamps\t engSpeed\t engOilPress\t engWaterTemp\t trainSpeed\t RunKM\t bat24_V\t bat24_A\t engWorkTime\t Soft_Version\n"); p += sprintf( databuffer+p, "%6d\t %4d-%2d-%2d %2d:%2d:%2d\t %10d\t %5d\t %5d\t %5d\t %5d\t %10d\t %5d\t %5d\t %6d\t %34d\n", z,year,month,day,hour,minute, statePkg.timesec,statePkg.lamps,statePkg.engSpeed, statePkg.engOilPress, statePkg.engWaterTemp, statePkg.trainSpeed, statePkg.RunKM, statePkg.bat24_V, statePkg.bat24_A, statePkg.engWorkTime,statePkg.Soft_Version); z++; //让计数加一 break; //此时返回databuffer的数据一共是256字节 } //第1条数据 //if((z==1)&&(lastfilelen==0)) //{ // p += sprintf( databuffer + p, "%6d\t %4d-%2d-%2d %2d:%2d:%2d\t %10d\t %5d\t %5d\t %5d\t %5d\t %10d\t %5d\t %5d\t %6d\t %24d\n", z,year,month,day,hour,minute,statePkg.timesec, statePkg.lamps,statePkg.engSpeed, statePkg.engOilPress, statePkg.engWaterTemp, statePkg.trainSpeed, statePkg.RunKM, statePkg.bat24_V, statePkg.bat24_A, statePkg.engWorkTime,statePkg.Soft_Version); // return; // } //在字节里又增加128字节 p += sprintf( databuffer + p, "%6d\t %4d-%2d-%2d %2d:%2d:%2d\t %10d\t %5d\t %5d\t %5d\t %5d\t %10d\t %5d\t %5d\t %6d\t %24d\n", z,year,month,day,hour,minute,statePkg.timesec, statePkg.lamps,statePkg.engSpeed, statePkg.engOilPress, statePkg.engWaterTemp, statePkg.trainSpeed, statePkg.RunKM, statePkg.bat24_V, statePkg.bat24_A, statePkg.en 4000 gWorkTime,statePkg.Soft_Version); if(z==1) { z++; //此时还差一条到达512字节 break; }else if(z==2){ //在这一条数据之后满足512字节了 p=0; } if(lastfilelen>0) { //表示已经有数据保存了 if(z==0) { z = lastfilelen+1; } } if(z>2) { if((z-2)%4!=0) { z++; break; }else{ p=0; } } if(z>=180002) { reload=0; } /* if(z>=180002) { reload=0; } */ NAND_FlashFatfsDemo("2:/1.xls",databuffer,512); z++; memset(databuffer, 0, sizeof(databuffer));//数组每次使用完,都要进行清空操作 break; default: break; } }
读写操作
/* ******************************************************************************************************** 函数名称:NAND_FlashFatfsDemo 函数功能: 测试 nand flash 读写功能,带 fatfs 文件管理系统操作 参数: 无 返回值: 无 ******************************************************************************************************** */ void NAND_FlashFatfsDemo(const TCHAR* path,const void* buff,int len) { uint8_t res; //打开之前改变文件权限 //如果是只读模式,那么打开文件的标识是不会生效的,也就是不能打开文件 //res = f_chmod(path,AM_ARC,AM_ARC|AM_RDO); res = f_open(myfile, path, FA_OPEN_ALWAYS | FA_WRITE); //打开文件,已经满足512字节了 f_sync(myfile); // delay_ms(10); //延时10ms if(FR_OK!=res) { //如果文件没有打开成功,直接退出 return; } //数据第一次被建立 offset=((z-1)/4)*512; res = f_lseek(myfile,offset); //delay_ms(20); //开始写数据 res=f_write(myfile,buff,512,&bw); //f_sync(myfile); //delay_ms(20); if(FR_OK!=res||bw==0) { z--; z--; z--; z--; f_close(myfile); return; } //关闭数据文件 f_close(myfile); delay_ms(50); //开始写计数文件 res = f_open(ftemp, "2:/number.txt", FA_CREATE_ALWAYS | FA_WRITE | FA_READ); //打开文件 f_sync(ftemp); // delay_ms(10); if(EOF==f_printf(ftemp,"%6d",z)) { // delay_ms(10); f_close(ftemp); //测试,如果写入失败的情况 //res = f_open(ftemp, "2:/err.txt", FA_CREATE_ALWAYS | FA_WRITE | FA_READ); //打开文件 // delay_ms(10); // f_close(ftemp); return; } //f_putc(z,myfile); f_close(ftemp); delay_ms(10); }
主要的思路是先将数据收集到512字节,然后一次性向文件里面写。当写完后,则开始写编号,这里的编号用来表示下一次重新开始的文件偏移位置。如果通过读取文件大小来操作文件的指针,就没有办法实现循环复写的功能了。所以只能思考采用两个文件来实现,一个专门写数据,另外一个专门计数。当上电时,则可以计数文件的数值。只用操作文件指针偏移到相应的位置,即可修改文件了。
遇到的问题
在操作过程中,刚开始写的数据不对,有点时候读出数据都是乱码。这里一般都是文件的偏移地址算的不对。在写完一条数据后,如果想让数据接着写,不覆盖之前的数据,首先就是文件的打开方式采用 FA_OPEN_ALWAYS,其次就是要将文件指针f_lseek移到该条数据结尾。不可移动太多了,如果移动太多,很可能会出现已经删除了的数据。这样就不对了。第二个问题就是插上USB,windows系统会提示驱动有问题,是否修复U盘,很有可能是文件写完数据后,还没来得及关闭数据,当没有调用f_close或者f_sync时,数据是没有的。所以有的时候会发现明明f_write写了数据,但是有的时候却没有数据的情况。还可能出现FAT表损坏的情况。其实这个问题很常见,有的时候一断电,数据文件正在写或者还没来得及关闭,都有可能发生。
第三个问题就是断电数据保存的问题。本人在网上找了大量的资料,没有发现合适的HAL库版本的掉电中断的文章,这里来进行一下简单的操作
void MyPVD_Init(void) { PWR_PVDTypeDef pvd; __HAL_RCC_PWR_CLK_ENABLE();//使能电源时钟PWR pvd.PVDLevel=PWR_CR_PLS_LEV7; pvd.Mode=PWR_PVD_MODE_IT_RISING; // HAL_PWR_DeInit(); HAL_PWR_ConfigPVD(&pvd); HAL_PWR_EnablePVD(); //LED1=!LED1; //__HAL_PWR_PVD_EXTI_ENABLE_IT(); HAL_NVIC_SetPriority(PVD_IRQn,0x00,0x02); //抢占优先级1,子优先级2 HAL_NVIC_EnableIRQ(PVD_IRQn); } //产生中断! void PVD_IRQHandler() { //LED1=0; HAL_PWR_PVD_IRQHandler(); } //产生中断后的回掉函数 void HAL_PWR_PVDCallback(void) { LED1=0; }
经过以上的配置,可以进入到中断里。这里用LED灯可以看到发光一下。但是仅靠这个中断想要实现数据的保存还是不够的,需要断电后电压维持一段时间,这段时间内足够操作nandflash。
相关文章推荐
- iOS开发:一个高仿美团的团购ipad客户端的设计和实现(功能:根据拼音进行检索并展示数据,离线缓存团购数据,浏览记录与收藏记录的批量删除等)
- 用多态实现模拟电脑-硬盘-U盘-MP3读写数据的功能
- 实现从“环信”下载聊天记录,显示在本地项目页面的功能(三)—— 将解析后的数据保存到本地DB中
- 利用ASP实现Oracle数据记录的分页显示
- 用xmlhttp将html的数据打包成multipart/form-data格式,实现异步上传文件功能[转]
- 实现GridView控件的删除多条记录功能系列(2)
- 利用接口灵活实现Excel导入/到出数据功能
- 用xmlhttp将html的数据打包成multipart/form-data格式,实现异步上传文件功能
- JQuery简便实现页面元素数据验证功能
- extremetable+hibernate实现分页 关于结合hibernate后台数据分页和eXtremeTable分页功能的使用
- AjaxPro.NET实现TextBox智能获取服务端数据功能(Asp.net 2.0)(示例代码下载)
- 如何用VS里的部署实现在Duwamish7安装时的自动创建数据功能
- 如何在VS.NET/C# Builder开发的网页中也能实现DOS下录入数据回车换行的功能
- 利用JQuery方便实现基于Ajax的数据查询、排序和分页功能
- AjaxPro.NET实现TextBox智能获取服务端数据功能(Asp.net 2.0)(示例代码下载)
- 用最愚蠢的方法实现了CVC 数据同步功能...
- 使用Session记录页面地址和实现页面返回功能
- 用Swing实现数据表格功能
- 实现GridView控件的删除多条记录功能系列(1)
- 实现多个WEB页面要接收同一个表单的数据的功能