博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[stm32] 一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO
阅读量:6844 次
发布时间:2019-06-26

本文共 10962 字,大约阅读时间需要 36 分钟。

 

书接上文:

最近在研究用低速、低RAM的单片机来驱动小LCD或TFT彩屏实现动画效果

首先我用一个16MHz晶振的m0内核的8位单片机nRF51822尝试驱动一个1.77寸的4线SPI屏(128X160),

发现,刷一屏大约要0.8s左右的时间,

具体收录在《》中

觉得,如果用72MHz的STM32也许效果会好很多

于是在stm32上做了个类似的版本,

具体收录在《》中

发现刷一屏0.2s左右,

效果是有的,但是还不能达到支持播放流畅动画的效果!

于是,决定将串行数据改成并行数据传输

本节将带来一个用stm32驱动的2.4寸240X320的8位并口tft屏的刷屏效果

 

工程结构

 

main.c

1 /* Includes ------------------------------------------------------------------*/ 2 #include "stm32f10x.h" 3 #include "LCD2.h" 4  5  6 void RCC_Configuration(void); 7 /**************************************************************************** 8 * 名    称:int main(void) 9 * 功    能:主函数10 * 入口参数:无11 * 出口参数:无12 * 说    明:13 * 调用方法:无 14 ****************************************************************************/ 15 int main(void)16 {17     RCC_Configuration();                   //系统时钟配置18     LCD2_GPIO_Init();19     LCD2_Init();20     while (1)21     {22         Show_RGB(0,240,0,320,0xff0f);23         DELAY_MS(1000);24         Show_RGB(0,240,0,320,0x00fe);25         DELAY_MS(1000);26     }27 }28 29 /****************************************************************************30 * 名    称:void RCC_Configuration(void)31 * 功    能:系统时钟配置为72MHZ32 * 入口参数:无33 * 出口参数:无34 * 说    明:35 * 调用方法:无 36 ****************************************************************************/ 37 void RCC_Configuration(void)38 {   39   SystemInit();40 }

 

LCD2.c

