prettyprint

2024年8月16日 星期五

STM32 HAL|| 16 bit parallel LCD-TFT driver using FSMC interface for LVGL || DMA

 本文章介紹如何移植LVGL graphic library 到STM32上,另外說明有關LCD-TFT的driver使用STM32F4xx 的FSMC介面,STM32透過FSMC external memory access的方式驅動LCD-TFT。

一、使用硬體:

  • LCD-TFT


  • 開發版STM32_F4VE

二、STM32F4xx Bus matrix:


CPU or DMA透過Bus Matrix可直接存取FSMC。

三、STM407xx memory map:

使用FSMC bank1 其範圍為0x6000 0000~0x6fff ffff。

四、 FSMC write waveform and LCD-TFT write cycle sequence 的時序圖。
LCD-TFT D/CX:  Low時為command, High 實為GRAM data or commana的parameter data。相對於FSMC_A[25:0]的某一個address pin。

五、LCD-TFT Command&DATA address

本文章專案的FSMC設定如下圖:

LCD register select使用A18, 16 bits Data。因此A18為low時Address 為0x6000 0000代表command(D/CX low),。當A18為high 時Address 為0x6008 0000代表Data。
A[18]=HADDR[19]

六、移植LVGL library到STM32上:

  1. copy lvgl中的scr資料夾與lvgl.h和lv_conf.h(由lv_conf_template.h更改檔名)檔案到專案中,並將檔案加到include paths中。
  2. 設定定期呼叫lv_tick_inc(x)的timer,本專案設定為5ms。

  3. 在main loop:定期呼叫lv_timer_handler()。
  4. 呼叫lv_init()並設定display與input device的driver。
詳細程式碼附於文末。

七、成果展示:


八、程式碼:
  • lcd_fsmc.c
#include <lcd_fsmc.h>
#include <stdlib.h>
#include <stdio.h>

static uint8_t LCD_Orientation=0;
static uint16_t lcd_width = LCD_WIDTH; //default 240
static uint16_t lcd_height = LCD_HEIGHT; //default 320

// MADCTL register: 			MY,MX,MV,ML,BGR,MH,x,x
static uint8_t LCD_MADCTL_PORTRAIT  		=	0b01001000;
static uint8_t LCD_MADCTL_LANDSCAPE  		=	0b00101000;
static uint8_t LCD_MADCTL_PORTRAIT_MIRROR  =	0b10001000;
static uint8_t LCD_MADCTL_LANDSCAPE_MIRROR = 	0b11101000;

void lcd_cmd_write(unsigned char command)
{
	LCD_CMD_WRITE(command);
}

void lcd_data_write(unsigned short data)
{
	LCD_DATA_WRITE(data);
}

uint16_t lcd_get_width() {
	return lcd_width;
}

uint16_t lcd_get_height() {
	return lcd_height;
}

static void lcd_reset(void)
{
	lcd_cmd_write(LCD_SOFTRESET);
	HAL_Delay(50);
}

void lcd_set_window(unsigned short x0, unsigned short y0, unsigned short x1, unsigned short y1)
{
  lcd_cmd_write(LCD_COLADDRSET);
  lcd_data_write((x0 >> 8) & 0xFF);
  lcd_data_write(x0 & 0xFF);
  lcd_data_write((x1 >> 8) & 0xFF);
  lcd_data_write(x1 & 0xFF);
  lcd_cmd_write(LCD_PAGEADDRSET);
  lcd_data_write((y0 >> 8) & 0xFF);
  lcd_data_write(y0 & 0xFF);
  lcd_data_write((y1 >> 8) & 0xFF);
  lcd_data_write(y1 & 0xFF);
  lcd_cmd_write(LCD_MEMORYWRITE);
}

