1.硬件平台
2.示例效果
SD卡检测和图片搜索
图片加载与显示
3.软件设计
3.1 遍历目录
遍历目录,搜索所有的bmp格式图片,以链表方式保存图片名,方便接下来图片切换。
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; /*创建链表*/ 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; } /*添加节点*/ 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);//创建链表头 res=f_opendir(&dp,path); FILINFO file_info; if(res) { printf("打开目录失败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);//添加节点 if(temp==NULL) { stat=2;//动态分配空间失败 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);//关闭目录 return stat; }
3.2 图片解析与显示
图片通过SD卡保存,SD卡采用SDIO驱动。由于STM32F103ZE主频只有72MHZ,为了提高刷新速度,将主频超频至128MHZ。再通过外扩SRAM建立屏幕缓冲区,借助DMA数据搬运,从而提升屏幕刷新效率。
超频处理后需要注意串口波特率计算和定时器工作频率
void STM32_Clock_Init(u8 PLL) { u8 temp; RCC->CFGR&=0XFFFFFFFC; //修改时钟频率为内部8M RCC->CR&=~0x01000000; //PLLOFF RCC->CFGR&=~(0XF<<18); //清空原来的设置 RCC->CR|=1<<16;//开启HSE时钟 while(!(RCC->CR>>17));//等待外部时钟就绪 RCC->CFGR|=0x4<<8;//APB1时钟由系统时钟2分频 PLL-=2;//实际倍频数和填入参数差2,9倍频写入的数值为7 RCC->CFGR|=PLL<<18;//PLL时钟9倍频 RCC->CFGR|=1<<16; //HSE作为PLL时钟输入源 FLASH->ACR|=0x32; //FLASH 2个延时周期 RCC->CR|=1<<24;//PLL时钟使能 while(!(RCC->CR>>25));//等待PLL锁定 RCC->CFGR|=0x2<<0;//PLL输出作为系统时钟 while(1) { temp=(RCC->CFGR>>2)&0x3; if(temp==0x2)break; } }
3.3 DMA配置
直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。
/******DMA_CH1从存储器到存储器************ **形参:u32 cpar -- 外设地址 ** u32 cmar -- 存储器地址 ** **************************************/ void DMA_CH1_Init(void) { RCC->AHBENR|=1<<0;//dma1时钟使能 DMA1_Channel1->CCR|=1<<14;//存储器到存储器模式 DMA1_Channel1->CCR|=0x3<<12;//设置CH1优先级为最高 DMA1_Channel1->CCR|=0x1<<10;//存储器数据宽度16位 DMA1_Channel1->CCR|=0x1<<8;//外设数据宽度16位 DMA1_Channel1->CCR|=1<<7;//存储器地址增量 DMA1_Channel1->CCR&=~(1<<6);//外设地址不增量 DMA1_Channel1->CCR&=~(1<<5);//不执行循环操作 //DMA1_Channel1->CCR|=1<<5;//执行循环操作 DMA1_Channel1->CCR&=~(1<<4);//从外设读 } /**********开启DMA1_CH1数据传输************* *** ***形参:u16 data_len -- DMA要传输数目 ***********************************************/ void DMA_CH1_Start(u32 cpar,u32 cmar,u16 data_len) { DMA1_Channel1->CPAR=cpar;//外设地址 DMA1_Channel1->CMAR=cmar;//存储器地址 DMA1_Channel1->CCR&=~(1<<0);//关闭通道传输 DMA1_Channel1->CNDTR=data_len;//设置传输数量 DMA1_Channel1->CCR|=1<<0;//开启通道传输 }
3.4 图片解析与显示
本示例主要以BMP图片为例,其他格式图形需要移植第三方库才可实现。
由于我们常规BMP图片多为24位真彩色,即RGB888;而本次使用的LCD屏是16位真彩色RGB565,因而需要进行颜色格式转换。
/*颜色转换RGB888转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;//图片总数量 /*BMP图片显示*/ static u8 buff_rgb888[320*3];//用来保存读取到的原始数据 static u16 buff_rgb565[320*480];//用来保存转换完成的RGB565数据 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("图片类型:%c%c\r\n",bmphead.bfType>>8,bmphead.bfType); // printf("图片尺寸:%d*%d\r\n",bmpinfo.biWidth,bmpinfo.biHeight); // printf("颜色位数:%d\r\n",bmpinfo.biBitCount); w=bmpinfo.biWidth; h=bmpinfo.biHeight; u32 oneline_size=bmpinfo.biWidth*3;//一行的字节数 u32 read_oneline_size=oneline_size;//要读取的一行字节数 /*取出有效的rgb颜色值的一行字节数*/ while(oneline_size%4)oneline_size++;/*保存一行字节数为4的倍数*/ 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 主函数main.c
在主函数main.c中主要完成各个外设初始化、SD卡挂载、图片获取、触摸屏坐标和按键值获取,最终实现通过触摸屏滑动或者按下切换图片。
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();//触摸屏校准 printf("触摸屏校准完成\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("请检查SD卡是否插好!")*12/2,210,24,(u8 *)"请检查SD卡是否插好!",RED); LCD_Display_Str(LCD_WIDTH/2-strlen("注意文件系统格式须为FAT32!")*12/2,240,24,(u8 *)"注意文件系统格式须为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("请将图片存储在/photo下")*12/2,240,24,(u8 *)"请将图片存储在/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)//等待松开 { 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); } } }
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
- lcd
+关注
关注
34文章
4346浏览量
165751 - STM32
+关注
关注
2253文章
10776浏览量
351554 - TFT
+关注
关注
10文章
378浏览量
110374 - STM32F103ZE
+关注
关注
2文章
14浏览量
10832
发布评论请先登录
相关推荐
基于STM32设计的数码相册
项目是基于
STM32设计的
数码相册,能够通过LCD显示屏解码显示主流的图片,支持bmp、jpg、gif等格式。用户可以通过按键或者触摸屏来切换图片,同时还可以旋转显示,并能够自适应居中显示,小尺寸图片居中显示,大尺寸图片自动缩小显示(超出屏幕范围)。图片从SD卡中获取。
STM32F103ZE最小系统版
1.单片机:
STM32F103ZE最小系统版6.0✔N1RVcKX0SpK₴回????/宝或點***击***链节至瑬览器【
STM32F103ZET6小系统板
STM32
开发板
发表于08-06 07:51
STM32F103ze简介
一、
STM32F103ze简介本文中,采用的 MCU 具体型号为
STM32F103ZET6,其拥有丰富的外设资源(USB,IIC,USART,TIMER)等,大容量的RAM和ROM,以及上百
发表于02-11 06:04
【技术精选】嵌入式STM32原创征文活动精选文章
应用案例基于PAJ7620和
STM32手势识别应用案例
STM32应用案例 基于
STM32F103ZE
开发的
数码相册基于
发表于07-27 18:26
嵌入式STM32F103ZE主要特性
Embest公司的
STM32F103ZEARM Cortex-M3嵌入式评估板采用ST公司的
STM32F103ZE处理器,工作频率72MHz.评估板集成了USB, CAN, SD卡接口
发表于05-08 11:17
•
1.5w次阅读
基于STM32F103ZE的USART2 端口时钟
STM32F103ZE默认的USART2就是PA03PA02,如果配置映射,USART2端口是PD05PD06了。
发表于06-04 07:26
•
6199次阅读
评论