[硬件]单片机小制作----Flash存储图片句子,彩屏显示

前言:这么多天在家做了一个小玩意,里面存储了几十张我和对象的照片,还存了将近五十多句话,有一个“每日一乐”模式,就是随机显示一张照片,然后再随机显示一句情话,(女票总让我说句好听的,我也想不上来,做个这个让她自己看吧)0.0
文章内容主要讲解各个环节的难点,具体程序最下面下载自己看吧。
展示一下:


在这里插入图片描述      在这里插入图片描述
"每日一乐"模式       “句子浏览”模式(有密码)

一、前期准备

  • 共使用的器件:STC12C5A60S2单片机最小系统开发板,TFT彩屏1.44寸,W25Q128一个(flash),洞洞板7x9cm,按键2个(1k电阻要配着),有条件可以加一个RAM芯片
  • STC12C5A60S2单片机最小系统开发板
      这个里面就是最小系统,有一个开关,复位,就多一个东西,就是TFT的一个排座,由于是11针的,所以我也只能买11针的TFT1.44彩屏。有一个排座比较方便,就不用单独去焊一个。
  • TFT彩屏1.44寸
      这是个全彩屏,使用他给的这个函数,颜色深度是16位的(R-G-B是5-6-5),8针和11针的一样的用,看一下手册基本上都是ST7735驱动的,用SPI协议都是一样的只用8个。为了方便安在板子上,就用了11针的。
  • W25Q128一个(flash)
      flash,非易失存储器件,可以存储128Mb,也就是16MB,当然还有小一点的W25Q16(2MB),W25Q32(4MB),W25Q64(8MB),根据自己需要来。我想着能多放一些照片,就来了大的,其实用不完。。
  • 洞洞板7x9cm
      因为要往最小系统板上添加这个flash,没有直接的接口,只能取中,把最小系统和flash,还有俩按键都焊到板上就行了,就这用途。
  • 需要存储的照片和句子取模数据 <重点>

咱没有文件系统,就是最基本的字符形式,

  • 图片:由于TFT1.44寸的这个屏只有128x128的这个分辨率,所以图片只能裁剪成这个尺寸,然后取模,128*128是16384个像素点,每个点16位颜色数据,所以一共是32768 Byte一张图,也就是32KB大小存一张图。
  • 汉字:一个汉字16*16的,算法同上,一个字取完模占32 Byte。
  • 句子:先前想过两种存储方式,
  • 第一种,是存一个字库,常用汉字最多也就是1000-2000这个样子,最好按笔画分组,因为在keil里一个汉字,他默认是存成两个字符(这也就是为什么keil 中删除汉字要按删除两次),这样索引查找字库的方式比较快。
      假设是这样的:(假定 甲 这个字是0x08,0x67,具体是啥我也不知道。再加上32B的字模数据)  “甲”,0x00,0x00,0x3F,0xF8,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,0x21,0x08,0x21,0x08,
    0x21,0x08,0x3F,0xF8,0x21,0x08,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
      一个字占用34Byte ,不过为了对齐,“甲”这两个字符最好直接占用32Byte,一共64Byte一个字。
      这样索引直接在程序里写“甲,乙,丙,丁”,而不是“甲”这个字放在第120这个位置,程序写这个“120,121,122,123”。
  • 第二种,这种就是直接存储句子,但是由于句子长度不同,存储就比9*麻烦,最好是对齐的,这样方便我们调用查找使用
      我一共就50多个句子,总共还没一千多个字,就是用这种方法了,我的句子都改成了最多32个字,就是为了对齐。所以1句话正好1KB。不够32个字的补充空白到32个字。

