打印
[STM32]

振南ZN-X开发板【STM32M3版】高难实验 之 JPEG图片解码显示实验

[复制链接]
4673|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
znmcu|  楼主 | 2014-10-10 14:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 znmcu 于 2014-10-10 14:15 编辑

振南网站还在继续美化改进,暂时提供一个平台来发布振南的实验和相关资料!
http://www.znmcu.cn/znx_m3_exps_tjpgd_test.html
振南QQ:987582714  群:198521880
JPEG图片解码显示实验(使用TJpgD开源方案)【STM32 M3版】
实验说明:
振南很早以前就已经实现过对JPEG图片的解码显示,但是当时使用的是一个PC上的开源代码,它的最大问题在于1、解码的效率与速度不够理想 2、占用的RAM比较多。后来我在网上看到了TJpgDTiny JPEG Decompressor),以下是它的官方介绍:
TJpgDec is a generic JPEG image decompressor module that highly optimized for small embedded systems. It works with very low memory consumption so that it can be incorporated into tiny microcontrollers, such as AVR, 8051, PIC, Z80, Cortex-M0 and etc.
它号称最少只需要4.5KROM3KRAM
【以上内容摘自TJpgD官方网站
此实验使用振南znFAT文件系统方案读取SD卡中的JPG文件,经过TJpgD解码后得到原始的RGB像素数据,最终送到TFT液晶中进行显示。经过一些优化之后,解码320x240JPG图片大约可以达到每秒2-3幅。
【注:此实验需要使用SD卡与TFT液晶模块,在实验之前,请首先确保模块工作正确。可以参考振南的模块单项专门测试实验,先把模块调通,这是此实验成功的根基!!
所需硬件:
此实验中需要的硬件有:
ZN-X开发板基板(STM32 M3)【也可使用自己的开发板,不过TFT液晶的接口信号比较多,自己接线可能会比较麻烦】
ARM-OBJLINK仿真器(用于仿真与程序下载)
USB转串口模块(用于串口通信与程序下载)
TFT液晶(320X240像素,控制器为ILI9325
SD卡读写模块与SD
【注:此实验中使用的是SD2接口SD1连接的STM32IO,没有硬件SPI功能,因此SD1只能使用IO模拟SPI方式,这样会影响JPG的解码速度。这里使用硬件SPI+DAM方式,尽量提高SD卡和文件数据的读取速度】
电路原理图及详解:
原理图注解:上图是此实验的ZN-X基板(STM32 M3)主要原理图(与此实验无关的部分均已裁掉)ZN-X开发板上有两个SD卡模块接口,如图中⑤和⑥,它们由2x5的双排母接口与SD卡模块相插接,如下图所示。
此实验中使用SD卡模块接口2(因为它与硬件SPI相连,可以提高SD卡的读写速度,SD1只能使用IO模拟SPI方式)。
图中③为USB串口模块专用接口,主要用于完成供电、串口通信与程序下载,如下图。
图中④是STM32 M3芯片,型号为STM32F103RBT6128KB ROM20KB RAM、主频最高可达74MHz)。两个SD卡接口IO分配如下:
SD接口1信号

连到STM32F103  IO


SD接口2信号


连到STM32F103  IO


SD1-CS


PB8


SD2-CS


PB9


SD1-SI


PB5


SD2-SI


PB15/SPI2-MOSI


SD1-SO


PB4


SD2-SO


PB14/SPI2-MISO


SD1-CLK


PB3


SD2-CLK


PB13/SPI2-SCLK

图中⑸是ARM-OB SWDP仿真调试器接口(ARM-OB其实是JLINK的简化版,它只支持SWDP接口方式,而非JTAG方式)。
上图是SD卡模块的原理图,对照模块实物图,不难理解其意义。
在此实验中可以看到我们将SD卡模块上的跳线设置为J3-J2,就是因为我们直接使用了ZN-X基板,它所使用的CPU(STM32F103RBT6)3.3V的,而无需分压电路。
(1)ZN-X基板上TFT液晶模块的接口。如下图:
图中上方的2X20排母接口就是此实验中TFT模块要插接的位置。有些人询问下方的2X17的接口是作什么用的。因为ZN-X可以支持多种TFT液晶模块,它们的接口都不尽相同,所以在ZN-X基板上有两个TFT液晶模块的接口。同时这些接口为其它模块的扩展提供了余地和机会,从而使得ZN-X开发板更加灵活,实验资源更加丰富。
(2)TFT液晶的RD信号(读使能信号,主要用于TFT液晶上像素数据的读取)的复用开关。STM32RD-CLK信号连接到了74HC32的一个输入端,另一个输入端与RD-CLK-SEL相连,通过它来控制RD-CLK是否可以控制TFT的读使能(RD-CLK-SEL0,则选通;反之TFT-RD则一直为1)。ZN-X上的这一设计方式有重要的作用,在后面的实验中大家可以深刻得领悟到。
图中③为USB串口模块专用接口,主要用于完成供电、串口通信与程序下载,如下图。
TFT液晶模块说明:
此实验中所使用的TFT液晶模块控制器为ILI9325,分辨率为320x240(QVGA),16位色(6万5千色)。接口定义如下图:
ILI9325支持8位与16位接口模式(J3断开为8位模式,短接为16位模式)。此实验中将提供这两种接口模式的源代码。8位模式更适合低端单片机,比如51AVR等,可以节省IO资源,不过每读写一个像素都要有两个数据读写过程,显示速度并不太理想。16位模式适合ARM这种比较高端的芯片,可以得到较高的显示速度。实际上,使用ARM来驱动TFT,如果使用8位模式反而会比较麻烦,而且效率低下,通过对两种模式下源代码的比较大家应该能有所体会。
【此实验中为了提高图像的显示速度,所以使用的是16位模式,所以需要将TFT液晶模块的J3短接!!!】
实验方法与流程:
主要代码如下:首先向SD卡根目录中拷贝一个JPG图片(最好不要超过240x320尺寸,否则TFT液晶模块将会显示不完整,或显示有误。)将此JPG图片命名为test.jpg。然后烧入此实验对应的代码,如果顺利的话,实验效果即可呈现!!【如果不成功,请仔细检查各个环节!!】
以下是主要代码:
struct znFAT_Init_Args Init_Args; //初始化参数集合
struct FileInfo fileinfo; //文件信息集合

