目录

一、图片显示部分

GIF

piclib.c介绍

图像显示实验main.c介绍

二、SD卡模块

1、SD卡基础知识

2、SD卡读操作

3、SD卡写操作


一、图片显示部分

GIF

  • GIF(Graphics Interchange Format)的原义是“图像互换格式”,是CompuServe公司在1987年开发的图像文件格式。GIF文件的数据。是一种基于LZW算法的连续色调的无损压缩格式。其压缩率一般在50%左右,它不属于任何应用程序。
  • GIF主要分为两个版本,即GIF 89a和GIF 87a

GIF 87a:是在1987年制定的版本GIF

GIF 89a:是1989年制定的版本。

本质上是动态地显示多个连续的图片

piclib.c介绍

piclib.c中定义了LCD液晶显示需要使用的函数

#include "piclib.h"
#include "lcd.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK MiniSTM32开发板
//图片解码 驱动代码
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2014/3/14
//版本:V2.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
//********************************************************************************
//升级说明
//V2.0
//1,将jpeg解码库换成了TJPGD,支持更多的jpg/jpeg文件,支持小尺寸图片快速jpeg显示
//2,pic_phy里面新增fillcolor函数,用于填充显示,以提高小尺寸jpg图片的显示速度
//3,ai_load_picfile函数,新增一个参数:fast,用于设置是否使能jpeg/jpg快速显示
//注意:这里的小尺寸是指:jpg/jpeg图片尺寸小于等于LCD尺寸.
//_pic_info picinfo;        //图片信息
_pic_phy pic_phy;           //图片显示物理接口
//
//lcd.h没有提供划横线函数,需要自己实现
void piclib_draw_hline(u16 x0,u16 y0,u16 len,u16 color)
{if((len==0)||(x0>lcddev.width)||(y0>lcddev.height))return;LCD_Fill(x0,y0,x0+len-1,y0,color);
}
//填充颜色
//x,y:起始坐标
//width,height:宽度和高度。
//*color:颜色数组
void piclib_fill_color(u16 x,u16 y,u16 width,u16 height,u16 *color)
{  LCD_Color_Fill(x,y,x+width-1,y+height-1,color);
}
//
//画图初始化,在画图之前,必须先调用此函数
//指定画点/读点
void piclib_init(void)
{pic_phy.read_point=LCD_ReadPoint;         //读点函数实现pic_phy.draw_point=LCD_Fast_DrawPoint; //画点函数实现pic_phy.fill=LCD_Fill;                 //填充函数实现pic_phy.draw_hline=piclib_draw_hline;      //画线函数实现pic_phy.fillcolor=piclib_fill_color;   //颜色填充函数实现 picinfo.lcdwidth=lcddev.width;  //得到LCD的宽度像素picinfo.lcdheight=lcddev.height;//得到LCD的高度像素picinfo.ImgWidth=0;   //初始化宽度为0picinfo.ImgHeight=0;//初始化高度为0picinfo.Div_Fac=0;  //初始化缩放系数为0picinfo.S_Height=0; //初始化设定的高度为0picinfo.S_Width=0; //初始化设定的宽度为0picinfo.S_XOFF=0;  //初始化x轴的偏移量为0picinfo.S_YOFF=0; //初始化y轴的偏移量为0picinfo.staticx=0;    //初始化当前显示到的x坐标为0picinfo.staticy=0; //初始化当前显示到的y坐标为0
}
//快速ALPHA BLENDING算法.
//src:源颜色
//dst:目标颜色
//alpha:透明程度(0~32)
//返回值:混合后的颜色.
u16 piclib_alpha_blend(u16 src,u16 dst,u8 alpha)
{u32 src2;u32 dst2;  //Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB|src2=((src<<16)|src)&0x07E0F81F;dst2=((dst<<16)|dst)&0x07E0F81F;   //Perform blending R:G:B with alpha in range 0..32//Note that the reason that alpha may not exceed 32 is that there are only//5bits of space between each R:G:B value, any higher value will overflow//into the next component and deliver ugly result.dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;return (dst2>>16)|dst2;
}
//初始化智能画点
//内部调用
void ai_draw_init(void)
{float temp,temp1;     temp=(float)picinfo.S_Width/picinfo.ImgWidth;temp1=(float)picinfo.S_Height/picinfo.ImgHeight;                       if(temp<temp1)temp1=temp;//取较小的那个   if(temp1>1)temp1=1;      //使图片处于所给区域的中间picinfo.S_XOFF+=(picinfo.S_Width-temp1*picinfo.ImgWidth)/2;picinfo.S_YOFF+=(picinfo.S_Height-temp1*picinfo.ImgHeight)/2;temp1*=8192;//扩大8192倍   picinfo.Div_Fac=temp1;picinfo.staticx=0xffff;picinfo.staticy=0xffff;//放到一个不可能的值上面
}
//判断这个像素是否可以显示
//(x,y) :像素原始坐标
//chg   :功能变量.
//返回值:0,不需要显示.1,需要显示
u8 is_element_ok(u16 x,u16 y,u8 chg)
{                 if(x!=picinfo.staticx||y!=picinfo.staticy){if(chg==1){picinfo.staticx=x;picinfo.staticy=y;} return 1;}else return 0;
}
//智能画图
//FileName:要显示的图片文件  BMP/JPG/JPEG/GIF
//x,y,width,height:坐标及显示区域尺寸
//fast:使能jpeg/jpg小图片(图片尺寸小于等于液晶分辨率)快速解码,0,不使能;1,使能.
//图片在开始和结束的坐标点范围内显示
u8 ai_load_picfile(const u8 *filename,u16 x,u16 y,u16 width,u16 height,u8 fast)
{   u8  res;//返回值u8 temp;   if((x+width)>picinfo.lcdwidth)return PIC_WINDOW_ERR;        //x坐标超范围了.if((y+height)>picinfo.lcdheight)return PIC_WINDOW_ERR;        //y坐标超范围了.  //得到显示方框大小       if(width==0||height==0)return PIC_WINDOW_ERR;  //窗口设定错误picinfo.S_Height=height;picinfo.S_Width=width;//显示区域无效if(picinfo.S_Height==0||picinfo.S_Width==0){picinfo.S_Height=lcddev.height;picinfo.S_Width=lcddev.width;return FALSE;   }if(pic_phy.fillcolor==NULL)fast=0;//颜色填充函数未实现,不能快速显示//显示的开始坐标点picinfo.S_YOFF=y;picinfo.S_XOFF=x;//文件名传递      temp=f_typetell((u8*)filename);   //得到文件的类型switch(temp){                                            case T_BMP:res=stdbmp_decode(filename);              //解码bmp       break;case T_JPG:case T_JPEG:res=jpg_decode(filename,fast);              //解码JPG/JPEG          break;case T_GIF:res=gif_decode(filename,x,y,width,height);  //解码gif       break;default:res=PIC_FORMAT_ERR;                        //非图片格式!!!  break;}                                                return res;
}

