#include "ws_drive_tft.h" #include "drive_dzcode.h" #include #include #include "string.h" // 注意: // 使用只需修改映射地址 // FSMC_BANK1_1 对应 NE1 , 以此类推 // " 1<<24 " 中的 24 对应A23, 以此类推 __IO uint16_t *FSMC_TFT_Dat_Addr; // 写数据地址 __IO uint16_t *FSMC_TFT_Cmd_Addr; // 写命令地址 #define WS_TFT_Write_Cmd(d) (*FSMC_TFT_Cmd_Addr) = (d) #define WS_TFT_Write_Dat(d) (*FSMC_TFT_Dat_Addr) = (d) #define WS_TFT_Write_Cmd_Dat(r,d) (*FSMC_TFT_Cmd_Addr) = (r),(*FSMC_TFT_Dat_Addr) = (d) // 设置TFT对应的内存地址 void WS_TFT_FSMC_Addr_Init(void) { // 注意: // 使用只需修改映射地址 // FSMC_BANK1_1 对应 NE1 , 以此类推 // " 1<<24 " 中的24对应A23, 以此类推 // 16bit位宽 , LCD_RS->A23(NE1) , 对应第24个地址位 FSMC_TFT_Dat_Addr = (uint16_t *)(((uint32_t)(FSMC_BANK1_1 | 1<<17))); FSMC_TFT_Cmd_Addr = (uint16_t *)(((uint32_t)(FSMC_BANK1_1 | 1<<17))-2); } //LCD重要参数集 typedef struct { uint16_t width; //LCD 宽度 uint16_t height; //LCD 高度 uint16_t id; //LCD ID uint8_t dir; //横屏还是竖屏控制:0,竖屏;1,横屏。 uint16_t wramcmd; //开始写gram指令 uint16_t setxcmd; //设置x坐标指令 uint16_t setycmd; //设置y坐标指令 }_lcd_dev; _lcd_dev lcddev; #define USE_HORIZONTAL LCD_DIR_MODE // 0//1 void WS_TFT_Set_Param(void) { lcddev.setxcmd=0x2A; lcddev.setycmd=0x2B; lcddev.wramcmd=0x2C; #if USE_HORIZONTAL==1 //使用横屏 lcddev.dir=1;//横屏 lcddev.width=TFT_X_MAX; lcddev.height=TFT_Y_MAX; WS_TFT_Write_Cmd_Dat(0x36,(1<<3)|(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1 #else//竖屏 lcddev.dir=0;//竖屏 lcddev.width =TFT_X_MAX; lcddev.height=TFT_Y_MAX; WS_TFT_Write_Cmd_Dat(0x36,(1<<3)|(0<<6)|(0<<7));//BGR==1,MY==0,MX==0,MV==0 #endif } // 按照指定颜色清屏 void WS_TFT_Clear(uint16_t color) { uint32_t index=0; // 239 , 319 WS_TFT_Set_Windows(0,0,lcddev.width-1,lcddev.height-1); for(index=0 ; index>8); WS_TFT_Write_Dat(0x00FF&xStar); WS_TFT_Write_Dat(xEnd>>8); WS_TFT_Write_Dat(0x00FF&xEnd); WS_TFT_Write_Cmd(lcddev.setycmd); WS_TFT_Write_Dat(yStar>>8); WS_TFT_Write_Dat(0x00FF&yStar); WS_TFT_Write_Dat(yEnd>>8); WS_TFT_Write_Dat(0x00FF&yEnd); // 开始跟新选择区域内的GRAM WS_TFT_Write_Cmd(lcddev.wramcmd); } // 画点 void WS_TFT_Draw_Point(uint16_t x,uint16_t y,uint16_t color) { // 设置区域 WS_TFT_Set_Windows(x,y,x+1,y+1); // 写入数据 WS_TFT_Write_Dat(color) ; } // 画实心矩形 void WS_TFT_Draw_Rectangle(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd,uint16_t color) { uint16_t i = 0; // 设置区域 WS_TFT_Set_Windows(xStar,yStar,xEnd,yEnd); // 写入数据 for(;yStar < yEnd ; yStar ++ ) { for(i = xStar; i <= xEnd; i ++ ) WS_TFT_Write_Dat(color) ; } } // 获取16点 字库数据 // 虚函数, 在SD卡或spi flash实现 读取数据 // buffer: 数据缓存地址 // gbk : 汉字内码数据 // size : 读取汉字个数 // 返回值: 读取的数据个数 __weak uint32_t WS_Font16_Read_Date(uint8_t *buffer , uint8_t * gbk , uint32_t size) { buffer = buffer ; gbk = gbk ; size = size ; return 0 ; } // 获取24点 字库数据 // 虚函数, 在SD卡或spi flas h实现 读取数据 // buffer: 数据缓存地址 // gbk : 汉字内码数据 // size : 读取汉字个数 // 返回值: 读取的数据个数 __weak uint32_t WS_Font24_Read_Date(uint8_t *buffer , uint8_t * gbk , uint32_t size) { buffer = buffer ; gbk = gbk ; size = size ; return 0 ; } // 获取32点 字库数据 // 虚函数, 在SD卡或spi flas h实现 读取数据 // buffer: 数据缓存地址 // gbk : 汉字内码数据 // size : 读取汉字个数 // 返回值: 读取的数据个数 __weak uint32_t WS_Font32_Read_Date(uint8_t *buffer , uint8_t * gbk , uint32_t size) { buffer = buffer ; gbk = gbk ; size = size ; return 0 ; } // 刷16*16点区域 void WS_TFT_Dis_16X16_Date (int x, int y, uint8_t * buffer , uint16_t n, uint16_t backColor ,uint16_t forColor) { int i , j; uint16_t dat = 0; while(n -- > 0) { WS_TFT_Set_Windows(x,y,x+15,y+15); for(i=0;i<32;i+=2) { dat = buffer[i] <<8 ; dat |= buffer[i+1] ; for(j=15;j>=0;j--) { if((dat & 1< TFT_X_MAX - 16) return; } } // 刷24*24点区域 void WS_TFT_Dis_24X24_Date (int x, int y, uint8_t *buffer ,uint16_t n, uint16_t backColor ,uint16_t forColor) { int i , j; uint8_t dat = 0; while(n -- > 0) { WS_TFT_Set_Windows(x,y,x+23,y+23); for(i=0;i<72;i++) { dat = buffer[i] ; for(j=7;j>=0;j--) { if((dat & 1< TFT_X_MAX - 24) return; } } // 刷32*32点区域 void WS_TFT_Dis_32X32_Date (int x, int y, uint8_t *buffer ,uint16_t n, uint16_t backColor ,uint16_t forColor) { int i , j; uint8_t dat = 0; while(n -- > 0) { WS_TFT_Set_Windows(x,y,x+31,y+31); for(i=0;i<128;i++) { dat = buffer[i] ; for(j=7;j>=0;j--) { if((dat & 1< TFT_X_MAX - 32) return; } } // 显示5X7字符串 void WS_TFT_Dis_5X7_String (int x,int y,char *string , uint16_t backColor ,uint16_t forColor) { int i , j ; uint8_t len=strlen((char *)string); uint8_t idex=0 , *p_dat , dat ; for(idex=0;idex=2;j--) { if((dat & (1<= TFT_X_MAX - 6) return; // } } uint8_t font_buffer[1280]; // 最大存储10个32点字库数据 // 显示8X16字符串 void WS_TFT_Dis_8X16_String (int x,int y, char *string , uint16_t backColor ,uint16_t forColor) { uint16_t i , j ; uint8_t len=strlen((char *)string); uint8_t idex=0 , *p_dat , dat ; //buffer[320] ; for(idex=0;idex 0) { WS_TFT_Dis_16X16_Date(x,y,font_buffer,size/32,backColor,forColor); x += size/2; } if(size != 0) idex += size/16; else idex += 2; } if(x > TFT_X_MAX - 8) return; } } // 显示12X24字符串 void WS_TFT_Dis_12X24_String (int x,int y, char *string , uint16_t backColor ,uint16_t forColor) { uint16_t i , j, dat ; uint8_t len=strlen((char *)string); uint8_t idex=0 , *p_dat ; for(idex=0;idex=4;j--) { if((dat & 1< 0) { WS_TFT_Dis_24X24_Date(x,y,font_buffer,size/72,backColor,forColor); x += size / 3; // 24 * size/72 } if(size != 0) idex += size/36; // 2 * size/72 else idex += 2; } if(x > TFT_X_MAX - 12) return; //??????????????????????? } } // 显示16X32字符串 void WS_TFT_Dis_16X32_String (int x,int y, char *string , uint16_t backColor ,uint16_t forColor) { int i , j ; uint16_t dat ; uint8_t len=strlen((char *)string); uint8_t idex=0 , *p_dat ; for(idex=0;idex=0;j--) { if((dat & 1< 0) { WS_TFT_Dis_32X32_Date(x,y,font_buffer,size/128,backColor,forColor); x += size / 4; // 32 * size/128 } if(size != 0) idex += size/64; // 2 * size/128 else idex += 2; } if(x > TFT_X_MAX - 12) return; //??????????????????????? } } // 在TFT上打印 “8X16” 调试信息 void WS_TFT_Dis_Debug(int x,int y, uint16_t forColor , char *p,...) { char formatBuf[48] ; va_list ap; va_start(ap,p); vsprintf(formatBuf,p,ap); va_end(ap); WS_TFT_Dis_8X16_String(x,y,formatBuf,WHITE,forColor); } // 计算 X、Y轴 一元一次函数的k、b // 实测ADC值 #define TOUTH_X_LITF_ADC 3875 // 左上角X,Y的ADC值 #define TOUTH_Y_UP_ADC 3865 #define TOUTH_X_RIGHT_ADC 215 // 右下角X,Y的ADC值 #define TOUTH_Y_DOWN_ADC 400 // k = (y2-y1)/(x2-x1) // b = #define touchX_k (float)(240-10) / (TOUTH_X_RIGHT_ADC - TOUTH_X_LITF_ADC ) #define touchX_b (5*TOUTH_X_RIGHT_ADC - 235*TOUTH_X_LITF_ADC) / (TOUTH_X_RIGHT_ADC - TOUTH_X_LITF_ADC) #define touchY_k (float)(320-10) / (TOUTH_Y_DOWN_ADC - TOUTH_Y_UP_ADC ) #define touchY_b ((5*TOUTH_Y_DOWN_ADC - 315*TOUTH_Y_UP_ADC) / (TOUTH_Y_DOWN_ADC - TOUTH_Y_UP_ADC)) // 读取XPT2046 X、Y数据 // hspi: spi外设句柄 // cmd : 读取控制字节, 0xd0读x轴,0x90读y轴。 uint16_t WS_TFT_Touth_Read_XPT2046(SPI_HandleTypeDef *hspi,uint16_t cmd) { uint16_t num = 0; // 以片选定义为条件控制编译, 防止在没有定义下编译报错。 #if defined( LCD_T_CS_GPIO_Port ) uint8_t spi_r[2] , spi_t ; // 没有触控,直接返回0 if(HAL_GPIO_ReadPin(LCD_T_PEN_GPIO_Port,LCD_T_PEN_Pin) != GPIO_PIN_RESET) return 0; // 片选使能 HAL_GPIO_WritePin(LCD_T_CS_GPIO_Port,LCD_T_CS_Pin,GPIO_PIN_RESET); spi_t = cmd; // 写命令 HAL_SPI_TransmitReceive(hspi,&spi_t,spi_r,1,1); // 延时等待转换 num = 50; while(num --); spi_t = 0 ; // 读取16位数据 HAL_SPI_TransmitReceive(hspi,&spi_t,spi_r,2,1); // 数据转换 , 保留中间12位 num = (spi_r[0] << 8) | spi_r[1]; num &= ~(1<<15); num >>= 3; // 片选失能 HAL_GPIO_WritePin(LCD_T_CS_GPIO_Port,LCD_T_CS_Pin,GPIO_PIN_SET); #endif return num; } // 排序函数 void sort(uint16_t arr[], int size) { int j,i,tem; for (i = 0; i < size-1;i ++)//size-1是因为不用与自己比较,所以比的数就少一个 { int count = 0; for (j = 0; j < size-1 - i; j++) //size-1-i是因为每一趟就会少一个数比较 { if (arr[j] > arr[j+1])//这是升序排法,前一个数和后一个数比较,如果前数大则与后一个数换位置 { tem = arr[j]; arr[j] = arr[j+1]; arr[j+1] = tem; count = 1; } } if (count == 0) //如果某一趟没有交换位置,则说明已经排好序,直接退出循环 break; } } // 读取触摸芯片数据,并转化位位置数据,周期调用 // 10ms 调用一次 , 统计5次转换数据,排序后去大去小,在求平均 // 返回值高16位存X值,低16位存y值 uint32_t WS_TFT_Touth_Get_Point(SPI_HandleTypeDef *hspi) { uint16_t adc_x , adc_y ; static uint16_t x_buf[5] , y_buf[5], count = 0; uint32_t num = 0; // 以XPT2046中断输出定义为条件控制编译, 防止在没有定义下编译报错。 #if defined( LCD_T_PEN_GPIO_Port ) if(HAL_GPIO_ReadPin(LCD_T_PEN_GPIO_Port,LCD_T_PEN_Pin) == GPIO_PIN_RESET) { if(count < 5) { x_buf[count] = WS_TFT_Touth_Read_XPT2046(hspi,0xd0); // 获取X轴数据 y_buf[count] = WS_TFT_Touth_Read_XPT2046(hspi,0x90); // 获取Y轴数据 count ++; } else { count = 0; sort (x_buf,5) ; sort (y_buf,5) ; adc_x = (x_buf[1] + x_buf[2] + x_buf[3]) / 3 ; adc_y = (y_buf[1] + y_buf[2] + y_buf[3]) / 3 ; } // 合成数据 num = (uint16_t)(touchX_k * adc_x + touchX_b) ; // 存高16位 num <<= 16; num |= (uint16_t)(touchY_k * adc_y + touchY_b) ; // 存低16位 } #endif return num; }