void lcd_init(void)
{
  lcd_reset();

  lcd_cmd_write(LCD_DISPLAYOFF);

  lcd_cmd_write(0xCF);
  lcd_data_write(0x00);
  lcd_data_write(0x83);
  lcd_data_write(0x30);

  lcd_cmd_write(0xED);
  lcd_data_write(0x64);
  lcd_data_write(0x03);
  lcd_data_write(0x12);
  lcd_data_write(0x81);

  lcd_cmd_write(0xE8);
  lcd_data_write(0x85);
  lcd_data_write(0x01);
  lcd_data_write(0x79);

  lcd_cmd_write(0xCB);
  lcd_data_write(0x39);
  lcd_data_write(0x2C);
  lcd_data_write(0x00);
  lcd_data_write(0x34);
  lcd_data_write(0x02);

  lcd_cmd_write(0xF7);
  lcd_data_write(0x20);

  lcd_cmd_write(0xEA);
  lcd_data_write(0x00);
  lcd_data_write(0x00);

  lcd_cmd_write(LCD_POWERCONTROL1);
  lcd_data_write(0x26);

  lcd_cmd_write(LCD_POWERCONTROL2);
  lcd_data_write(0x11);

  lcd_cmd_write(LCD_VCOMCONTROL1);
  lcd_data_write(0x35);
  lcd_data_write(0x3E);

  lcd_cmd_write(LCD_VCOMCONTROL2);
  lcd_data_write(0xBE);

  lcd_cmd_write(LCD_MEMCONTROL);
  lcd_data_write(LCD_MADCTL_PORTRAIT);
  LCD_Orientation = LCD_ORIENTATION_PORTRAIT; // set TFT orientation default

  lcd_cmd_write(LCD_PIXELFORMAT);
  lcd_data_write(0x55);

  lcd_cmd_write(LCD_FRAMECONTROLNORMAL);
  lcd_data_write(0x00);
  lcd_data_write(0x1B);

  lcd_cmd_write(0xF2);
  lcd_data_write(0x08);

  lcd_cmd_write(LCD_GAMMASET);
  lcd_data_write(0x01);

  lcd_cmd_write(LCD_POSITIVEGAMMCORR);
  lcd_data_write(0x1F);
  lcd_data_write(0x1A);
  lcd_data_write(0x18);
  lcd_data_write(0x0A);
  lcd_data_write(0x0F);
  lcd_data_write(0x06);
  lcd_data_write(0x45);
  lcd_data_write(0x87);
  lcd_data_write(0x32);
  lcd_data_write(0x0A);
  lcd_data_write(0x07);
  lcd_data_write(0x02);
  lcd_data_write(0x07);
  lcd_data_write(0x05);
  lcd_data_write(0x00);

  lcd_cmd_write(LCD_NEGATIVEGAMMCORR);
  lcd_data_write(0x00);
  lcd_data_write(0x25);
  lcd_data_write(0x27);
  lcd_data_write(0x05);
  lcd_data_write(0x10);
  lcd_data_write(0x09);
  lcd_data_write(0x3A);
  lcd_data_write(0x78);
  lcd_data_write(0x4D);
  lcd_data_write(0x05);
  lcd_data_write(0x18);
  lcd_data_write(0x0D);
  lcd_data_write(0x38);
  lcd_data_write(0x3A);
  lcd_data_write(0x1F);

  lcd_cmd_write(LCD_COLADDRSET);
  lcd_data_write(0x00);
  lcd_data_write(0x00);
  lcd_data_write(0x00);
  lcd_data_write(0xEF);

  lcd_cmd_write(LCD_PAGEADDRSET);
  lcd_data_write(0x00);
  lcd_data_write(0x00);
  lcd_data_write(0x01);
  lcd_data_write(0x3F);

  lcd_cmd_write(LCD_ENTRYMODE);
  lcd_data_write(0x07);

  lcd_cmd_write(LCD_DISPLAYFUNC);
  lcd_data_write(0x0A);
  lcd_data_write(0x82);
  lcd_data_write(0x27);
  lcd_data_write(0x00);

  lcd_cmd_write(LCD_SLEEPOUT);
  HAL_Delay(100);
  lcd_cmd_write(LCD_DISPLAYON);
  HAL_Delay(100);
  lcd_cmd_write(LCD_MEMORYWRITE);
}

