×
单片机 > 单片机程序设计 > 详情

一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO

发布时间:2020-06-06 发布时间:
|

书接上文:

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

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

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

具体收录在《1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO》中

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

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

具体收录在《一个简单的stm32vet6驱动的天马4线SPI-1.77寸LCD彩屏DEMO》中

发现刷一屏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 * 功    能:系统时钟配置为72MHZ

32 * 入口参数:无

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 VGHVGL

120     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); //0x001b

130     //DELAY_MS(100); 

131     //vom amplitude

132     Write_Cmd_Data(0x0013,0x1500);

133     //DELAY_MS(100); 

134     //vom H

135     Write_Cmd_Data(0x0029,0x0018); 

136     Write_Cmd_Data(0x002B,0x000D); 

137 

138     //gamma

139     Write_Cmd_Data(0x0030,0x0004);

140     Write_Cmd_Data(0x0031,0x0307);

141     Write_Cmd_Data(0x0032,0x0002);// 0006

142     Write_Cmd_Data(0x0035,0x0206);

143     Write_Cmd_Data(0x0036,0x0408);

144     Write_Cmd_Data(0x0037,0x0507); 

145     Write_Cmd_Data(0x0038,0x0204);//0200

146     Write_Cmd_Data(0x0039,0x0707); 

147     Write_Cmd_Data(0x003C,0x0405);// 0504

148     Write_Cmd_Data(0x003D,0x0F02); 

149     //ram

150     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 Set

183 #define WINDOW_XADDR_END    0x0051 // Horizontal End Address Set

184 #define WINDOW_YADDR_START    0x0052 // Vertical Start Address Set

185 #define WINDOW_YADDR_END    0x0053 // Vertical End Address Set

186 #define GRAM_XADDR            0x0020 // GRAM Horizontal Address Set

187 #define GRAM_YADDR            0x0021 // GRAM Vertical Address Set

188 #define GRAMWR                 0x0022 // memory write

189 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 }

本篇中资源链接:http://pan.baidu.com/s/1bnjw1Fh

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





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址