1.硬件平台 cpu:stm32f103ze 屏幕:3.5寸tftlcd屏 触控:电阻式触摸屏xpt2046 sd卡、外扩sram 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
17));//等待外部时钟就绪 rcc->cfgr|=0x425));//等待pll锁定 rcc->cfgr|=0x2>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|=1ccr&=~(1ccr|=1<>16)>>3; g=(rgb>>8)>>2; b=(rgb&0xff)>>3; rgb565=(r<<11)|(g<<5)|(b8,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); } }}
电动机自耦降压起动电气控制原理图
齿轮pitch值对CH504的影响
30V MOS管N沟道PKC26BB替代料SVG032R4NL5
实验室气密测试和生产线气密性检测使用的方法有何区别
一款定制设计的压电机构促动器,可用于阀门、液滴等!
STM32应用案例 基于STM32F103ZE开发的数码相册
索尼携4K专业医疗产品参展第三十届全国泌尿外科学术会议
选择电源滤波器时需要注意什么
苹果舍弃VR而选择AR 价格是其中需要考虑的因素
可探测非线性气流力的皮牛级光纤微力传感
明年MiniLED终端装置市场有望爆发性增长
广电计量入选河南省用能权有偿使用和交易第三方审核机构
比魅族手机更受关注?一款神秘新品,名字定位“HALO”
谷歌Nexus5X拆解:搭载高通骁龙808和指纹识别
Pico小怪兽2VR一体机评测 物美价廉
虚拟现实技术能改变如今的直播方式吗?
联想小新笔记本,配置12GB内存和双风扇散热
【喜报】多项荣誉赋能国产FPGA企业——中科亿海微
传英特尔拿下iPhone7一半基带芯片 高通怎么办?
华为手环3Pro表现到底如何