1 #include "LCD2.h"  2   3   4   5 void LCD2_GPIO_Init()  6 {  7     GPIO_InitTypeDef GPIO_InitStructure;  8   9     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); 10      11      12     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9; 13     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 14     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             //口线翻转速度为50MHz 15     GPIO_Init(GPIOB, &GPIO_InitStructure); 16      17     //8位数据输出 18     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 19     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 20     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;             //口线翻转速度为50MHz 21     GPIO_Init(GPIOD, &GPIO_InitStructure);             22 } 23  24 // 25 //最底层数据传输函数 26 // 27 //写命令 28 void Write_Cmd(unsigned char DH,unsigned char DL) 29 { 30     LCD2_CS=0; 31     LCD2_RS=0; 32  33     DataPort=DH; 34     LCD2_RW=0; 35     LCD2_RW=1; 36  37     DataPort=DL; 38      39     LCD2_RW=0; 40     LCD2_RW=1; 41     LCD2_CS=1; 42 } 43 //写数据 双8位 44 void Write_Data(unsigned char DH,unsigned char DL) 45 { 46     LCD2_CS=0; 47      48     LCD2_RS=1; 49     DataPort=DH; 50     LCD2_RW=0; 51     LCD2_RW=1; 52  53     DataPort=DL;     54     LCD2_RW=0; 55     LCD2_RW=1; 56     LCD2_CS=1; 57 } 58  59 //写数据 双8位 60 void Write_Data2(unsigned char DH,unsigned char DL) 61 { 62     DataPort=DH; 63     LCD2_RW=0; 64     LCD2_RW=1; 65  66     DataPort=DL;     67     LCD2_RW=0; 68     LCD2_RW=1; 69 } 70  71 // 72 //调用上面最底层实现稍高层写命令和数据函数 73 // 74 /*---------------------------------------------------------------- 75                          写命令、写数据 76 输入参数:x 需要输入的命令 16位 77           y 需要输入的数据 16位 78 ----------------------------------------------------------------*/ 79 void  Write_Cmd_Data (unsigned char x,unsigned int y) 80 { 81     unsigned char m,n; 82     m=y>>8; 83     n=y; 84     Write_Cmd(0x00,x); 85     Write_Data(m,n); 86 } 87 /*---------------------------------------------------------------- 88                          写16位数据 89 ----------------------------------------------------------------*/ 90 void  Write_Data_U16(unsigned int y) 91 { 92     unsigned char m,n; 93     m=y>>8; 94     n=y; 95     Write_Data2(m,n); 96 } 97  98 /*---------------------------------------------------------------- 99                             液晶初始化100 ----------------------------------------------------------------*/101 void LCD2_Init(void)102 { 103     LCD2_CS=1;104     DELAY_MS(5);105     LCD2_RES=0;106     DELAY_MS(5);107     LCD2_RES=1;108     DELAY_MS(50);109     Write_Cmd_Data(0x0001,0x0100); 110     Write_Cmd_Data(0x0002,0x0700); 111     Write_Cmd_Data(0x0003,0x1030); 112     Write_Cmd_Data(0x0004,0x0000); 113     Write_Cmd_Data(0x0008,0x0207);  114     Write_Cmd_Data(0x0009,0x0000);115     Write_Cmd_Data(0x000A,0x0000); 116     Write_Cmd_Data(0x000C,0x0000); 117     Write_Cmd_Data(0x000D,0x0000);118     Write_Cmd_Data(0x000F,0x0000);119     //power on sequence VGHVGL120     Write_Cmd_Data(0x0010,0x0000);   121     Write_Cmd_Data(0x0011,0x0007);  122     Write_Cmd_Data(0x0012,0x0000);  123     Write_Cmd_Data(0x0013,0x0000); 124     //vgh 125     Write_Cmd_Data(0x0010,0x1290);   126     Write_Cmd_Data(0x0011,0x0227);127     //DELAY_MS(100);128     //vregiout 129     Write_Cmd_Data(0x0012,0x001d); //0x001b130     //DELAY_MS(100); 131     //vom amplitude132     Write_Cmd_Data(0x0013,0x1500);133     //DELAY_MS(100); 134     //vom H135     Write_Cmd_Data(0x0029,0x0018); 136     Write_Cmd_Data(0x002B,0x000D); 137 138     //gamma139     Write_Cmd_Data(0x0030,0x0004);140     Write_Cmd_Data(0x0031,0x0307);141     Write_Cmd_Data(0x0032,0x0002);// 0006142     Write_Cmd_Data(0x0035,0x0206);143     Write_Cmd_Data(0x0036,0x0408);144     Write_Cmd_Data(0x0037,0x0507); 145     Write_Cmd_Data(0x0038,0x0204);//0200146     Write_Cmd_Data(0x0039,0x0707); 147     Write_Cmd_Data(0x003C,0x0405);// 0504148     Write_Cmd_Data(0x003D,0x0F02); 149     //ram150     Write_Cmd_Data(0x0050,0x0000); 151     Write_Cmd_Data(0x0051,0x00EF);152     Write_Cmd_Data(0x0052,0x0000); 153     Write_Cmd_Data(0x0053,0x013F);  154     Write_Cmd_Data(0x0060,0xA700); 155     Write_Cmd_Data(0x0061,0x0001); 156     Write_Cmd_Data(0x006A,0x0000); 157     //158     Write_Cmd_Data(0x0080,0x0000); 159     Write_Cmd_Data(0x0081,0x0000); 160     Write_Cmd_Data(0x0082,0x0000); 161     Write_Cmd_Data(0x0083,0x0000); 162     Write_Cmd_Data(0x0084,0x0000); 163     Write_Cmd_Data(0x0085,0x0000); 164     //165     Write_Cmd_Data(0x0090,0x0010); 166     Write_Cmd_Data(0x0092,0x0600); 167     Write_Cmd_Data(0x0093,0x0003); 168     Write_Cmd_Data(0x0095,0x0110); 169     Write_Cmd_Data(0x0097,0x0000); 170     Write_Cmd_Data(0x0098,0x0000);171     Write_Cmd_Data(0x0007,0x0133);172     173     //    Write_Cmd_Data(0x0022);//        174 }175 176 /*----------------------------------------------------------------177                          设置坐标178 ----------------------------------------------------------------*/179 /*----------------------------------------------------------------180                             全局变量181 ----------------------------------------------------------------*/182 #define WINDOW_XADDR_START    0x0050 // Horizontal Start Address Set183 #define WINDOW_XADDR_END    0x0051 // Horizontal End Address Set184 #define WINDOW_YADDR_START    0x0052 // Vertical Start Address Set185 #define WINDOW_YADDR_END    0x0053 // Vertical End Address Set186 #define GRAM_XADDR            0x0020 // GRAM Horizontal Address Set187 #define GRAM_YADDR            0x0021 // GRAM Vertical Address Set188 #define GRAMWR                 0x0022 // memory write189 void LCD_SetPos(unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1)190 {191     Write_Cmd_Data(WINDOW_XADDR_START,x0);192     Write_Cmd_Data(WINDOW_XADDR_END,x1);193     Write_Cmd_Data(WINDOW_YADDR_START,y0);194     Write_Cmd_Data(WINDOW_YADDR_END,y1);195     Write_Cmd_Data(GRAM_XADDR,x0);196     Write_Cmd_Data(GRAM_YADDR,y0);197     Write_Cmd (0x00,0x22);//LCD_WriteCMD(GRAMWR);198 }199 200 /*----------------------------------------------------------------201                             显示RGB颜色202 输入参数:x0,y0 起始坐标203           x1,y1 结束坐标204           Color  背景颜色205 ----------------------------------------------------------------*/206 void Show_RGB (unsigned int x0,unsigned int x1,unsigned int y0,unsigned int y1,unsigned int Color)207 {208     unsigned int i,j;209     LCD_SetPos(x0,x1,y0,y1);210     LCD2_CS=0;211     LCD2_RS=1;212 //    for (i=y0;i<=y1;i++)213 //    {214 //       for (j=x0;j<=x1;j++)215 //           Write_Data_U16(Color);216 //    }217     218     for (i=0;i<=(y1-y0+1)*(x1-x0+1);i+=32)219     {220          Write_Data_U16(Color);221          Write_Data_U16(Color);222         Write_Data_U16(Color);223          Write_Data_U16(Color);224          Write_Data_U16(Color);225          Write_Data_U16(Color);226         Write_Data_U16(Color);227          Write_Data_U16(Color);228         Write_Data_U16(Color);229          Write_Data_U16(Color);230         Write_Data_U16(Color);231          Write_Data_U16(Color);232          Write_Data_U16(Color);233          Write_Data_U16(Color);234         Write_Data_U16(Color);235          Write_Data_U16(Color);236          Write_Data_U16(Color);237          Write_Data_U16(Color);238         Write_Data_U16(Color);239          Write_Data_U16(Color);240          Write_Data_U16(Color);241          Write_Data_U16(Color);242         Write_Data_U16(Color);243          Write_Data_U16(Color);244         Write_Data_U16(Color);245          Write_Data_U16(Color);246         Write_Data_U16(Color);247          Write_Data_U16(Color);248          Write_Data_U16(Color);249          Write_Data_U16(Color);250         Write_Data_U16(Color);251          Write_Data_U16(Color);252     }253         LCD2_CS=1;254 }255 256 257 void Delay_ms(u16 time)258 {259     u16 i=0;  260     while(time--)261     {262         i=12000; 263         while(i--);    264     }265 }