void lcd_set_orientation(uint8_t Orientation)
{
	LCD_Orientation = Orientation;
	lcd_cmd_write(LCD_MEMCONTROL);

	switch (LCD_Orientation)
	{
		case LCD_ORIENTATION_PORTRAIT:
			lcd_data_write(LCD_MADCTL_PORTRAIT);
			lcd_width = LCD_WIDTH;
			lcd_height = LCD_HEIGHT;
			break;
		case LCD_ORIENTATION_PORTRAIT_MIRROR:
			lcd_data_write(LCD_MADCTL_PORTRAIT_MIRROR);
			lcd_width = LCD_WIDTH;
			lcd_height = LCD_HEIGHT;
			break;
		case LCD_ORIENTATION_LANDSCAPE:
			lcd_data_write(LCD_MADCTL_LANDSCAPE);
			lcd_width = LCD_HEIGHT;
			lcd_height = LCD_WIDTH;
			break;
		case LCD_ORIENTATION_LANDSCAPE_MIRROR:
			lcd_data_write(LCD_MADCTL_LANDSCAPE_MIRROR);
			lcd_width = LCD_HEIGHT;
			lcd_height = LCD_WIDTH;
			break;
		default:
			break;
	}

	lcd_cmd_write(LCD_MEMORYWRITE);
	lcd_set_window(0, 0, lcd_width - 1, lcd_height - 1);
}

void lcd_backlight_off(void)
{
	LCD_BL_OFF();
}

void lcd_backlight_on(void)
{
	LCD_BL_ON();
}

void lcd_display_off(void)
{
	lcd_cmd_write(LCD_DISPLAYOFF);
	LCD_BL_OFF();
}

void lcd_display_on(void)
{
	lcd_cmd_write(LCD_DISPLAYON);
	LCD_BL_ON();
}

uint8_t lcd_get_orientation(void)
{
  return LCD_Orientation;
}


void lcd_fill_RGB(uint16_t color, uint16_t x, uint16_t y, uint16_t width, uint16_t height)
{
  lcd_set_window(x, y, x+width - 1, y+height - 1);
  int dimensions = width * height;
  while(dimensions--)
  {
    lcd_data_write(color);
  }
}

  
  • lcd_fsmc.h
#ifndef __LCD_FSMC_H_
#define __LCD_FSMC_H_

#include "main.h"
#include <stdbool.h>

#define LCD_WIDTH		240
#define LCD_HEIGHT 		320

#define LCD_BL_ON() HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_RESET)
#define LCD_BL_OFF() HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_SET)

#define LCD_CMD_BASE        		((uint32_t)0x60000000)
#define LCD_DATA_BASE        		((uint32_t)0x60080000)

#define LCD_CMD_WRITE(command)	*(volatile uint16_t *) (LCD_CMD_BASE) = (command)
#define LCD_DATA_WRITE(data)	*(volatile uint16_t *) (LCD_DATA_BASE) = (data)
#define	LCD_REGISTER_READ()		*(volatile uint16_t *) (LCD_CMD_BASE)
#define	LCD_DATA_READ()			*(volatile uint16_t *) (LCD_DATA_BASE)

enum
{
	LCD_ORIENTATION_PORTRAIT 			= 0,
	LCD_ORIENTATION_LANDSCAPE 			= 1,
	LCD_ORIENTATION_PORTRAIT_MIRROR 	= 2,
	LCD_ORIENTATION_LANDSCAPE_MIRROR 	= 3
};