_pic_phy是函数指针结构体

typedef struct
{u16(*read_point)(u16,u16);             //u16 read_point(u16 x,u16 y)                       读点函数void(*draw_point)(u16,u16,u16);         //void draw_point(u16 x,u16 y,u16 color)            画点函数void(*fill)(u16,u16,u16,u16,u16);       ///void fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color) 单色填充函数   void(*draw_hline)(u16,u16,u16,u16);        //void draw_hline(u16 x0,u16 y0,u16 len,u16 color)  画水平线函数   void(*fillcolor)(u16,u16,u16,u16,u16*);    //void piclib_fill_color(u16 x,u16 y,u16 width,u16 height,u16 *color) 颜色填充
}_pic_phy; 

ALPHA BLENDING算法是图像透明度处理算法

//快速ALPHA BLENDING算法.
//src:源颜色
//dst:目标颜色
//alpha:透明程度(0~32)
//返回值:混合后的颜色.
u16 piclib_alpha_blend(u16 src,u16 dst,u8 alpha)
{u32 src2;u32 dst2;  //Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB|src2=((src<<16)|src)&0x07E0F81F;dst2=((dst<<16)|dst)&0x07E0F81F;   //Perform blending R:G:B with alpha in range 0..32//Note that the reason that alpha may not exceed 32 is that there are only//5bits of space between each R:G:B value, any higher value will overflow//into the next component and deliver ugly result.dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F;return (dst2>>16)|dst2;
}

is_element_ok主要用于图像压缩显示部分

