新建STemWin工程STemWin篇1

Posted:   2020-09-17

Status:   Completed

Tags :   STM32 emWin STemWin

Categories :   STM32 emWin STemWin

Previous:   STM32标准外设库RTC SPL篇25

Next:   GUIBuidler的使用STemWin篇2


参考文档

STemWin参考例程

  • 官方例程在emWin官方库SeggerEval_WIN32_MSVC_MinGW_GUI_V548\Sample\Tutorial
  • emWin库

StemWin库分析

  • 最新版StemWin库集成到STM32CubeFW对应的软件包中了
  • 在Cube库Middlewares\ST\

STemWin文件

  • Config: 包含库和LCD驱动程序的配置文件
  • Documentation: 包含emWin“用户和参考指南”
  • inc :包含库组件的头文件
  • Lib :包含作为对象代码库绑定于 STM32 产品,可在所有基于CortexM0,CortexM3,CortexM4F 或CortexM7内核的STM32设备上运行,无论是否支持操作系统.
    命名格式为STemWin_CM x _ YY_wc_ot_zzzz .a,其中
    • x:CMx核心类别(CM0,CM3,CM4或CM7)
    • YY:操作系统支持
    • wc: Wchar_t类型大小(wc16或wc32)
    • ot: 高速优化生成的二进制文件
    • zzzz:支持ARGB
  • OS: 包含与RTOS的库接口
  • Simulation:以预编译的库格式包含WIN32的系统资源
  • Software: 包含软件工具(位图转换器,字体转换器,GUIBuilder,JPEG2Movie,emVNC,U2C,Bin2C和emWinPlayer)
  • Release_Notes.html 关于emWin 库不同发行版本的简要更新说明文档

配置文件解析

  • 配置系统功能GUIConf.h
1
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
#ifndef GUICONF_H
#define GUICONF_H

/*********************************************************************
*
*       Multi layer/display support
*/
#define GUI_NUM_LAYERS            2    // Maximum number of available layers//设置了emWin 最大支持的显示图层数

/*********************************************************************
*
*       Multi tasking support
*/
#ifdef OS_SUPPORT
 #define GUI_OS                    (1)  // Compile with multitasking support //是否支持操作系统和多任务功能
#else
 #define GUI_OS                    (0)
#endif

/*********************************************************************
*
*       Configuration of touch support
*/
#ifndef   GUI_SUPPORT_TOUCH
  #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen //是否支持触摸操作
#endif

/*********************************************************************
*
*       Default font
*/
#define GUI_DEFAULT_FONT          &GUI_Font6x8 //默认字体大小

/*********************************************************************
*
*         Configuration of available packages
*/
#define GUI_SUPPORT_MOUSE             (1)    /* Support a mouse *///是否启用鼠标
#define GUI_WINSUPPORT                (1)    /* Use window manager *///是否使用窗口管理器
#define GUI_SUPPORT_MEMDEV            (1)    /* Memory device package available *///是否使用内存设备
#define GUI_SUPPORT_DEVICES           (1)    /* Enable use of device pointers *///是否使用设备指针

#endif  /* Avoid multiple inclusion */

  • 配置操作系统接口GUI_X_OS.c
操作系统接口 功能
GUI_X_GetTime 获取当前系统时间(单位:毫秒)
GUI_X_Delay 延时函数(单位:毫秒)
GUI_X_ExecIdle 窗口管理器空闲时调用
GUI_X_InitOS 创建互斥信号量和二值信号量
GUI_X_Unlock 互斥解锁
GUI_X_Lock 互斥锁定
GUI_X_GetTaskId 获取当前任务句柄
GUI_X_WaitEvent 等待二值信号量
GUI_X_SignalEvent 发送二值信号量
  • 无操作系统时用GUI_X.c
操作系统接口 功能
GUI_X_GetTime 获取当前系统时间(单位:毫秒)
GUI_X_Delay 延时函数(单位:毫秒)
GUI_X_Init 初始化
GUI_X_ExecIdle 窗口管理器空闲时调用
  • 配置显示驱动接口LCDConf_FlexColor.c
显示驱动接口 功能
LcdWriteReg 向液晶屏寄存器写入命令功能
LcdWriteData 向液晶屏寄存器写入单字节
LcdWriteDataMultiple 向液晶屏寄存器写入多个字节
LcdReadDataMultiple 读取多个字节
LCD_X_Config 创建一个显示驱动器件,设置颜色转换程序,并配置物理显示尺寸
LCD_X_DisplayDriver 对不同的液晶层进行控制或初始化
  • 配置触摸接口
触摸驱动接口 功能
GUI_TOUCH_X_ActivateX 准备X 轴的测量
GUI_TOUCH_X_ActivateX 准备Y 轴的测量
GUI_TOUCH_X_ActivateX 返回A / D 转换器的X 轴结果
GUI_TOUCH_X_ActivateX 返回A / D 转换器的Y 轴结果

STemWin移植

新建工程

添加库函数

  • 打开 Manage Run-Time Environment
  • 选择Device->Startup
  • 选择Device->StdPeriph Drivers->SPI
  • 选择Device->StdPeriph Drivers->GPIO
  • 选择Device->StdPeriph Drivers->USART

添加开发板程序

  • 复制触摸屏程序的my_usart.cmy_usart.h,my_gpio.cmy_gpio.h,my_ILI9341.c,my_ILI9341.h,my_XPT2046.c,my_XPT2046.h到工程
  • 复制SD卡工程的my_SD.cmy_SD.h到工程
  • 添加以上文件

修改LCD驱动

  • my_ILI9341.h
1
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
#ifndef __MY_ILI9341_H
#define __MY_ILI9341_H
#include "stm32f10x.h"
/******************************* ILI9341 显示屏8080通讯引脚定义 ***************************/
/******控制信号线******/
//片选
#define ILI9341_CS_CLK      RCC_APB2Periph_GPIOC
#define ILI9341_CS_PORT     GPIOC
#define ILI9341_CS_PIN      GPIO_Pin_4

//DC引脚
#define ILI9341_DC_CLK      RCC_APB2Periph_GPIOC
#define ILI9341_DC_PORT     GPIOC
#define ILI9341_DC_PIN      GPIO_Pin_7

//写使能
#define ILI9341_WR_CLK      RCC_APB2Periph_GPIOC
#define ILI9341_WR_PORT     GPIOC
#define ILI9341_WR_PIN      GPIO_Pin_6

//读使能
#define ILI9341_RD_CLK      RCC_APB2Periph_GPIOC
#define ILI9341_RD_PORT     GPIOC
#define ILI9341_RD_PIN      GPIO_Pin_5
//复位引脚直接使用NRST,开发板复位的时候会使液晶复位


//背光引脚
#define ILI9341_BK_CLK      RCC_APB2Periph_GPIOD
#define ILI9341_BK_PORT     GPIOD
#define ILI9341_BK_PIN      GPIO_Pin_2

/********数据信号线***************/
#define ILI9341_DATA_CLK    RCC_APB2Periph_GPIOB
#define ILI9341_DATA_PORT   GPIOB
#define ILI9341_DATA_PIN    GPIO_Pin_All

