STM32学习之路-LCD(3)<显示图片>

祝大家端午和六一快乐!原本今天是想休息休息的,但是实在无奈没什么事干.所以就来学习学习LCD显示图片的函数

函数是照搬奋斗的例子,算是些笔记吧.不过奋斗的例子注释的不是很详细.今天去看了正点原子的论坛,唉..瞬间感觉正点原子做得真的很好

能把所有的资料都开源,并且论坛上大多问题都耐心的解答了.这实在是非常非常好的售后服务了!!自己也偷偷的去下了写资料来看看,(*^__^*) 嘻嘻……

好,进入主题:

开发板:奋斗V5

LCD:3寸 400X240

直接上代码吧

void lcd_DrawPicture(u16 StartX,u16 StartY,u8 Dir,u8 *pic)
{
  u32  i=8, len;
  u16 temp,x,y;

  /**************************************/
	/*a1 长:240 宽:400*/
	/*a2 长:400 宽:240*/

  x=((uint16_t)(pic[2]<<8)+pic[3])-1;	  	//从图像数组里取出图像的长度
  y=((uint16_t)(pic[4]<<8)+pic[5])-1;	  	//从图像数组里取出图像的高度    

  if(Dir==0){
	LCD_WR_CMD(0x0003,0x1030);   			//图像显示方向为左下起  行递增  列递增
        LCD_WR_CMD(0x0210, StartX); 			//水平显示区起始地址 0-239
  	LCD_WR_CMD(0x0211, StartX+x);           	//水平显示区结束地址 0-239
  	LCD_WR_CMD(0x0212, StartY);     		//垂直显示区起始地址 0-399
  	LCD_WR_CMD(0x0213, StartY+y);         	        //垂直显示区结束地址 0-399

  	LCD_WR_CMD(0x0200, StartX);		          	//水平显示区地址
  	LCD_WR_CMD(0x0201, StartY);		      		//垂直显示区地址
  }
  else if(Dir==1){
	LCD_WR_CMD(0x0003,0x1018);   			//图像显示方向为左下起  行递增  列递减
        LCD_WR_CMD(0x0210, StartY); 			//水平显示区起始地址 0-239
  	LCD_WR_CMD(0x0211, StartY+y);           //水平显示区结束地址 0-239
  	LCD_WR_CMD(0x0212, 399-(x+StartX));     //垂直显示区起始地址 0-399
  	LCD_WR_CMD(0x0213, 399-StartX);         //垂直显示区结束地址 0-399

  	LCD_WR_CMD(0x200, StartY);		          	//水平显示区地址
  	LCD_WR_CMD(0x201, 399-StartX);		      	//垂直显示区地址
  }
  LCD_WR_REG(0x0202);				          	//写数据到显示区

   len=2*((uint16_t)(pic[2]<<8)+pic[3])*((uint16_t)(pic[4]<<8)+pic[5]);   //计算出图像所占的字节数  

  while(i<(len+8)) {							 //从图像数组的第9位开始递增
  	temp=(uint16_t)( pic[i]<<8)+pic[i+1];		 //16位总线, 需要一次发送2个字节的数据
  	LCD_WR_Data(temp);				 //将取出的16位像素数据送入显示区
	i=i+2;						 //取模位置加2,以为获取下一个像素数据
  }
}

这是奋斗给的原版例子,其中的注释都给出了各行待会的功能,让我们来看看他们具体是怎么实现的

x=((uint16_t)(pic[2]<<8)+pic[3])-1;  y=((uint16_t)(pic[4]<<8)+pic[5])-1;

为什么要这样计算图片的长和宽呢? 这时候就要看看图片的数组了.图片经过取模软件(这里用的是Image2LCD)把图片变成16进制的数组,很长很长的一个数组,但是

我们这里只关心它的前8个字符,这是400X240的一个图片取模出来的结果(当然只是前面一小部分)

这是240X400的图片的取模:

我想头8位应该是固定的,而且240X400格式的照片前8位应该是一样的,400X240格式的也应该是一样的,这里我只是自己下了两张照片

取模的结果和奋斗给的例子中的图片是一样的,所以我猜是一样的,具体我也没去研究.还有就是取模然间要设置得对,取模结果才会和上面