//判断这个像素是否可以显示
//(x,y) :像素原始坐标
//chg   :功能变量.
//返回值:0,不需要显示.1,需要显示
u8 is_element_ok(u16 x,u16 y,u8 chg)
{                 if(x!=picinfo.staticx||y!=picinfo.staticy){if(chg==1){picinfo.staticx=x;picinfo.staticy=y;} return 1;}else return 0;
}

智能画图函数ai_load_picfile,自动判断文件类型并将文件显示在你所指定的位置上

//智能画图
//FileName:要显示的图片文件  BMP/JPG/JPEG/GIF
//x,y,width,height:坐标及显示区域尺寸
//fast:使能jpeg/jpg小图片(图片尺寸小于等于液晶分辨率)快速解码,0,不使能;1,使能.
//图片在开始和结束的坐标点范围内显示
u8 ai_load_picfile(const u8 *filename,u16 x,u16 y,u16 width,u16 height,u8 fast)
{   u8  res;//返回值u8 temp;   if((x+width)>picinfo.lcdwidth)return PIC_WINDOW_ERR;        //x坐标超范围了.if((y+height)>picinfo.lcdheight)return PIC_WINDOW_ERR;        //y坐标超范围了.  //得到显示方框大小       if(width==0||height==0)return PIC_WINDOW_ERR;  //窗口设定错误picinfo.S_Height=height;picinfo.S_Width=width;//显示区域无效if(picinfo.S_Height==0||picinfo.S_Width==0){picinfo.S_Height=lcddev.height;picinfo.S_Width=lcddev.width;return FALSE;   }if(pic_phy.fillcolor==NULL)fast=0;//颜色填充函数未实现,不能快速显示//显示的开始坐标点picinfo.S_YOFF=y;picinfo.S_XOFF=x;//文件名传递      temp=f_typetell((u8*)filename);   //得到文件的类型switch(temp){                                            case T_BMP:res=stdbmp_decode(filename);              //解码bmp       break;case T_JPG:case T_JPEG:res=jpg_decode(filename,fast);              //解码JPG/JPEG          break;case T_GIF:res=gif_decode(filename,x,y,width,height);  //解码gif       break;default:res=PIC_FORMAT_ERR;                        //非图片格式!!!  break;}                                                return res;
}

图像显示实验main.c介绍

pic_get_tnum函数用来得到path路径下存储目标文件的个数,关键是使用了f_readdir函数。此函数来自于FATFS文件操作系统。

//得到path路径下,目标文件的总个数
//path:路径
//返回值:总有效文件数
u16 pic_get_tnum(u8 *path)
{     u8 res;u16 rval=0;DIR tdir;          //临时目录FILINFO tfileinfo;    //临时文件信息    u8 *fn;                                          res=f_opendir(&tdir,(const TCHAR*)path);  //打开目录tfileinfo.lfsize=_MAX_LFN*2+1;              //长文件名最大长度tfileinfo.lfname=mymalloc(tfileinfo.lfsize);//为长文件缓存区分配内存if(res==FR_OK&&tfileinfo.lfname!=NULL){while(1)//查询总的有效文件数{res=f_readdir(&tdir,&tfileinfo);             //读取目录下的一个文件if(res!=FR_OK||tfileinfo.fname[0]==0)break;  //错误了/到末尾了,退出         fn=(u8*)(*tfileinfo.lfname?tfileinfo.lfname:tfileinfo.fname);             res=f_typetell(fn);   if((res&0XF0)==0X50)//取高四位,看看是不是图片文件  {rval++;//有效文件数增加1}       }  } return rval;
}

dir_sdi函数用来改变当前目录的索引,同样也是来源于ff.c文件

while(res==FR_OK)//打开成功{   dir_sdi(&picdir,picindextbl[curindex]);         //改变当前目录索引     res=f_readdir(&picdir,&picfileinfo);            //读取目录下的一个文件if(res!=FR_OK||picfileinfo.fname[0]==0)break;    //错误了/到末尾了,退出fn=(u8*)(*picfileinfo.lfname?picfileinfo.lfname:picfileinfo.fname);            strcpy((char*)pname,"0:/PICTURE/");              //复制路径(目录)strcat((char*)pname,(const char*)fn);             //将文件名接在后面LCD_Clear(BLACK);ai_load_picfile(pname,0,0,lcddev.width,lcddev.height,1);//显示图片    Show_Str(2,2,240,16,pname,16,1);               //显示图片名字t=0;while(1) {key=KEY_Scan(0);        //扫描按键if(t>250)key=1;           //模拟一次按下KEY0    if((t%20)==0)LED0=!LED0;//LED0闪烁,提示程序正在运行.if(key==KEY1_PRES)       //上一张{if(curindex)curindex--;else curindex=totpicnum-1;break;}else if(key==KEY0_PRES)//下一张{curindex++;         if(curindex>=totpicnum)curindex=0;//到末尾的时候,自动从头开始break;}else if(key==WKUP_PRES){pause=!pause;LED1=!pause;  //暂停的时候LED1亮.  }if(pause==0)t++;delay_ms(10); }                     res=0;  }                                      