/********信号线控制相关的宏***************/
#define ILI9341_CS_SET      ILI9341_CS_PORT->BSRR=ILI9341_CS_PIN  //片选端口  		
#define	ILI9341_DC_SET      ILI9341_DC_PORT->BSRR=ILI9341_DC_PIN  //数据/命令 	  
#define	ILI9341_WR_SET      ILI9341_WR_PORT->BSRR=ILI9341_WR_PIN  //写数据			
#define	ILI9341_RD_SET      ILI9341_RD_PORT->BSRR=ILI9341_RD_PIN  //读数据			

#define	ILI9341_CS_CLR      ILI9341_CS_PORT->BRR=ILI9341_CS_PIN   //片选端口  		
#define	ILI9341_DC_CLR      ILI9341_DC_PORT->BRR=ILI9341_DC_PIN   //数据/命令		     
#define	ILI9341_WR_CLR      ILI9341_WR_PORT->BRR=ILI9341_WR_PIN   //写数据			
#define	ILI9341_RD_CLR      ILI9341_RD_PORT->BRR=ILI9341_RD_PIN   //读数据			

//数据线输入输出
#define DATAOUT(x)          ILI9341_DATA_PORT->ODR=x; //数据输出
#define DATAIN              ILI9341_DATA_PORT->IDR;   //数据输入	


/*************************************** 调试预用 ******************************************/
#define DEBUG_DELAY()       ILI9341_Delay(0xFFFF)

/***************************** ILI934 显示区域的起始坐标和总行列数 ***************************/
#define ILI9341_DispWindow_X_Star   0 //起始点的X坐标
#define ILI9341_DispWindow_Y_Star   0 //起始点的Y坐标

#define ILI9341_LESS_PIXEL	240   //液晶屏较短方向的像素宽度
#define ILI9341_MORE_PIXEL	320   //液晶屏较长方向的像素宽度


/******************************* 定义 ILI934 常用命令 ********************************/
#define CMD_SetCoordinateX  0x2A  //设置X坐标
#define CMD_SetCoordinateY  0x2B  //设置Y坐标
#define CMD_SetPixel        0x2C  //填充像素

/********************************** 声明 ILI934 函数 ***************************************/
void  ILI9341_Init( void );
void  ILI9341_BackLed_Control( FunctionalState enumState );
void  ILI9341_GramScan( uint8_t ucOtion );
uint16_t  ILI9341_Read_ID(void);

__inline void ILI9341_Write_Cmd( uint16_t usCmd );
__inline void ILI9341_Write_Data( uint16_t usData );
__inline uint16_t ILI9341_Read_Data( void );

#endif

  • my_ILI9341.c
1
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
#include "my_ILI9341.h"

//根据液晶扫描方向而变化的XY像素宽度
//调用ILI9341_GramScan函数设置方向时会自动更改
uint16_t LCD_X_LENGTH = ILI9341_LESS_PIXEL;
uint16_t LCD_Y_LENGTH = ILI9341_MORE_PIXEL;

//液晶屏扫描模式,本变量主要用于方便选择触摸屏的计算参数
//参数可选值为0-7
//调用ILI9341_GramScan函数设置方向时会自动更改
//LCD刚初始化完成时会使用本默认值
uint8_t LCD_SCAN_MODE = 6;

static void ILI9341_Delay( __IO uint32_t nCount );
static void ILI9341_GPIO_Config( void );
static void ILI9341_REG_Config( void );

/**
  * @brief  用于 ILI9341 简单延时函数
  * @param  nCount :延时计数值
  * @retval 无
  */
static void ILI9341_Delay ( __IO uint32_t nCount )
{
    for ( ; nCount != 0; nCount -- );

}
/**
  * @brief  向ILI9341写入命令
  * @param  usCmd :要写入的命令(表寄存器地址)
  * @retval 无
  */
__inline void ILI9341_Write_Cmd ( uint16_t usCmd )
{
    ILI9341_CS_CLR;//开始片选
    ILI9341_DC_CLR;//写命令
    ILI9341_RD_SET;//禁止读
    DATAOUT(usCmd);//输出命令
    ILI9341_WR_CLR;//写入开始
    ILI9341_WR_SET;//写入结束
    ILI9341_CS_SET;//结束片选
}
/**
  * @brief  向ILI9341写入数据
  * @param  usData :要写入的数据
  * @retval 无
  */
__inline void ILI9341_Write_Data ( uint16_t usData )
{
    ILI9341_CS_CLR;//开始片选
    ILI9341_DC_SET;//写数据
    ILI9341_RD_SET;//禁止读
    DATAOUT(usData);//输出数据
    ILI9341_WR_CLR;//写入开始
    ILI9341_WR_SET;//写入结束
    ILI9341_CS_SET;//结束片选
}

/**
  * @brief  从ILI9341读取数据
  * @param  无
  * @retval 读取到的数据
  */
__inline uint16_t ILI9341_Read_Data ( void )
{
    uint16_t data;
    ILI9341_DATA_PORT->CRL=0X88888888; //上拉输入
    ILI9341_DATA_PORT->CRH=0X88888888; //上拉输入
    ILI9341_DATA_PORT->ODR=0X0000;     //全部输出0

    ILI9341_DC_SET;
    ILI9341_WR_SET;

    ILI9341_CS_CLR;
    //读取数据
    ILI9341_RD_CLR;

    data=DATAIN;
    ILI9341_RD_SET;
    ILI9341_CS_SET;

    ILI9341_DATA_PORT->CRL=0X33333333; // 上拉输出
    ILI9341_DATA_PORT->CRH=0X33333333; // 上拉输出
    ILI9341_DATA_PORT->ODR=0XFFFF;    //全部输出高
    return data;
}
/**
  * @brief  初始化ILI9341的IO引脚
  * @param  无
  * @retval 无
  */
