天狼的学习与思考 https://bbs.21ic.com/?540120 [收藏] [复制] [RSS] 记录我学习过程中的点点滴滴

日志

STM32 & 电子书 数码相框

已有 2591 次阅读2010-5-13 13:34 |系统分类:ARM| stm32, 电子书, 数码相框

这几天一直在搞电子书和数码相框。取得了一点小小成绩。在这分享一下。


txt文档和图片存在sd卡里,翻阅的时候通过 文件系统访问sd卡,从里边读出数据。先前的sd卡读写函数用的是sdio模式,速度是很快的,这次我尝试了spi模式(考虑到可以用到8位机上),参考了一些前人的程序,做了很多地方的修改,最后的效果很稳定,速度测试: 读达到了120kbyte per sec


写 23kbyte per sec。


    做电子书 当然要上 文件系统,我上次移植了fatfs0.07e这次刚好能用上,再根据上次的方式做了移植,然后在ffconfg.h里选择codepage 为 936  #define _CODE_PAGE 936 接下来 在disk io.c 里#include "cc936.c"  这样就支持中文文件名了。网上很多人都以为fatfs0.07e不支持中文文件名,其实这样做 就能让它支持了。只不过cc936.c"占用很大的程序空间 有将近200k的 flash 都会被占用。当然对于小容量的片子这就是致命伤,这时我们可以考虑把这个文件放到外扩的eeprm里然后修改下 文件系统里查表的函数,不光是这个表 想中文字库 这样耗程序空间的东东 都可以放到外部存储器里。


   电子书要用到滚屏,我在写lcd底层驱动的时候就开始研究ili9325如何能实现滚屏,可惜ili9325的0x6a这个寄存器和0x61寄存器所描述的滚屏 只能实现一次滚,第2次滚的的时候就失效了,再把滚屏禁止 原来的数据又回来了,弄了好久 滚屏这块我还是没弄懂。最后我只能每次翻一页,每次重新刷数据。还有一个问题是这样的,翻页问题。因为一个文档里可以有英文、汉字、特殊符号(ascii里 小于32的那些)这样一屏显示多少数据是不固定的,有可能是540 也有可能是530 或者更少,所以每次翻页文件指针移动的多少都不固定。向下翻页的时候很简单,只要记录上一屏给lcd上显示了几个数据,然后下翻的时候只要把文件指针向后移动多少就行了。但向上翻页时怎么办?必须要知道 上上一屏的数据是从哪个文件指针开始读的,这就要做记录。我开了一个20 长度的unsigned long型数据来存储当然这只能支持向上翻18页,其实这块完全可以根据要读的txt文档的大小来计算出最坏情况下需要的数据长度,然后用malloc动态分配出这么长的内存单元来做记录(这要保证 启动代码里分配了足够大的heap,因为malloc申请的内存来源于堆)。最后我加上了按键动作,我的这个电子书就这么完成了。


    做完了电子书,我本来是想玩玩mp3 播放的,vs1003的驱动都写好了,焊好硬件 兴冲冲的去做 vs1003的正弦测试,发现 DREQ这个脚一直为低,程序根本走不下去。一阵排查,硬件没有问题啊,再goole 百度 了大半天,最后只能怀疑我的vs1003 挂了,因为我用的烙铁很破,可能焊接的时候vs1003 被静电整挂了。无奈 mp3 暂时是玩不了了。


    数码相框这块 bmp的显示速度还可以,但是jpg的解码速度很慢,除了很慢之外,还有别的问题,到现在 我还没完全搞定。


下面附上 电子书的 那段程序:


/*-------------------------------------------------------------------------*/
#define FN_BuffLen  541
#define Per_Len         20
/*-------------------------------------------------------------------------*/



/*-------------------------------------------------------------------------*/


 