二、SD卡模块

1、SD卡基础知识

SD卡 (Secure Digital Memory Card)即:安全数码卡,它是在MMC的基础上发展而来,是一种基于半导体快闪记忆器的新一代记忆设备,它被广泛地于便携式装置上使用,例如数码相机、个人数码助理(PDA)和多媒体播放器等。SD卡由日本松下、东芝及美国SanDisk公司于1999年8月共同开发研制。
SD卡按容量分类,可以分为3类:SD卡、SDHC卡、SDXC卡,如下表所示:

容量

命名

简称

0~2G

Standard Capacity SD Memory Card

SDSC或SD

2G~32G

High Capacity SD Memory Card

SDHC

32G~2T

Extended Capacity SD Memory Card

SDXC

①初始化SPI接口及相关IO。

通过SPI连接SD卡,所以先要初始化MCU的SPI接口,以及相关IO。

②上电延时(>74个CLK)。

③卡复位(CMD0),进入IDLE状态。

发送CMD0时,CS必须为低电平,使得SD卡进入SPI模式。

④发送CMD8,检查是否支持SD卡2.0协议。

⑤根据不同协议检查SD卡(相关命令:CMD55、CMD41、CMD58和CMD1等)。

⑥取消片选,发多8个CLK,结束初始化 。

下图来自《SD卡2.0协议.pdf》这个文档。

下图是MiniSTM插入卡座

正点原子提供了SD卡驱动代码

1.SD_Initialize函数讲解
2.SD_ReadDisk函数讲解
3.SD_WriteDisk函数讲解
4.SD_GetSectorCount函数讲解

SD_Select函数主要用来选定SD卡

//选择sd卡,并且等待卡准备OK
//返回值:0,成功;1,失败;
u8 SD_Select(void)
{SD_CS=0;if(SD_WaitReady()==0)return 0;//等待成功SD_DisSelect();return 1;//等待失败
}

SD_SendCmd命令用来向SD卡发送命令,cmd——8位,arg——32位,crc——8位。

//向SD卡发送一个命令
//输入: u8 cmd   命令
//      u32 arg  命令参数
//      u8 crc   crc校验值
//返回值:SD卡返回的响应
u8 SD_SendCmd(u8 cmd, u32 arg, u8 crc)
{u8 r1; u8 Retry=0; SD_DisSelect();//取消上次片选if(SD_Select())return 0XFF;//片选失效 //发送SD_SPI_ReadWriteByte(cmd | 0x40);//分别写入命令SD_SPI_ReadWriteByte(arg >> 24);SD_SPI_ReadWriteByte(arg >> 16);SD_SPI_ReadWriteByte(arg >> 8);SD_SPI_ReadWriteByte(arg);    SD_SPI_ReadWriteByte(crc); if(cmd==CMD12)SD_SPI_ReadWriteByte(0xff);//Skip a stuff byte when stop reading//等待响应,或超时退出Retry=0X1F;do{r1=SD_SPI_ReadWriteByte(0xFF);}while((r1&0X80) && Retry--);  //返回状态值return r1;
}                                                                       

SD卡的类型也被宏定义后放在了 MMC_SD.h头文件下面

其中SD_TYPE_ERR 表示SD卡类型无效,值为0

// SD卡类型定义
#define SD_TYPE_ERR     0X00
#define SD_TYPE_MMC     0X01
#define SD_TYPE_V1      0X02
#define SD_TYPE_V2      0X04
#define SD_TYPE_V2HC    0X06       

SD卡初始化的时候需要低速模式,正常工作是高速模式。可以设置为4分频。