static void ILI9341_GPIO_Config ( void )
{
    GPIO_InitTypeDef GPIO_InitStructure;

    /* 使能复用IO时钟*/
    RCC_APB2PeriphClockCmd ( RCC_APB2Periph_AFIO, ENABLE );

    //复位引脚直接使用NRST,开发板复位的时候会使液晶复位

    /* 使能FSMC对应相应管脚时钟*/
    RCC_APB2PeriphClockCmd (
        /*控制信号*/
        ILI9341_CS_CLK|ILI9341_DC_CLK|ILI9341_WR_CLK|
        ILI9341_RD_CLK	|ILI9341_BK_CLK|
        /*数据信号*/
        ILI9341_DATA_CLK, ENABLE );

    //开启SWD,失能JTAG (部分PB引脚用在了jtag接口,改成SWD接口就不会有干扰)
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);


    /* 配置液晶相对应的数据线,PORT-D0~D15 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_Out_PP;

    GPIO_InitStructure.GPIO_Pin = ILI9341_DATA_PIN;
    GPIO_Init ( ILI9341_DATA_PORT, &GPIO_InitStructure );

    /* 配置液晶相对应的控制线
     * 读   			:LCD-RD
     * 写   			:LCD-WR
     * 片选   		:LCD-CS
     * 数据/命令 	:LCD-DC
     */
    GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN;
    GPIO_Init (ILI9341_RD_PORT, & GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = ILI9341_WR_PIN;
    GPIO_Init (ILI9341_WR_PORT, & GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN;
    GPIO_Init ( ILI9341_CS_PORT, & GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN;
    GPIO_Init ( ILI9341_DC_PORT, & GPIO_InitStructure );

    /* 配置LCD背光控制管脚BK*/
    GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN;
    GPIO_Init ( ILI9341_BK_PORT, &GPIO_InitStructure );
}


/**
 * @brief  初始化ILI9341寄存器
 * @param  无
 * @retval 无
 */
static void ILI9341_REG_Config ( void )
{
    /*  Power control B (CFh)  */
    DEBUG_DELAY  ();
    ILI9341_Write_Cmd ( 0xCF  );
    ILI9341_Write_Data ( 0x00  );
    ILI9341_Write_Data ( 0x81  );
    ILI9341_Write_Data ( 0x30  );

    /*  Power on sequence control (EDh) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xED );
    ILI9341_Write_Data ( 0x64 );
    ILI9341_Write_Data ( 0x03 );
    ILI9341_Write_Data ( 0x12 );
    ILI9341_Write_Data ( 0x81 );

    /*  Driver timing control A (E8h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xE8 );
    ILI9341_Write_Data ( 0x85 );
    ILI9341_Write_Data ( 0x10 );
    ILI9341_Write_Data ( 0x78 );

    /*  Power control A (CBh) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xCB );
    ILI9341_Write_Data ( 0x39 );
    ILI9341_Write_Data ( 0x2C );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x34 );
    ILI9341_Write_Data ( 0x02 );

    /* Pump ratio control (F7h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xF7 );
    ILI9341_Write_Data ( 0x20 );

    /* Driver timing control B */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xEA );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );

    /* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xB1 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x1B );

    /*  Display Function Control (B6h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xB6 );
    ILI9341_Write_Data ( 0x0A );
    ILI9341_Write_Data ( 0xA2 );

    /* Power Control 1 (C0h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xC0 );
    ILI9341_Write_Data ( 0x35 );

    /* Power Control 2 (C1h) */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0xC1 );
    ILI9341_Write_Data ( 0x11 );

    /* VCOM Control 1 (C5h) */
    ILI9341_Write_Cmd ( 0xC5 );
    ILI9341_Write_Data ( 0x45 );
    ILI9341_Write_Data ( 0x45 );

    /*  VCOM Control 2 (C7h)  */
    ILI9341_Write_Cmd ( 0xC7 );
    ILI9341_Write_Data ( 0xA2 );

    /* Enable 3G (F2h) */
    ILI9341_Write_Cmd ( 0xF2 );
    ILI9341_Write_Data ( 0x00 );

    /* Gamma Set (26h) */
    ILI9341_Write_Cmd ( 0x26 );
    ILI9341_Write_Data ( 0x01 );
    DEBUG_DELAY ();

    /* Positive Gamma Correction */
    ILI9341_Write_Cmd ( 0xE0 ); //Set Gamma
    ILI9341_Write_Data ( 0x0F );
    ILI9341_Write_Data ( 0x26 );
    ILI9341_Write_Data ( 0x24 );
    ILI9341_Write_Data ( 0x0B );
    ILI9341_Write_Data ( 0x0E );
    ILI9341_Write_Data ( 0x09 );
    ILI9341_Write_Data ( 0x54 );
    ILI9341_Write_Data ( 0xA8 );
    ILI9341_Write_Data ( 0x46 );
    ILI9341_Write_Data ( 0x0C );
    ILI9341_Write_Data ( 0x17 );
    ILI9341_Write_Data ( 0x09 );
    ILI9341_Write_Data ( 0x0F );
    ILI9341_Write_Data ( 0x07 );
    ILI9341_Write_Data ( 0x00 );

    /* Negative Gamma Correction (E1h) */
    ILI9341_Write_Cmd ( 0XE1 ); //Set Gamma
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x19 );
    ILI9341_Write_Data ( 0x1B );
    ILI9341_Write_Data ( 0x04 );
    ILI9341_Write_Data ( 0x10 );
    ILI9341_Write_Data ( 0x07 );
    ILI9341_Write_Data ( 0x2A );
    ILI9341_Write_Data ( 0x47 );
    ILI9341_Write_Data ( 0x39 );
    ILI9341_Write_Data ( 0x03 );
    ILI9341_Write_Data ( 0x06 );
    ILI9341_Write_Data ( 0x06 );
    ILI9341_Write_Data ( 0x30 );
    ILI9341_Write_Data ( 0x38 );
    ILI9341_Write_Data ( 0x0F );

    /* memory access control set */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0x36 );
    ILI9341_Write_Data ( 0xC8 );    /*竖屏  左上角到 (起点)到右下角 (终点)扫描方式*/
    DEBUG_DELAY ();

    /* column address control set */
    ILI9341_Write_Cmd ( CMD_SetCoordinateX );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0xEF );

    /* page address control set */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( CMD_SetCoordinateY );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x00 );
    ILI9341_Write_Data ( 0x01 );
    ILI9341_Write_Data ( 0x3F );

    /*  Pixel Format Set (3Ah)  */
    DEBUG_DELAY ();
    ILI9341_Write_Cmd ( 0x3a );
    ILI9341_Write_Data ( 0x55 );

    /* Sleep Out (11h)  */
    ILI9341_Write_Cmd ( 0x11 );
    ILI9341_Delay ( 0xAFFf<<2 );
    DEBUG_DELAY ();

    /* Display ON (29h) */
    ILI9341_Write_Cmd ( 0x29 );

}

/**
 * @brief  ILI9341读取芯片ID函数,可用于测试底层的读写函数
 * @param  无
 * @retval 正常时返回值为 0x9341
 */
uint16_t ILI9341_Read_ID(void)
{
    uint16_t id = 0;

    ILI9341_Write_Cmd(0xD3);
    ILI9341_Read_Data();
    ILI9341_Read_Data();
    id = ILI9341_Read_Data();
    id<<=8;
    id|=ILI9341_Read_Data();

    return id;

}

/**
 * @brief  ILI9341初始化函数,如果要用到lcd,一定要调用这个函数
 * @param  无
 * @retval 无
 */
void ILI9341_Init ( void )
{
    ILI9341_GPIO_Config ();

    ILI9341_BackLed_Control ( ENABLE );      //点亮LCD背光灯

    ILI9341_REG_Config ();

    //设置默认扫描方向,其中 6 模式为大部分液晶例程的默认显示方向
    ILI9341_GramScan(LCD_SCAN_MODE);
}


/**
 * @brief  ILI9341背光LED控制
 * @param  enumState :决定是否使能背光LED
  *   该参数为以下值之一:
  *     @arg ENABLE :使能背光LED
  *     @arg DISABLE :禁用背光LED
 * @retval 无
 */