注:代码比较容易理解,不做详解

 

另外补上这三个小实验的连线图:

1、这个是本节的并行接口与屏幕的连接方式:

2、这是上两节串行接口的连线,上面对应的引脚连接是与nRF51822的(第一次试验),下面对应的连接是与stm32的(第二次试验)

 

小结

从效果图上看,即使采用stm32的8位并行来驱动屏幕速度还是达不到刷新动画的效果~

之后我也传输数据的函数上做了些优化,可效果还是不明显——

第一点:优化前RS等引脚的定义要通过宏展开,每次计算BitBand后面的式子~

1 #define BitBand(Addr, Bit) *((volatile int*)(((int)(Addr) & 0x60000000) + 0x02000000 + (int)(Addr) * 0x20 + (Bit) * 4))2 #define LCD2_CS         BitBand(&GPIOB->ODR, 8)3 #define LCD2_RES        BitBand(&GPIOB->ODR, 9)4 #define LCD2_RS         BitBand(&GPIOB->ODR, 7)5 #define LCD2_RW         BitBand(&GPIOB->ODR, 6)6 #define DataPort         GPIOD->ODR

优化后采用直接把值赋给对应的引脚来减少运算量

1 #define BitBand(Addr, Bit) *((volatile int*)(((int)(Addr) & 0x60000000) + 0x02000000 + (int)(Addr) * 0x20 + (Bit) * 4))2 #define LCD2_CS         (*((volatile int*)0x422181A0))   //BitBand(&GPIOB->ODR, 8)3 #define LCD2_RES        (*((volatile int*)0x422181A4))   //BitBand(&GPIOB->ODR, 9)4 #define LCD2_RS         (*((volatile int*)0x4221819C))   //BitBand(&GPIOB->ODR, 7)5 #define LCD2_RW         (*((volatile int*)0x42218198))   //BitBand(&GPIOB->ODR, 6)6 #define DataPort         (*((volatile int*)0x4001140C)) //GPIOD->ODR

