29.1 触摸屏简介
1.1 电阻式触摸屏检测原理
1.2 电阻触摸屏控制芯片
1.3 电容式触摸屏检测原理
29.2 电阻触摸屏—触摸画板实验
2.1 硬件设计
2.2 软件设计
2.2.1 编程要点
(1) 编写软件模拟 SPI 协议的驱动;
(2) 编写触摸芯片的控制驱动,如发送命令字,获取触摸坐标等;
(3) 编写触摸校正程序;
(4) 编写测试程序检验驱动。
2.2.2 代码分析
1.触摸屏硬件相关宏定义
2.初始化触摸屏控制引脚
3.模拟 SPI 协议的读写时序
4.采集触摸原始数据
5.多次采样求平均值
6.根据原始数据计算坐标值
7.触摸校正
8.触摸检测状态机
9.触摸坐标获取及处理
2.2.3 main 函数
main.c
/**
******************************************************************************
* @file main.c
* @author fire
* @version V1.0
* @date 2013-xx-xx
* @brief 触摸画板实验
******************************************************************************
* @attention
*
* 实验平台:野火 F103-指南者 STM32 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************************
*/
#include "stm32f10x.h"
#include "./usart/bsp_usart.h"
#include "./lcd/bsp_ili9341_lcd.h"
#include "./lcd/bsp_xpt2046_lcd.h"
#include "./flash/bsp_spi_flash.h"
#include "./led/bsp_led.h"
#include "palette.h"
#include <string.h>
int main(void)
{
//LCD 初始化
ILI9341_Init();
//触摸屏初始化
XPT2046_Init();
//从FLASH里获取校正参数,若FLASH无参数,则使用模式3进行校正
Calibrate_or_Get_TouchParaWithFlash(3,0);
/* USART config */
USART_Config();
LED_GPIO_Config();
printf("\r\n ********** 触摸画板程序 *********** \r\n");
printf("\r\n 若汉字显示不正常,请阅读工程中的readme.txt文件说明,根据要求给FLASH重刷字模数据\r\n");
//其中0、3、5、6 模式适合从左至右显示文字,
//不推荐使用其它模式显示文字 其它模式显示文字会有镜像效果
//其中 6 模式为大部分液晶例程的默认显示方向
ILI9341_GramScan ( 3 );
//绘制触摸画板界面
Palette_Init(LCD_SCAN_MODE);
while ( 1 )
{
//触摸检测函数,本函数至少10ms调用一次
XPT2046_TouchEvenHandler();
}
}
/* ------------------------------------------end of file---------------------------------------- */
palette.h
#ifndef _PALETTE_H
#define _PALETTE_H
#include "stm32f10x.h"
#include "./lcd/bsp_ili9341_lcd.h"
#define COLOR_BLOCK_WIDTH 40
#define COLOR_BLOCK_HEIGHT 28
#define BUTTON_NUM 16
#define PALETTE_START_Y 0
#define PALETTE_END_Y LCD_Y_LENGTH
#if 1 //按钮栏在左边
#define BUTTON_START_X 0
#define PALETTE_START_X (COLOR_BLOCK_WIDTH*2+1)
#define PALETTE_END_X LCD_X_LENGTH
#else //按钮栏在右边,(存在触摸按键时也会的bug仅用于测试触摸屏左边界)
#define BUTTON_START_X (LCD_X_LENGTH-2*COLOR_BLOCK_WIDTH)
#define PALETTE_START_X 0
#define PALETTE_END_X (LCD_X_LENGTH-2*COLOR_BLOCK_WIDTH)
#endif
/*
LCD 颜色代码,CL_是Color的简写
16Bit由高位至低位, RRRR RGGG GGGB BBBB
下面的RGB 宏将24位的RGB值转换为16位格式。
启动windows的画笔程序,点击编辑颜色,选择自定义颜色,可以获得的RGB值。
推荐使用迷你取色器软件获得你看到的界面颜色。
*/
#if LCD_RGB_888
/*RGB888颜色转换*/
#define RGB(R,G,B) ( (R<< 16) | (G << 8) | (B)) /* 将8位R,G,B转化为 24位RGB888格式 */
#else
/*RGB565 颜色转换*/
#define RGB(R,G,B) (((R >> 3) << 11) | ((G >> 2) << 5) | (B >> 3)) /* 将8位R,G,B转化为 16位RGB565格式 */
#define RGB565_R(x) ((x >> 8) & 0xF8)
#define RGB565_G(x) ((x >> 3) & 0xFC)
#define RGB565_B(x) ((x << 3) & 0xF8)
#endif
enum
{
CL_WHITE = RGB(255,255,255), /* 白色 */
CL_BLACK = RGB( 0, 0, 0), /* 黑色 */
CL_RED = RGB(255, 0, 0), /* 红色 */
CL_GREEN = RGB( 0,255, 0), /* 绿色 */
CL_BLUE = RGB( 0, 0,255), /* 蓝色 */
CL_YELLOW = RGB(255,255, 0), /* 黄色 */
CL_GREY = RGB( 98, 98, 98), /* 深灰色 */
CL_GREY1 = RGB( 150, 150, 150), /* 浅灰色 */
CL_GREY2 = RGB( 180, 180, 180), /* 浅灰色 */
CL_GREY3 = RGB( 200, 200, 200), /* 最浅灰色 */
CL_GREY4 = RGB( 230, 230, 230), /* 最浅灰色 */
CL_BUTTON_GREY = RGB( 195, 195, 195), /* WINDOWS 按钮表面灰色 */
CL_MAGENTA = RGB(255, 0, 255), /* 红紫色,洋红色 */
CL_CYAN = RGB( 0, 255, 255), /* 蓝绿色,青色 */
CL_BLUE1 = RGB( 0, 0, 240), /* 深蓝色 */
CL_BLUE2 = RGB( 0, 0, 128), /* 深蓝色 */
CL_BLUE3 = RGB( 68, 68, 255), /* 浅蓝色1 */
CL_BLUE4 = RGB( 0, 64, 128), /* 浅蓝色1 */
/* UI 界面 Windows控件常用色 */
CL_BTN_FACE = RGB(236, 233, 216), /* 按钮表面颜色(灰) */
CL_BOX_BORDER1 = RGB(172, 168,153), /* 分组框主线颜色 */
CL_BOX_BORDER2 = RGB(255, 255,255), /* 分组框阴影线颜色 */
CL_MASK = 0x7FFF /* RGB565颜色掩码,用于文字背景透明 */
};
typedef struct
{
uint16_t start_x; //按键的x起始坐标
uint16_t start_y; //按键的y起始坐标
uint16_t end_x; //按键的x结束坐标
uint16_t end_y; //按键的y结束坐标
uint32_t para; //颜色按钮中表示选择的颜色,笔迹形状按钮中表示选择的画刷
uint8_t touch_flag; //按键按下的标志
void (*draw_btn)(void * btn); //按键描绘函数
void (*btn_command)(void * btn); //按键功能执行函数,例如切换颜色、画刷
}Touch_Button;
/*画刷形状列表*/
typedef enum
{
LINE_SINGLE_PIXCEL = 0, //单像素线
LINE_2_PIXCEL, //2像素线
LINE_4_PIXCEL, //4像素线
LINE_6_PIXCEL, //6像素线
LINE_8_PIXCEL, //8像素线
LINE_16_PIXCEL, //16像素线
LINE_20_PIXCEL, //20像素线
LINE_WITH_CIRCLE, //珠子连线
RUBBER, //橡皮
}SHAPE;
/*画刷参数*/
typedef struct
{
uint32_t color;
SHAPE shape;
}Brush_Style;
/*brush全局变量在其它文件有使用到*/
extern Brush_Style brush;
void Palette_Init(uint8_t LCD_Mode);
void Touch_Button_Init(void);
void Touch_Button_Down(uint16_t x,uint16_t y);
void Touch_Button_Up(uint16_t x,uint16_t y);
void Draw_Trail(int16_t pre_x,int16_t pre_y,int16_t x,int16_t y,Brush_Style* brush);
#endif //_PALETTE_H
palette.c
/**
******************************************************************************
* @file palette.c
* @author fire
* @version V1.0
* @date 2015-xx-xx
* @brief 触摸画板应用函数
******************************************************************************
* @attention
*
* 实验平台:野火 STM32 F429 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
******************************************************************************
*/
#include "palette.h"
#include "./lcd/bsp_xpt2046_lcd.h"
#include "./lcd/bsp_ili9341_lcd.h"
/*按钮结构体数组*/
Touch_Button button[BUTTON_NUM];
/*画笔参数*/
Brush_Style brush;
static void Draw_Color_Button(void *btn);
static void Draw_Clear_Button(void *btn);
static void Draw_Shape_Button(void *btn);
static void Command_Select_Color(void *btn);
static void Command_Select_Brush(void *btn);
static void Command_Clear_Palette(void *btn);
static void LCD_DrawUniLineCircle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint8_t thick );
/**
* @brief Palette_Init 画板初始化
* @param 无
* @retval 无
*/
void Palette_Init(uint8_t LCD_Mode)
{
uint8_t i;
ILI9341_GramScan ( LCD_Mode );
/* 整屏清为白色 */
LCD_SetBackColor(CL_WHITE);
ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);
/* 初始化按钮 */
Touch_Button_Init();
/* 描绘按钮 */
for(i=0;i<BUTTON_NUM;i++)
{
button[i].draw_btn(&button[i]);
}
/* 初始化画笔 */
brush.color = CL_BLACK;
brush.shape = LINE_SINGLE_PIXCEL;
LCD_SetTextColor(brush.color);
}
/**
* @brief Touch_Button_Init 初始化按钮参数
* @param 无
* @retval 无
*/
void Touch_Button_Init(void)
{
/*第一列,主要为颜色按钮*/
button[0].start_x = BUTTON_START_X;
button[0].start_y = 0;
button[0].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[0].end_y = COLOR_BLOCK_HEIGHT;
button[0].para = CL_BLACK;
button[0].touch_flag = 0;
button[0].draw_btn = Draw_Color_Button ;
button[0].btn_command = Command_Select_Color ;
button[1].start_x = BUTTON_START_X;
button[1].start_y = COLOR_BLOCK_HEIGHT;
button[1].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[1].end_y = COLOR_BLOCK_HEIGHT*2;
button[1].para = CL_GREY;
button[1].touch_flag = 0;
button[1].draw_btn = Draw_Color_Button ;
button[1].btn_command = Command_Select_Color ;
button[2].start_x = BUTTON_START_X;
button[2].start_y = COLOR_BLOCK_HEIGHT*2;
button[2].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[2].end_y = COLOR_BLOCK_HEIGHT*3;
button[2].para = CL_BLUE;
button[2].touch_flag = 0;
button[2].draw_btn = Draw_Color_Button ;
button[2].btn_command = Command_Select_Color ;
button[3].start_x = BUTTON_START_X;
button[3].start_y = COLOR_BLOCK_HEIGHT*3;
button[3].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[3].end_y = COLOR_BLOCK_HEIGHT*4;
button[3].para = CL_CYAN;
button[3].touch_flag = 0;
button[3].draw_btn = Draw_Color_Button ;
button[3].btn_command = Command_Select_Color ;
button[4].start_x = BUTTON_START_X;
button[4].start_y = COLOR_BLOCK_HEIGHT*4;
button[4].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[4].end_y = COLOR_BLOCK_HEIGHT*5;
button[4].para = CL_RED;
button[4].touch_flag = 0;
button[4].draw_btn = Draw_Color_Button ;
button[4].btn_command = Command_Select_Color ;
button[5].start_x = BUTTON_START_X;
button[5].start_y = COLOR_BLOCK_HEIGHT*5;
button[5].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[5].end_y = COLOR_BLOCK_HEIGHT*6;
button[5].para = CL_MAGENTA;
button[5].touch_flag = 0;
button[5].draw_btn = Draw_Color_Button ;
button[5].btn_command = Command_Select_Color ;
button[6].start_x = BUTTON_START_X;
button[6].start_y = COLOR_BLOCK_HEIGHT*6;
button[6].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[6].end_y = COLOR_BLOCK_HEIGHT*7;
button[6].para = CL_GREEN;
button[6].touch_flag = 0;
button[6].draw_btn = Draw_Color_Button ;
button[6].btn_command = Command_Select_Color ;
button[7].start_x = BUTTON_START_X;
button[7].start_y = COLOR_BLOCK_HEIGHT*7;
button[7].end_x = BUTTON_START_X+COLOR_BLOCK_WIDTH ;
button[7].end_y = LCD_Y_LENGTH;
button[7].para = CL_BUTTON_GREY;
button[7].touch_flag = 0;
button[7].draw_btn = Draw_Clear_Button ;
button[7].btn_command = Command_Clear_Palette ;
/*第二列,主要为画刷按钮*/
button[8].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[8].start_y = 0;
button[8].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[8].end_y = COLOR_BLOCK_HEIGHT;
button[8].para = LINE_SINGLE_PIXCEL;
button[8].touch_flag = 0;
button[8].draw_btn = Draw_Shape_Button ;
button[8].btn_command = Command_Select_Brush ;
button[9].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[9].start_y = COLOR_BLOCK_HEIGHT;
button[9].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[9].end_y = COLOR_BLOCK_HEIGHT*2;
button[9].para = LINE_2_PIXCEL;
button[9].touch_flag = 0;
button[9].draw_btn = Draw_Shape_Button ;
button[9].btn_command = Command_Select_Brush ;
button[10].start_x =BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[10].start_y = COLOR_BLOCK_HEIGHT*2;
button[10].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[10].end_y = COLOR_BLOCK_HEIGHT*3;
button[10].para = LINE_4_PIXCEL;
button[10].touch_flag = 0;
button[10].draw_btn = Draw_Shape_Button ;
button[10].btn_command = Command_Select_Brush ;
button[11].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[11].start_y = COLOR_BLOCK_HEIGHT*3;
button[11].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[11].end_y = COLOR_BLOCK_HEIGHT*4;
button[11].para = LINE_6_PIXCEL;
button[11].touch_flag = 0;
button[11].draw_btn = Draw_Shape_Button ;
button[11].btn_command = Command_Select_Brush ;
button[12].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[12].start_y = COLOR_BLOCK_HEIGHT*4;
button[12].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[12].end_y = COLOR_BLOCK_HEIGHT*5;
button[12].para = LINE_8_PIXCEL;
button[12].touch_flag = 0;
button[12].draw_btn = Draw_Shape_Button ;
button[12].btn_command = Command_Select_Brush ;
button[13].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[13].start_y = COLOR_BLOCK_HEIGHT*5;
button[13].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[13].end_y = COLOR_BLOCK_HEIGHT*6;
button[13].para = LINE_16_PIXCEL;
button[13].touch_flag = 0;
button[13].draw_btn = Draw_Shape_Button ;
button[13].btn_command = Command_Select_Brush ;
button[14].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[14].start_y = COLOR_BLOCK_HEIGHT*6;
button[14].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[14].end_y = COLOR_BLOCK_HEIGHT*7;
button[14].para = LINE_20_PIXCEL;
button[14].touch_flag = 0;
button[14].draw_btn = Draw_Shape_Button ;
button[14].btn_command = Command_Select_Brush ;
button[15].start_x = BUTTON_START_X + COLOR_BLOCK_WIDTH;
button[15].start_y = COLOR_BLOCK_HEIGHT*7;
button[15].end_x = BUTTON_START_X + COLOR_BLOCK_WIDTH*2 ;
button[15].end_y = LCD_Y_LENGTH;
button[15].para = RUBBER;
button[15].touch_flag = 0;
button[15].draw_btn = Draw_Shape_Button ;
button[15].btn_command = Command_Select_Brush ;
}
/**
* @brief Touch_Button_Down 按键被按下时调用的函数,由触摸屏调用
* @param x 触摸位置的x坐标
* @param y 触摸位置的y坐标
* @retval 无
*/
void Touch_Button_Down(uint16_t x,uint16_t y)
{
uint8_t i;
for(i=0;i<BUTTON_NUM;i++)
{
/* 触摸到了按钮 */
if(x<=button[i].end_x && y<=button[i].end_y && y>=button[i].start_y && x>=button[i].start_x )
{
if(button[i].touch_flag == 0) /*原本的状态为没有按下,则更新状态*/
{
button[i].touch_flag = 1; /* 记录按下标志 */
button[i].draw_btn(&button[i]); /*重绘按钮*/
}
}
else if(button[i].touch_flag == 1) /* 触摸移出了按键的范围且之前有按下按钮 */
{
button[i].touch_flag = 0; /* 清除按下标志,判断为误操作*/
button[i].draw_btn(&button[i]); /*重绘按钮*/
}
}
}
/**
* @brief Touch_Button_Up 按键被释放时调用的函数,由触摸屏调用
* @param x 触摸最后释放时的x坐标
* @param y 触摸最后释放时的y坐标
* @retval 无
*/
void Touch_Button_Up(uint16_t x,uint16_t y)
{
uint8_t i;
for(i=0;i<BUTTON_NUM;i++)
{
/* 触笔在按钮区域释放 */
if((x<button[i].end_x && x>button[i].start_x && y<button[i].end_y && y>button[i].start_y))
{
button[i].touch_flag = 0; /*释放触摸标志*/
button[i].draw_btn(&button[i]); /*重绘按钮*/
button[i].btn_command(&button[i]); /*执行按键的功能命令*/
break;
}
}
}
/**
* @brief Draw_Trail 在画板区域描绘触摸轨迹
* @param pre_x 上一点的x坐标
* @param pre_y 上一点的y坐标
* @param x 最新一点的x坐标
* @param y 最新一点的y坐标
* @param brush 画刷参数
* @retval 无
*/
void Draw_Trail(int16_t pre_x,int16_t pre_y,int16_t x,int16_t y,Brush_Style* brush)
{
/*设置画板区域为活动窗口,bsp_lcd.c驱动还没有这样的函数,用于限制绘画窗口*/
// RA8875_SetActiveWindow(PALETTE_START_X,PALETTE_START_Y,PALETTE_END_X,PALETTE_END_Y);
/*触摸位置在画板区域*/
if(x>PALETTE_START_X && pre_x>PALETTE_START_X )
{
switch(brush->shape) /*根据画刷参数描绘不同的轨迹*/
{
/* 描绘1像素宽度的轨迹线 */
case LINE_SINGLE_PIXCEL:
if(pre_x< 0 || pre_y < 0) //新的笔迹
{
ILI9341_SetPointPixel(x,y);
}
else //继续上一次的笔迹
{
ILI9341_DrawLine(pre_x,pre_y,x,y);
}
break;
case LINE_2_PIXCEL:
if(x-1<PALETTE_START_X||pre_x-1<PALETTE_START_X) //画板左边界
break;
/* 描绘2像素宽度的轨迹线 */
LCD_DrawUniLineCircle(pre_x,pre_y,x,y,1);
break;
case LINE_4_PIXCEL:
if(x-2<PALETTE_START_X||pre_x-2<PALETTE_START_X) //画板左边界
break;
LCD_DrawUniLineCircle(pre_x,pre_y,x,y,2);
break;
case LINE_6_PIXCEL:
if(x-3<PALETTE_START_X||pre_x-3<PALETTE_START_X) //画板左边界
break;
LCD_DrawUniLineCircle(pre_x,pre_y,x,y,3);
break;
case LINE_8_PIXCEL:
if(x-4<PALETTE_START_X||pre_x-4<PALETTE_START_X) //画板左边界
break;
LCD_DrawUniLineCircle(pre_x,pre_y,x,y,4);
break;
case LINE_16_PIXCEL:
if(x-8<PALETTE_START_X||pre_x-8<PALETTE_START_X) //画板左边界
break;
LCD_DrawUniLineCircle(pre_x,pre_y,x,y,8);
break;
case LINE_20_PIXCEL:
if(x-10<PALETTE_START_X ||pre_x-10<PALETTE_START_X) //画板左边界
break;
LCD_DrawUniLineCircle(pre_x,pre_y,x,y,10);
break;
/*描绘带珠子的单像素线*/
case LINE_WITH_CIRCLE:
if(x-3<PALETTE_START_X||pre_x-3<PALETTE_START_X) //画板左边界
break;
if(pre_x< 0 || pre_y< 0)//新的笔迹
{
ILI9341_SetPointPixel(x,y);
}
else //继续上一次的笔迹
{
ILI9341_DrawLine(pre_x,pre_y,x,y);
ILI9341_DrawCircle(x,y,3,1);
}
break;
/*橡皮功能*/
case RUBBER:
if(x-20<PALETTE_START_X || //画板左边界
x+20>LCD_X_LENGTH || x-20<0 || //液晶左右边界
y+20>LCD_Y_LENGTH || y-20<0) //液晶上下边界
break;
// if(x>PALETTE_START_X+20)
{
LCD_SetColors(CL_WHITE,CL_WHITE);
ILI9341_DrawRectangle( x-40/2,y-40/2,40,40,1);
}
break;
}
}
/*退出局限画板的绘图窗口,bsp_lcd.c驱动还没有这样的函数,用于限制绘画窗口*/
// RA8875_SetActiveWindow(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);
}
/**
* @brief Draw_Color_Button 颜色按钮的描绘函数
* @param btn Touch_Button 类型的按键参数
* @retval 无
*/
static void Draw_Color_Button(void *btn)
{
Touch_Button *ptr = (Touch_Button *)btn;
/*释放按键*/
if(ptr->touch_flag == 0)
{
/*背景为功能键相应的颜色*/
LCD_SetColors(ptr->para,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,1);
}
else /*按键按下*/
{
/*白色背景*/
LCD_SetColors(CL_WHITE,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,1);
}
/*按钮边框*/
LCD_SetColors(CL_BLUE4,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,0);
}
/**
* @brief Draw_Clear_Button 清屏按钮的描绘函数
* @param btn Touch_Button 类型的按键参数
* @retval 无
*/
static void Draw_Clear_Button(void *btn)
{
Touch_Button *ptr = (Touch_Button *)btn;
/*释放按键*/
if(ptr->touch_flag == 0)
{
LCD_SetColors(CL_BUTTON_GREY,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,1);
LCD_SetColors(CL_RED,CL_BUTTON_GREY);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是16*16的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( ptr->start_x + (ptr->end_x - ptr->start_x - 16*2 )/2,
// ptr->start_y+15,
ptr->start_y+ ((ptr->end_y - ptr->start_y-16)/2),
"清屏");
}
else /*按键按下*/
{
LCD_SetColors(CL_WHITE,CL_WHITE);
ILI9341_DrawRectangle(ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,1);
LCD_SetColors(CL_RED,CL_WHITE);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是16*16的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( ptr->start_x + (ptr->end_x - ptr->start_x - 16*2 )/2,
// ptr->start_y+15,
ptr->start_y+ ((ptr->end_y - ptr->start_y-16)/2),
"清屏");
}
/*按钮边框*/
LCD_SetColors(CL_BLUE4,CL_WHITE);
ILI9341_DrawRectangle(ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,0);
}
/**
* @brief Draw_Shape_Button 笔刷按钮的描绘函数
* @param btn Touch_Button 类型的按键参数
* @retval 无
*/
static void Draw_Shape_Button(void *btn)
{
Touch_Button *ptr = (Touch_Button *)btn;
uint16_t i;
/* 背景颜色 没按下时为灰色,按下时为白色*/
if(ptr->touch_flag ==0 )
{
LCD_SetColors(CL_BUTTON_GREY,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,1);
/*显示文字时的背景颜色*/
LCD_SetColors(CL_BLUE4,CL_BUTTON_GREY);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,0);
}
else
{
LCD_SetColors(CL_WHITE,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,1);
/*显示文字时的背景颜色*/
LCD_SetColors(CL_BLUE4,CL_WHITE);
ILI9341_DrawRectangle( ptr->start_x,
ptr->start_y,
ptr->end_x - ptr->start_x,
ptr->end_y - ptr->start_y,0);
}
LCD_SetColors(CL_BLACK,CL_WHITE);
/*根据画刷形状描绘按钮图案*/
switch(ptr->para)
{
case LINE_SINGLE_PIXCEL:
LCD_SetColors(CL_BLACK,CL_WHITE);
ILI9341_DrawLine(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2);
break;
case LINE_2_PIXCEL:
LCD_DrawUniLineCircle(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
1);
break;
case LINE_4_PIXCEL:
LCD_DrawUniLineCircle(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
2);
break;
case LINE_6_PIXCEL:
LCD_DrawUniLineCircle(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
3);
break;
case LINE_8_PIXCEL:
LCD_DrawUniLineCircle(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
4);
break;
case LINE_16_PIXCEL:
LCD_DrawUniLineCircle(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
8 );
break;
case LINE_20_PIXCEL:
LCD_DrawUniLineCircle(ptr->start_x+20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,ptr->end_x-20,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
10);
break;
case LINE_WITH_CIRCLE:
LCD_SetColors(CL_BLACK,CL_WHITE);
ILI9341_DrawLine(ptr->start_x+5,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
ptr->end_x-5,
ptr->start_y+(ptr->end_y-ptr->start_y)/2);
for(i=0;i<((ptr->end_x - ptr->start_x-10)/10);i++)
{
ILI9341_DrawCircle( ptr->start_x+5+i*10,
ptr->start_y+(ptr->end_y-ptr->start_y)/2,
3,1);
}
break;
case RUBBER:
LCD_SetColors(CL_WHITE,CL_BLACK);
ILI9341_DrawRectangle( ptr->start_x+((ptr->end_x - ptr->start_x -24)/2),
ptr->start_y+ ((ptr->end_y - ptr->start_y-24 -16)/2),
24,
24,1 );
LCD_SetColors(CL_RED,CL_BUTTON_GREY);
/*选择字体,使用中英文显示时,尽量把英文选择成8*16的字体,
*中文字体大小是24*24的,需要其它字体请自行制作字模*/
/*这个函数只对英文字体起作用*/
LCD_SetFont(&Font8x16);
ILI9341_DispString_EN_CH( ptr->start_x+(ptr->end_x - ptr->start_x -16*2)/2,
ptr->start_y+ ((ptr->end_y - ptr->start_y-24 -16)/2)+24,
"橡皮");
break;
}
}
/**
* @brief Command_Select_Color 切换画刷颜色,颜色按键的功能执行函数
* @param btn Touch_Button 类型的按键参数
* @retval 无
*/
static void Command_Select_Color(void *btn)
{
Touch_Button *ptr = (Touch_Button *)btn;
brush.color = ptr->para;
LCD_SetColors(brush.color,CL_WHITE);
if(brush.shape == RUBBER)
{
brush.shape = LINE_SINGLE_PIXCEL;
}
}
/**
* @brief Command_Select_Brush 切换画刷颜色,画刷按键的功能执行函数
* @param btn Touch_Button 类型的按键参数
* @retval 无
*/
static void Command_Select_Brush(void *btn)
{
Touch_Button *ptr = (Touch_Button *)btn;
brush.shape =(SHAPE) ptr->para;
LCD_SetColors(brush.color,CL_WHITE);
}
/**
* @brief Command_Select_Brush 切换画刷颜色,清屏按键的功能执行函数
* @param btn Touch_Button 类型的按键参数
* @retval 无
*/
static void Command_Clear_Palette(void *btn)
{
LCD_SetColors(CL_WHITE,CL_WHITE);
ILI9341_DrawRectangle( PALETTE_START_X,
PALETTE_START_Y,
PALETTE_END_X-(PALETTE_START_X+1),
PALETTE_END_Y-PALETTE_START_Y ,1);
}
#define ABS(X) ((X) > 0 ? (X) : -(X))
/**
* @brief 在两点之间描绘轨迹
* @param x1: specifies the point 1 x position.
* @param y1: specifies the point 1 y position.
* @param x2: specifies the point 2 x position.
* @param y2: specifies the point 2 y position.
* @retval None
*/
static void LCD_DrawUniLineCircle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint8_t thick )
{
int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
curpixel = 0;
deltax = ABS(x2 - x1); /* The difference between the x's */
deltay = ABS(y2 - y1); /* The difference between the y's */
x = x1; /* Start x off at the first pixel */
y = y1; /* Start y off at the first pixel */
if (x2 >= x1) /* The x-values are increasing */
{
xinc1 = 1;
xinc2 = 1;
}
else /* The x-values are decreasing */
{
xinc1 = -1;
xinc2 = -1;
}
if (y2 >= y1) /* The y-values are increasing */
{
yinc1 = 1;
yinc2 = 1;
}
else /* The y-values are decreasing */
{
yinc1 = -1;
yinc2 = -1;
}
if (deltax >= deltay) /* There is at least one x-value for every y-value */
{
xinc1 = 0; /* Don't change the x when numerator >= denominator */
yinc2 = 0; /* Don't change the y for every iteration */
den = deltax;
num = deltax / 2;
numadd = deltay;
numpixels = deltax; /* There are more x-values than y-values */
}
else /* There is at least one y-value for every x-value */
{
xinc2 = 0; /* Don't change the x for every iteration */
yinc1 = 0; /* Don't change the y when numerator >= denominator */
den = deltay;
num = deltay / 2;
numadd = deltax;
numpixels = deltay; /* There are more y-values than x-values */
}
for (curpixel = 0; curpixel <= numpixels; curpixel++)
{
//判断边界
if(x+thick>LCD_X_LENGTH || x-thick<0 || //液晶左右边界
y+thick>LCD_Y_LENGTH || y-thick<0 ) //液晶上下边界
continue;
ILI9341_DrawCircle(x,y,thick,1); /* Draw the current pixel */
num += numadd; /* Increase the numerator by the top of the fraction */
if (num >= den) /* Check if numerator >= denominator */
{
num -= den; /* Calculate the new numerator value */
x += xinc1; /* Change the x as appropriate */
y += yinc1; /* Change the y as appropriate */
}
x += xinc2; /* Change the x as appropriate */
y += yinc2; /* Change the y as appropriate */
}
}
/* ------------------------------------------end of file---------------------------------------- */
**
其他配置:
**