二、步骤:

  • < >:
      焊板子,将最小系统,flash芯片,按键都含在板子上,怎么好看怎么来,然后记住好这下期间都用的什么引脚。
      例如我安排的:TFT彩屏的CS-P2.0,RST-P2.1, TS-P2.2, SDA-P2.3, SCL-P2.4, LED-P2.5
             W25Q128的CS-P1.1, DO-P1.2, CLK-P1.4 , DI-P1.5
      把电源都接好,按键需要1k电阻,都焊好烙铁什么的就不用了,开始编程。

  • < >:
       (程序分成两部分,第一部分要是将所准备的照片和句子写入到这个flash中去,第二部分是最后要用的展示的。)
    程序第一部分–下载部分:

    注:这一部分内容,都是学习 无量寿经的《STC51单片机入门(C语言)》,出版的纸版书名称为《51单片机轻松入门—基于STC15W4K系列》第24章 2M字节Flash Rom存储器W25Q16/W25X16 的使用。

    • 先简要介绍一下W25Q128这个器件
        (为了方便,我直接用书上的W25Q16来说这个flash,我用的是W25Q128只是比他大,东西都是一样的)
      W25Q16一共16Mbit,也就是2MB,分为8192页,
      1页=256字节
      1扇区=16页= 16x256字节=4096字节 (W25X16有512个扇区)。
      1块 =16扇区 =256x256字节=65536字节 (W25X16有32块)。
      重点
        用“页编程指令”每次就可以编程256字节,而且“页编程指令”是最小的写入指令,也就是说一次最少要写入256字节,就算只想写入一个字节,那剩下255字节的也要填充。
      用“扇区擦除指令”每次可擦除16页,
      用“块擦除指令”每次可擦除256页,
      用“整片擦除指令”可一次擦除整个芯片,W25X16有512个可擦除扇区或32个可擦除块。

    • 为什么flash写之前需要将每byte擦除为0xff?
        (开始胡诌,我记得看过一些,但记不清了,欢迎指正)因为这个存储器件每一个存储bit都是由一个基础元件(电容或是mos管)构成,当存储的1变成0,可以有效存储,就是将电荷放掉,但是直接将0变成1 是变不了的,没有办法自主充电荷,所以由之前数据如果是0,那么必须重新擦除都刷成1,然后再重新写。

    • 这时就要考虑一个问题了,每次最少写入256Byte,怎么将图片数据存进去是个问题,一个图片数据就32KB,如果你将这个图片数据放到一个C文件放入工程,编译出来的hex文件要96KB,要知道12C5A60S2单片机ROM只有60KB,放不下。三个办法:

      第一种:
        STC12C5A60S2这个单片机有1280B的RAM,其中256B是内部RAM,剩下的1024B是内部扩展RAM,内部留作中间计算用,就不占用了,【这是重点,下面还要用】内部扩展的RAM可以用“unsigned char xdata a[1024];"来调用。因为main函数中放不了这么大的数组,咱最大的数组只能用这个了。(单片机内部扩展RAM是否可以访问受辅助寄存器AUXR(地址为8EH)中的EXTRAM位控制。)
        然后写一个URAT串口收的程序,每次从电脑端发送1024B的数据,然后串口接收到一一放入这个数组中,然后写入W25Q128中。工作量较大。
        (注意:在电脑上串口助手发送的数据,注意选择字符模式还是hex模式。发送文件默认是字符模式
        字符模式就很麻烦,发送0x58,也就是发送58,实际上串口发的是 0x35和0x38,一个数变成了两个)
         
      第二种:
        在安装一个外部RAM,这样就方便多了,一下子通过串口将一个照片的32KB数据都发过去,然后直接写入,工作量小(没买这个RAM,由于是年前开始做的,那会快递都停了,想了想用最麻烦的法子做了)
       
      第三种:
      (本人使用)最麻烦的。。。
        将这个图片数据 的一半 放到一个pic.c文件放入工程,也就是16384 B大小的数组,用code段来保存这个很大的数组。code段是存放程序代码的地方,将数据放到这里是固定写死的,所以也不能在这个段创一个很大的数组当RAM用。
        编译出来的hex文件要50KB多一些,然后就是更改pic.c文件数据,然后更改写入的地址,下载程序。。。更改pic.c文件数据,然后更改写入的地址,下载程序。。。
        也亏了是可以擦写10万次。。。25个图片 我下了50次,句子50句,3次就行了。也就是这些内容,我最少下了53次(当然不止,调试下了更多)

    • W25Q128的地址相关问题
         地址是24位的,所以一个long int型的变量来存
        一个图片是32KB,也就是0x8000大小,所以存照片可以以这个为基准,#define pic_size 0x8000
        然后第一张就是 0x pic_size,第二张就是 1x pic_size。。。以此类推
        上面出现了一个问题,在使用W25Q128的写入函数时,我发现传入的地址高8位一直是0(long 型一共32位,最高的8位用不到就不管,低16位是正常的),例如地址是0x10000,最后传入的是0x00000。这个问题我找了好久,后来通过串口发送地址数据检查出来的。。。。
        最后用移位的方式解决的,就是需要发送0x10000,我就发送(0x10)<<12; 来完成的,因为低12位是不变的,所以移位12位就好。

      扫描二维码关注公众号,回复: 9231856 查看本文章
  • < >:
     程序第二部分–展示的程序:

    • 所有的界面介绍:
      1. 开始界面(放了一张“滑稽”图片,点击确定进入主界面)
      2. 主界面(选择界面,三种模式:每日一乐,图片浏览,句子浏览)
      3. 每日一乐(做这个的初衷,就是随机显示一张图片,点击确认然后随机显示一句话,然后再显示一个“mua”的图片)
      4. 图片浏览(这个是所有图片的一个浏览,不过设置密码了,密码在那些句子里)
      5. 句子浏览(就是所有情话的一个浏览,也设置密码了,就俩按键,也就是左右左右左什么的。)
    • 图片的显示
        这个里面就要说到上面的RAM,因为只有1024B的RAM,而显示一张图片有32K的数据呢,所以就只能分成32次显示,每次从flash中读取1024B的数据,然后显示一行,一行是4x128,每次确定好区域 Lcd_SetRegion(0, n<<2,128-1, (n<<2)-1); // n是32次循环的一个计量,然后就可以挨个传输数据点了。不过这样显示一张图片,加上清屏大概1s,还是挺慢的。(所以如果外加了一块RAM,就更方便了,一次显示。)
    • 句子显示
        同理,1KB的RAM正好是一句话,32个字,直接显示就行了。字的显示也是描点,不过是就只有两种颜色,字模数据是1那就是字的颜色,0就是背景色。
    • 随机数
        用定时器来做的,按键按一下来进行选择,做到真正的随机。

三、最后

程序我都放在了CSDN的下载里,设置了0分,取用的,大家在这页点个赞让我看到就好,嘿嘿0.0. 下载链接
  不过还要说一句,文档是一定要看的,尤其是单片机的文档,用到别的芯片也要看文档,因为出了问题,查文档是最快的,有时候直接看一眼时序图就什么都理解了。
  调试的过程中记住好好的用 串口,真的很有用。
  上面单片机的RAM部分,我觉得也很重要,码住!

发布了14 篇原创文章 · 获赞 15 · 访问量 5612

猜你喜欢

转载自blog.csdn.net/GG_band/article/details/104362496