void ILI9341_BackLed_Control ( FunctionalState enumState )
{
    if ( enumState )
        GPIO_ResetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN );
    else
        GPIO_SetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN );

}
/**
 * @brief  设置ILI9341的GRAM的扫描方向
 * @param  ucOption :选择GRAM的扫描方向
 *     @arg 0-7 :参数可选值为0-7这八个方向
 *
 *	!!!其中0、3、5、6 模式适合从左至右显示文字,
 *				不推荐使用其它模式显示文字	其它模式显示文字会有镜像效果
 *
 *	其中0、2、4、6 模式的X方向像素为240,Y方向像素为320
 *	其中1、3、5、7 模式下X方向像素为320,Y方向像素为240
 *
 *	其中 6 模式为大部分液晶例程的默认显示方向
 *	其中 3 模式为摄像头例程使用的方向
 *	其中 0 模式为BMP图片显示例程使用的方向
 *
 * @retval 无
 * @note  坐标图例:A表示向上,V表示向下,<表示向左,>表示向右
					X表示X轴,Y表示Y轴

------------------------------------------------------------
模式0:       . 模式1:      . 模式2:     .  模式3:
          A  .          A  .  A         .   A
          |  .          |  .  |         .   |
          Y  .          X  .  Y         .   X
          0  .          1  .  2         .   3
  <--- X0 o  .  <----Y1 o  .  o 2X--->  .   o 3Y--->
------------------------------------------------------------
模式4:      . 模式5:     . 模式6:    .  模式7:
  <--- X4 o  .  <--- Y5 o  .  o 6X--->  .   o 7Y--->
          4  .          5  .  6         .   7
          Y  .          X  .  Y         .   X
          |  .          |  .  |         .   |
          V  .          V  .  V         .   V
---------------------------------------------------------
                    LCD屏示例
                |-----------------|
                |                 |
                |                 |
                |                 |
                |                 |
                |                 |
                |                 |
                |                 |
                |                 |
                |                 |
                |-----------------|
                屏幕正面(宽240,高320)

 *******************************************************/
void ILI9341_GramScan ( uint8_t ucOption )
{
    //参数检查,只可输入0-7
    if(ucOption >7 )
        return;

    //根据模式更新LCD_SCAN_MODE的值,主要用于触摸屏选择计算参数
    LCD_SCAN_MODE = ucOption;

    //根据模式更新XY方向的像素宽度
    if(ucOption%2 == 0)
    {
        //0 2 4 6模式下X方向像素宽度为240,Y方向为320
        LCD_X_LENGTH = ILI9341_LESS_PIXEL;
        LCD_Y_LENGTH =	ILI9341_MORE_PIXEL;
    }
    else
    {
        //1 3 5 7模式下X方向像素宽度为320,Y方向为240
        LCD_X_LENGTH = ILI9341_MORE_PIXEL;
        LCD_Y_LENGTH =	ILI9341_LESS_PIXEL;
    }

    //0x36命令参数的高3位可用于设置GRAM扫描方向
    ILI9341_Write_Cmd ( 0x36 );
    ILI9341_Write_Data ( 0x08 |(ucOption<<5));//根据ucOption的值设置LCD参数,共0-7种模式
    ILI9341_Write_Cmd ( CMD_SetCoordinateX );
    ILI9341_Write_Data ( 0x00 );		/* x 起始坐标高8位 */
    ILI9341_Write_Data ( 0x00 );		/* x 起始坐标低8位 */
    ILI9341_Write_Data ( ((LCD_X_LENGTH-1)>>8)&0xFF ); /* x 结束坐标高8位 */
    ILI9341_Write_Data ( (LCD_X_LENGTH-1)&0xFF );				/* x 结束坐标低8位 */

    ILI9341_Write_Cmd ( CMD_SetCoordinateY );
    ILI9341_Write_Data ( 0x00 );		/* y 起始坐标高8位 */
    ILI9341_Write_Data ( 0x00 );		/* y 起始坐标低8位 */
    ILI9341_Write_Data ( ((LCD_Y_LENGTH-1)>>8)&0xFF );	/* y 结束坐标高8位 */
    ILI9341_Write_Data ( (LCD_Y_LENGTH-1)&0xFF );				/* y 结束坐标低8位 */

    /* write gram start */
    ILI9341_Write_Cmd ( CMD_SetPixel );
}

修改触摸屏驱动

  • my_XPT2046.h
1
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
#ifndef __MY_XPT2046_H
#define	__MY_XPT2046_H
#include "stm32f10x.h"

/******************************* XPT2046 触摸屏触摸信号指示引脚定义(不使用中断) ***************************/
#define XPT2046_PENIRQ_GPIO_CLK     RCC_APB2Periph_GPIOC
#define XPT2046_PENIRQ_GPIO_PORT    GPIOC
#define XPT2046_PENIRQ_GPIO_PIN     GPIO_Pin_12

//触屏信号有效电平
#define XPT2046_PENIRQ_ActiveLevel  0
#define XPT2046_PENIRQ_Read()       GPIO_ReadInputDataBit ( XPT2046_PENIRQ_GPIO_PORT, XPT2046_PENIRQ_GPIO_PIN )

/******************************* XPT2046 触摸屏模拟SPI引脚定义 ***************************/
#define XPT2046_SPI_GPIO_CLK        RCC_APB2Periph_GPIOC

#define XPT2046_SPI_CS_PIN          GPIO_Pin_9
#define XPT2046_SPI_CS_PORT         GPIOC

#define XPT2046_SPI_CLK_PIN         GPIO_Pin_8
#define XPT2046_SPI_CLK_PORT        GPIOC

#define XPT2046_SPI_MOSI_PIN        GPIO_Pin_10
#define XPT2046_SPI_MOSI_PORT       GPIOC

#define XPT2046_SPI_MISO_PIN        GPIO_Pin_11
#define XPT2046_SPI_MISO_PORT       GPIOC


#define XPT2046_CS_ENABLE()         GPIO_SetBits ( XPT2046_SPI_CS_PORT, XPT2046_SPI_CS_PIN )
#define XPT2046_CS_DISABLE()        GPIO_ResetBits ( XPT2046_SPI_CS_PORT, XPT2046_SPI_CS_PIN )

#define XPT2046_CLK_HIGH()          GPIO_SetBits ( XPT2046_SPI_CLK_PORT, XPT2046_SPI_CLK_PIN )
#define XPT2046_CLK_LOW()           GPIO_ResetBits ( XPT2046_SPI_CLK_PORT, XPT2046_SPI_CLK_PIN )

#define XPT2046_MOSI_1()            GPIO_SetBits ( XPT2046_SPI_MOSI_PORT, XPT2046_SPI_MOSI_PIN )
#define XPT2046_MOSI_0()            GPIO_ResetBits ( XPT2046_SPI_MOSI_PORT, XPT2046_SPI_MOSI_PIN )

#define XPT2046_MISO()              GPIO_ReadInputDataBit ( XPT2046_SPI_MISO_PORT, XPT2046_SPI_MISO_PIN )

/******************************* XPT2046 触摸屏参数定义 ***************************/

#define XPT2046_CHANNEL_X            0x90   //通道Y+的选择控制字	
#define XPT2046_CHANNEL_Y            0xD0   //通道X+的选择控制字



/******************************** XPT2046 触摸屏函数声明 **********************************/
void XPT2046_Init( void );
uint16_t XPT2046_ReadAdc_Fliter(uint8_t channel);