//SD卡初始化的时候,需要低速
void SD_SPI_SpeedLow(void)
{SPI1_SetSpeed(SPI_BaudRatePrescaler_256);//设置到低速模式
}
//SD卡正常工作的时候,可以高速了
void SD_SPI_SpeedHigh(void)
{SPI1_SetSpeed(SPI_BaudRatePrescaler_2);//设置到高速模式
}

2、SD卡读操作

SD_ReadDisk用来读取数据,cnt=1表示只读取一个扇区,否则是连续读取。

//读SD卡
//buf:数据缓存区
//sector:扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_ReadDisk(u8*buf,u32 sector,u8 cnt)
{u8 r1;if(SD_Type!=SD_TYPE_V2HC)sector <<= 9;//转换为字节地址if(cnt==1){r1=SD_SendCmd(CMD17,sector,0X01);//读命令if(r1==0)//指令发送成功{r1=SD_RecvData(buf,512);//接收512个字节      }}else{r1=SD_SendCmd(CMD18,sector,0X01);//连续读命令do{r1=SD_RecvData(buf,512);//接收512个字节    buf+=512;  }while(--cnt && r1==0);     SD_SendCmd(CMD12,0,0X01);   //发送停止命令}   SD_DisSelect();//取消片选return r1;//
}

if是单块数据块的读取,else是多块的读取。

if(cnt==1)
else{}

多块数据读取的最后我们要加上发送CMD12指令,结束数据块的读取。

SD_SendCmd(CMD12,0,0X01);    //发送停止命令

SD_GetResponse  用来等待SD卡返回想要的值,1表示返回成功,0表示失败。

//等待SD卡回应
//Response:要得到的回应值
//返回值:0,成功得到了该回应值
//    其他,得到回应值失败
u8 SD_GetResponse(u8 Response)
{u16 Count=0xFFFF;//等待次数                             while ((SD_SPI_ReadWriteByte(0XFF)!=Response)&&Count)Count--;//等待得到准确的回应       if (Count==0)return MSD_RESPONSE_FAILURE;//得到回应失败   else return MSD_RESPONSE_NO_ERROR;//正确回应
}

3、SD卡写操作

SD_WriteDisk是为了写入数据,同样也要先判断SD_Type的类型。

//写SD卡
//buf:数据缓存区
//sector:起始扇区
//cnt:扇区数
//返回值:0,ok;其他,失败.
u8 SD_WriteDisk(u8*buf,u32 sector,u8 cnt)
{u8 r1;if(SD_Type!=SD_TYPE_V2HC)sector *= 512;//转换为字节地址if(cnt==1){r1=SD_SendCmd(CMD24,sector,0X01);//读命令if(r1==0)//指令发送成功{r1=SD_SendBlock(buf,0xFE);//写512个字节      }}else{if(SD_Type!=SD_TYPE_MMC){SD_SendCmd(CMD55,0,0X01);   SD_SendCmd(CMD23,cnt,0X01);//发送指令   }r1=SD_SendCmd(CMD25,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;//
}   

SD_GetSectorCount可以得到SD卡的总扇区数量,对于V2.0版本以后的SD卡是固定512Byte(即一个sector)大小。

//获取SD卡的总扇区数(扇区数)
//返回值:0: 取容量出错
//       其他:SD卡的容量(扇区数/512字节)
//每扇区的字节数必为512,因为如果不是512,则初始化不能通过.
u32 SD_GetSectorCount(void)
{u8 csd[16];u32 Capacity;  u8 n;u16 csize;                          //取CSD信息,如果期间出错,返回0if(SD_GetCSD(csd)!=0) return 0;       //如果为SDHC卡,按照下面方式计算if((csd[0]&0xC0)==0x40)  //V2.00的卡{ csize = csd[9] + ((u16)csd[8] << 8) + 1;Capacity = (u32)csize << 10;//得到扇区数            }else//V1.XX的卡{  n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;csize = (csd[8] >> 6) + ((u16)csd[7] << 2) + ((u16)(csd[6] & 3) << 10) + 1;Capacity= (u32)csize << (n - 9);//得到扇区数   }return Capacity;
}

三、实验31 图片显示实验main函数学习

Show_Str用来显示字符串

