本帖最后由 y909334873 于 2016-9-5 11:03 编辑
刚开始学习文件系统,给单片机移植了fat文件系统,出现了这样一个问题,我创建了一个文本文件(比如说是y.txt),然后给这个文本文件写入一段文本,通过电脑查看SD卡里的内容,显示这个文本文件(y.txt)显示还是0字节;
同时连接是会出现修复U盘的提示。也就是说往文本文件里写数据没有成功。
但是如果我通过电脑给这个文本文件写一句话,保存后是这样的
接下来我在通过单片机给这个文件进行写数据,那么我写的数据量不能超过这个文本文件的13字节,不超过的部分,可以通过电脑正常显示,也可以通过单片机读文件操作。超过的部分通过电脑查看,或者单片机读文件操作读是不成功看不到的
此帖出自
小平头技术问答
修改了
- void Test_f_write(void)//写数据到文件,如果没有此文件则创建文件
- {
- FATFS fs; // Work area (file system object) for logical drive
- FRESULT res; // FatFs function common result code
- FIL Make_file;
- char file_name[20]="jj.txt";
- char Storage_buffer[] ="1234567890";
- UINT bw;
- //检测磁盘是否插好
- if( disk_detect_OK()==FALSE ) return;
- logout("
inaert_ok:>");
- // Register a work area for logical drive 0
- f_mount(0, &fs);
- logout("
Make file Name:>");
- // USART_Scanf_Name(file_name);//通过串口输入源文件路径名/dir/file.txt或者0:dir/file.txt或者0:/dir/file.txt
- res = f_open(&Make_file, file_name, FA_OPEN_ALWAYS | FA_WRITE); //可写方式打开 没有文件则创建
- logout("
open_ok:>");
- die(res);
- res = f_lseek(&Make_file, bsize); //指针移到文件最后
- logout("
seek_ok:>");
- die(res);
- res = f_write(&Make_file, Storage_buffer, (sizeof (Storage_buffer))-1 , &bw); //每次需要写入的数据字节数,去掉最后的 所以-1
- logout("
write_ok:>");
- die(res);
- //logout("文件大小=%d字节
",Make_file.fsize);
- res = f_lseek(&Make_file, Make_file.fsize); //指针移到文件最后
- //logout("文件大小=%d字节
",Make_file.fsize);
- f_close(&Make_file);//关闭文件
- logout("
close_ok:>");
- //logout("文件大小=%d字节
",Make_file.fsize);
- logout("
写文件测试OK!
");
- // Unregister a work area before discard it
- f_mount(0, NULL);
- }
- //其中调用的f_wriite函数如下
- FRESULT f_write (
- FIL *fp, /* Pointer to the file object */
- const void *buff, /* Pointer to the data to be written */
- UINT btw, /* Number of bytes to write */
- UINT *bw /* Pointer to number of bytes written */
- )
- {
- FRESULT res;
- DWORD clst, sect;
- UINT wcnt, cc;
- const BYTE *wbuff = buff;
-
- BYTE csect;
- bsize+=btw;
- *bw = 0; /* Initialize byte counter */
- logout("1111111111111111111
");
- res = validate(fp->fs, fp->id); /* Check validity */
- fp->fsize =fp->fsize +btw;
- logout("wenjian=%d
",fp->fsize);
- //f_sync (fp);
- if (res != FR_OK) LEAVE_FF(fp->fs, res);
- if (fp->flag & FA__ERROR) /* Aborted file? */
- LEAVE_FF(fp->fs, FR_INT_ERR);
- logout("22222222222222222222222222
");
- if (!(fp->flag & FA_WRITE)) /* Check access mode */
- LEAVE_FF(fp->fs, FR_DENIED);
- if ((DWORD)(fp->fsize + btw) < fp->fsize) btw = 0; /* File size cannot reach 4GB */
- logout("333333333333333333333333
");
- for ( ; btw; /* Repeat until all data written */
- wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
- logout("44444444444444444
");
- if ((fp->fptr % SS(fp->fs)) == 0)
- { /* On the sector boundary? */
-
- csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
- if (!csect)
- {
- /* On the cluster boundary? */
- if (fp->fptr == 0) { /* On the top of the file? */
- clst = fp->sclust; /* Follow from the origin */
- if (clst == 0) /* When no cluster is allocated, */
- fp->sclust = clst = create_chain(fp->fs, 0); /* Create a new cluster chain */
- } else { /* Middle or end of the file */
- #if _USE_FASTSEEK
- if (fp->cltbl)
- clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
- else
- #endif
-
- clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */
- }
- if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
- if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
-
- if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
- fp->clust = clst; /* Update current cluster */
- //fp->pad1 = 0;
- }
-
- #if _FS_TINY
- if (fp->fs->winsect == fp->dsect && move_window(fp->fs, 0)) /* Write-back sector cache */
- ABORT(fp->fs, FR_DISK_ERR);
- #else
- if (fp->flag & FA__DIRTY) { /* Write-back sector cache */
- if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- fp->flag &= ~FA__DIRTY;
- }
- #endif
- sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
- if (!sect) ABORT(fp->fs, FR_INT_ERR);
- sect += csect;
- cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
- if (cc) { /* Write maximum contiguous sectors directly */
- if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
- cc = fp->fs->csize - csect;
- if (disk_write(fp->fs->drv, wbuff, sect, (BYTE)cc) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- #if _FS_TINY
- if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
- mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
- //logout("tiny");
- fp->fs->wflag = 0;
- }
- #else
- if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
- mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
- //logout("no tiny");
- fp->flag &= ~FA__DIRTY;
- }
- #endif
- wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
- continue;
- }
- #if _FS_TINY
- if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */
- if (move_window(fp->fs, 0)) ABORT(fp->fs, FR_DISK_ERR);
- fp->fs->winsect = sect;
- }
- #else
- if (fp->dsect != sect) { /* Fill sector cache with file data */
- if (fp->fptr < fp->fsize &&
- disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
- ABORT(fp->fs, FR_DISK_ERR);
- }
- #endif
- fp->dsect = sect;
- }
- logout("555555555555555555
");
- wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
- if (wcnt > btw) wcnt = btw;
- #if _FS_TINY
- if (move_window(fp->fs, fp->dsect)) /* Move sector window */
- ABORT(fp->fs, FR_DISK_ERR);
- mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
- fp->fs->wflag = 1;
- #else
- mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
- fp->flag |= FA__DIRTY;
- #endif
- }
- if (fp->fptr > fp->fsize)
- fp->fsize = fp->fptr; /* Update file size if needed */
- fp->flag |= FA__WRITTEN; /* Set file change flag */
- LEAVE_FF(fp->fs, FR_OK);
- }
- //感觉涉及的函数有点多,不知道该贴些啥。。。
复制代码贴了一段代码不知道能不能看出些什么问题
- void SD_LowLevel_DeInit(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
-
- SPI_Cmd(SD_SPI, DISABLE); /*!< SD_SPI disable */
- SPI_DeInit(SD_SPI); /*!< DeInitializes the SD_SPI */
-
- /*!< SD_SPI Periph clock disable */
- RCC_APB1PeriphClockCmd(SD_SPI_CLK, DISABLE);
- /*!< Configure SD_SPI pins: SCK */
- GPIO_InitStructure.GPIO_Pin = SD_SPI_SCK_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(SD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
- /*!< Configure SD_SPI pins: MISO */
- GPIO_InitStructure.GPIO_Pin = SD_SPI_MISO_PIN;
- GPIO_Init(SD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
- /*!< Configure SD_SPI pins: MOSI */
- GPIO_InitStructure.GPIO_Pin = SD_SPI_MOSI_PIN;
- GPIO_Init(SD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
- /*!< Configure SD_SPI_CS_PIN pin: SD Card CS pin */
- GPIO_InitStructure.GPIO_Pin = SD_CS_PIN;
- GPIO_Init(SD_CS_GPIO_PORT, &GPIO_InitStructure);
- /*!< Configure SD_SPI_DETECT_PIN pin: SD Card detect pin */
- // GPIO_InitStructure.GPIO_Pin = SD_DETECT_PIN;
- // GPIO_Init(SD_DETECT_GPIO_PORT, &GPIO_InitStructure);
- }
复制代码SPI初始化,应该没有什么问题,sd卡 的读文件,创建文件,和删除文件功能都是正常的- SD_Error SD_Init(void)
- {
- uint32_t i = 0;
- uint8_t r1 = 0;
- uint16_t retry = 0;
- uint8_t buf[4];
- //SPI_InitTypeDef SPI_InitStructure;
- //logout("sd init
");
- /*!< Initialize SD_SPI */
- for(i=0;i<0xf00;i++);
- //logout("SD_LowLevel_Init done
");
- /*!< SD chip select high */
-
- SPI2_SetSpeed(SPI_BaudRatePrescaler_256);
- /*!< Send dummy byte 0xFF, 10 times with CS high */
- /*!< Rise CS and MOSI for 80 clocks cycles */
- for(i=0;i<10;i++)SD_ReadWriteByte(0XFF);//发送最少74个脉冲
- retry=20;
- do
- {
- r1 = SD_SendCmd1(SD_CMD_GO_IDLE_STATE,0,0x95);//进入IDLE状态
- }while((r1!=0X01) && retry--);
- //logout("SD_idle_pass
");
- //logout("R1 = %d
",r1);
- SD_Type=0;//默认无卡
-
- if(r1==0X01)
- {
- //logout("1111");
- if(SD_SendCmd1(SD_CMD_SEND_IF_COND,0x1AA,0x87)==1)//SD V2.0
- {
- for(i=0;i<4;i++)buf[i]=SD_ReadWriteByte(0XFF); //Get trailing return value of R7 resp
- if(buf[2]==0X01&&buf[3]==0XAA)//卡是否支持2.7~3.6V
- {
- retry=0XFFFE;
- do
- {
- SD_SendCmd1(55,0,0X01); //发送CMD55
- r1=SD_SendCmd1(41,0x40000000,0X01);//发送CMD41
- }while(r1&&retry--);
- if(retry&&SD_SendCmd1(58,0,0X01)==0)//鉴别SD2.0卡版本开始
- {
- for(i=0;i<4;i++)buf[i]=SD_ReadWriteByte(0XFF);//得到OCR值
- if(buf[0]&0x40)SD_Type=SD_TYPE_V2HC; //检查CCS
- else SD_Type=SD_TYPE_V2;
- }
- }
- }
- else//SD V1.x/ MMC V3
- {
- //logout("222");
- SD_SendCmd1(55,0,0X01); //发送CMD55
- r1=SD_SendCmd1(41,0,0X01); //发送CMD41
- if(r1<=1)
- {
- SD_Type=SD_TYPE_V1;
- retry=0XFFFE;
- do //等待退出IDLE模式
- {
- SD_SendCmd1(55,0,0X01); //发送CMD55
- r1=SD_SendCmd1(41,0,0X01);//发送CMD41
- }while(r1&&retry--);
- }else//MMC卡不支持CMD55+CMD41识别
- {
- SD_Type=SD_TYPE_MMC;//MMC V3
- logout("MMC");
- retry=0XFFFE;
- do //等待退出IDLE模式
- {
- r1=SD_SendCmd1(1,0,0X01);//发送CMD1
- }while(r1&&retry--);
- }
- if(retry==0||SD_SendCmd1(16,512,0X01)!=0)SD_Type=SD_TYPE_ERR,logout("fau");//错误的卡
- }
- }
- SD_DisSelect();//取消片选
- SPI2_SetSpeed(SPI_BaudRatePrescaler_2);
- if(SD_Type)
- {
- //logout("0");
- return 0;
- }
- else if(r1)
- {
- logout("R1 = %d
",r1);
- return r1;
- }
-
- }
复制代码SD卡 的初始化仿照f103的写的
- uint8_t SD_SendCmd1(uint8_t cmd, uint32_t arg, uint8_t crc)
- {
- uint8_t r1;
- uint8_t Retry=0;
- SD_DisSelect();//取消上次片选
- if(SD_Select())return 0XFF;//片选失效
- //发送
- SD_ReadWriteByte(cmd | 0x40);//分别写入命令
- SD_ReadWriteByte(arg >> 24);
- SD_ReadWriteByte(arg >> 16);
- SD_ReadWriteByte(arg >> 8);
- SD_ReadWriteByte(arg);
- SD_ReadWriteByte(crc);
- if(cmd==SD_CMD_STOP_TRANSMISSION)SD_ReadWriteByte(0xff);//Skip a stuff byte when stop reading
- //等待响应,或超时退出
- Retry=0X1F;
- do
- {
- r1=SD_ReadWriteByte(0xff);
- }while((r1&0X80) && Retry--);
- //返回状态值
- return r1;
- }
- ///////////////////////////////////////////////////////////////////////////////////
- //取消选择,释放SPI总线
- void SD_DisSelect(void)
- {
- SD_CS_HIGH();
- SD_ReadWriteByte(0xff);//提供额外的8个时钟
- }
- //选择sd卡,并且等待卡准备OK
- //返回值:0,成功;1,失败;
- uint8_t SD_Select(void)
- {
- SD_CS_LOW();
- if(SD_WaitReady()==0)return 0;//等待成功
- SD_DisSelect();
- return 1;//等待失败
- }
- //等待卡准备好
- //返回值:0,准备好了;其他,错误代码
- uint8_t SD_WaitReady(void)
- {
- uint32_t t=0;
- do
- {
- if(SD_ReadWriteByte(0XFF)==0XFF)return 0;//OK
- t++;
- }while(t<0XFFFFFF);//等待
- return 1;
- }
- uint32_t SD_GetSectorCount(void)
- {
- uint8_t csd[16];
- uint32_t Capacity;
- uint8_t n;
- uint16_t csize;
- //取CSD信息,如果期间出错,返回0
- if(SD_GetCSD(csd)!=0)
- {
- logout("csd fail
");
- return 0;
- }
- //如果为SDHC卡,按照下面方式计算
- if((csd[0]&0xC0)==0x40) //V2.00的卡
- {
- csize = csd[9] + ((uint16_t)csd[8] << 8) + 1;
- Capacity = (uint32_t)csize << 10;//得到扇区数
- }else//V1.XX的卡
- {
- n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
- csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 3) << 10) + 1;
- Capacity= (uint32_t)csize << (n - 9);//得到扇区数
- }
- return Capacity;
- }
- //获取SD卡的CSD信息,包括容量和速度信息
- //输入:uint8_t *cid_data(存放CID的内存,至少16Byte)
- //返回值:0:NO_ERR
- // 1:错误
- uint8_t SD_GetCSD(uint8_t *csd_data)
- {
- uint8_t r1;
- logout("gCSD1
");
- r1 = SD_SendCmd1(SD_CMD_SEND_CSD,0,0x01);//发CMD9命令,读CSD
- logout("gCSD2
");
- if(r1==0)
- {
- r1= SD_RecvData(csd_data, 16);//接收16个字节的数据
- }
- SD_DisSelect();//取消片选
- if(r1)return 1;
- else return 0;
- }
- //从sd卡读取一个数据包的内容
- //buf:数据缓存区
- //len:要读取的数据长度.
- //返回值:0,成功;其他,失败;
- uint8_t SD_RecvData(uint8_t *buf,uint16_t len)
- {
- if(SD_GetResponse(0xFE))return 1;//等待SD卡发回数据起始令牌0xFE
- while(len--)//开始接收数据
- {
- *buf=SD_ReadWriteByte(0xFF);
- buf++;
- }
- //下面是2个伪CRC(dummy CRC)
- SD_ReadWriteByte(0xFF);
- SD_ReadWriteByte(0xFF);
- return 0;//读取成功
- }
- void SPI2_SetSpeed(uint8_t SpeedSet)
- {
- SPI_InitStructure.SPI_BaudRatePrescaler = SpeedSet ;
- SPI_Init(SPI2, &SPI_InitStructure);
- SPI_Cmd(SPI2,ENABLE);
- }
- //读SD卡
- //buf:数据缓存区
- //sector:扇区
- //cnt:扇区数
- //返回值:0,ok;其他,失败.
- uint8_t SD_ReadDisk(uint8_t*buf,uint32_t sector,uint8_t cnt)
- {
- uint8_t r1;
- if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址
- if(cnt==1)
- {
- r1=SD_SendCmd1(SD_CMD_READ_SINGLE_BLOCK,sector,0X01);//读命令
- if(r1==0)//指令发送成功
- {
- r1=SD_RecvData(buf,512);//接收512个字节
- }
- }else
- {
- r1=SD_SendCmd1(SD_CMD_READ_MULT_BLOCK,sector,0X01);//连续读命令
- do
- {
- r1=SD_RecvData(buf,512);//接收512个字节
- buf+=512;
- }while(--cnt && r1==0);
- SD_SendCmd(SD_CMD_STOP_TRANSMISSION,0,0X01); //发送停止命令
- }
- SD_DisSelect();//取消片选
- return r1;//
- }
- //写SD卡
- //buf:数据缓存区
- //sector:起始扇区
- //cnt:扇区数
- //返回值:0,ok;其他,失败.
- uint8_t SD_WriteDisk(const uint8_t*buf,uint32_t sector,uint8_t cnt)
- {
- uint8_t r1;
- if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址
- if(cnt==1)
- {
- r1=SD_SendCmd1(SD_CMD_WRITE_SINGLE_BLOCK,sector,0X01);//读命令
- if(r1==0)//指令发送成功
- {
- r1=SD_SendBlock(buf,0xFE);//写512个字节
- }
- }else
- {
- if(SD_Type!=SD_TYPE_MMC)
- {
- SD_SendCmd1(55,0,0X01);
- SD_SendCmd1(SD_CMD_SET_BLOCK_COUNT,cnt,0X01);//发送指令
- }
- r1=SD_SendCmd1(SD_CMD_WRITE_MULT_BLOCK,sector,0X01);//连续读命令
- if(r1==0)
- {
- do
- {
- r1=SD_SendBlock(buf,0xFC);//接收512个字节
- buf+=512;
- }while(--cnt && r1==0);
- r1=SD_SendBlock(0,0xFD);//接收512个字节
- }
- }
- SD_DisSelect();//取消片选
- return r1;//
- }
- uint8_t SD_SendBlock(const uint8_t *buf,uint8_t cmd)
- {
- uint16_t t;
- if(SD_WaitReady())return 1;//等待准备失效
- SD_ReadWriteByte(cmd);
- if(cmd!=0XFD)//不是结束指令
- {
- for(t=0;t<512;t++)SD_ReadWriteByte(buf[t]);//提高速度,减少函数传参时间
- SD_ReadWriteByte(0xFF);//忽略crc
- SD_ReadWriteByte(0xFF);
- t=SD_ReadWriteByte(0xFF);//接收响应
- if((t&0x1F)!=0x05)return 2;//响应错误
- }
- return 0;//写入成功
- }
复制代码后面的这些也是照着写的
一周热门 更多>