#endif

  • my_XPT2046.c
1
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
#include "my_XPT2046.h"

/******************************* 声明 XPT2046 相关的静态函数 ***************************/
static void XPT2046_DelayUS( __IO uint32_t ulCount );
static void XPT2046_WriteCMD( uint8_t ucCmd );
static uint16_t XPT2046_ReadCMD( void );


/**
  * @brief  XPT2046 初始化函数
  * @param  无
  * @retval 无
  */
void XPT2046_Init ( void )
{
    GPIO_InitTypeDef  GPIO_InitStructure;

    /* 开启GPIO时钟 */
    RCC_APB2PeriphClockCmd ( XPT2046_SPI_GPIO_CLK|XPT2046_PENIRQ_GPIO_CLK, ENABLE );

    /* 模拟SPI GPIO初始化 */
    GPIO_InitStructure.GPIO_Pin=XPT2046_SPI_CLK_PIN;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz ;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
    GPIO_Init(XPT2046_SPI_CLK_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XPT2046_SPI_MOSI_PIN;
    GPIO_Init(XPT2046_SPI_MOSI_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XPT2046_SPI_MISO_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(XPT2046_SPI_MISO_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = XPT2046_SPI_CS_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(XPT2046_SPI_CS_PORT, &GPIO_InitStructure);

    /* 拉低片选,选择XPT2046 */
    XPT2046_CS_DISABLE();

    //触摸屏触摸信号指示引脚,不使用中断
    GPIO_InitStructure.GPIO_Pin = XPT2046_PENIRQ_GPIO_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	 // 上拉输入
    GPIO_Init(XPT2046_PENIRQ_GPIO_PORT, &GPIO_InitStructure);
}
/**
  * @brief  用于 XPT2046 的简单微秒级延时函数
  * @param  nCount :延时计数值,单位为微妙
  * @retval 无
  */
static void XPT2046_DelayUS ( __IO uint32_t ulCount )
{
    uint32_t i;


    for ( i = 0; i < ulCount; i ++ )
    {
        uint8_t uc = 12;     //设置值为12,大约延1微秒

        while ( uc -- );     //延1微秒

    }

}
/**
  * @brief  XPT2046 的写入命令
  * @param  ucCmd :命令
  *   该参数为以下值之一:
  *     @arg 0x90 :通道Y+的选择控制字
  *     @arg 0xd0 :通道X+的选择控制字
  * @retval 无
  */
static void XPT2046_WriteCMD ( uint8_t ucCmd )
{
    uint8_t i;
    XPT2046_MOSI_0();

    XPT2046_CLK_LOW();

    for ( i = 0; i < 8; i ++ )
    {
        ( ( ucCmd >> ( 7 - i ) ) & 0x01 ) ? XPT2046_MOSI_1() : XPT2046_MOSI_0();

        XPT2046_DelayUS ( 5 );

        XPT2046_CLK_HIGH();

        XPT2046_DelayUS ( 5 );

        XPT2046_CLK_LOW();
    }
}
/**
  * @brief  XPT2046 的读取命令
  * @param  无
  * @retval 读取到的数据
  */
static uint16_t XPT2046_ReadCMD ( void )
{
    uint8_t i;
    uint16_t usBuf=0, usTemp;
    XPT2046_MOSI_0();

    XPT2046_CLK_HIGH();

    for ( i=0; i<12; i++ )
    {
        XPT2046_CLK_LOW();

        usTemp = XPT2046_MISO();

        usBuf |= usTemp << ( 11 - i );

        XPT2046_CLK_HIGH();

    }
    return usBuf;
}
/**
  * @brief  对 XPT2046 选择一个模拟通道后,启动ADC,并返回ADC采样结果
  * @param  ucChannel
  *   该参数为以下值之一:
  *     @arg 0x90 :通道Y+的选择控制字
  *     @arg 0xd0 :通道X+的选择控制字
  * @retval 该通道的ADC采样结果
  */
static uint16_t XPT2046_ReadAdc ( uint8_t ucChannel )
{
    XPT2046_WriteCMD ( ucChannel );

    return 	XPT2046_ReadCMD ();

}
#define SAMP_CNT 4
#define SAMP_CNT_DIV2 2
/*
*********************************************************************************************************
*	函 数 名: XPT2046_ReadAdc_Fliter
*	功能说明: 选择一个模拟通道,启动ADC,并返回ADC采样结果
*	形    参:_ucCh = 0x90 表示Y通道; 0xd0 表示X通道
*	返 回 值: 滤波后的12位ADC值
*********************************************************************************************************
*/
uint16_t XPT2046_ReadAdc_Fliter(uint8_t channel)
{
    uint8_t i, j, min;
    uint16_t temp;
    uint16_t tempXY[SAMP_CNT];

    static uint16_t adc_x = 0,adc_y = 0;
    if(XPT2046_PENIRQ_Read()== XPT2046_PENIRQ_ActiveLevel)
    {
        for(i = 0; i < SAMP_CNT; i++)
        {
            tempXY[i] = XPT2046_ReadAdc(channel);
        }
        // 降序排列
        for(i=0; i<SAMP_CNT-1; i++)
        {
            min=i;
            for (j=i+1; j<SAMP_CNT; j++)
            {
                if (tempXY[min] > tempXY[j]) min=j;
            }
            temp = tempXY[i];
            tempXY[i] = tempXY[min];
            tempXY[min] = temp;
        }

        // 设定阈值
        if((tempXY[SAMP_CNT_DIV2]-tempXY[SAMP_CNT_DIV2-1]) > 5)
        {
            /* 若两个中间值相差太远,则舍弃这个新数据,返回上一次的触摸数据*/
            if(channel == XPT2046_CHANNEL_Y )
                return adc_x; //x通道
            else
                return adc_y; //y通道

        }

        // 求中间值的均值
        if(channel == XPT2046_CHANNEL_Y)
        {
            adc_x = (tempXY[SAMP_CNT_DIV2]+tempXY[SAMP_CNT_DIV2-1]) / 2;
            return adc_x;
        }
        else
        {
            adc_y = (tempXY[SAMP_CNT_DIV2]+tempXY[SAMP_CNT_DIV2-1]) / 2;
            return adc_y;
        }

    }
    else
    {
        return 0;   //没有触摸,返回0
    }
}

添加FatFs库

  • 把FatFs-SD工程的source复制到工程
  • source文件夹下的文件添加到工程

添加FREERTOS库

  • 打开 Manage Run-Time Environment
  • 选择RTOSFreeRTOS
  • 选择RTOS->ConfigFreeRTOS
  • 点击Resolve会自动选择其他必须的选择
  • 配置FreeRTOSConfig.h
1
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
/*
 * FreeRTOS Kernel V10.2.0
 * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * http://www.FreeRTOS.org
 * http://aws.amazon.com/freertos
 *
 * 1 tab == 4 spaces!
 */


#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

/*-----------------------------------------------------------
 * Application specific definitions.
 *
 * These definitions should be adjusted for your particular hardware and
 * application requirements.
 *
 * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
 * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
 *
 * See http://www.freertos.org/a00110.html
 *----------------------------------------------------------*/

#if (defined(__ARMCC_VERSION) || defined(__GNUC__) || defined(__ICCARM__))
#include <stdint.h>

extern uint32_t SystemCoreClock;
#endif

/* Constants that describe the hardware and memory usage. */
#define configCPU_CLOCK_HZ                    (SystemCoreClock)
#define configTICK_RATE_HZ                    ((TickType_t)1000)
#define configTOTAL_HEAP_SIZE                 ((size_t)16*1024)
#define configMINIMAL_STACK_SIZE              ((uint16_t)128)
#define configSUPPORT_DYNAMIC_ALLOCATION      1
#define configSUPPORT_STATIC_ALLOCATION       0

/* Constants related to the behaviour or the scheduler. */
#define configMAX_PRIORITIES                  10
#define configUSE_PREEMPTION                  1
#define configUSE_TIME_SLICING                1
#define configIDLE_SHOULD_YIELD               1
#define configMAX_TASK_NAME_LEN               (16)
#define configUSE_16_BIT_TICKS                0

/* Software timer definitions. */
#define configUSE_TIMERS                      0
#define configTIMER_TASK_PRIORITY             configMAX_PRIORITIES-1
#define configTIMER_QUEUE_LENGTH              10
#define configTIMER_TASK_STACK_DEPTH          (configMINIMAL_STACK_SIZE * 2)

/* Constants that build features in or out. */
#define configUSE_MUTEXES                     1
#define configUSE_RECURSIVE_MUTEXES           1
#define configUSE_COUNTING_SEMAPHORES         1
#define configUSE_QUEUE_SETS                  1
#define configUSE_TASK_NOTIFICATIONS          1
#define configUSE_TRACE_FACILITY              1
#define configUSE_TICKLESS_IDLE               0
#define configUSE_APPLICATION_TASK_TAG        0
#define configUSE_NEWLIB_REENTRANT            0
#define configUSE_CO_ROUTINES                 0

/* Constants provided for debugging and optimisation assistance. */
#define configCHECK_FOR_STACK_OVERFLOW        0
#define configQUEUE_REGISTRY_SIZE             0
#define configASSERT( x )                     if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }

/* Constants that define which hook (callback) functions should be used. */
#define configUSE_IDLE_HOOK                   0
#define configUSE_TICK_HOOK                   0
#define configUSE_DAEMON_TASK_STARTUP_HOOK    0
#define configUSE_MALLOC_FAILED_HOOK          0

/* Port specific configuration. */
#define configENABLE_MPU                      0
#define configENABLE_FPU                      1
#define configENABLE_TRUSTZONE                1
#define configMINIMAL_SECURE_STACK_SIZE       ((uint32_t)1024)
#define configRUN_FREERTOS_SECURE_ONLY        0

/* Cortex-M specific definitions. */
#ifdef __NVIC_PRIO_BITS
  /* __NVIC_PRIO_BITS will be specified when CMSIS is being used. */
  #define configPRIO_BITS                     __NVIC_PRIO_BITS
#else
  /* 7 priority levels */
  #define configPRIO_BITS                     4
#endif

/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY       0x0F

/* The highest interrupt priority that can be used by any interrupt service
 * routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT
 * CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A
 * HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values). */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY  5

/* Interrupt priorities used by the kernel port layer itself.  These are generic
 * to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY               (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 * See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY          (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

/* Set the following definitions to 1 to include the API function, or zero
 * to exclude the API function.  NOTE:  Setting an INCLUDE_ parameter to 0 is
 * only necessary if the linker does not automatically remove functions that are
 * not referenced anyway. */
#define INCLUDE_vTaskPrioritySet              1
#define INCLUDE_uxTaskPriorityGet             1
#define INCLUDE_vTaskDelete                   1
#define INCLUDE_vTaskSuspend                  1
#define INCLUDE_vTaskDelayUntil               1
#define INCLUDE_vTaskDelay                    1
#define INCLUDE_xTaskGetIdleTaskHandle        1
#define INCLUDE_xTaskAbortDelay               1
#define INCLUDE_xQueueGetMutexHolder          1
#define INCLUDE_xSemaphoreGetMutexHolder      1
#define INCLUDE_xTaskGetHandle                1
#define INCLUDE_uxTaskGetStackHighWaterMark   1
#define INCLUDE_uxTaskGetStackHighWaterMark2  1
#define INCLUDE_eTaskGetState                 1
#define INCLUDE_xTaskResumeFromISR            1
#define INCLUDE_xTimerPendFunctionCall        0
#define INCLUDE_xTaskGetSchedulerState        1
#define INCLUDE_xTaskGetCurrentTaskHandle     1

/* Map the FreeRTOS port interrupt handlers to their CMSIS standard names. */
#define xPortPendSVHandler                    PendSV_Handler
#define vPortSVCHandler                       SVC_Handler
#define xPortSysTickHandler                   SysTick_Handler

#if (defined(__ARMCC_VERSION) || defined(__GNUC__) || defined(__ICCARM__))
/* Include debug event definitions */
#include "freertos_evr.h"
#endif

#endif /* FREERTOS_CONFIG_H */

添加STemWin库

  • 复制STemWin库到工程目录
  • Config,inc添加到工程Include Paths
  • GUIConf.c文件添加到工程
  • 复制GUI_X_OS.c文件为GUI_X_FREERTOS.c
  • 复制LCDConf_FlexColor_Template.c文件为LCDConf_FlexColor.c并添加到工程
  • 添加STemWin_CM3_OS_wc16_ARGB.a到工程,File TypeLibrary file

修改配置文件

配置系统功能

  • 在C/C++选项添加预编译OS_SUPPORT
  • GUIConf.h添加
1
#define GUI_USE_ARGB                  (1)

配置显示驱动接口

  • LCDConf_FlexColor.c
1
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
#include "GUI.h"
#include "GUIDRV_FlexColor.h"
#include "my_ILI9341.h"
/*********************************************************************
*
*       Layer configuration (to be modified)
*
**********************************************************************
*/

//
// Physical display size
//
#define XSIZE_PHYS  ILI9341_LESS_PIXEL // 设置屏幕分辨率
#define YSIZE_PHYS  ILI9341_MORE_PIXEL // 设置屏幕分辨率

//触摸校准数据
#define TOUCH_AD_TOP 	 				3670  //YPhys0
#define TOUCH_AD_BOTTOM  			223   //YPhys1
#define TOUCH_AD_LEFT 	 			208   //XPhys0
#define TOUCH_AD_RIGHT 	 			3492  //XPhys1
/*********************************************************************
*
*       Configuration checking
*
**********************************************************************
*/
#ifndef   VXSIZE_PHYS
  #define VXSIZE_PHYS XSIZE_PHYS
#endif
#ifndef   VYSIZE_PHYS
  #define VYSIZE_PHYS YSIZE_PHYS
#endif
#ifndef   XSIZE_PHYS
  #error Physical X size of display is not defined!
#endif
#ifndef   YSIZE_PHYS
  #error Physical Y size of display is not defined!
#endif
#ifndef   GUICC_565
  #error Color conversion not defined!
#endif
#ifndef   GUIDRV_FLEXCOLOR
  #error No display driver defined!
#endif

/*********************************************************************
*
*       Local functions
*
**********************************************************************
*/
/********************************************************************
*
*       LcdWriteReg
*
* Function description:
*   Sets display register
*/
static void LcdWriteReg(U16 Data) {
  // ... TBD by user
  ILI9341_Write_Cmd(Data);//写命令
}

/********************************************************************
*
*       LcdWriteData
*
* Function description:
*   Writes a value to a display register
*/
static void LcdWriteData(U16 Data) {
  // ... TBD by user
  ILI9341_Write_Data(Data);//写数据
}

/********************************************************************
*
*       LcdWriteDataMultiple
*
* Function description:
*   Writes multiple values to a display register.
*/
static void LcdWriteDataMultiple(U16 * pData, int NumItems) {
  while (NumItems--) {
    // ... TBD by user
    ILI9341_Write_Data(*pData++);//写数据
  }
}

/********************************************************************
*
*       LcdReadDataMultiple
*
* Function description:
*   Reads multiple values from a display register.
*/
static void LcdReadDataMultiple(U16 * pData, int NumItems) {
  while (NumItems--) {
    // ... TBD by user
    *pData++=ILI9341_Read_Data();//读取
  }
}

/*********************************************************************
*
*       Public functions
*
**********************************************************************
*/
/*********************************************************************
*
*       LCD_X_Config
*
* Function description:
*   Called during the initialization process in order to set up the
*   display driver configuration.
*
*/
void LCD_X_Config(void) {
  GUI_DEVICE * pDevice;
  CONFIG_FLEXCOLOR Config = {0};
  GUI_PORT_API PortAPI = {0};
  //
  // Set display driver and color conversion
  //
  pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565, 0, 0);
  //
  // Display driver configuration, required for Lin-driver
  //
  LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
  LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
  //
  // Orientation
  //
  //Config.Orientation = GUI_SWAP_XY | GUI_MIRROR_Y;
  //竖屏
  Config.Orientation = GUI_MIRROR_X | GUI_MIRROR_Y;
  //ILI9341 液晶控制器在进行读数据操作时,第1 个读操作是无效的,在第2 次进行读操作才会读出正确的数据
  Config.NumDummyReads = 2;
  GUIDRV_FlexColor_Config(pDevice, &Config);
  //
  // Set controller and operation mode
  //
  PortAPI.pfWrite16_A0  = LcdWriteReg;
  PortAPI.pfWrite16_A1  = LcdWriteData;
  PortAPI.pfWriteM16_A1 = LcdWriteDataMultiple;
  PortAPI.pfReadM16_A1  = LcdReadDataMultiple;
//  GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66708, GUIDRV_FLEXCOLOR_M16C0B16);
  //修改为ILI9341的驱动
  GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66709, GUIDRV_FLEXCOLOR_M16C0B16);
  
  /*设置触摸原点 */
  GUI_TOUCH_SetOrientation((GUI_MIRROR_X * LCD_GetMirrorXEx(0)) |
                           (GUI_MIRROR_Y * LCD_GetMirrorYEx(0)) |
                           (GUI_SWAP_XY  * LCD_GetSwapXYEx (0)));
  /*设置触摸校准 */
  GUI_TOUCH_Calibrate(GUI_COORD_X, 0, 240-1, TOUCH_AD_RIGHT ,TOUCH_AD_LEFT );
  GUI_TOUCH_Calibrate(GUI_COORD_Y, 0, 320-1,TOUCH_AD_BOTTOM ,TOUCH_AD_TOP );

}

/*********************************************************************
*
*       LCD_X_DisplayDriver
*
* Function description:
*   This function is called by the display driver for several purposes.
*   To support the according task the routine needs to be adapted to
*   the display controller. Please note that the commands marked with
*   'optional' are not cogently required and should only be adapted if
*   the display controller supports these features.
*
* Parameter:
*   LayerIndex - Index of layer to be configured
*   Cmd        - Please refer to the details in the switch statement below
*   pData      - Pointer to a LCD_X_DATA structure
*
* Return Value:
*   < -1 - Error
*     -1 - Command not handled
*      0 - Ok
*/
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
  int r;
  (void) LayerIndex;
  (void) pData;
  
  switch (Cmd) {
  case LCD_X_INITCONTROLLER: {
    ILI9341_Init();//初始化
    return 0;
  }
  default:
    r = -1;
  }
  return r;
}

