漢字顯示操作流程
第一,進入主函數
1 int main(void) 2 { 3 u32 fontcnt; 4 u8 i,j; 5 u8 fontx[2];//gbk碼 6 u8 key,t; 7 8 delay_init(); //延時函數初始化 9 NVIC_Configuration(); //設置NVIC中斷分組2:2位搶占優先級,2位響應優先級 10 uart_init(9600); //串口初始化為9600 11 LED_Init(); //LED端口初始化 12 LCD_Init(); //初始化液晶 13 KEY_Init(); //按鍵初始化 14 usmart_dev.init(72); //usmart初始化 15 mem_init(SRAMIN); //初始化內部內存池 16 17 exfuns_init(); //為fatfs相關變量申請內存 18 f_mount(0,fs[0]); //掛載SD卡 19 f_mount(1,fs[1]); //掛載FLASH. 20 key=KEY_Scan(0); //按鍵掃描 21 LCD_ShowString(60,50,200,16,16,"Warship STM32"); 22 23 while(font_init()||key==KEY_UP) //檢查字庫 24 { 25 UPD: 26 LCD_Clear(WHITE); //清屏 27 POINT_COLOR=RED; //設置字體為紅色 28 LCD_ShowString(60,50,200,16,16,"Warship STM32"); 29 while(SD_Initialize()) //檢測SD卡 30 { 31 LCD_ShowString(60,70,200,16,16,"SD Card Failed!"); 32 delay_ms(200); 33 LCD_Fill(60,70,200+60,70+16,WHITE); 34 delay_ms(200); 35 } 36 LCD_ShowString(60,70,200,16,16,"SD Card OK"); 37 LCD_ShowString(60,90,200,16,16,"Font Updating..."); 38 key=update_font(20,110,16,0);//從SD卡更新 39 while(key)//更新失敗 40 { 41 LCD_ShowString(60,110,200,16,16,"Font Update Failed!"); 42 delay_ms(200); 43 LCD_Fill(20,110,200+20,110+16,WHITE); 44 delay_ms(200); 45 } 46 LCD_ShowString(60,110,200,16,16,"Font Update Success!"); 47 delay_ms(1500); 48 LCD_Clear(WHITE);//清屏 49 }
主函數主要是做了,外設初始化,磁盤掛載,字庫檢查,顯示漢字信息
第二,進入檢查字庫函數
1 u8 font_init(void) 2 { 3 SPI_Flash_Init(); 4 FONTINFOADDR=(1024*6+500)*1024; //W25Q64,6M以后 5 ftinfo.ugbkaddr=FONTINFOADDR+25; //UNICODEGBK 表存放首地址固定地址 6 SPI_Flash_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo));//讀出ftinfo結構體數據 7 if(ftinfo.fontok!=0XAA)return 1; //字庫錯誤. 8 return 0; 9 }
沒有檢測到字庫就需要更新字庫
第3行,初始化Flash
第4行,確定字庫開始的地址,Flash的前6M給FatFS使用,后接500K用戶使用區,
第5行,再接25Bytes的字庫表頭信息
第6行,讀取表頭結構體信息數據
第7行,檢測字庫表頭結構體成員字體正確標志
第三,進入更新字庫函數
1 u8 update_font(u16 x,u16 y,u8 size,u8 src) 2 { 3 u8 *gbk16_path; 4 u8 *gbk12_path; 5 u8 *unigbk_path; 6 u8 res; 7 if(src)//從25qxx更新 8 { 9 unigbk_path=(u8*)UNIGBK_25QPATH; 10 gbk12_path=(u8*)GBK12_25QPATH; 11 gbk16_path=(u8*)GBK16_25QPATH; 12 }else//從sd卡更新 13 { 14 unigbk_path=(u8*)UNIGBK_SDPATH; 15 gbk12_path=(u8*)GBK12_SDPATH; 16 gbk16_path=(u8*)GBK16_SDPATH; 17 } 18 res=0XFF; 19 ftinfo.fontok=0XFF; 20 SPI_Flash_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //清除之前字庫成功的標志.防止更新到一半重啟,導致的字庫部分數據丟失. 21 SPI_Flash_Read((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //重新讀出ftinfo結構體數據 22 LCD_ShowString(x,y,240,320,size,"Updating UNIGBK.BIN"); 23 res=updata_fontx(x+20*size/2,y,size,unigbk_path,0); //更新UNIGBK.BIN 24 if(res)return 1; 25 LCD_ShowString(x,y,240,320,size,"Updating GBK12.BIN "); 26 res=updata_fontx(x+20*size/2,y,size,gbk12_path,1); //更新GBK12.FON 27 if(res)return 2; 28 LCD_ShowString(x,y,240,320,size,"Updating GBK16.BIN "); 29 res=updata_fontx(x+20*size/2,y,size,gbk16_path,2); //更新GBK16.FON 30 if(res)return 3; 31 //全部更新好了 32 ftinfo.fontok=0XAA; 33 SPI_Flash_Write((u8*)&ftinfo,FONTINFOADDR,sizeof(ftinfo)); //保存字庫信息 34 return 0;//無錯誤. 35 }
第7行,選擇字庫更新來源
第8行,讀取字庫所在目錄
第19行,清除字庫表頭信息中的字庫正確標志
第20行,將修改過的字庫表頭信息寫入Flash(修改了字庫正常標志)
第21行,將字庫表頭信息從Flash中讀出,用以跟最后字庫更新成功后的正常標志一起寫入Flash
第23行,更新字庫文件
第32行,在確認字庫更新正確后,標志字庫表頭信息中的字庫更新正常標志
第33行,將最終正確的字庫表頭寫入Flash,供之后檢查字庫使用
字庫更新底層函數
1 u8 updata_fontx(u16 x,u16 y,u8 size,u8 *fxpath,u8 fx) 2 { 3 u32 flashaddr=0; 4 FIL * fftemp; 5 u8 *tempbuf; 6 u8 res; 7 u16 bread; 8 u32 offx=0; 9 u8 rval=0; 10 fftemp=(FIL*)mymalloc(SRAMIN,sizeof(FIL)); //分配內存 11 if(fftemp==NULL)rval=1; 12 tempbuf=mymalloc(SRAMIN,4096); //分配4096個字節空間 13 if(tempbuf==NULL)rval=1; 14 res=f_open(fftemp,(const TCHAR*)fxpath,FA_READ); 15 if(res)rval=2; //打開文件失敗 16 if(rval==0) 17 { 18 if(fx==0) //更新UNIGBK.BIN 19 { 20 ftinfo.ugbkaddr=FONTINFOADDR+sizeof(ftinfo); //信息頭之后,緊跟UNIGBK轉換碼表 21 ftinfo.ugbksize=fftemp->fsize; //UNIGBK大小 22 flashaddr=ftinfo.ugbkaddr; 23 }else if(fx==1) //GBK12 24 { 25 ftinfo.f12addr=ftinfo.ugbkaddr+ftinfo.ugbksize; //UNIGBK之后,緊跟GBK12字庫 26 ftinfo.gbk12size=fftemp->fsize; //GBK12字庫大小 27 flashaddr=ftinfo.f12addr; //GBK12的起始地址 28 }else //GBK16 29 { 30 ftinfo.f16addr=ftinfo.f12addr+ftinfo.gbk12size; //GBK12之后,緊跟GBK16字庫 31 ftinfo.gkb16size=fftemp->fsize; //GBK16字庫大小 32 flashaddr=ftinfo.f16addr; //GBK16的起始地址 33 } 34 while(res==FR_OK)//死循環執行 35 { 36 res=f_read(fftemp,tempbuf,4096,(UINT *)&bread); //讀取數據 37 if(res!=FR_OK)break; //執行錯誤 38 SPI_Flash_Write(tempbuf,offx+flashaddr,4096); //從0開始寫入4096個數據 39 offx+=bread; 40 fupd_prog(x,y,size,fftemp->fsize,offx); //進度顯示 41 if(bread!=4096)break; //讀完了. 42 } 43 f_close(fftemp); 44 } 45 myfree(SRAMIN,fftemp); //釋放內存 46 myfree(SRAMIN,tempbuf); //釋放內存 47 return res; 48 }
第14行,打開字庫文件,獲取fftemp對應結構體的文件信息
第20行,確認字庫要寫入Flash中的地址
第21行,確認字庫文件的大小
第36行,從fftemp所指的字庫文件中讀取4096Bytes的數據到tempbuf緩沖區中,並且將當前讀到數據的位置存入bread變量中
第38行,將讀到的4096Byte的字庫數據寫入Flash中
第39行,字庫的寫入地址偏移增加
第41行,判斷字庫數據是否已讀取完