JDEC jd; //TJpgD的解码体
unsigned char work_buf[4096]; //TJpgD的工作缓冲

int main(void)
{         
u32 res=0,len=0;
delay_init();
uart_init(115200); //串口初始化为115200
printf("串口设置完毕\r\n");
TFT_Init();
TFT_Clear(0x8888); //TFT初始化与清屏
znFAT_Device_Init(); //存储设备初始化
printf("SD卡初始化完毕\r\n");
znFAT_Select_Device(0,&Init_Args); //选择设备
res=znFAT_Init(); //文件系统初始化         
if(!res) //文件系统初始化成功
{
  printf("Suc. to init FS\r\n");

  printf("BPB_Sector_No: %d\r\n",Init_Args.BPB_Sector_No);   
  printf("Total_SizeKB: %d\r\n",Init_Args.Total_SizeKB);
  printf("BytesPerSector: %d\r\n",Init_Args.BytesPerSector);
  printf("FATsectors: %d\r\n",Init_Args.FATsectors);  
  printf("SectorsPerClust: %d\r\n",Init_Args.SectorsPerClust);
  printf("FirstFATSector: %d\r\n",Init_Args.FirstFATSector);
  printf("FirstDirSector: %d\r\n",Init_Args.FirstDirSector);
  printf("FSsec: %d\r\n",Init_Args.FSINFO_Sec);
  printf("Next_Free_Cluster: %d\r\n",Init_Args.Next_Free_Cluster);
  printf("FreenCluster: %d\r\n",Init_Args.Free_nCluster);
}
else //文件系统初始化失败
{
printf("Fail to init FS , Err Code: %d\r\n",res);
}

res=znFAT_Open_File(&fileinfo,"/test.jpg",0,1); //打开文件
if(!res) //如果打开文件成功
{
  printf("Suc. to open file.\r\n");
  printf("================================\r\n");
  printf("File_Name(Short 8.3):%s\r\n",fileinfo.File_Name);
  printf("File_Size:%d\r\n",fileinfo.File_Size);

  printf("File_CDate:%d-%d-%d %d:%d:%d\r\n",fileinfo.File_CDate.year, \
  fileinfo.File_CDate.month,fileinfo.File_CDate.day,fileinfo.File_CTime.hour, \
  fileinfo.File_CTime.min,fileinfo.File_CTime.sec);

  printf("File_StartClust:%d\r\n",fileinfo.File_StartClust);
  printf("File_CurClust:%d\r\n",fileinfo.File_CurClust);
  printf("File_CurSec:%d\r\n",fileinfo.File_CurSec);
  printf("File_CurPos:%d\r\n",fileinfo.File_CurPos);
  printf("File_CurOffset:%d\r\n",fileinfo.File_CurOffset);
  printf("================================\r\n");
  printf("Start to read data....\r\n"); //开始读取数据
  jd_prepare(&jd, input_func, work_buf, 4096, &fileinfo); //TJpdD解码前的准备

  printf("JPEG info:\r\n");
  printf("width:%d height:%d\r\n",jd.width,jd.height);

  jd_decomp(&jd, output_func, 0); //开始解码


  znFAT_Close_File(&fileinfo); //关闭文件
}
else //如果打开文件不成功
{
  printf("Fail to open file , Err Code:%d\n",res);
}

znFAT_Flush_FS(); //刷新文件系统

while(1);            
}   
实验结果如下图所示:
注:此实验中JPG图片解码显示的速度基本达到每秒3帧的水平(STM32F103 芯片有适当的超频,而且加大了文件读取缓冲大小,还有优化了图像显示驱动。)虽然速度上并不尽如人意,但是基本的功能已经实现了。要实现高速的解码与显示,还是要依靠更好的硬件性能和主频,比如使用振南的ZN-X M4平台
源代码下载:


相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:振南的znFAT -- 单片机上上的FAT32文件系统 www.znmcu.cn

4474

主题

5195

帖子

33

粉丝