//在指定位置开始显示一个字符串
//支持自动换行
//(x,y):起始坐标
//width,height:区域
//str  :字符串
//size :字体大小
//mode:0,非叠加方式;1,叠加方式
void Show_Str(u16 x,u16 y,u16 width,u16 height,u8*str,u8 size,u8 mode)
{                   u16 x0=x;u16 y0=y;                                  u8 bHz=0;     //字符或者中文                                                 while(*str!=0)//数据未结束{ if(!bHz){if(*str>0x80)bHz=1;//中文 else              //字符{      if(x>(x0+width-size/2))//换行{                   y+=size;x=x0;    }                                if(y>(y0+height-size))break;//越界返回      if(*str==13)//换行符号{         y+=size;x=x0;str++; }  else LCD_ShowChar(x,y,*str,size,mode);//有效部分写入 str++; x+=size/2; //字符,为全字的一半 }}else//中文 {     bHz=0;//有汉字库    if(x>(x0+width-size))//换行{     y+=size;x=x0;          }if(y>(y0+height-size))break;//越界返回                            Show_Font(x,y,str,size,mode); //显示这个汉字,空心显示 str+=2; x+=size;//下一个汉字偏移      }                        }
}                    

DIR是定义的结构体

typedef struct {FATFS*   fs;             /* Pointer to the owner file system object (**do not change order**) */WORD id;             /* Owner file system mount ID (**do not change order**) */WORD  index;          /* Current read/write index number */DWORD  sclust;         /* Table start cluster (0:Root dir) */DWORD clust;          /* Current cluster */DWORD  sect;           /* Current sector */BYTE*   dir;            /* Pointer to the current SFN entry in the win[] */BYTE*    fn;             /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
#if _FS_LOCKUINT    lockid;         /* File lock ID (index of file semaphore table Files[]) */
#endif
#if _USE_LFNWCHAR*  lfn;            /* Pointer to the LFN working buffer */WORD lfn_idx;        /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
} DIR;

首先尝试打开图片文件夹的目录

while(f_opendir(&picdir,"0:/PICTURE"))//打开图片文件夹{       Show_Str(60,170,240,16,"PICTURE文件夹错误!",16,0);delay_ms(200);                 LCD_Fill(60,170,240,186,WHITE);//清除显示      delay_ms(200);               }  

f_opendir的返回值FRESULT也是一个结构体

/* File function return code (FRESULT) */typedef enum {FR_OK = 0,               /* (0) Succeeded */FR_DISK_ERR,         /* (1) A hard error occurred in the low level disk I/O layer */FR_INT_ERR,              /* (2) Assertion failed */FR_NOT_READY,         /* (3) The physical drive cannot work */FR_NO_FILE,             /* (4) Could not find the file */FR_NO_PATH,                /* (5) Could not find the path */FR_INVALID_NAME,       /* (6) The path name format is invalid */FR_DENIED,             /* (7) Access denied due to prohibited access or directory full */FR_EXIST,             /* (8) Access denied due to prohibited access */FR_INVALID_OBJECT,      /* (9) The file/directory object is invalid */FR_WRITE_PROTECTED,       /* (10) The physical drive is write protected */FR_INVALID_DRIVE,       /* (11) The logical drive number is invalid */FR_NOT_ENABLED,           /* (12) The volume has no work area */FR_NO_FILESYSTEM,     /* (13) There is no valid FAT volume */FR_MKFS_ABORTED,     /* (14) The f_mkfs() aborted due to any parameter error */FR_TIMEOUT,               /* (15) Could not get a grant to access the volume within defined period */FR_LOCKED,               /* (16) The operation is rejected according to the file sharing policy */FR_NOT_ENOUGH_CORE,        /* (17) LFN working buffer could not be allocated */FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */FR_INVALID_PARAMETER  /* (19) Given parameter is invalid */
} FRESULT;

main函数的一开头就定义了一个u16 *picindexbl 指针

u16 *picindextbl;    //图片索引表

如果判断res的结果是图片文件,就将当前的curindex存放到picindexbl中。

res=f_typetell(fn);
if((res&0XF0)==0X50)//取高四位,看看是不是图片文件   {picindextbl[curindex]=temp;//记录索引curindex++;}       