// LCD registers
#define	LCD_NOP					0x00
#define LCD_SOFTRESET			0x01
#define LCD_READID				0x04
#define LCD_READSTATUS			0x09
#define LCD_READPOWERMODE		0x0A
#define LCD_READMADCTL			0x0B
#define LCD_READPIXELFORMAT		0x0C
#define LCD_READIMAGEFORMAT		0x0D
#define LCD_READSIGNALMODE		0x0E
#define LCD_READSELFDIAGNOSTIC	0x0F
#define LCD_SLEEPIN				0x10
#define LCD_SLEEPOUT			0x11
#define LCD_PARTIALMODE			0x12
#define LCD_NORMALDISP			0x13
#define LCD_INVERTOFF			0x20
#define LCD_INVERTON			0x21
#define LCD_GAMMASET			0x26
#define LCD_DISPLAYOFF			0x28
#define LCD_DISPLAYON			0x29
#define LCD_COLADDRSET			0x2A
#define LCD_PAGEADDRSET			0x2B
#define LCD_MEMORYWRITE			0x2C
#define LCD_COLORSET			0x2D
#define LCD_MEMORYREAD			0x2E
#define LCD_PARTIALAREA			0x30
#define LCD_VERTICALSCROLING	0x33
#define LCD_TEARINGEFFECTOFF	0x34
#define LCD_TEARINGEFFECTON		0x35
#define LCD_MEMCONTROL			0x36
#define LCD_VSCROLLSTARTADDRESS	0x37
#define LCD_IDLEMODEOFF			0x38
#define LCD_IDLEMODEON			0x39
#define LCD_PIXELFORMAT			0x3A
#define LCD_WRITEMEMCONTINUE	0x3C
#define LCD_READMEMCONTINUE		0x3E
#define LCD_SETSCANLINE			0x44
#define LCD_GETSCANLINE			0x45
#define LCD_WRITEBRIGHTNESS		0x51
#define LCD_READBRIGHTNESS		0x52
#define LCD_WRITECTRL			0x53
#define LCD_READCTRL			0x54
#define LCD_WRITECABC			0x55
#define LCD_READCABC			0x56
#define LCD_WRITECABCMIN		0x5E
#define LCD_READCABCMIN			0x5F
#define LCD_RGBSIGNALCONTROL	0xB0
#define LCD_FRAMECONTROLNORMAL	0xB1
#define LCD_FRAMECONTROLIDLE	0xB2
#define LCD_FRAMECONTROLPARTIAL	0xB3
#define LCD_INVERSIONCONTROL	0xB4
#define LCD_BLANKINGPORCHCONT	0xB5
#define LCD_DISPLAYFUNC			0xB6
#define LCD_ENTRYMODE			0xB7
#define LCD_BACKLIGHTCONTROL1	0xB8
#define LCD_BACKLIGHTCONTROL2	0xB9
#define LCD_BACKLIGHTCONTROL3	0xBA
#define LCD_BACKLIGHTCONTROL4	0xBB
#define LCD_BACKLIGHTCONTROL5	0xBC
#define LCD_BACKLIGHTCONTROL7	0xBE
#define LCD_BACKLIGHTCONTROL8	0xBF
#define LCD_POWERCONTROL1		0xC0
#define LCD_POWERCONTROL2		0xC1
#define LCD_VCOMCONTROL1		0xC5
#define LCD_VCOMCONTROL2		0xC7
#define LCD_NVMEMORYWRITE		0xD0
#define LCD_NVMEMORYKEY			0xD1
#define LCD_NVMEMORYSTATUSREAD	0xD2
#define LCD_READID4				0xD3
#define LCD_READID1				0xDA
#define LCD_READID2				0xDB
#define LCD_READID3				0xDC
#define LCD_POSITIVEGAMMCORR	0xE0
#define LCD_NEGATIVEGAMMCORR	0xE1
#define LCD_DIGITALGAMMCONTROL1	0xE2
#define LCD_DIGITALGAMMCONTROL2	0xE3
#define LCD_INTERFACECONTROL	0xF6
// LCD Registers

void lcd_init(void);
void lcd_fill_RGB(uint16_t color, uint16_t x, uint16_t y, uint16_t width, uint16_t height);
void lcd_set_orientation(uint8_t Orientation);
void lcd_set_window(unsigned short x0, unsigned short y0, unsigned short x1, unsigned short y1);
void lcd_display_off(void);
void lcd_display_on(void);
void lcd_data_write(unsigned short data);
void lcd_cmd_write(unsigned char command);
void lcd_backlight_on();
void lcd_backlight_off();

uint16_t lcd_get_width();
uint16_t lcd_get_height();
uint8_t lcd_get_orientation();



#endif /* __LCD_FSMC_H_ */

  
  • lcd_lvgl.c
#include <lcd_lvgl.h>

/* Memory-to-memory DMA Handler */
extern DMA_HandleTypeDef hdma_memtomem_dma2_stream0;

extern uint8_t test_with_dma;
void tft_lvgl_draw_bitmap(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t *bitmap)
{
	uint32_t total_pixels = (x2-x1+1) * (y2-y1+1);

	lcd_set_window(x1, y1, x2, y2);

	// use memory-to-memory DMA
	HAL_DMA_Start(&hdma_memtomem_dma2_stream0, (uint32_t)bitmap, (LCD_DATA_BASE), total_pixels);
	HAL_DMA_PollForTransfer(&hdma_memtomem_dma2_stream0, HAL_DMA_FULL_TRANSFER, 1000);

	// if not use DMA translation
	//	for (int i=0; i < total_pixels; i++) {
	//		lcd_data_write(*(bitmap+i));
	//	}

}