第二点:为了减少Show_RGB函数中循环中的Write_Data_U16的调用,直接将Write_Data_U16计算拆到最细放到循环内

第三点:为了排除Write_Data_U16中4、5两行移位运算和类型转换所带来的时间花销,直接采用上图中全局变量color1、color2来直接赋值,查看效果有没有提升~

1 void  Write_Data_U16(unsigned int y)2 {3     unsigned char m,n;4     m=y>>8;5     n=y;6     Write_Data2(m,n);7 }

本篇中资源链接:

注:其中未优化版工程比较简洁方便理解学习,优化测试版是为了提升传输速率做的几点优化(效果不大,代码稍乱)

 

 

 

@beautifulzzzz 

  2015-11-28 持续更新中~

转载地址:http://evsul.baihongyu.com/

你可能感兴趣的文章
【Linux】操作系统
查看>>
如何使用zabbix初级监控
查看>>
TPC-H Q1 测试显示 PgSQL 11 JIT 带来 30% 性能提升
查看>>
Confluence 6 使用 LDAP 授权连接一个内部目录 - 成员 Schema 设置
查看>>
如何编写linux下nand flash驱动-4
查看>>
poj-1146 ID codes
查看>>
查看Java的汇编指令
查看>>
【亲测有效】无法定位链接器!请检查 tools\link.ini 中的配置是否正确的解决方案...
查看>>
2018-08-31
查看>>
Zookeeper的集群配置和Java测试程序
查看>>
求浮点数的整数次幂
查看>>
请求https错误: unable to find valid certification path to requested target
查看>>
从零开始撸一个Fresco之总结
查看>>
[python skill]Python 中 NaN 和 None 的详细比较
查看>>
「架构技术专题」作为java程序员的你还不知道网站架构的演化(2)?
查看>>
业界 | Nature:AI为什么总是歧视重重?
查看>>
9- Flask构建弹幕微电影网站-后台逻辑(一)
查看>>
Linux_服务器_03_xxx is not in the sudoers file.This incident will be reported.的解决方法
查看>>
程序员的桌面(家)
查看>>
jQuery Validate自定义各种验证方法
查看>>