一、模块来源
采购链接: 1.47寸lcd显示屏高清ips172x320 st7789驱动液晶屏高清液晶显示屏
资料下载链接: https://pan.baidu.com/s/15OWpndYzyW8kFPqmfKNfxQ
资料提取码:8888
二、规格参数
工作电压:3.3V
工作电流:90MA
模块尺寸:30(H) x 37(V) MM
像素大小:172(H) x 320(V)RGB
驱动芯片:ST7789V3
通信协议:SPI
管脚数量:8 Pin(2.54mm间距排针)
以上信息见厂家资料文件
三、移植过程
我们的目标是将例程移植至MSPM0G3507开发板上。按照以下步骤,即可完成移植。
- 将源码导入工程;
- 根据编译报错处进行粗改;
- 修改引脚配置;
- 修改时序配置;
- 移植验证。
1、查看资料
打开厂家资料例程(例程下载见百度网盘链接下载)。具体路径见例程路径
2、移植至工程
将厂家资料路径下的【LCD】文件夹,复制到自己的工程中。(工程可以参考工程模板)
我们导入工程,将我们刚刚复制到文件夹中的文件,导入C文件和路径。
将lcd_init.h文件下的 sys.h 改为 tjx_init.h。还要将lcd.h文件下的 sys.h 改为 tjx_init.h
TIP
(在左边将lcd.c和lcd_init.c的工程目录展开,就发现有lcd_init.h和lcd.h)
3、引脚选择
该屏幕需要设置8个接口,具体接口说明见 各引脚说明。
模块为SPI通信协议的从机,SCL为SPI信号线(SCK),SDA为SPI输出线(MOSI),CS为SPI片选线(NSS)。 如果MCU的GPIO引脚不足,可以将屏幕的两个引脚接口不接入MCU的GPIO。
- 将RES接入MCU的复位引脚,当MCU复位时,屏幕也跟着复位;
- 可以将BLK接入3.3V或悬空,代价是无法控制背光亮度。
硬件SPI移植
GND | GND |
VCC | 3V3 |
SCL | GPIO52 |
SDA | GPIO50 |
RES | GPIO48 |
DC | GPIO30 |
CS | GPIO53 |
BLK | GPIO14 |
接下来我们配置 SYSCONFIG
- 双击 c2000.syscfg 文件,打开它。
- 点击 ADD 添加GPIO配置
- 添加配置【根据下方图片进行添加】
4根引脚一样的配置,除了名字不一样
- 点击ADD添加SPI配置
- 配置SPI
Ctrl + S
保存配置文件Ctrl + B
构建工一次工程(可能会报错,我们不用管!)然后我们所有设定的引脚和功能就会在 board.h 中定义。因为这个文件我们包含进了 tjx_init.h 所以我们只需要引用 tjx_init.h 即可。【这里的 tjx_init.h 就充当了芯片头文件的作用】
选择好引脚后,进入工程开始编写屏幕引脚初始化代码。
我们更改 lcd_init.h
中的 LCD
端口定义
//-----------------LCD端口定义----------------
#define LCD_RES_Clr() GPIO_writePin(LCD_RES, 0)//RES
#define LCD_RES_Set() GPIO_writePin(LCD_RES, 1)
#define LCD_DC_Clr() GPIO_writePin(LCD_DC,0)//DC
#define LCD_DC_Set() GPIO_writePin(LCD_DC,1)
#define LCD_CS_Clr() GPIO_writePin(LCD_CS,0)//CS
#define LCD_CS_Set() GPIO_writePin(LCD_CS,1)
#define LCD_BLK_Clr() GPIO_writePin(LCD_BLK,0)//BLK
#define LCD_BLK_Set() GPIO_writePin(LCD_BLK,1)
2
3
4
5
6
7
8
9
10
11
12
13
引脚初始化函数见如下代码。因为引脚已经在 SYSCONFIG 中自动配置了,不需要进行初始化了。
void LCD_GPIO_Init(void)
{
}
2
3
4
将 lcd_init.c
中的 LCD_Writ_Bus
函数替换成下面的代码:
/******************************************************************************
函数说明:LCD串行数据写入函数
入口数据:dat 要写入的串行数据
返回值: 无
******************************************************************************/
void LCD_Writ_Bus(u8 dat)
{
uint8_t recv_data = 0;
LCD_CS_Clr();
// Transmit data
SPI_writeDataNonBlocking(SPI_LCD_BASE, dat<<8);
// Block until data is received and then return it
recv_data = SPI_readDataBlockingNonFIFO(SPI_LCD_BASE);
LCD_CS_Set();
return recv_data;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
打开 lcd.c
文件将 LCD_ShowChinese
函数中的 s+=2
改为 s+=3
:
打开 lcdfont.c
文件将 typFNT_GB12
、typFNT_GB16
、typFNT_GB24
、typFNT_GB32
、 结构体中的 Index[2]
改为 Index[3]
例如:
到这里就移植完成了,可以进行移植验证。
四、关键代码
lcd_init.c
#include "lcd_init.h"
// #include "delay.h"
void LCD_GPIO_Init(void)
{
}
/******************************************************************************
函数说明:LCD串行数据写入函数
入口数据:dat 要写入的串行数据
返回值: 无
******************************************************************************/
void LCD_Writ_Bus(u8 dat)
{
uint8_t recv_data = 0;
LCD_CS_Clr();
// Transmit data
SPI_writeDataNonBlocking(SPI_LCD_BASE, dat<<8);
// Block until data is received and then return it
recv_data = SPI_readDataBlockingNonFIFO(SPI_LCD_BASE);
LCD_CS_Set();
return recv_data;
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA8(u8 dat)
{
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA(u16 dat)
{
LCD_Writ_Bus(dat>>8);
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入命令
入口数据:dat 写入的命令
返回值: 无
******************************************************************************/
void LCD_WR_REG(u8 dat)
{
LCD_DC_Clr();//写命令
LCD_Writ_Bus(dat);
LCD_DC_Set();//写数据
}
/******************************************************************************
函数说明:设置起始和结束地址
入口数据:x1,x2 设置列的起始和结束地址
y1,y2 设置行的起始和结束地址
返回值: 无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
if(USE_HORIZONTAL==0)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+34);
LCD_WR_DATA(x2+34);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1);
LCD_WR_DATA(y2);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==1)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1+34);
LCD_WR_DATA(x2+34);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1);
LCD_WR_DATA(y2);
LCD_WR_REG(0x2c);//储存器写
}
else if(USE_HORIZONTAL==2)
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);
LCD_WR_DATA(x2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+34);
LCD_WR_DATA(y2+34);
LCD_WR_REG(0x2c);//储存器写
}
else
{
LCD_WR_REG(0x2a);//列地址设置
LCD_WR_DATA(x1);
LCD_WR_DATA(x2);
LCD_WR_REG(0x2b);//行地址设置
LCD_WR_DATA(y1+34);
LCD_WR_DATA(y2+34);
LCD_WR_REG(0x2c);//储存器写
}
}
void LCD_Init(void)
{
LCD_GPIO_Init();//初始化GPIO
LCD_RES_Clr();//复位
delay_ms(30);
LCD_RES_Set();
delay_ms(100);
LCD_BLK_Set();//打开背光
delay_ms(100);
//
LCD_WR_REG(0x11);
// delay_ms(120);
LCD_WR_REG(0x36);
if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
else LCD_WR_DATA8(0xA0);
LCD_WR_REG(0x3A);
LCD_WR_DATA8(0x05);
LCD_WR_REG(0xB2);
LCD_WR_DATA8(0x0C);
LCD_WR_DATA8(0x0C);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x33);
LCD_WR_DATA8(0x33);
LCD_WR_REG(0xB7);
LCD_WR_DATA8(0x35);
LCD_WR_REG(0xBB);
LCD_WR_DATA8(0x35);
LCD_WR_REG(0xC0);
LCD_WR_DATA8(0x2C);
LCD_WR_REG(0xC2);
LCD_WR_DATA8(0x01);
LCD_WR_REG(0xC3);
LCD_WR_DATA8(0x13);
LCD_WR_REG(0xC4);
LCD_WR_DATA8(0x20);
LCD_WR_REG(0xC6);
LCD_WR_DATA8(0x0F);
LCD_WR_REG(0xD0);
LCD_WR_DATA8(0xA4);
LCD_WR_DATA8(0xA1);
LCD_WR_REG(0xD6);
LCD_WR_DATA8(0xA1);
LCD_WR_REG(0xE0);
LCD_WR_DATA8(0xF0);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x29);
LCD_WR_DATA8(0x33);
LCD_WR_DATA8(0x3E);
LCD_WR_DATA8(0x38);
LCD_WR_DATA8(0x12);
LCD_WR_DATA8(0x12);
LCD_WR_DATA8(0x28);
LCD_WR_DATA8(0x30);
LCD_WR_REG(0xE1);
LCD_WR_DATA8(0xF0);
LCD_WR_DATA8(0x07);
LCD_WR_DATA8(0x0A);
LCD_WR_DATA8(0x0D);
LCD_WR_DATA8(0x0B);
LCD_WR_DATA8(0x07);
LCD_WR_DATA8(0x28);
LCD_WR_DATA8(0x33);
LCD_WR_DATA8(0x3E);
LCD_WR_DATA8(0x36);
LCD_WR_DATA8(0x14);
LCD_WR_DATA8(0x14);
LCD_WR_DATA8(0x29);
LCD_WR_DATA8(0x32);
// LCD_WR_REG(0x2A);
// LCD_WR_DATA8(0x00);
// LCD_WR_DATA8(0x22);
// LCD_WR_DATA8(0x00);
// LCD_WR_DATA8(0xCD);
// LCD_WR_DATA8(0x2B);
// LCD_WR_DATA8(0x00);
// LCD_WR_DATA8(0x00);
// LCD_WR_DATA8(0x01);
// LCD_WR_DATA8(0x3F);
// LCD_WR_REG(0x2C);
LCD_WR_REG(0x21);
LCD_WR_REG(0x11);
delay_ms(120);
LCD_WR_REG(0x29);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
lcd_init.h
#ifndef __LCD_INIT_H
#define __LCD_INIT_H
#include "tjx_init.h"
#define USE_HORIZONTAL 2 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏
#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 172
#define LCD_H 320
#else
#define LCD_W 320
#define LCD_H 172
#endif
//-----------------LCD端口定义----------------
#define LCD_RES_Clr() GPIO_writePin(LCD_RES, 0)//RES
#define LCD_RES_Set() GPIO_writePin(LCD_RES, 1)
#define LCD_DC_Clr() GPIO_writePin(LCD_DC,0)//DC
#define LCD_DC_Set() GPIO_writePin(LCD_DC,1)
#define LCD_CS_Clr() GPIO_writePin(LCD_CS,0)//CS
#define LCD_CS_Set() GPIO_writePin(LCD_CS,1)
#define LCD_BLK_Clr() GPIO_writePin(LCD_BLK,0)//BLK
#define LCD_BLK_Set() GPIO_writePin(LCD_BLK,1)
void LCD_GPIO_Init(void);//初始化GPIO
void LCD_Writ_Bus(u8 dat);//模拟SPI时序
void LCD_WR_DATA8(u8 dat);//写入一个字节
void LCD_WR_DATA(u16 dat);//写入两个字节
void LCD_WR_REG(u8 dat);//写入一个指令
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2);//设置坐标函数
void LCD_Init(void);//LCD初始化
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
五、移植验证
在 empty_driverlib_main.c
中输入代码如下:
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "c2000ware_libraries.h"
#include "tjx_init.h"
#include "lcd_init.h"
#include "lcd.h"
#include "pic.h"
void main(void)
{
/* The initialization code automatically generated by CCS [Start] */
Device_init();
Device_initGPIO();
Interrupt_initModule();
Interrupt_initVectorTable();
Board_init();
C2000Ware_libraries_init();
EINT;
ERTM;
/* The initialization code automatically generated by CCS [End] */
lc_printf("\r\n= = = = = = = = = = = = = = = = = = = = = = = = =\r\n");
lc_printf("\r\n=== Welcome to use the LC-TJX-TMS320F28P550 ====\r\n");
lc_printf("\r\n============== www.lckfb.com ===================\r\n");
lc_printf("\r\n============== wiki.lckfb.com ==================\r\n");
lc_printf("\r\n= = = = = = = = = = = = = = = = = = = = = = = = =\r\n");
float t = 0;
LCD_Init(); //LCD初始化
LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
delay_ms(1000);
LCD_Fill(0,0,LCD_W,LCD_H,RED);
delay_ms(1000);
LCD_Fill(0,0,LCD_W,LCD_H,GREEN);
delay_ms(1000);
LCD_Fill(0,0,LCD_W,LCD_H,BLUE);
delay_ms(1000);
LCD_Fill(0,0,LCD_W,LCD_H,WHITE);
delay_ms(1000);
while(1)
{
LCD_ShowChinese(40,0,(const char *)"中景园电子",RED,WHITE,32,0);
LCD_ShowString(10,33,"LCD_W:",RED,WHITE,32,0);
LCD_ShowIntNum(106,33,LCD_W,3,RED,WHITE,32);
LCD_ShowString(10,66,"LCD_H:",RED,WHITE,32,0);
LCD_ShowIntNum(106,66,LCD_H,3,RED,WHITE,32);
LCD_ShowFloatNum1(10,99,t,4,RED,WHITE,32);
t+=0.11;
LCD_ShowPicture(160,95,40,40,gImage_1);
delay_ms(100);
}
}
__interrupt void INT_Debug_Serial_RX_ISR(void)
{
//清除接收中断标志位
SCI_clearInterruptStatus(SCIA_BASE, SCI_INT_RXFF);
//清除中断标志位
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
然后编译,调试烧录。
不知道如何操作的可以去看CCS的入门手册
上电效果:
【代码下载】
- 跳转到
下载中心
去下载CCS模块移植代码:【点击跳转🚀】