之前看到了公众号大佬法的应该学着写点技术博客,再加上搞这个屏幕的时候网上没有找到成套的教程,所以写下了这个博客,请多指教。(STM32F103RCT6,测试时使用的是正点原子的mini开发板,其实用谁的开发版并不重要)

目录

一、模块的使用

二、编写驱动

三、显示图片


一、模块的使用

最近在做毕设,想用一块大一点的屏幕,最后挑了这款ips屏,ili9431驱动,模块出厂40pin。(具体某宝哪家买的就不说了)

测试屏幕时我买了转接板,方便测试。

厂家给出的引脚图是这样的(手册中的详细描述略)

显然 ,6 7 脚是供电脚,接上3.3V ;5脚GND

9脚cs 是片选脚,低电平有效  ;10脚RS/SPI SCL/SCK  使用SPI的时候是时钟线 SCK;

11脚WR/A0   换了个说法,其实就是CMD/DATA引脚(命令/数据)引脚 ;12脚RD读控制脚

13脚 是串口数据的输入信号,接stm32的MOSI(单片机是主机往从机发);同理,14脚接单片机MISO

15屏复位脚 常见说法就是RST;

33脚A,34-36脚K,分别是背光的正极和负极,这两个一个接3.3,一个接地,屏幕才能亮起来,否则哪怕显示出来了,你得打折强光手电才看到的。

我们用4线spi,所以IM0 IM1 IM2 分别接地,3.3,3.3 ;

以上就是屏幕正常工作,必须要使用的引脚,其余的按手册上处理(要么接地 要么悬空即可).

引脚资源分配如下

RST(复位) PC1
DC/A0(命令/数据) PC2
 CS(片选)  PC3
BLK(背光控制) (就是上面的K引脚) PB9
Spi_sck   PA5
Spi_miso    PA6
Spi_mosi    PA7
  PA5 6 7 均为复用,注意配置

显示屏模块电路

二、编写驱动

到csdn上下载了一个别人写好了的驱动,那位老哥的驱动只有驱动文件,具体单片机实现留好了接口,十分感谢,但是文件上没有具体写作者是哪位,太可惜了。

函数里对于引脚的操作通过宏定义进行了一次封装,如果单片机不是stm32 只需修改为自己对应的引脚操作函数即可。

屏幕的初始化,大致是: 初始化引脚(GPIO,SPI),初始化外设 ,然后就可以调用函数看看效果了

void SPI1_idev_Init(void)
{   SPI_InitTypeDef  SPI_InitStructure;SPI1_IO_Init();RCC_APB2PeriphClockCmd(   RCC_APB2Periph_SPI1,  ENABLE );//SPI1时钟使能   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;     //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;       //串行同步时钟的空闲状态为High电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   //串行同步时钟的第2个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;     //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;       //定义波特率预分频的值:波特率预分频值为,SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;  //CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器//DMA_SPI1_idev_init();    //配置SPI1的DMA功能SPI_Cmd(SPI1, ENABLE); //使能SPI外设
} 
//csdn上卸载的驱动这个函数只留了接口,所以我们把内容填上
void ILI9341_io_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOC, ENABLE );GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 |GPIO_Pin_2 |GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStructure);GPIO_SetBits(GPIOC, GPIO_Pin_1 |GPIO_Pin_2 |GPIO_Pin_3);  RCC_APB2PeriphClockCmd(   RCC_APB2Periph_GPIOB, ENABLE );GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_ResetBits(GPIOB, GPIO_Pin_9 );  }
//初始化外设
void SPI1_idev_Init(void)
{   SPI_InitTypeDef  SPI_InitStructure;SPI1_IO_Init();RCC_APB2PeriphClockCmd(   RCC_APB2Periph_SPI1,  ENABLE );//SPI1时钟使能   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;     //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;       //串行同步时钟的空闲状态为High电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   //串行同步时钟的第2个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;     //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;       //定义波特率预分频的值:波特率预分频值为,SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;  //CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器//DMA_SPI1_idev_init();    //配置SPI1的DMA功能SPI_Cmd(SPI1, ENABLE); //使能SPI外设
}
//初始化外设
void SPI1_idev_Init(void)
{   SPI_InitTypeDef  SPI_InitStructure;SPI1_IO_Init();RCC_APB2PeriphClockCmd(   RCC_APB2Periph_SPI1,  ENABLE );//SPI1时钟使能   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master;     //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;       //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;       //串行同步时钟的空闲状态为High电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;   //串行同步时钟的第2个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;     //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;       //定义波特率预分频的值:波特率预分频值为,SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;   //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7;  //CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器//DMA_SPI1_idev_init();    //配置SPI1的DMA功能SPI_Cmd(SPI1, ENABLE); //使能SPI外设
}

然后就可以开始愉快的调用了;