STM32正点原子图片——显示实验相关推荐

  1. 正点原子OLED显示实验

    目录 简介 原理 接口方式 1.8080并行接口 2.SPI方式 常用命令 编写代码 IO口 软件设计 OLED初始化代码: OLED_Refresh_Gram函数 OLED_WR_Byte函数 画点 ...

  2. 【正点原子STM32连载】第四十八章 图片显示实验 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1

    1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频 ...

  3. 音频电平vu显示表软件下载_正点原子开拓者 Nios II资料连载第十章MCU TFT-LCD图片显示实验...

    1)实验平台:正点原子开拓者FPGA 开发板 2)摘自<开拓者 Nios II开发指南>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载地址:http://w ...

  4. c语言头文件格式图片_阿波罗 STM32F767 开发板资料连载第四十九章 图片显示实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第四十九章 图片显示实验 ...

  5. 基于STM32F407图片显示实验(有代码)

    一.实验目的 在开发产品的时候,很多时候,我们都会用到图片解码,本次实验介绍如何通过 STM32F4 来解码 BMP/JPG/JPEG/GIF 等图片,并在 LCD 上显示出来. 二.图片格式简介 我 ...

  6. (48)STM32——图片显示实验

    目录 学习目标 图片格式 BMP 组成 JPG GIF 介绍 代码 总结 学习目标 本节要学习的是使用单片机来显示图片,但是因为目前SD卡还没有图片,暂时做不了实验,等我把图片放到SD卡之后再把实验补 ...

  7. 正点原子 在ADC实验中添加USMART,通过串口查看电压值

    结合了实验十七和实验十四.由于没有买LCD的板子,所以通过串口调试来查看电压值. 目录 一.准备工作:头文件 二.添加一些代码 三.开始调试 一.准备工作:头文件 1.首先将实验十四的USMART文件 ...

  8. STM32正点原子TFT-LCD1.3寸(240x240)液晶显示屏移植

    吐槽 屏幕太贵了....40多一块,而且还只有1.3寸.记录本篇的目的是为了我换了更大的屏幕,为了以后需要特此记录. 如何移植 我相信各位都拘泥于库,有人用hal库,有人用标准库等等,万变不离其宗,库 ...

  9. STM32——EMWIN PNG 图片显示(二十五)

    EMWIN 文章目录 EMWIN 前言 一.RAM 使用 二.PNG 文件 API 函数 三.实验演示 前言 PNG 格式是一种图像格式,其目的是试图替代 GIF 和 TIFF 文件格式,同时增加一些 ...

最新文章

  1. java 线性表定义_Java数据结构的线性表是怎样的
  2. linux待机流程,Linux睡眠喚醒機制--Kernel態
  3. Zabbix监控SQLServer TPS
  4. C#LeetCode刷题之#122-买卖股票的最佳时机 II(Best Time to Buy and Sell Stock II)
  5. 计算机电子琴音乐,电脑电子琴软件
  6. CentOS 6U7分区大于2TB的磁盘以及挂载大于16TB分区磁盘的解决方案
  7. Android WiFi 扫描并选择网络进行连接
  8. Atitit。Tree文件解析器的原理流程与设计实现  java  c# php js
  9. 机器学习- 吴恩达Andrew Ng Week6 知识总结 Machine Learning System Design
  10. MTK 如何更换开机 LOGO?
  11. 基于FPGA/数字IC的数字信号处理课程
  12. 河北省高中会考计算机试题及答案,河北省高中信息技术会考题.doc
  13. android 9.0系统下载地址,安卓9.0正式版下载地址
  14. Chrome上关于微信网页版WeChat不能正常登录的解决方案
  15. 思路分享——hdu 3233
  16. C++、Java、JavaScript中的正则表达式
  17. 关于SX1308升压芯片的使用说明
  18. iphone xr xs_如何关闭iPhone X,XS和XR
  19. 面向6G网络的太赫兹通信技术研究综述
  20. 前端将后端数据流转为图片(微信小程序)

热门文章

  1. 一个字符究竟占多少字节辨析
  2. postman入门到精通
  3. Linux管道的容量大小及管道的数据结构
  4. html计算机之间的距离,如何使用百度地图测量两地之间距离知道大概需要多少时间...
  5. import、from...improt、from...import *三者的区别
  6. 尴尬!买了几台华为路由器却不会配置~看完就会了
  7. 200元/天的APP充场拉新项目可以做吗?
  8. 11种常见的多变量分析方法
  9. 产品经理 MRD PRD BRD
  10. CSDN博文中实现点击文字超链接跳转新页面