/*---------------------------------------------------------------------------
功能:   


  down键长按 下一个文件
  down键短按 下一屏
  up键短按   上一屏
---------------------------------------------------------------------------*/
FRESULT Ebook_View(char* path)
{    //      路径        格式     此格式的有多少个
    FRESULT res;
    FILINFO fno;
 FIL F ;
 FATFS fs;
    DIR dir;
    u32 i, j, z;
 vu8 fs_type_copy = 0; 
 UINT bytesWritten = 0;//从这个可看出文件读完了没 或从 FIL.fsize
    char *fn;
 u8 *pdata;
 u8 databuf[FN_BuffLen]= {0};//存储读出来的数据
 
 u8 Point = 0;
 u32 File_Dptr[Per_Len] = {0};//存储上一屏数据指针值,向上翻页时用到
                              //Per_Len-1值决定可以向上翻多少页  
 


#if _USE_LFN  //为 长文件名区指针赋初值
    static char lfn[_MAX_LFN * (_DF1S ? 2 : 1) + 1];
    fno.lfname = lfn;
    fno.lfsize = sizeof(lfn);
#endif


 //每次 open一个对象时都先要注册一个缓冲区
 res =f_mount(0, &fs);
 // 打开指定的目录
    res = f_opendir(&dir, path);
    if (res == FR_OK) {
    for (;;)
 {
repet:           
 //第一次执行读一个文件,第二次执行读第二个文件………………
 res = f_readdir(&dir, &fno);//读出目录里的 文件信息 存入 fno
 fs_type_copy = dir.fs->fs_type;


    if (res != FR_OK || fno.fname[0] == 0) break;
#if _USE_LFN
 {
 fn = *fno.lfname ? fno.lfname : fno.fname; 
 j = *fno.lfname ? (fno.lfsize-1): (8+1+3 -1);
 }   
#else
    {
 fn = fno.fname; j=8+1+3 -1; 
 }
#endif


   for(i = j; i >= 3; i--) //文件名 从右到左判断 当文件扩展名为 XXX时成立
   {
             if ((*(fn+i-2) == 't')&&(*(fn+i-1) == 'x')&&(*(fn+i) == 't'))
    {
  
       //成功检测到相符的文件了
           
    //lcd开个矩形框显示文件名  xxxx…………txt
    lcd_fill_rect(2, 2, 32, 236, yellow);
    lcd_text_color(black);
    lcd_back_color(yellow);
   
    lcd_display(8, 5, (u8 *)fn);
     
    memcpy(databuf, "ebook/", 6);
    memcpy(&databuf[6], fn, j+1);
    fn = databuf; 
    *(fn+i+1+6)='\0';//为文件名添加字符串结束符 



    lcd_text_color(red);
    lcd_back_color(cyan);
    //开始显示 文件内容
    z = 0;//文件定位
       res = f_open (&F, fn, FA_OPEN_EXISTING | FA_WRITE | FA_READ);
    memset(databuf, 0, FN_BuffLen); 
    Point = 0;
/*--------------------------------------------*/
                 for (;;)
     {
     next:


      if (Point > Per_Len)
      { //数组被写满了
       for (j = 0; j < Per_Len-1; j++)
       {
        //数据向左移,新数据放到数组最后一个元素
        File_Dptr[j] = File_Dptr[j+1];
       }
       File_Dptr[Per_Len-1] = z;
      }
      else
      {
       File_Dptr[Point] = z;//每一屏数据的起始地址进行存储
       Point += 1;
      }


 


         i = 32; j = 0;//记行列
      res = f_lseek (&F, z);
      res = f_read(&F, databuf, FN_BuffLen, &bytesWritten);//读出541个数据
      if (bytesWritten == FN_BuffLen)
      {
      pdata = databuf;
  
      while(*pdata) 
      {
        if (*pdata < 128)
        {
         if (*pdata < 32)//回车
         {
          *pdata = ' ';
         }
         lcd_display_char(i, j, *pdata);
         j += 8;
         pdata += 1;
         z += 1;
         }
        else
        {
         lcd_display_hzchar(i, j, pdata);
           j += 16;
         pdata += 2; 
         z +=2;          
        }


        if ((j > 224)&&(*pdata > 128)&& (j!=240))//防止一行的最后半字
        {
         lcd_display_char(i, j, ' ');//清边界残留
         j = 240 ;
        }


        if (j >= 240)
        {
         j = 0;
         i += 16; //一行写满了,换行
         if (i >= 320)
         {
          i = 0; //整屏写满了


          //动态停机 等待按键
          while (1)
          {
           event = read_fifo();
           switch (event)
           {
            case  key_up_s:
              
              if (Point >=2) //
              {
               Point -= 2;
               z = File_Dptr[Point];
                  memset(databuf, 0, FN_BuffLen);
               goto next;//显示上一屏数据
              }
              else
              {
               break;
              }


            case  key_down_s:


              memset(databuf, 0, FN_BuffLen);
              goto next; //显示下一屏数据


            case  key_down_l://浏览下一个文件


              //memset(databuf, 0, FN_BuffLen);
              goto repet;
           
           }
          }
         }
         
         }
         }


       }
       else  //文件快结束了这是一个文件的最后
       {
       pdata = databuf;
       //后面补空格,以清掉上页留下的数据
       memset(&databuf[bytesWritten], ' ', FN_BuffLen-bytesWritten-1 );


       while(*pdata) 
       {
        if (*pdata < 128)
        {
         if (*pdata < 32)//回车
         {
          *pdata = ' ';
         }
         lcd_display_char(i, j, *pdata);
         j += 8;
         pdata += 1;
         z += 1;
         }
        else
        {
         lcd_display_hzchar(i, j, pdata);
           j += 16;
         pdata += 2; 
         z +=2;        
         }


        if ((j > 224) && (*pdata > 128))//防止一行的最后半字
        {
         lcd_display_char(i, j, ' ');//清边界残留
         j = 240 ;
        }


        if (j >= 240)
        {
         j = 0;
         i += 16; //一行写满了,换行
        }
          }      
          //动态停机 等待按键
          while (1)
          {
           event = read_fifo();
           switch (event)
           {
            case  key_up_s:
              
              if (Point >=2) //
              {
               Point -= 2;
               z = File_Dptr[Point];
               memset(databuf, 0, FN_BuffLen);
               goto next;
              }
              else
              {
               break;
              }


            case  key_down_l:


              //memset(databuf, 0, FN_BuffLen);
              goto repet;
             }
            }


       }     


       }
/*--------------------------------------------*/
      dir.fs->fs_type=fs_type_copy; 
//打开文件时,dir.fs->fs_type被改动了,所以下一次打开目录时要恢复dir.fs->fs_type
    goto repet;
    }    
   }
  goto repet;
  }
    }
    return res;
}


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)