调用发现,屏幕上想要显示字符的部分是一个黑色马赛克,并未成功,所以我硬着头皮debug,屏幕显示的基本原理就是画点

通过debug发现,原作者的函数中,画笔的颜色和当前背景颜色是通过lcddev中的cur_brushcl ,cur_backcl两个成员来表示的,在调用函数前对这两个变量没有赋值,所以程序出了bug。经过多重考虑,我把这两个变量直接写死,反正我只需要白底黑字;

void LCD_ShowChar(unsigned short int x,unsigned short int y,unsigned char ch,unsigned char csize,unsigned char mode)
{unsigned char temp,t1,t;unsigned short int y0=y;unsigned char sz=(csize/8+((csize%8)?1:0))*(csize/2);       //得到字体一个字符对应点阵集所占的字节数ch=ch-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)for(t=0;t<sz;t++){   if(csize==12)temp=ascii_1206[ch][t];       //调用1206字体else if(csize==16)temp=ascii_1608[ch][t];  //调用1608字体else if(csize==24)temp=ascii_2412[ch][t];  //调用2412字体else return;                              //没有的字库for(t1=0;t1<8;t1++){               if(temp&0x80){LCD_DrawPoint_Color(x,y,BLACK);//lcddev.cur_brushcl;我这里直接写成了黑色}else if(mode==0){LCD_DrawPoint_Color(x,y,WHITE);//lcddev.cur_backcl;写死,白色}    temp<<=1;y++;if(y>=lcddev.height)return;       //超区域了if((y-y0)==csize){y=y0;x++;if(x>=lcddev.width)return;    //超区域了break;}}       }
}

三、显示图片

对于这类屏幕要想显示图片,肯定得先取模,经过调查,取模应该采用水平扫描,不带数据头,16位彩色格式进行取模

取模后获得数据(上图仅为展示注意参数),我实际上取模了一个320*240的图片,16位rgb格式的话这个对存储空间的需求还是很大的,所以测试成功一次后,我加了一个宏定义,需要的时候才编译进去,缩短每次下载时间。(我用的dap下载器,文件大了就很慢)

使用网上老哥提供的函数进行调用

/*************************************************************************************
* 名    称:void LCD_DrawPicture(unsigned short int StartX,unsigned short int StartY,unsigned short int PicXend,unsigned short int PicYend,const unsigned char *pic)
* 功    能:在指定座标范围显示一副图片
* 入口参数:StartX     行起始座标
*           StartY     列起始座标
*           PicXend      图片的X像素
*           PicYend       图片的Y像素pic             图片头指针
* 出口参数:无
* 说    明:图片取模格式为水平扫描,16位颜色模式
*LCD_DrawPicture(0,0,320,240,gImage_logo);
*************************************************************************************/
void LCD_DrawPicture(unsigned short int StartX,unsigned short int StartY,unsigned short int PicXend,unsigned short int PicYend,const unsigned char *pic)
{unsigned long j=0;    unsigned char *pdata = (unsigned char *)pic;LCD_set_windows(StartX,StartY,StartX+PicXend-1,StartY+PicYend-1);    //设置显示窗口for(j=0;j<PicXend*PicYend;j++)    //向窗口中填入内容,即图片的模值{LCD_wt8bitData(pdata[j*2+1]);LCD_wt8bitData(pdata[j*2]);}
}

最终开机logo效果图。(事实上,一是可以用字符串显示代替,二也可以拆分成三个图片分别在屏幕上不同位置显示,这样可以缩小数据大小,你看,图像中白色部分那么多,浪费了存储空间)

你还别说这ips屏还挺好用,其实也没比那个一点几寸的oled单色屏幕贵多少。

模块到这里测试就结束了,工程、代码我会上传。

后续我会把驱动进行一个移植,因为我的项目想用cubemx (HAL库)做,并且有freertos操作系统。

第一次写博客,语言也不专业,欢迎大家批评指正。

