主机环境: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可以很方便我们做出丰富的界面。