主机环境:Windows 7 SP1
开发环境:MDK5.14
目标板:ST NUCLEO-F303RE
TFT型号:2.4英寸,带触摸,SD卡,240*320分辨率,26万色
驱动IC:ILI9325
ST库版本:STM32Cube_FW_F3_V1.1.0
之前ST社区搞活动抢了一块NUCLEO-F303RE的开发板,本来是想研究一哈USB开发的,后来拿到手之后发现硬件不得行,得自己接个USB接口,板子自带的USB是下载和当作串口用的,属于ST-LINK板。没搞头了,板子就研究了一哈串口,点亮了一下LED。。。后来在淘宝上看到一块TFT屏挺便宜的,就拍了回来配合NUCLEO板调调TFT吧,毕竟之前也一直没弄过TFT,只搞过12864液晶屏,哔格不够。
TFT的接口如下
NUCLEO-F303RE接口图如下
该版TFT模块支持5V供电和3.3V供电,我使用的是3.3V供电,毕竟STM32一般都是3.3V的工作电压,通过TFT的接口我们可以发现其使用16bit数据口DB0~DB15,触屏和SD卡暂时不需要,此外还需要电源线和地线,以及5个控制线RS、WR、RD、CS、RST,BL是没接的,因为TFT模块的背光由VCC控制了,因此省略了该BL口,对于NUCLEO板来说,使用PB口来作为数据口PC0作为CS口、PC1作为RST口、PA4作为RS口、PA1作为WR口、PA0作为RD口
再连接好电源线和地线,上电之后就可以发现TFT屏被点亮了,说明供电还是正常的,接下来就是敲代码了,来读取ILI9325的ID。
ILI9325的操作时序可以在其手册中看到如下:
照着这个敲代码就可以了,
/********************************************************************** 函数:ILI9325_Write_Reg() 函数作用:向ILI9325寄存器写入16bit数据 参数: uint16_t reg_addr-----------------------------------寄存器地址 uint16_t reg_value--------------------------------------16bit数据 返回值:无 上一版本:无 当前版本:1.0 作者:anobodykey 最后修改时间:2015-07-27 说明: ILI9325地址和数据都是使用PB口通信,因此PB口是 复用的,需先写寄存器地址再写入数据 **********************************************************************/ void ILI9325_Write_Reg(uint16_t reg_addr, uint16_t reg_value) { ILI9325_nCS_Set_Low();//拉低片选,使其有效 ILI9325_RS_Set_Low();//拉低RS信号,选择index寄存器 ILI9325_nWR_Set_Low();//拉低写使能,使其有效 GPIOB->ODR = reg_addr;//写寄存器地址 ILI9325_nWR_Set_High(); ILI9325_RS_Set_High();//拉高RS信号,选择control寄存器 ILI9325_nWR_Set_Low(); GPIOB->ODR = reg_value; ILI9325_nWR_Set_High(); ILI9325_nCS_Set_High(); } /********************************************************************** 函数:ILI9325_Read_Reg() 函数作用:从ILI9325寄存器读取16bit数据 参数: uint16_t reg_addr-----------------------------------寄存器地址 返回值:16bit数据 上一版本:无 当前版本:1.0 作者:anobodykey 最后修改时间:2015-07-27 说明: PB口工作在推挽输出模式,读取寄存器数据时需 设置成上拉输入模式才可读取 **********************************************************************/ uint16_t ILI9325_Read_Reg(uint16_t reg_addr) { GPIO_InitTypeDef GPIO_InitStruct; uint16_t reg_value = 0; ILI9325_nCS_Set_Low();//拉低片选,使其有效 ILI9325_RS_Set_Low();//拉低RS信号,选择index寄存器 ILI9325_nWR_Set_Low();//拉低写使能,使其有效 GPIOB->ODR = reg_addr;//写寄存器地址 ILI9325_nWR_Set_High(); ILI9325_RS_Set_High();//拉高RS信号,选择control寄存器 //将PB口设置为输入口读取寄存器数据 GPIO_InitStruct.Pin = ILI9325_DATA_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(ILI9325_DATA_GPIO_PORT, &GPIO_InitStruct); ILI9325_nRD_Set_Low(); reg_value = (GPIOB->IDR&GPIO_PIN_All); ILI9325_nRD_Set_High(); ILI9325_nCS_Set_High(); //将PB口恢复成推挽输出模式 GPIO_InitStruct.Pin = ILI9325_DATA_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; HAL_GPIO_Init(ILI9325_DATA_GPIO_PORT, &GPIO_InitStruct); return reg_value; }
/********************************************************************** 函数:HAL_ILI9325_MspInit() 函数作用:初始化与ILI9325 连接的io口资源 参数:无 返回值:无 上一版本:无 当前版本:1.0 作者:anobodykey 最后修改时间:2015-07-27 说明: MCU与ILI9325连接的io口均作为推挽输出口 **********************************************************************/ void HAL_ILI9325_MspInit(void) { GPIO_InitTypeDef GPIO_InitStruct; //打开控制端口及数据时钟 ILI9325_nCS_GPIO_CLK_ENABLE(); ILI9325_nRST_GPIO_CLK_ENABLE(); ILI9325_RS_GPIO_CLK_ENABLE(); ILI9325_nWR_GPIO_CLK_ENABLE(); ILI9325_nRD_GPIO_CLK_ENABLE(); ILI9325_DATA_GPIO_CLK_ENABLE(); //设置端口引脚 GPIO_InitStruct.Pin = ILI9325_nCS_PIN; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; HAL_GPIO_Init(ILI9325_nCS_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = ILI9325_nRST_PIN; HAL_GPIO_Init(ILI9325_nRST_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = ILI9325_RS_PIN; HAL_GPIO_Init(ILI9325_RS_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = ILI9325_nWR_PIN; HAL_GPIO_Init(ILI9325_nWR_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = ILI9325_nRD_PIN; HAL_GPIO_Init(ILI9325_nRD_GPIO_PORT, &GPIO_InitStruct); GPIO_InitStruct.Pin = ILI9325_DATA_PIN; HAL_GPIO_Init(ILI9325_DATA_GPIO_PORT, &GPIO_InitStruct); } /********************************************************************** 函数:ILI9325_Init() 函数作用:ILI9325初始化 参数:无 返回值:无 上一版本:无 当前版本:1.0 作者:anobodykey 最后修改时间:2015-07-27 说明: **********************************************************************/ void ILI9325_Init(void) { HAL_ILI9325_MspInit(); ILI9325_nRST_Set_High(); HAL_Delay(50); ILI9325_nRST_Set_Low();//复位ILI9325低电平有效 HAL_Delay(100); ILI9325_nRST_Set_High(); //总线处于空闲状态 ILI9325_nCS_Set_High(); ILI9325_RS_Set_High(); ILI9325_nRD_Set_High(); ILI9325_nWR_Set_High(); HAL_Delay(50); }
int main(void) { uint8_t fmt = 0; uint16_t version = 0; HAL_Init(); SystemClock_Config(); uart_init(115200); BSP_LED_Init(LED2); ILI9325_Init(); isr_init(); version = ILI9325_Read_Reg(0x00); printf("ili9325 version:%X\r\n",version); printf("PLEASE ENTER YOUR CHOICE:"); while(1) { if (0 == uart_read(&fmt,0x2400)) { switch(fmt) { case 1: BSP_LED_On(LED2); printf("THE LED2 IS LIGHTED UP!\r\n"); break; case 0: BSP_LED_Off(LED2); printf("THE LED2 IS CLOSED!\r\n"); break; default: break; } printf("PLEASE ENTER YOUR CHOICE:\r\n"); } } return 0; }
可以看到读到的ID是正确的,证明我们的代码是没错的,硬件连线也是正确的,接下来就是使用TFT来实现图形显示了,一步一个脚印,慢慢来吧。网上有很多使用FSMC来驱动TFT的,由于我还没使用过FSMC一,因此就从最简单易懂的IO口操作学起吧!