ILI9431的LCD屏使用,STM32F1控制相关推荐

  1. python编程lcd显示_PyQt5快速上手基础篇2-按钮控制LCD屏显示

    前言 上一节我们完成了PyQt5开发环境搭建,本节开始我们正式进入PyQt5的世界,首先我给大家介绍下QT的信号与槽,然后利用这一特点完成点击按钮触发LCD屏显示功能. 一.基础知识 1. PyQt5 ...

  2. LCD屏参:手把手教你计算LCD屏参(proch值)

    LCD屏参(proch值)解释和计算 Linux内核的lcd控制器使用clcd_panel结构体表示一个LCD屏的硬件参数: /* include/linux/fb.h */   struct fb_ ...

  3. rust怎么调整夜晚亮度_买手机时LCD屏和OLED屏怎么选?终于明白了!

    手机近几年来更新的速度越发的快,屏幕色彩的艳丽程度也越来越绚丽.目前最为主流的LCD屏和OLED屏,这两款屏幕都有什么优缺点,比较一下做一个明了. 苹果最新的iPhone11系列新机中,iPhone1 ...

  4. mipi接口 1280(RGB)*720 LCD屏开发驱动笔记帖

    ps:创业开发产品,自学笔记,不一定适合教材性的阅读,零碎整理,自我总结用 材料:4.1寸lcd屏两块,屏自带触控,屏幕资料具备,rk3399和MK8788开发版上分别开发. 开发环境: 1]rk33 ...

  5. 简单了解一下LCD屏工作原理

    谈及LCD屏,想必绝大多数人都耳熟能详,现实中运用到LCD屏的地方还是有很多的.例如家用电视显示屏,电子秤显示屏,手机显示屏等. 知道LCD屏这个名词的人居多,但是真正了解其工作原理的,应该还不是很多 ...

  6. QSPI驱动带NV3030B的LCD屏

    (说明:本文没有详细描写有关QSPI通信时的细节,只是作为一个简要记录,说明一下QSPI驱动屏幕时的一些要点) 1.引脚说明: (1)LED_K:LCD屏背光负极 (2)LED_A:LCD屏背光正极 ...

  7. lcd屏和amoled屏的优缺点 lcd屏和amoled屏哪个效果好

    LCD和AMOLED各有优缺点,而且随着LCD技术的不断优化和AMOLED技术的不断完善,在一些中高端手机上,LCD和AMOLED之间的差距已经非常小了,不足以对日常使用构成巨大影响. 选lcd屏还是 ...

  8. STM32 FSMC接口驱动4.3寸TFT LCD屏

    STM32 FSMC接口驱动4.3寸TFT LCD屏 STM32的FSMC接口是并行总线接口,可以用于驱动存储芯片如FLASH/SRAM等,也可以用于驱动并口LCD屏. 这里以STM32F103VET ...

  9. LCD屏应用--笔记

    当前主流的显示器件 1.LED大屏幕 主要应用在大型的商场,也是由一块块的小型的屏幕拼接到一起的,背面会比较厚  在工作过程中会产生大量的热,有些LED后边会有一个空调 专门用来散热. 2.数码管 5 ...

  10. 屏幕篇—如何最快速驱动LCD屏

    屏幕篇-如何最快速驱动LCD屏 前言 LCD屏的驱动对于新手来说,这是一个很大的拦路虎.学完基础外设后,在这里就不知道怎么下手了.一个完整的LCD驱动包含的内容是非常多的,最基础的描点,画线,显示字符 ...

最新文章

  1. python读取html内容 dom获取_python学习笔记十三 JS,Dom(进阶篇)
  2. 独家 | 一文读懂随机森林的解释和实现(附python代码)
  3. 2012年度最受欢迎中国开源软件评选
  4. # 20180908 2018-2019-2 《密码与安全新技术专题》第9周作业
  5. qt5中服务器文件传输,POST在Qt5中发送JSON文件的请求
  6. 自锁时间电路plc_PLC对两台三相交流电动机联锁启停控制
  7. Docker学习总结(52)—— Docker容器环境变量相关知识点的总结
  8. dojo/dom-class源码学习
  9. 2021美赛MCM选题
  10. 水系图一般在哪里找得到_进展 | 水系钾离子电池研究取得重要进展
  11. 华为薪酬体系的整体框架
  12. 车型代号对照表_车型和VIN代号对照表3.24.doc
  13. java实现png转ico,支持尺寸选择
  14. 倍福--本地电脑配置EtherCAT网卡
  15. buu-[WUSTCTF2020]level3
  16. Mac安装sshpass
  17. 计算机职称落户,人才引进落户等6类落户方式 新政策全部在这里
  18. 射影几何 -- 平面射影几何 1
  19. java从入门到精通二十四(三层架构完成增删改查)
  20. Vulkan免费版VulkanRT 1.0.65.0

热门文章

  1. HTML+CSS期末网页课设——游戏宣传网页(全部源码)
  2. 固定在计算机主机箱体上的起到连接计算机,固定在计算机主机箱箱体上的、起到连接计算机各种部件的纽带和桥梁作用的是( )。...
  3. Java多线程--概述-转自林炳文Evankaka
  4. SpringBoot线程池获取service实例空指针
  5. 4200: [Noi2015]小园丁与老司机
  6. 《实用python程序设计》练习题:向量点积计算
  7. 第二章课后习题 华氏温度与摄氏温度的java简单转换
  8. QT入门第四天消息盒子+对话框+定时器+日期和时间(源码)
  9. 数格子算面积的方法_数格子估算面积与数格点估算面积
  10. awflasher的Vplayer 2.1 ( FLV Player )