一样,显示照片才会正常,这个问题下面再说.好,回到上面的长度和宽度的分析:

这时候你可以拿起笔来计算一下了,以240X400为例, x=((uint16_t)(pic[2]<<8)+pic[3])-1; y=((uint16_t)(pic[4]<<8)+pic[5])-1;

pic[2] << 8 即 0x00左移8位,还是0x00,然后加上0xF0(十进制240),所以x=240-1=239(为了不超过屏幕范围)

同理pic[4] <<8 等于0x100,然后加上0x90等于0x190(十进制400),所以y=400-1=399;

400X240的也是这样算的...

然后接下来是显示方向的问题,dir=0是竖屏(240x400),dir=1是横屏(400x240),然后接下来就是写数据了,上面已经有注释了,这里就不说了,不明白的可以看前一篇文章

len=2*((uint16_t)(pic[2]<<8)+pic[3])*((uint16_t)(pic[4]<<8)+pic[5]); 计算图像所占字节数,这里我似懂非懂,不知道理解的对不对,这里按我的理解是长X宽,这个容易懂,

为什么要乘于2,我想应该是求长和宽的时候是用了2个的字符合起来求的,所以这里要分成1个字节就要乘于2(这些是瞎写的,如果真的正确答案的朋友,就请帮忙解答下)