void tft_lvgl_disp_flush(lv_disp_drv_t * disp, const lv_area_t * area, lv_color_t * color_p)
{
    tft_lvgl_draw_bitmap(
            (uint16_t)(area->x1),
            (uint16_t)(area->y1),
            (uint16_t)(area->x2),
            (uint16_t)(area->y2), (uint16_t*)color_p
            );

    lv_disp_flush_ready(disp);         /* Indicate you are ready with the flushing*/
}


void lvgl_init() {
	lv_init();

	static lv_disp_draw_buf_t draw_buf;
	static lv_color_t buf1[LCD_WIDTH * LCD_HEIGHT / 10];                        /*Declare a buffer for 1/10 screen size*/
	lv_disp_draw_buf_init(&draw_buf, buf1, NULL, LCD_WIDTH * LCD_HEIGHT / 10);  /*Initialize the display buffer.*/

	static lv_disp_drv_t disp_drv;        /*Descriptor of a display driver*/
	lv_disp_drv_init(&disp_drv);          /*Basic initialization*/
	disp_drv.flush_cb = tft_lvgl_disp_flush;    /*Set your driver function*/
	disp_drv.draw_buf = &draw_buf;        /*Assign the buffer to the display*/
	disp_drv.hor_res = lcd_get_width();   /*Set the horizontal resolution of the display*/
	disp_drv.ver_res = lcd_get_height();   /*Set the vertical resolution of the display*/
	lv_disp_drv_register(&disp_drv);      /*Finally register the driver*/

}

void lvgl_xpt2046_read_cb(lv_indev_drv_t * drv, lv_indev_data_t*data)
{
	static uint16_t x, y;
	if(XPT2046_TouchPressed()) {
		XPT2046_TouchGetCoordinates(&x, &y);
		data->point.x = x;
		data->point.y = y;
		data->state = LV_INDEV_STATE_PRESSED;
	} else {
		data->state = LV_INDEV_STATE_RELEASED;
	}
}

void lvgl_xpt2046_touch_init() {
	static lv_indev_drv_t indev_drv;
	lv_indev_drv_init(&indev_drv);      	/*Basic initialization*/
	indev_drv.type = LV_INDEV_TYPE_POINTER;
	indev_drv.read_cb = lvgl_xpt2046_read_cb;
	/*Register the driver in LVGL and save the created input device object*/
	lv_indev_drv_register(&indev_drv);
}


  
  • lcd_lvgl.h
#ifndef __LCD_LVGL_H
#define __LCD_LVGL_H

#include <lcd_fsmc.h>
#include <lvgl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "XPT2046_touch.h"


void lvgl_init();
void lvgl_xpt2046_touch_init();

#endif /*__LCD_LVGL_H */

  
  • XPT2046_touch.c
#include <lcd_fsmc.h>
#include <stdio.h>
#include <stdlib.h>
#include "XPT2046_touch.h"


#define READ_X 0xD0
#define READ_Y 0x90


uint16_t cRawX_min = XPT2046_MIN_RAW_X;
uint16_t cRawX_max = XPT2046_MAX_RAW_X;
uint16_t cRawY_min = XPT2046_MIN_RAW_Y;
uint16_t cRawY_max = XPT2046_MAX_RAW_Y;


static void XPT2046_TouchSelect()
{
    HAL_GPIO_WritePin(XPT2046_CS_GPIO_Port, XPT2046_CS_Pin, GPIO_PIN_RESET);
}

void XPT2046_TouchUnselect()
{
    HAL_GPIO_WritePin(XPT2046_CS_GPIO_Port, XPT2046_CS_Pin, GPIO_PIN_SET);
}

bool XPT2046_TouchPressed()
{
    return HAL_GPIO_ReadPin(XPT2046_IRQ_GPIO_Port, XPT2046_IRQ_Pin) == GPIO_PIN_RESET;
}