配置内存管理

  • 修改GUIConf.c
1
2
//#define GUI_NUMBYTES  0x200000
#define GUI_NUMBYTES  (1024 * 24)

配置触摸屏驱动

  • GUIConf.c添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "my_XPT2046.h"
void GUI_TOUCH_X_ActivateX(void) 
{
 
}

void GUI_TOUCH_X_ActivateY(void)
{
  
}

int  GUI_TOUCH_X_MeasureX(void) 
{
    return XPT2046_ReadAdc_Fliter(XPT2046_CHANNEL_Y);

}

int  GUI_TOUCH_X_MeasureY(void) 
{	
    return XPT2046_ReadAdc_Fliter(XPT2046_CHANNEL_X);
}

配置操作系统接口

  • GUI_X_FREERTOS.c
1
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
/*********************************************************************
*                SEGGER Microcontroller GmbH & Co. KG                *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2017  SEGGER Microcontroller GmbH & Co. KG       *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V5.44 - Graphical user interface for embedded applications **
All  Intellectual Property rights  in the Software belongs to  SEGGER.
emWin is protected by  international copyright laws.  Knowledge of the
source code may not be used to write a similar product.  This file may
only be used in accordance with the following terms:

The  software has  been licensed  to STMicroelectronics International
N.V. a Dutch company with a Swiss branch and its headquarters in Plan-
les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the
purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_
troller products commercialized by Licensee only, sublicensed and dis_
tributed under the terms and conditions of the End User License Agree_
ment supplied by STMicroelectronics International N.V.
Full source code is available at: www.segger.com

We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : GUI_X_OS.C
Purpose     : This file provides emWin Interface with FreeRTOS
---------------------------END-OF-HEADER------------------------------
*/

