主机环境:Windows 7 SP1
开发环境:MDK5.14
目标板:ST NUCLEO-F303RE
TFT型号:2.4英寸,带触摸,SD卡,240*320分辨率,26万色
驱动IC:ILI9325
ST库版本:STM32Cube_FW_F3_V1.1.0
SD卡:Kingston 16GB Micro SDHC Class 10
触摸IC:XPT2046
关于XPT2016的说明可以从网上下载很多资料,XPT2046使用SPI通信接口,接口说明如下:
多出了一个BUSY脚和一个PENIRQ脚,BUSY信号指示XPT2046工作状态,但是在使用过程中发现其不起作用,所以就没用了,PENIRQ为中断指示脚,当触摸屏有接触时其信号会变成低电平。对于NUCLEO-F303RE来说SPI1接口在BSP里面用作了SD卡接口,因此这里使用SPI3接口来跟XPT2046进行通信,接口声明如下
/* Definition for SPI_XPT2046 clock resources */
#define SPI_XPT2046 SPI3
#define SPI_XPT2046_CLK_ENABLE() __SPI3_CLK_ENABLE()
#define SPI_XPT2046_CLK_DISABLE() __SPI3_CLK_DISABLE()
#define SPI_XPT2046_nCS_GPIO_CLK_ENABLE() __GPIOA_CLK_ENABLE()
#define SPI_XPT2046_SCK_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define SPI_XPT2046_MISO_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define SPI_XPT2046_MOSI_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define SPI_XPT2046_FORCE_RESET() __SPI3_FORCE_RESET()
#define SPI_XPT2046_RELEASE_RESET() __SPI3_RELEASE_RESET()
/* Definition for SPIx Pins */
#define SPI_XPT2046_SCK_PIN GPIO_PIN_10
#define SPI_XPT2046_SCK_GPIO_PORT GPIOC
#define SPI_XPT2046_SCK_AF GPIO_AF6_SPI3
#define SPI_XPT2046_MISO_PIN GPIO_PIN_11
#define SPI_XPT2046_MISO_GPIO_PORT GPIOC
#define SPI_XPT2046_MISO_AF GPIO_AF6_SPI3
#define SPI_XPT2046_MOSI_PIN GPIO_PIN_12
#define SPI_XPT2046_MOSI_GPIO_PORT GPIOC
#define SPI_XPT2046_MOSI_AF GPIO_AF6_SPI3
#define SPI_XPT2046_nCS_PIN GPIO_PIN_15
#define SPI_XPT2046_nCS_GPIO_PORT GPIOA
#define SPI_XPT2046_nCS_Set_Low() (GPIOA->BRR = GPIO_PIN_15)
#define SPI_XPT2046_nCS_Set_High() (GPIOA->BSRRL = GPIO_PIN_15)
#define SPI_XPT2046_TIMEOUT 1000
通信主时钟为2MHz据此编辑我们的spi3初始化以及读写代码
SPI_HandleTypeDef spi_xpt_Handle;
/**
* @brief SPI MSP Initialization
* This function configures the hardware resources used in this example:
* - Peripheral's clock enable
* - Peripheral's GPIO Configuration
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(SPI_XPT2046 != hspi->Instance)
{
return ;
}
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO TX/RX clock */
SPI_XPT2046_SCK_GPIO_CLK_ENABLE();
SPI_XPT2046_MISO_GPIO_CLK_ENABLE();
SPI_XPT2046_MOSI_GPIO_CLK_ENABLE();
SPI_XPT2046_nCS_GPIO_CLK_ENABLE();
/* Enable SPI clock */
SPI_XPT2046_CLK_ENABLE();
/*##-2- Configure peripheral GPIO ##########################################*/
/* SPI SCK GPIO pin configuration */
GPIO_InitStruct.Pin = SPI_XPT2046_SCK_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = SPI_XPT2046_SCK_AF;
HAL_GPIO_Init(SPI_XPT2046_SCK_GPIO_PORT, &GPIO_InitStruct);
/* SPI MISO GPIO pin configuration */
GPIO_InitStruct.Pin = SPI_XPT2046_MISO_PIN;
GPIO_InitStruct.Alternate = SPI_XPT2046_MISO_AF;
HAL_GPIO_Init(SPI_XPT2046_MISO_GPIO_PORT, &GPIO_InitStruct);
/* SPI MOSI GPIO pin configuration */
GPIO_InitStruct.Pin = SPI_XPT2046_MOSI_PIN;
GPIO_InitStruct.Alternate = SPI_XPT2046_MOSI_AF;
HAL_GPIO_Init(SPI_XPT2046_MOSI_GPIO_PORT, &GPIO_InitStruct);
/* SPI nCS GPIO pin configuration */
GPIO_InitStruct.Pin = SPI_XPT2046_nCS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(SPI_XPT2046_nCS_GPIO_PORT, &GPIO_InitStruct);
}
/**
* @brief SPI MSP De-Initialization
* This function frees the hardware resources used in this example:
* - Disable the Peripheral's clock
* - Revert GPIO configuration to its default state
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
{
if(SPI_XPT2046 != hspi->Instance)
{
return ;
}
/*##-1- Reset peripherals ##################################################*/
SPI_XPT2046_FORCE_RESET();
SPI_XPT2046_RELEASE_RESET();
/*##-2- Disable peripherals and GPIO Clocks ################################*/
/* Configure SPI SCK as alternate function */
HAL_GPIO_DeInit(SPI_XPT2046_SCK_GPIO_PORT, SPI_XPT2046_SCK_PIN);
/* Configure SPI MISO as alternate function */
HAL_GPIO_DeInit(SPI_XPT2046_MISO_GPIO_PORT, SPI_XPT2046_MISO_PIN);
/* Configure SPI MOSI as alternate function */
HAL_GPIO_DeInit(SPI_XPT2046_MOSI_GPIO_PORT, SPI_XPT2046_MOSI_PIN);
/* Configure SPI nCS as alternate function */
HAL_GPIO_DeInit(SPI_XPT2046_nCS_GPIO_PORT, SPI_XPT2046_nCS_PIN);
}
/**********************************************************************
函数:SPI3_Init()
函数作用:SPI3初始化
参数:无
返回值:无
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-07-31
说明: SPI3使用的时钟为APB1,在时钟初始化时该时钟为
32MHz,跟xpt2046通信设置成2MHz速率,CLK空闲状态为低
电平,数据在时钟上升沿锁存,8bit数据位,MSB,主模式
**********************************************************************/
void SPI3_Init(void)
{
/* Set the SPI parameters */
spi_xpt_Handle.Instance = SPI_XPT2046;
spi_xpt_Handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
spi_xpt_Handle.Init.Direction = SPI_DIRECTION_2LINES;
spi_xpt_Handle.Init.CLKPhase = SPI_PHASE_1EDGE;
spi_xpt_Handle.Init.CLKPolarity = SPI_POLARITY_LOW;
spi_xpt_Handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
spi_xpt_Handle.Init.CRCPolynomial = 7;
spi_xpt_Handle.Init.DataSize = SPI_DATASIZE_8BIT;
spi_xpt_Handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
spi_xpt_Handle.Init.NSS = SPI_NSS_SOFT;
spi_xpt_Handle.Init.TIMode = SPI_TIMODE_DISABLED;
spi_xpt_Handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
spi_xpt_Handle.Init.CRCLength = SPI_CRC_LENGTH_8BIT;
spi_xpt_Handle.Init.Mode = SPI_MODE_MASTER;
HAL_SPI_Init(&spi_xpt_Handle);//初始化spi
return ;
}
/**********************************************************************
函数:SPI3_Write()
函数作用:SPI3发送一个字节数据
参数:
uint8_t value----------------------------待发送的字节数据
返回值:0:成功-1:失败
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-07-31
说明: SPI3通信超时时间为1S
**********************************************************************/
int8_t SPI3_Write(uint8_t value)
{
HAL_StatusTypeDef status = HAL_OK;
status = HAL_SPI_Transmit(&spi_xpt_Handle, &value, 1, SPI_XPT2046_TIMEOUT);
/* Check the communication status */
if(status != HAL_OK)
{
return (int8_t)-1;
}
return 0;
}
/**********************************************************************
函数:SPI3_Read()
函数作用:SPI3接收一个16bit数据
参数:
uint8_t *value------------------------------接收数据的地址
返回值:0:成功-1:失败
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-07-31
说明: SPI3通信超时时间为1S
**********************************************************************/
int8_t SPI3_Read(uint8_t *readvalue)
{
HAL_StatusTypeDef status = HAL_OK;
uint8_t writevalue = 0x00;
status = HAL_SPI_TransmitReceive(&spi_xpt_Handle, &writevalue, readvalue, 1, SPI_XPT2046_TIMEOUT);
/* Check the communication status */
if(status != HAL_OK)
{
return (int8_t)-1;
}
return 0;
}
#define TOUCHPANEL_PEN_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define TOUCHPANEL_BUSY_GPIO_CLK_ENABLE() __GPIOC_CLK_ENABLE()
#define TOUCHPANEL_PEN_PIN GPIO_PIN_2
#define TOUCHPANEL_PEN_GPIO_PORT GPIOC
#define TOUCHPANEL_BUSY_PIN GPIO_PIN_3
#define TOUCHPANEL_BUSY_GPIO_PORT GPIOC
#define TOUCHPANEL_BUSY_Read() (GPIOC->IDR & GPIO_PIN_3)
//#define TOUCHPANEL_PEN_Read() (GPIOC->IDR & GPIO_PIN_2)
#define TOUCHPANEL_BUSY (GPIO_PIN_3)
#define TOUCHPANEL_IDLE (0x00)
/**********************************************************************
函数:HAL_TouchPanel_MspInit()
函数作用:触摸屏端口资源初始化
参数:无
返回值:无
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-07-31
说明: 这里端口是PEN口和BUSY口其他口都是spi通讯口
**********************************************************************/
void HAL_TouchPanel_MspInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/*##-1- Enable peripherals and GPIO Clocks #################################*/
/* Enable GPIO clock */
TOUCHPANEL_PEN_GPIO_CLK_ENABLE();
TOUCHPANEL_BUSY_GPIO_CLK_ENABLE();
/*##-2- Configure peripheral GPIO #######################################*/
/* PEN GPIO pin configuration */
GPIO_InitStruct.Pin = TOUCHPANEL_BUSY_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Pin = TOUCHPANEL_BUSY_PIN;
HAL_GPIO_Init(TOUCHPANEL_BUSY_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = TOUCHPANEL_PEN_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
HAL_GPIO_Init(TOUCHPANEL_PEN_GPIO_PORT, &GPIO_InitStruct);
/*Enable an set EXTI line 2 Interrupt to the lowest priority*/
HAL_NVIC_SetPriority(EXTI2_TSC_IRQn,2,0);
HAL_NVIC_EnableIRQ(EXTI2_TSC_IRQn);
return ;
}
/**********************************************************************
函数:TouchPanel_Init()
函数作用:触摸屏初始化
参数:无
返回值:无
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-07-31
说明:
**********************************************************************/
void TouchPanel_Init(void)
{
HAL_TouchPanel_MspInit();//初始化io口资源
SPI_XPT2046_nCS_Set_High();//片选拉高
}
MSB一直为1,MODE=012bit转换模式,SER/DFR=0:差分模式转换,文档中提到在测量X、Y坐标时首选差分模式,PD1,PD0=0,A2、A1、A0说明如下
001是测量X坐标,101是测量Y坐标
构造一个采样点结构体,存储测量值,如下
typedef struct
{
uint16_t sample_x;
uint16_t sample_y;
}Touch_Point;
/**********************************************************************
函数:TouchPanel_GetPoint()
函数作用:获取触摸点
参数:无
返回值:无
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-07-31
说明:
**********************************************************************/
int8_t TouchPanel_GetPoint(Touch_Point *touch_point)
{
uint8_t sample_value_h=0,sample_value_l=0;
SPI_XPT2046_nCS_Set_Low();
if(SPI3_Write(0x90) != 0)//测量Y-
{
return (int8_t)-1;
}
if(0 != SPI3_Read(&sample_value_h))
{
printf("read err1\r\n");
}
if(0 != SPI3_Read(&sample_value_l))
{
printf("read err1\r\n");
}
touch_point->sample_x = ((sample_value_h&0x7F)<<5|(sample_value_l>>3));
if(0 != SPI3_Write(0xD0))//测量X-
{
printf("write err2\r\n");
}
sample_value_h = 0;
sample_value_l = 0;
if(0 != SPI3_Read(&sample_value_h))
{
printf("read err2\r\n");
}
if(0 != SPI3_Read(&sample_value_l))
{
printf("read err2\r\n");
}
touch_point->sample_y = ((sample_value_h&0x7F)<<5|(sample_value_l>>3));
SPI_XPT2046_nCS_Set_High();
return 0;
}
uint8_t flag = 0;
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
{
switch(GPIO_Pin)
{
case TOUCHPANEL_PEN_PIN:
flag = 1;
break;
default:
break;
}
}
/**********************************************************************
函数:EXTI2_TSC_IRQHandler()
函数作用:EXTI2_TSC中断响应函数
参数:无
返回值:无
上一版本:无
当前版本:1.0
作者:anobodykey
最后修改时间:2015-08-10
说明: 只处理EXTI2中断
**********************************************************************/
void EXTI2_TSC_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler (TOUCHPANEL_PEN_PIN);
}
在主循环中代码如下
while(1)
{
if(flag)
{
//PEN为低电平表示有触摸点
printf("get the touch!\r\n");
TouchPanel_GetPoint(&touch_point);
printf("sample y:%04X\r\n",touch_point.sample_y);
printf("sample x:%04X\r\n",touch_point.sample_x);
flag = 0;
}
}
现在只是获取了采样值还没有转换成X、Y坐标,同时对于电阻屏来说第一步就是校正,关于校正流程网上有很多资源,做完这些下面就可以使用STemWin来制作图形界面了,使用STemWin可以很方便我们做出丰富的界面。