接下来是

 while(i<(len+8)) {					  //从图像数组的第9位开始递增
  	temp=(uint16_t)( pic[i]<<8)+pic[i+1];		 //16位总线, 需要一次发送2个字节的数据
  	LCD_WR_Data(temp);<span style="white-space:pre">				</span>//将取出的16位像素数据送入显示区
	i=i+2;					       //取模位置加2,以为获取下一个像素数据

i的初始值为8,目的也就是为了跳过前8个字符,这也说明了前8个字符应该不是照片的内容,应该是前缀.

好了,这就完了,接下来说说取模软件的设置吧,不小心这东西也会让你费很多事情的,这里用的是Image2LCD

第一个注意的点是输入的设置:最大宽度和最大高度要和你的照片相符,这张相片是400X240的

第二个注意的点是输出图像:一开始输出图像并不是(400,240)的,你要先设置最大宽度和最大高度以后,然后按上面的重新载入一下,它才会输出正确的大小格式,要不然图像就不能正常显示,或者是不能显示.

第三个注意的点是高位在前:要勾上它,要不然图像显示就不正常了!

至于输出多少位的图片,是根据你的LCD接口方式来的.16位并口,就选择16位真彩色

好了~这样就可以了,开发板图片就不传了,手机烂拍照不好看.

STM32学习之路-LCD(3)<显示图片>

时间: 2024-11-08 23:26:56

STM32学习之路-LCD(3)<显示图片>的相关文章

STM32学习之路-LCD(2)&lt;LCD初始化&gt;

这些天一直在研究LCD的初始化函数,因为不过是用IO口模拟时序还是用FSMC来驱动LCD,都必须要弄好LCD的初始化 其实LCD的初始化就是跟着LCD IC的datasheet来写寄存器,大部分都使用上面的默认值,网上有很多修改的例子,这里就不 放出来了.但是我想写下一些比较重要的东西. 这是从网上下载来的一个文件的前半部分: 当然,别的型号的IC也是有这些东西的,不过可能有些地址不同而已. R0,这个命令有两个功能,如果对它写,则最低位为OSC,用于开启和关闭振荡器.而如果对它读操作, 则返回

STM32学习之路-LCD驱动(1)&lt;基础知识&gt;

[1]以下关于 JVM 的叙述,哪些项正确? A.JVM 运行于操作系统之上,它依赖于操作系统 B.JVM 运行于操作系统之上,它与操作系统无关 C.JVM 支持 Java 程序运行,它能够直接运行 Java 字节码文件 D.JVM 支持 Java 程序运行,它能够直接运行 Java 源代码文件 扩展名为.java的是源代码文件(文本文件):开发时编写代码的文件 扩展名为.class的是字节码文件(二进制):系统运行时执行的文件 [2]下列选项中正确的表达式是: A.byte b = 128; 

STM32学习之路-LCD(4)&amp;lt;显示字符&amp;gt;

昨晚疯狂的打了一夜的LOL,感觉L多了,今天一天精神萎靡.还是继续把显示字符给看了,可是在犹豫要不要写这篇文章 事实上写的东西也就是copy别人家的代码,不想写那么多,就记录下自己困惑的地方吧.也许改天回来看的时候能让自己高速的明确 也也许能帮助到有些朋友.. 看了奋斗给的样例和偷偷去下了正点原子的样例,事实上都是差点儿相同的,仅仅要略微改下都能够通用的,原理就在那里,跑不了. 奋斗给的样例,都是人家的 void lcd_wr_zf(u16 StartX, u16 StartY, u16 X,

STM32学习之路-外部中断(2)

OK,继续上篇的内容. 配置好外部中断源以后, 就得使能外部中断线了. 为了方便看再借下这个图: 对外部中断的使能其实就是配置上面这些寄存器.即使能哪EXIT线,选择上面模式,是中断还是事件,选择下降沿还是上升沿. 具体怎么写寄存器这就不研究了, = = 太麻烦了.. 直接用STM32的库就行了,来看看它的代码吧 这是EXTI结构体的初始化函数, void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct) { EXTI_InitStruct->

STM32学习之路-按键中断测试(外部中断)

终于有时间再来学习STM32了~ 这几天都在忙着该死的考试.直接进入正题 开发板:奋斗V5 这个按键中断测试的要求是:按键2(K2)按下,LED2(V7)亮, 再一次按下就灭,循环.. 好,先看看按键和LED的原理图 好吧~ 虽然图截得不是很好看,但是能看到K2接的是PC2, LED2接的是PD6 ok,剩下的就是配置工作了.. 先来理一理思路: (1)初始化系统时钟 (2)初始化外部时钟(你所用到的东西) (3)配置LED (4)配置中断优先级 (5)配置外部中断线 (6)中断处理函数 恩,差

STM32学习之路-不得不说的SysTick时钟

SysTick时钟,俗称"嘀嗒定时器",这家伙能按固定的时间产生一次中断,通常是多长时间产生一次中断呢?官方给出的一个时间是1ms 那么,它是怎么准确的产生1ms的呢.. 先来看看这家伙在时钟树的哪里吧 是它,是它,就是它,红色框里的东东,可以看到,它是由HCLK/8得到的,也就是:72MHz/8=9MHz 我们还能在STM32手册上找到这么一句话:系统嘀嗒校准值固定位9000,当系统嘀嗒时钟设为9MHz,产生1ms时间基准. 让我们来看看9000是怎么来的,这里要看下SysTick寄

STM32学习之路-外部中断(1)

今天起得比较晚,又浪费了点时间,真可耻.. 下午又为校赛出了俩题,至此,校赛的四道题目已经完毕.又检查了一番,没有错误,就等待着明天的汇总了~. AC自动机的题目今天就刷了三道,还是没有完成之前的目标.现在vj也进不去了,想通宵,都不给机会~~ 只能等明天再刷完了,拖延不是一个好习惯. ----------------------------------------------------------------------------------------------------------

STM32学习之路-中断优先级&lt;NIVC(2)&gt;

优先级的问题可以分为以下情况: 抢占优先级和响应优先级 (1)抢占优先级高的可以打断抢占优先级低的,形成嵌套. (2)抢占优先级相同时,看响应优先级.如果两个中断前后发生的话,后来的中断不能打断前一个中断 只能等,如果两个中断同时发生的话,则响应优先级高的先响应. (3)抢占级别和响应级别都一样时,按照中断的地址来响应,地址低的先响应 这样就解决了优先级的问题. 哪个级别高呢?  0>1>2>...... STM32共有5组分别是0-4组,还是借那个图 可以看到第4组所有的位都用来设置抢

[学习OpenCV攻略][011][显示图片]

学习资料: http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/tutorials.html   包含头文件 core.hpp:包含了基本的定义和库 highgui.hpp:包含了基本的输入输出操作 #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> 创建一个矩阵对象来存储和载入图像数据 Mat image; imread函