/**
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license SLA0044,
  * the "License"; You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *                      http://www.st.com/SLA0044
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include "GUI.h"

/* FreeRTOS include files */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/*********************************************************************
*
* Global data
*/
static xSemaphoreHandle xQueueMutex = NULL;
static xSemaphoreHandle xSemaTxDone = NULL;
/*********************************************************************
*
* Timing:
* GUI_X_GetTime()
* GUI_X_Delay(int)

Some timing dependent routines require a GetTime
and delay function. Default time unit (tick), normally is
1 ms.
*/

int GUI_X_GetTime(void)
{
    return ((int) xTaskGetTickCount());
}

void GUI_X_Delay(int ms)
{
    vTaskDelay( ms );
}

/*********************************************************************
*
* GUI_X_Init()
*
* Note:
* GUI_X_Init() is called from GUI_Init is a possibility to init
* some hardware which needs to be up and running before the GUI.
* If not required, leave this routine blank.
*/

void GUI_X_Init(void) {
}


/*********************************************************************
*
* GUI_X_ExecIdle
*
* Note:
* Called if WM is in idle state
*/

void GUI_X_ExecIdle(void) {}

/*********************************************************************
*
* Multitasking:
*
* GUI_X_InitOS()
* GUI_X_GetTaskId()
* GUI_X_Lock()
* GUI_X_Unlock()
*
* Note:
* The following routines are required only if emWin is used in a
* true multi task environment, which means you have more than one
* thread using the emWin API.
* In this case the
* #define GUI_OS 1
* needs to be in GUIConf.h
*/

