1.硬件平臺(tái)
2.示例效果
SD卡檢測(cè)和圖片搜索
圖片加載與顯示
3.軟件設(shè)計(jì)
3.1 遍歷目錄
??遍歷目錄,搜索所有的bmp格式圖片,以鏈表方式保存圖片名,方便接下來(lái)圖片切換。
typedef struct FILE_info
{
char file_name[100];
u16 number;//保存第幾張圖片
struct FILE_info *next;
struct FILE_info *pre;
}FILE_INFO;
FILE_INFO *bmp_head=NULL;
/*創(chuàng)建鏈表*/
FILE_INFO *List_CreateHead(FILE_INFO *head)
{
if(head!=NULL)return head;
head=malloc(sizeof(FILE_INFO));
memset(head,0,sizeof(FILE_INFO));
head->next=NULL;
head->pre=NULL;
return head;
}
/*添加節(jié)點(diǎn)*/
FILE_INFO *List_AddNode(FILE_INFO *head)
{
if(head==NULL)return NULL;//鏈表頭不存在
FILE_INFO *phead=head;
while(phead->next!=NULL)
{
phead=phead->next;
}
FILE_INFO *new_node=malloc(sizeof(FILE_INFO));
memset(new_node,0,sizeof(FILE_INFO));
new_node->pre=phead;
phead->next=new_node;
new_node->next=NULL;
return new_node;
}
/*遍歷目錄*/
u8 SDCard_PrintDir(const TCHAR* path)
{
DIR dp;
u8 res;
u8 stat=0;
bmp_head=List_CreateHead(bmp_head);//創(chuàng)建鏈表頭
res=f_opendir(&dp,path);
FILINFO file_info;
if(res)
{
printf("打開(kāi)目錄失敗res=%d\r\n",res);
free(bmp_head);//釋放鏈表頭
return 1;
}
FILE_INFO *temp=NULL;
while(1)
{
res=f_readdir(&dp,&file_info);
if(res!=FR_OK || file_info.fname[0]==0)break;
if(strstr(file_info.fname,".bmp"))//查找bmp圖片
{
temp=List_AddNode(bmp_head);//添加節(jié)點(diǎn)
if(temp==NULL)
{
stat=2;//動(dòng)態(tài)分配空間失敗
goto AA;
}
strcpy(temp->file_name,file_info.fname);//文件名
picture_count++;
temp->number=picture_count;//第幾張圖片
//printf("文件名:%s\r\n",temp->file_name);
}
}
AA:
f_closedir(&dp);//關(guān)閉目錄
return stat;
}
3.2 圖片解析與顯示
??圖片通過(guò)SD卡保存,SD卡采用SDIO驅(qū)動(dòng)。由于STM32F103ZE主頻只有72MHZ,為了提高刷新速度,將主頻超頻至128MHZ。再通過(guò)外擴(kuò)SRAM建立屏幕緩沖區(qū),借助DMA數(shù)據(jù)搬運(yùn),從而提升屏幕刷新效率。
超頻處理后需要注意串口波特率計(jì)算和定時(shí)器工作頻率
void STM32_Clock_Init(u8 PLL)
{
u8 temp;
RCC->CFGR&=0XFFFFFFFC; //修改時(shí)鐘頻率為內(nèi)部8M
RCC->CR&=~0x01000000; //PLLOFF
RCC->CFGR&=~(0XF<<18); //清空原來(lái)的設(shè)置
RCC->CR|=1<<16;//開(kāi)啟HSE時(shí)鐘
while(!(RCC->CR>>17));//等待外部時(shí)鐘就緒
RCC->CFGR|=0x4<<8;//APB1時(shí)鐘由系統(tǒng)時(shí)鐘2分頻
PLL-=2;//實(shí)際倍頻數(shù)和填入?yún)?shù)差2,9倍頻寫(xiě)入的數(shù)值為7
RCC->CFGR|=PLL<<18;//PLL時(shí)鐘9倍頻
RCC->CFGR|=1<<16; //HSE作為PLL時(shí)鐘輸入源
FLASH->ACR|=0x32; //FLASH 2個(gè)延時(shí)周期
RCC->CR|=1<<24;//PLL時(shí)鐘使能
while(!(RCC->CR>>25));//等待PLL鎖定
RCC->CFGR|=0x2<<0;//PLL輸出作為系統(tǒng)時(shí)鐘
while(1)
{
temp=(RCC->CFGR>>2)&0x3;
if(temp==0x2)break;
}
}
3.3 DMA配置
??直接存儲(chǔ)器存取(DMA)用來(lái)提供在外設(shè)和存儲(chǔ)器之間或者存儲(chǔ)器和存儲(chǔ)器之間的高速數(shù)據(jù)傳輸。無(wú)須CPU干預(yù),數(shù)據(jù)可以通過(guò)DMA快速地移動(dòng),這就節(jié)省了CPU的資源來(lái)做其他操作。
/******DMA_CH1從存儲(chǔ)器到存儲(chǔ)器************
**形參:u32 cpar -- 外設(shè)地址
** u32 cmar -- 存儲(chǔ)器地址
**
**************************************/
void DMA_CH1_Init(void)
{
RCC->AHBENR|=1<<0;//dma1時(shí)鐘使能
DMA1_Channel1->CCR|=1<<14;//存儲(chǔ)器到存儲(chǔ)器模式
DMA1_Channel1->CCR|=0x3<<12;//設(shè)置CH1優(yōu)先級(jí)為最高
DMA1_Channel1->CCR|=0x1<<10;//存儲(chǔ)器數(shù)據(jù)寬度16位
DMA1_Channel1->CCR|=0x1<<8;//外設(shè)數(shù)據(jù)寬度16位
DMA1_Channel1->CCR|=1<<7;//存儲(chǔ)器地址增量
DMA1_Channel1->CCR&=~(1<<6);//外設(shè)地址不增量
DMA1_Channel1->CCR&=~(1<<5);//不執(zhí)行循環(huán)操作
//DMA1_Channel1->CCR|=1<<5;//執(zhí)行循環(huán)操作
DMA1_Channel1->CCR&=~(1<<4);//從外設(shè)讀
}
/**********開(kāi)啟DMA1_CH1數(shù)據(jù)傳輸*************
***
***形參:u16 data_len -- DMA要傳輸數(shù)目
***********************************************/
void DMA_CH1_Start(u32 cpar,u32 cmar,u16 data_len)
{
DMA1_Channel1->CPAR=cpar;//外設(shè)地址
DMA1_Channel1->CMAR=cmar;//存儲(chǔ)器地址
DMA1_Channel1->CCR&=~(1<<0);//關(guān)閉通道傳輸
DMA1_Channel1->CNDTR=data_len;//設(shè)置傳輸數(shù)量
DMA1_Channel1->CCR|=1<<0;//開(kāi)啟通道傳輸
}
3.4 圖片解析與顯示
本示例主要以BMP圖片為例,其他格式圖形需要移植第三方庫(kù)才可實(shí)現(xiàn)。
由于我們常規(guī)BMP圖片多為24位真彩色,即RGB888;而本次使用的LCD屏是16位真彩色RGB565,因而需要進(jìn)行顏色格式轉(zhuǎn)換。
/*顏色轉(zhuǎn)換RGB888轉(zhuǎn)RGB565*/
u16 RGB888_Transform_RGB565(u32 rgb)
{
u8 r,g,b;
u16 rgb565;
r=(rgb>>16)>>3;
g=(rgb>>8)>>2;
b=(rgb&0xff)>>3;
rgb565=(r<<11)|(g<<5)|(b<<0);
return rgb565;
}
u16 picture_count=0;//圖片總數(shù)量
/*BMP圖片顯示*/
static u8 buff_rgb888[320*3];//用來(lái)保存讀取到的原始數(shù)據(jù)
static u16 buff_rgb565[320*480];//用來(lái)保存轉(zhuǎn)換完成的RGB565數(shù)據(jù)
u8 BMP_Display(const char *file,u16 number)
{
FIL fp;
FRESULT res;
UINT br;
u16 w,h;
char buff[100];
snprintf(buff,sizeof(buff),"0:/photo/%s",file);
res=f_open(&fp,buff,FA_READ);
if(res!=FR_OK)return 1;
BMP_HEADER bmphead;
BMP_INFO bmpinfo;
memset(&bmphead,0,sizeof(BMP_HEADER));
memset(&bmpinfo,0,sizeof(BMP_INFO));
res=f_read(&fp,&bmphead,sizeof(BMP_HEADER),&br);
if(res!=FR_OK)return 2;
res=f_read(&fp,&bmpinfo,sizeof(BMP_INFO),&br);
if(res!=FR_OK)return 2;
// printf("圖片類(lèi)型:%c%c\r\n",bmphead.bfType>>8,bmphead.bfType);
// printf("圖片尺寸:%d*%d\r\n",bmpinfo.biWidth,bmpinfo.biHeight);
// printf("顏色位數(shù):%d\r\n",bmpinfo.biBitCount);
w=bmpinfo.biWidth;
h=bmpinfo.biHeight;
u32 oneline_size=bmpinfo.biWidth*3;//一行的字節(jié)數(shù)
u32 read_oneline_size=oneline_size;//要讀取的一行字節(jié)數(shù)
/*取出有效的rgb顏色值的一行字節(jié)數(shù)*/
while(oneline_size%4)oneline_size++;/*保存一行字節(jié)數(shù)為4的倍數(shù)*/
u32 addr=bmphead.bfOffBits+(bmpinfo.biHeight-1)*oneline_size;
/*將指針偏移到最后一行*/
u32 i=0,j=0;;
u32 rgb888;
u32 cnt=0;
for(i=0;i
3.5 主函數(shù)main.c
??在主函數(shù)main.c中主要完成各個(gè)外設(shè)初始化、SD卡掛載、圖片獲取、觸摸屏坐標(biāo)和按鍵值獲取,最終實(shí)現(xiàn)通過(guò)觸摸屏滑動(dòng)或者按下切換圖片。
FATFS fs;
int main()
{
u8 key;
STM32_Clock_Init(16);
Beep_Init();
Led_Init();
Key_Init();
Usartx_Init(USART1,115200,128);
TIMx_Init(TIM2,128,20*1000);
W25Q64_Init();//W25Q64初始化
IIC_Init();//IIC初始化
NT35310_Init();//LCD初始化
XPT2046_Init();
TOUCH_Calibration();//觸摸屏校準(zhǔn)
printf("觸摸屏校準(zhǔn)完成\r\n");
SRAM_Init();
u8 res;
AA:
res=f_mount(&fs,"0",1);
if(res)
{
LCD_Clear(LIGHTBLUE);
LCD_Display_Str(LCD_WIDTH/2-strlen("請(qǐng)檢查SD卡是否插好!")*12/2,210,24,(u8 *)"請(qǐng)檢查SD卡是否插好!",RED);
LCD_Display_Str(LCD_WIDTH/2-strlen("注意文件系統(tǒng)格式須為FAT32!")*12/2,240,24,(u8 *)"注意文件系統(tǒng)格式須為FAT32!",RED);
LCD_Refresh();//更新顯示
Delay_Ms(1000);
goto AA;
}
BB:
LCD_Clear(LIGHTBLUE);
res=SDCard_PrintDir("photo");//遍歷目錄
if(res)
{
LCD_Refresh();//更新顯示
LCD_Display_Str(LCD_WIDTH/2-strlen("BMP圖片不存在!")*12/2,210,24,(u8 *)"BMP圖片不存在!",RED);
LCD_Display_Str(LCD_WIDTH/2-strlen("請(qǐng)將圖片存儲(chǔ)在/photo下")*12/2,240,24,(u8 *)"請(qǐng)將圖片存儲(chǔ)在/photo下",RED);
LCD_Refresh();//更新顯示
Delay_Ms(1000);
goto BB;
}
LCD_Clear(LIGHTBLUE);
LCD_Display_Str(LCD_WIDTH/2-strlen("正在加載圖片。。")*12/2,210,24,(u8 *)"正在加載圖片。。",RED);
LCD_Refresh();//更新顯示
Delay_Ms(1000);
FILE_INFO *bmp_temp=bmp_head;
if(bmp_temp->next!=NULL)
{
bmp_temp=bmp_temp->next;
BMP_Display(bmp_temp->file_name,bmp_temp->number);
}
u16 x1,x2;
int stat=0;
while(1)
{
res=XPT2046_ReadXY();
if(res)
{
x1=touch_info.x;
while(T_PEN==0)//等待松開(kāi)
{
XPT2046_ReadXY();
x2=touch_info.x;
}
if(x1-x2>50)stat=1;
else if(x2-x1>50)stat=2;
}
key=Key_Scan();
if(key==1 || stat==1)
{
stat=0;
BEEP=1;
Delay_Ms(50);
BEEP=0;
if(bmp_temp->next!=NULL)
{
bmp_temp=bmp_temp->next;
BMP_Display(bmp_temp->file_name,bmp_temp->number);
}
}
else if(key==2 || stat==2)
{
stat=0;
BEEP=1;
Delay_Ms(50);
BEEP=0;
if(bmp_temp->pre!=NULL && bmp_temp->pre->file_name[0]!=0)
{
bmp_temp=bmp_temp->pre;
BMP_Display(bmp_temp->file_name,bmp_temp->number);
}
//printf("%s\r\n",bmp_temp->file_name);
}
}
}
-
lcd
+關(guān)注
關(guān)注
34文章
4424瀏覽量
167396 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355728 -
TFT
+關(guān)注
關(guān)注
10文章
385瀏覽量
111061 -
STM32F103ZE
+關(guān)注
關(guān)注
2文章
14瀏覽量
10886
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論