bool XPT2046_TouchGetCoordinates(uint16_t* x, uint16_t* y)
{
	bool ret_value=false;
	uint16_t tx,ty;
	uint32_t raw_x;
	uint32_t raw_y;
	if (XPT2046_TouchGetRawCoordinates(&raw_x, &raw_y))
	{
		if(raw_x < cRawX_min) raw_x = cRawX_min;
		if(raw_x > cRawX_max) raw_x = cRawX_max;

		if(raw_y < cRawY_min) raw_y = cRawY_min;
		if(raw_y > cRawY_max) raw_y = cRawY_max;

		tx = (raw_x - cRawX_min) * XPT2046_SCALE_X / (cRawX_max - cRawX_min);
		ty = (raw_y - cRawY_min) * XPT2046_SCALE_Y / (cRawY_max - cRawY_min);

		uint8_t lot = lcd_get_orientation();
		switch (lot)
		{
		case LCD_ORIENTATION_PORTRAIT:
			*x=tx;
			*y=ty;
			break;
		case LCD_ORIENTATION_LANDSCAPE:
			*x=ty;
			*y=LCD_WIDTH-tx;
					break;
		case LCD_ORIENTATION_PORTRAIT_MIRROR:
			*x=LCD_WIDTH-tx;
			*y=LCD_HEIGHT-ty;
					break;
		case LCD_ORIENTATION_LANDSCAPE_MIRROR:
			*x=LCD_HEIGHT-ty;
			*y=tx;
			break;
		}
		ret_value =true;
    }
	return ret_value;

}
bool XPT2046_TouchGetRawCoordinates(uint32_t* raw_x, uint32_t* raw_y)
{
    static const uint8_t cmd_read_x[] = { READ_X };
    static const uint8_t cmd_read_y[] = { READ_Y };
    static const uint8_t zeroes_tx[] = { 0x00, 0x00 };
    static const uint8_t SAMPLES=16;

    //if (!XPT2046_TouchPressed()) return false;
    //HAL_Delay(10);
    XPT2046_TouchSelect();

    uint32_t avg_x = 0;
    uint32_t avg_y = 0;
    uint8_t nsamples = 0;


    for(uint8_t i = 0; i < SAMPLES; i++)
    {
        if(!XPT2046_TouchPressed()) {
            break;
        }

        nsamples++;

        HAL_SPI_Transmit(&XPT2046_SPI_PORT, (uint8_t*)cmd_read_y, sizeof(cmd_read_y), HAL_MAX_DELAY);
        uint8_t y_raw[2];
        HAL_SPI_TransmitReceive(&XPT2046_SPI_PORT, (uint8_t*)zeroes_tx, y_raw, sizeof(y_raw), HAL_MAX_DELAY);

        HAL_SPI_Transmit(&XPT2046_SPI_PORT, (uint8_t*)cmd_read_x, sizeof(cmd_read_x), HAL_MAX_DELAY);
        uint8_t x_raw[2];
        HAL_SPI_TransmitReceive(&XPT2046_SPI_PORT, (uint8_t*)zeroes_tx, x_raw, sizeof(x_raw), HAL_MAX_DELAY);

        avg_x += (((uint16_t)x_raw[0]) << 8) | ((uint16_t)x_raw[1]);
        avg_y += (((uint16_t)y_raw[0]) << 8) | ((uint16_t)y_raw[1]);
    }

    XPT2046_TouchUnselect();

    if(nsamples < SAMPLES)
        return false;

    *raw_x = (avg_x / SAMPLES);
    *raw_y = (avg_y / SAMPLES);
    return true;

}

