STM32正点原子图片——显示实验
目錄
一、圖片顯示部分
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正点原子图片——显示实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DEDE教程:最新织梦搜索页如何调用ar
- 下一篇: UML系列图——用例图(Use Case