/* Init OS */
void GUI_X_InitOS(void)
{
    /* 创建互斥信号量 用于资源共享 */
    xQueueMutex = xSemaphoreCreateMutex();
    configASSERT (xQueueMutex != NULL);
    /* 创建二值信号量 用于事件触发 */
    vSemaphoreCreateBinary( xSemaTxDone );
    configASSERT ( xSemaTxDone != NULL );
}

void GUI_X_Unlock(void)
{
    /* 给出互斥量 */
    xSemaphoreGive(xQueueMutex);
}

void GUI_X_Lock(void)
{
    if(xQueueMutex == NULL)
    {
        GUI_X_InitOS();
    }
    /* 获取互斥量 */
    xSemaphoreTake(xQueueMutex,   /* 互斥量句柄 */
                   portMAX_DELAY);/* 阻塞等待 */
}

/* Get Task handle */
U32 GUI_X_GetTaskId(void)
{
    return ((U32) xTaskGetCurrentTaskHandle());
}


void GUI_X_WaitEvent (void)
{
    /* 获取信号量 */
    while(xSemaphoreTake(xSemaTxDone,              /* 信号量句柄 */
                         portMAX_DELAY) != pdTRUE);/* 阻塞等待 */
}


void GUI_X_SignalEvent (void)
{
    /* 给出信号量 */
    xSemaphoreGive(xSemaTxDone);
}

/*********************************************************************
*
* Logging: OS dependent

Note:
Logging is used in higher debug levels only. The typical target
build does not use logging and does therefor not require any of
the logging routines below. For a release build without logging
the routines below may be eliminated to save some space.
(If the linker is not function aware and eliminates unreferenced
functions automatically)

*/

void GUI_X_Log (const char *s) { }
void GUI_X_Warn (const char *s) { }
void GUI_X_ErrorOut(const char *s) { }

/*************************** End of file ****************************/

界面任务

  • 添加MainTask.c
1
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
#include "GUI.h"

/*******************************************************************************
 * 函数
 ******************************************************************************/
/**
  * @brief GUI主任务
  * @param 无
  * @retval 无
  */
void MainTask(void)
{
  GUI_SetBkColor(GUI_BLUE);
  GUI_Clear();
  
  GUI_CURSOR_Show();

  GUI_SetColor(GUI_WHITE);
  GUI_SetFont(GUI_FONT_24B_1);
  
  GUI_DispString("Hello World!\r\nUse FreeRTOS");
  
  while(1)
  {
    GUI_Delay(1000);
  }
}

程序运行主程序

  • 初始化中必须开启CRC时钟,CRC和emWin没有关系,只是他们为了库的保护而做的,这样STemWin的库只能用在ST的芯片上面,别的芯片是无法使用的
  • main.c
1
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
/* 开发板硬件头文件 */
#include "my_gpio.h"
#include "my_usart.h"
#include "my_ILI9341.h"
#include "my_XPT2046.h"
/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* STemWIN头文件 */
#include "GUI.h"


/**************************** 任务句柄 ********************************/
/* 创建任务句柄 */
static TaskHandle_t AppTaskCreate_Handle = NULL;
/* Touch任务句柄 */
static TaskHandle_t Touch_Task_Handle = NULL;
/* GUI任务句柄 */
static TaskHandle_t GUI_Task_Handle = NULL;

/*
*************************************************************************
*                             函数声明
*************************************************************************
*/
static void AppTaskCreate(void);/* 用于创建任务 */
static void GUI_Task(void* parameter);/* GUI_Task任务实现 */
static void Touch_Task(void* parameter);

/**
 * @brief  板级外设初始化,所有板子上的初始化均可放在这个函数里面
 * @param  无
 * @retval 无
 */
static void BSP_Init(void)
{
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
    NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
    /* LED 初始化 */
    LED_GPIO_Config();
    /* 串口初始化	*/
    USART_Config();
    /* 触摸屏初始化 */
    XPT2046_Init();
}


int main(void)
{
    BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
    BSP_Init();
    /* 创建AppTaskCreate任务 */
    xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate,  /* 任务入口函数 */
                          (const char*    )"AppTaskCreate",/* 任务名字 */
                          (uint16_t       )512,  /* 任务栈大小 */
                          (void*          )NULL,/* 任务入口函数参数 */
                          (UBaseType_t    )1, /* 任务的优先级 */
                          (TaskHandle_t*  )&AppTaskCreate_Handle);/* 任务控制块指针 */
    /* 启动任务调度 */
    if(pdPASS == xReturn)
        vTaskStartScheduler();   /* 启动任务,开启调度 */
    else
        return -1;
    while(1)
    {
    }
}
/**
 * @brief  为了方便管理,所有的任务创建函数都放在这个函数里面
 * @param  无
 * @retval 无
 */
static void AppTaskCreate(void)
{
    BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */

    taskENTER_CRITICAL();           //进入临界区

    xReturn = xTaskCreate((TaskFunction_t)Touch_Task,/* 任务入口函数 */
                          (const char*   )"Touch_Task",/* 任务名称 */
                          (uint16_t      )256,     /* 任务栈大小 */
                          (void*         )NULL,    /* 任务入口函数参数 */
                          (UBaseType_t   )3,       /* 任务的优先级 */
                          (TaskHandle_t* )&Touch_Task_Handle);/* 任务控制块指针 */
    if(pdPASS == xReturn)
        printf("创建Touch_Task任务成功!\r\n");

    xReturn = xTaskCreate((TaskFunction_t)GUI_Task,/* 任务入口函数 */
                          (const char*      )"GUI_Task",/* 任务名称 */
                          (uint16_t         )2048,      /* 任务栈大小 */
                          (void*            )NULL,      /* 任务入口函数参数 */
                          (UBaseType_t      )2,         /* 任务的优先级 */
                          (TaskHandle_t*    )&GUI_Task_Handle);/* 任务控制块指针 */
    if(pdPASS == xReturn)
        printf("创建GUI_Task任务成功!\r\n");

    vTaskDelete(AppTaskCreate_Handle);//删除AppTaskCreate任务

    taskEXIT_CRITICAL();//退出临界区
}
/**
  * @brief 触摸检测任务主体
  * @param parameter 参数
  * @retval 无
  */
static void Touch_Task(void* parameter)
{
	while(1)
	{
		GUI_TOUCH_Exec();//触摸屏定时扫描
		vTaskDelay(10);
	}
}

/**
  * @brief GUI任务主体
  * @param parameter 参数
  * @retval 无
  */
static void GUI_Task(void* parameter)
{
	/* 初始化STemWin */
  GUI_Init();

	while(1)
	{
		MainTask();
	}
}

编译调试

  • 编译并下载到开发板
  • 可以看到LCD显示