bool XPT2046_TouchCalibration()
{
	uint32_t x0=0,y0=0,x1=0,y1=0,x2=0,y2=0,x3=0,y3=0;
	bool correct=true;
	uint32_t width, height;
	uint8_t lot = lcd_get_orientation();
	lcd_set_orientation(LCD_ORIENTATION_PORTRAIT);
	width = lcd_get_width();
	height = lcd_get_height();
	lcd_fill_RGB(0x0000, 0, 0, width-1, height-1);



	lcd_fill_RGB(0xffff, 0, 0, 6,6);
	lcd_set_window(20,100 ,20 ,100);  // set LCD cursor to (20,100)
	while(!XPT2046_TouchPressed()) ;
	if (!XPT2046_TouchGetRawCoordinates(&x0, &y0))
	{
		lcd_set_orientation(lot);
		return false;
	}
	lcd_fill_RGB(0x0000, 0, 0, width-1, height-1);
	lcd_fill_RGB(0xffff, 0, height-7, 6, 6);

	while(XPT2046_TouchPressed());
	HAL_Delay(1);

	lcd_set_window(20, 100, 20, 100);
	while(!XPT2046_TouchPressed());
	if(!XPT2046_TouchGetRawCoordinates(&x1, &y1))
	{
		lcd_set_orientation(lot);
		return false;
	}
	lcd_fill_RGB(0x0000, 0, 0, width-1, height-1);
	lcd_fill_RGB(0xffff,width-7, height-7, 6, 6);
	while(XPT2046_TouchPressed());
	HAL_Delay(1);


	lcd_set_window(20, 100, 20, 100);
	while(!XPT2046_TouchPressed());
	if (!XPT2046_TouchGetRawCoordinates(&x2, &y2))
	{
		lcd_set_orientation(lot);
		return false;
	}
	lcd_fill_RGB(0x0000, 0, 0, width-1, height-1);
	lcd_fill_RGB(0xffff, width-7, 0, 6, 6);
	while(XPT2046_TouchPressed());
	HAL_Delay(1);

	lcd_set_window(20, 100, 20, 100);
	while(!XPT2046_TouchPressed());
	if (!XPT2046_TouchGetRawCoordinates(&x3, &y3))
	{
		lcd_set_orientation(lot);
		return false;
	}
	while(XPT2046_TouchPressed());

	if (abs(x0-x1) > XTP2046_CALI_DIFF) correct = false;
	if (abs(x2-x3) > XTP2046_CALI_DIFF) correct = false;
	if (abs(y1-y2) > XTP2046_CALI_DIFF) correct = false;
	if (abs(y0-y3) > XTP2046_CALI_DIFF) correct = false;
	if (correct) {
		cRawX_min = (x0+x1)/2;
		cRawX_max = (x2+x3)/2;
		cRawY_min = (y0+y3)/2;
		cRawY_max = (y1+y2)/2;
	}

	lcd_fill_RGB(0x0000, 0, 0, width-1, height-1);
	lcd_set_window(20, 100, 20, 100);
	lcd_set_orientation(lot);
	return correct;
}
  • XPT2046_touch.h
#ifndef XPT2046_TOUCH_H_
#define XPT2046_TOUCH_H_

#include "main.h"
#include <stdbool.h>

/*** Redefine if necessary ***/

// Warning! Use SPI bus with < 2.5 Mbit speed, better ~650 Kbit to be save.
#define XPT2046_SPI_PORT hspi2
extern SPI_HandleTypeDef XPT2046_SPI_PORT;

#define XPT2046_IRQ_Pin       T_IRQ_Pin
#define XPT2046_IRQ_GPIO_Port T_IRQ_GPIO_Port
#define XPT2046_CS_Pin        T_CS_Pin
#define XPT2046_CS_GPIO_Port  T_CS_GPIO_Port

// change depending on screen orientation
#define XPT2046_SCALE_X 240
#define XPT2046_SCALE_Y 320

#define XPT2046_MIN_RAW_X 1860
#define XPT2046_MAX_RAW_X 29650
#define XPT2046_MIN_RAW_Y 1830
#define XPT2046_MAX_RAW_Y 29350

//#define XPT2046_MIN_RAW_X 2000
//#define XPT2046_MAX_RAW_X 30000
//#define XPT2046_MIN_RAW_Y 1500
//#define XPT2046_MAX_RAW_Y 29000

#define XTP2046_CALI_DIFF	2500

// call before initializing any SPI devices
void XPT2046_TouchUnselect(void);
bool XPT2046_TouchPressed(void);
bool XPT2046_TouchGetCoordinates(uint16_t* x, uint16_t* y);
bool XPT2046_TouchGetRawCoordinates(uint32_t* raw_, uint32_t* raw_y);
bool XPT2046_TouchCalibration(void);

#endif /* XPT2046_TOUCH_H_ */

沒有留言:

張貼留言