f407+HAL+freerots+tftlcd+emWin移植

Cube移植 (版本6.4)

我的板子是正点原子的,自己的板子要根据原理图配置引脚

只需要配置PB15,lcd背光调节,其他的引脚会在后面的touch.c里面配置

修改时钟基准

开启tim6,用作delay_us延时

根据原理图A6用作命令线

串口3调试信息,在freertos打开后就没法用keildebug了不知道为啥

开启crc,st购买了emwin版权,为了不让别人用就加了crc校验,打开才能使用emwin

开启freertos

创建2个任务

调大堆空间

LCD+Touch移植

LCD

使用正点原子提供的lcd历程

注意要将lcd.c和lcd.h改名,我改成了tftlcd.c和tftlcd.h,因为emwin里有LCD.h不能有重复的

EMWIN_LIB里面没东西不用加

进入keil后要进行一些修改,我的cube是6.4版本有些问题

main.c

注释MX_FATFS_Init();

重定向printf,串口3输出

int fputc(int ch,FILE *f){
	while((USART3->SR&0x40)==0);
	USART3->DR=(uint8_t)ch;
	return ch;
}

tftlcd.c

注释HAL_SRAM_MspInit

中间省略的直接复制正点原子里面的代码

void LCD_Init(void)
{ 	  
	GPIO_InitTypeDef GPIO_Initure;
	FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim;
	FSMC_NORSRAM_TimingTypeDef FSMC_WriteTim;

	__HAL_RCC_GPIOB_CLK_ENABLE();			//开启GPIOB时钟
	GPIO_Initure.Pin=GPIO_PIN_15;          	//PB15,背光控制
	GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
	GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
	GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
	HAL_GPIO_Init(GPIOB,&GPIO_Initure);

	TFTSRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;
	TFTSRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;

	TFTSRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK4;     				//使用NE4
	TFTSRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE; 	//地址/数据线不复用
	TFTSRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;   			//SRAM
	TFTSRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16; //16位数据宽度
	TFTSRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE; //是否使能突发访问,仅对同步突发存储器有效,此处未用到
	TFTSRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性,仅在突发模式访问下有用
	TFTSRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;   //存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT
	TFTSRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;    //存储器写使能
	TFTSRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;           //等待使能位,此处未用到
	TFTSRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_ENABLE;        //读写使用不同的时序
	TFTSRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;//是否使能同步传输模式下的等待信号,此处未用到
	TFTSRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE;           //禁止突发写
	TFTSRAM_Handler.Init.ContinuousClock=FSMC_CONTINUOUS_CLOCK_SYNC_ASYNC;

	//FMC读时序控制寄存器
	FSMC_ReadWriteTim.AddressSetupTime=0x0F;       	//地址建立时间(ADDSET)为16个HCLK 1/168M=6ns*16=96ns
	FSMC_ReadWriteTim.AddressHoldTime=0;
	FSMC_ReadWriteTim.DataSetupTime=60;				//数据保存时间为60个HCLK	=6*60=360ns
	FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式A
	//FMC写时序控制寄存器
	FSMC_WriteTim.BusTurnAroundDuration=0;			//总线周转阶段持续时间为0,此变量不赋值的话会莫名其妙的自动修改为4。导致程序运行正常
	FSMC_WriteTim.AddressSetupTime=9;          		//地址建立时间(ADDSET)为9个HCLK =54ns
	FSMC_WriteTim.AddressHoldTime=0;
	FSMC_WriteTim.DataSetupTime=8;              	//数据保存时间为6ns*9个HCLK=54n
	FSMC_WriteTim.AccessMode=FSMC_ACCESS_MODE_A;    //模式A
	HAL_SRAM_Init(&TFTSRAM_Handler,&FSMC_ReadWriteTim,&FSMC_WriteTim);

  delay_ms(50); // delay 50 ms 
	
	//尝试9341 ID的读取		
	LCD_WR_REG(0XD3);				   
	lcddev.id=LCD_RD_DATA();	//dummy read 	
	lcddev.id=LCD_RD_DATA();	//读到0X00
	lcddev.id=LCD_RD_DATA();   	//读取93								   
	lcddev.id<<=8;
	lcddev.id|=LCD_RD_DATA();  	//读取41 	   			   
	if(lcddev.id!=0X9341)		//非9341,尝试是不是7789
	{
        LCD_WR_REG(0X04);
        lcddev.id = LCD_RD_DATA();      //dummy read
        lcddev.id = LCD_RD_DATA();      //读到0X85
        lcddev.id = LCD_RD_DATA();      //读取0X85
        lcddev.id <<= 8;
        lcddev.id |= LCD_RD_DATA();     //读取0X52

        if (lcddev.id == 0X8552)        //将8552的ID转换成7789
        {
            lcddev.id = 0x7789;
        }

        if (lcddev.id != 0x7789)        //也不是ST7789, 尝试是不是 7789
        {
            LCD_WR_REG(0XD4);				   
            lcddev.id=LCD_RD_DATA();//dummy read  
            lcddev.id=LCD_RD_DATA();//读回0X01	 
            lcddev.id=LCD_RD_DATA();//读回0X53	
            lcddev.id<<=8;	 
            lcddev.id|=LCD_RD_DATA();	//这里读回0X10	 
            if(lcddev.id!=0X5310)		//也不是NT35310,尝试看看是不是NT35510
            {
                //发送秘钥(厂家提供,照搬即可)
                LCD_WriteReg(0xF000, 0x0055);
                LCD_WriteReg(0xF001, 0x00AA);
                LCD_WriteReg(0xF002, 0x0052);
                LCD_WriteReg(0xF003, 0x0008);
                LCD_WriteReg(0xF004, 0x0001);

                LCD_WR_REG(0xC500);             //读取ID高8位
                lcddev.id = LCD_RD_DATA();      //读回0X55
                lcddev.id <<= 8;

                LCD_WR_REG(0xC501);             //读取ID低8位
                lcddev.id |= LCD_RD_DATA();     //读回0X10
                delay_ms(5);
                if(lcddev.id==0x8000)lcddev.id=0x5510;//NT35510读回的ID是8000H,为方便区分,我们强制设置为5510
                if(lcddev.id!=0X5510)			//也不是NT5510,尝试看看是不是SSD1963
                {
                    LCD_WR_REG(0XA1);
                    lcddev.id=LCD_RD_DATA();
                    lcddev.id=LCD_RD_DATA();	//读回0X57
                    lcddev.id<<=8;	 
                    lcddev.id|=LCD_RD_DATA();	//读回0X61	
                    if(lcddev.id==0X5761)lcddev.id=0X1963;//SSD1963读回的ID是5761H,为方便区分,我们强制设置为1963
                } 
            }
		}
	}   
	printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID   
	if(lcddev.id==0X9341)	//9341初始化
	{	 
		...
	}
	else if(lcddev.id==0x5510)
	{
		...
	}
	else if(lcddev.id==0X1963)
	{
        ...
	}	 
    //初始化完成以后,提速
    if(lcddev.id==0X9341||lcddev.id==0X7789||lcddev.id==0X5310||lcddev.id==0X5510||lcddev.id==0X1963)//如果是这几个IC,则设置WR时序为最快
    {
        //重新配置写时序控制寄存器的时序
        FSMC_Bank1E->BWTR[6]&=~(0XF<<0);//地址建立时间(ADDSET)清零
        FSMC_Bank1E->BWTR[6]&=~(0XF<<8);//数据保存时间清零
        FSMC_Bank1E->BWTR[6]|=3<<0;     //地址建立时间(ADDSET)为4个HCLK =24ns
        if(lcddev.id==0X7789)           //7789独立设置,否则摄像头实验可能有问题
        {
            FSMC_Bank1E->BWTR[6]|=3<<8; //数据保存时间(DATAST)为6ns*4个HCLK=24ns
        }
        else
        {
            FSMC_Bank1E->BWTR[6]|=2<<8; //数据保存时间(DATAST)为6ns*3个HCLK=18ns
        }
    } 
	LCD_Display_Dir(0);		//默认为竖屏
	HAL_GPIO_WritePin(LCD_BLD_GPIO_Port, LCD_BLD_Pin, GPIO_PIN_SET);	//点亮背光
	LCD_Clear(WHITE);
}  

tftlcd.h

开头添加


#include "stdint.h"
#include "sys.h"

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;

fsmc.c

在HAL_SRAM_MspInit中添加代码

注意加的位置避免重新生成代码时消失

void HAL_SRAM_MspInit(SRAM_HandleTypeDef* sramHandle){
  /* USER CODE BEGIN SRAM_MspInit 0 */

  /* USER CODE END SRAM_MspInit 0 */
  HAL_FSMC_MspInit();
  /* USER CODE BEGIN SRAM_MspInit 1 */
GPIO_InitTypeDef GPIO_Initure;

    __HAL_RCC_FSMC_CLK_ENABLE();			//使能FSMC时钟
    __HAL_RCC_GPIOD_CLK_ENABLE();			//使能GPIOD时钟
    __HAL_RCC_GPIOE_CLK_ENABLE();			//使能GPIOE时钟
    __HAL_RCC_GPIOF_CLK_ENABLE();			//使能GPIOF时钟
    __HAL_RCC_GPIOG_CLK_ENABLE();			//使能GPIOG时钟

    //初始化PD0,1,4,5,8,9,10,14,15
    GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_8|\
					 GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14|GPIO_PIN_15;
    GPIO_Initure.Mode=GPIO_MODE_AF_PP; 		//推挽复用
    GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;		//高速
    GPIO_Initure.Alternate=GPIO_AF12_FSMC;	//复用为FSMC
    HAL_GPIO_Init(GPIOD,&GPIO_Initure);     //初始化

    //初始化PE7,8,9,10,11,12,13,14,15
    GPIO_Initure.Pin=GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|\
                     GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
    HAL_GPIO_Init(GPIOE,&GPIO_Initure);

    //初始化PF12
    GPIO_Initure.Pin=GPIO_PIN_12;
    HAL_GPIO_Init(GPIOF,&GPIO_Initure);

    //初始化PG12
    GPIO_Initure.Pin=GPIO_PIN_12;
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);
  /* USER CODE END SRAM_MspInit 1 */
}

还要修改sys.h

为了兼容标准库,也方便移植,我把一些接口移植了过来,这样就可以减少修改其他的文件

/** Function prototype for thread functions */
typedef void (*lwip_thread_fn)(void *arg);
typedef signed char err_t; 
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;

#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414    
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410 
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入
#define GPIO_A 				0
#define GPIO_B 				1
#define GPIO_C				2
#define GPIO_D 				3
#define GPIO_E 				4
#define GPIO_F 				5
#define GPIO_G 				6 
#define GPIO_H 				7 
#define GPIO_I 				8 

#define FTIR   				1  		//下降沿触发
#define RTIR   				2  		//上升沿触发

//GPIO设置专用宏定义
#define GPIO_MODE_IN    	0		//普通输入模式
#define GPIO_MODE_OUT		1		//普通输出模式
#define GPIO_MODE_AF		2		//AF功能模式
#define GPIO_MODE_AIN		3		//模拟输入模式

#define GPIO_SPEED_2M		0		//GPIO速度2Mhz
#define GPIO_SPEED_25M		1		//GPIO速度25Mhz
#define GPIO_SPEED_50M		2		//GPIO速度50Mhz
#define GPIO_SPEED_100M		3		//GPIO速度100Mhz

#define GPIO_PUPD_NONE		0		//不带上下拉
#define GPIO_PUPD_PU		1		//上拉
#define GPIO_PUPD_PD		2		//下拉
#define GPIO_PUPD_RES		3		//保留 

#define GPIO_OTYPE_PP		0		//推挽输出
#define GPIO_OTYPE_OD		1		//开漏输出 

//GPIO引脚编号定义
#define PIN0				1<<0
#define PIN1				1<<1
#define PIN2				1<<2
#define PIN3				1<<3
#define PIN4				1<<4
#define PIN5				1<<5
#define PIN6				1<<6
#define PIN7				1<<7
#define PIN8				1<<8
#define PIN9				1<<9
#define PIN10				1<<10
#define PIN11				1<<11
#define PIN12				1<<12
#define PIN13				1<<13
#define PIN14				1<<14
#define PIN15				1<<15 

delay.c/delay.h

使用rtos

要开启INCLUDE_vTaskDelayUntil宏为1

#include "delay.h"

void delay_us(uint16_t us)
{
    __HAL_TIM_SET_COUNTER(&htim6, 0); // 将计数器值重置为0
    HAL_TIM_Base_Start(&htim6); // 启动定时器
    while (__HAL_TIM_GET_COUNTER(&htim6) < us); // 等待计数器值达到 us
    HAL_TIM_Base_Stop(&htim6); // 停止定时器
}


void delay_ms(uint16_t nms){
#if(INCLUDE_vTaskDelayUntil==1)
	TickType_t lasttick=xTaskGetTickCount();
	vTaskDelayUntil(&lasttick,nms);
#else 
	HAL_Delay(nms);
#endif
}
	

至此tftlcd移植完毕,可以复制正点原子的main到freertos中实验

要将MX_FSMC_Init();加入到Touch_Task中,可以添加一些打印信息看是否移植成功

TOUCH

复制正点原子的

可以新建一个文件夹HAREWARE方便管理

LCD不用加,自己建一个DELAY就存放上面写的delay.c和.h

这几个里面都不用改,加一下路径就好了,吧sys.h和delay.h加上去之后就不会有报错了

可以测试一下

把这些加在

/* USER CODE BEGIN Header_Touch_Task */

这里加下面的代码

/**
  * @brief  Function implementing the TouchTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_Touch_Task */

void Load_Drow_Dialog(void)
{
	LCD_Clear(WHITE);//清屏   
 	POINT_COLOR=BLUE;//设置字体为蓝色 
	LCD_ShowString(lcddev.width-24,0,200,16,16,"RST");//显示清屏区域
  	POINT_COLOR=RED;//设置画笔蓝色 
}

//电容触摸屏专有部分
//画水平线
//x0,y0:坐标
//len:线长度
//color:颜色
void gui_draw_hline(u16 x0,u16 y0,u16 len,u16 color)
{
	if(len==0)return;
	LCD_Fill(x0,y0,x0+len-1,y0,color);	
}
//画实心圆
//x0,y0:坐标
//r:半径
//color:颜色
void gui_fill_circle(u16 x0,u16 y0,u16 r,u16 color)
{											  
	u32 i;
	u32 imax = ((u32)r*707)/1000+1;
	u32 sqmax = (u32)r*(u32)r+(u32)r/2;
	u32 x=r;
	gui_draw_hline(x0-r,y0,2*r,color);
	for (i=1;i<=imax;i++) 
	{
		if ((i*i+x*x)>sqmax)// draw lines from outside  
		{
 			if (x>imax) 
			{
				gui_draw_hline (x0-i+1,y0+x,2*(i-1),color);
				gui_draw_hline (x0-i+1,y0-x,2*(i-1),color);
			}
			x--;
		}
		// draw lines from inside (center)  
		gui_draw_hline(x0-x,y0+i,2*x,color);
		gui_draw_hline(x0-x,y0-i,2*x,color);
	}
}  
//两个数之差的绝对值 
//x1,x2:需取差值的两个数
//返回值:|x1-x2|
u16 my_abs(u16 x1,u16 x2)
{			 
	if(x1>x2)return x1-x2;
	else return x2-x1;
}  
//画一条粗线
//(x1,y1),(x2,y2):线条的起始坐标
//size:线条的粗细程度
//color:线条的颜色
void lcd_draw_bline(u16 x1, u16 y1, u16 x2, u16 y2,u8 size,u16 color)
{
	u16 t; 
	int xerr=0,yerr=0,delta_x,delta_y,distance; 
	int incx,incy,uRow,uCol; 
	if(x1<size|| x2<size||y1<size|| y2<size)return; 
	delta_x=x2-x1; //计算坐标增量 
	delta_y=y2-y1; 
	uRow=x1; 
	uCol=y1; 
	if(delta_x>0)incx=1; //设置单步方向 
	else if(delta_x==0)incx=0;//垂直线 
	else {incx=-1;delta_x=-delta_x;} 
	if(delta_y>0)incy=1; 
	else if(delta_y==0)incy=0;//水平线 
	else{incy=-1;delta_y=-delta_y;} 
	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
	else distance=delta_y; 
	for(t=0;t<=distance+1;t++ )//画线输出 
	{  
		gui_fill_circle(uRow,uCol,size,color);//画点 
		xerr+=delta_x ; 
		yerr+=delta_y ; 
		if(xerr>distance) 
		{ 
			xerr-=distance; 
			uRow+=incx; 
		} 
		if(yerr>distance) 
		{ 
			yerr-=distance; 
			uCol+=incy; 
		} 
	}  
}   

//5个触控点的颜色(电容触摸屏用)												 
const u16 POINT_COLOR_TBL[5]={RED,GREEN,BLUE,BROWN,GRED};  
//电阻触摸屏测试函数
void rtp_test(void)
{
}
//电容触摸屏测试函数
void ctp_test(void)
{
	u8 t=0;
	u8 i=0;	  	    
 	u16 lastpos[5][2];		//最后一次的数据 
	while(1)
	{
		tp_dev.scan(0);
		for(t=0;t<5;t++)
		{
			if((tp_dev.sta)&(1<<t))
			{
                printf("X坐标:%d,Y坐标:%d\r\n",tp_dev.x[0],tp_dev.y[0]);
				if(tp_dev.x[t]<lcddev.width&&tp_dev.y[t]<lcddev.height)
				{
					if(lastpos[t][0]==0XFFFF)
					{
						lastpos[t][0] = tp_dev.x[t];
						lastpos[t][1] = tp_dev.y[t];
					}
                    
					lcd_draw_bline(lastpos[t][0],lastpos[t][1],tp_dev.x[t],tp_dev.y[t],2,POINT_COLOR_TBL[t]);//画线
					lastpos[t][0]=tp_dev.x[t];
					lastpos[t][1]=tp_dev.y[t];
					if(tp_dev.x[t]>(lcddev.width-24)&&tp_dev.y[t]<20)
					{
						Load_Drow_Dialog();//清除
					}
				}
			}else lastpos[t][0]=0XFFFF;
		}
		
		delay_ms(5);i++;

	}	
}

然后再任务Touch_Task中,就只测试不切换任务,循环在ctp_test中(我的是电容屏)

void Touch_Task(void const * argument)
{
  /* init code for LWIP */
//  MX_LWIP_Init();
  /* USER CODE BEGIN Touch_Task */
//	
//  MX_FATFS_Init();
//	printf("fatfs is running\r\n");

	MX_FSMC_Init();

	LCD_Init();           			//初始化LCD
	tp_dev.init();				    //触摸屏初始化 
	
  	POINT_COLOR=RED;
	LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");	
	LCD_ShowString(30,70,200,16,16,"TOUCH TEST");	
	LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
	LCD_ShowString(30,110,200,16,16,"2017/4/14");	 		
   	if(tp_dev.touchtype!=0XFF)
	{
		LCD_ShowString(30,130,200,16,16,"Press KEY0 to Adjust");//电阻屏才显示
	}
	delay_ms(1500);
 	Load_Drow_Dialog();	 	
	
	if(tp_dev.touchtype&0X80)ctp_test();//电容屏测试
	else rtp_test(); 					//电阻屏测试  
}

至此touch移植完毕

STemWin移植

根据路径找到官方提供的文件我的是

C:\Users\Gideon\STM32Cube\Repository\STM32Cube_FW_F4_V1.26.2\Middlewares\ST\STemWin

复制emwin到projectemwin\Middlewares\Third_Party

在keil里面新建一个group改名为下面这个,然后添加以下的

修改文件属性

为libray file

加一下文件路径

编译一遍,会有找不到LCDConf.h的问题,直接在这里面新建一个空的LCDConf.h文件就好了

修改文件

GUI_Conf.c

#define GUI_NUMBYTES  1024*50

LCDConf_FlexColor_Template.c
LCD_X_Config
#define XSIZE_PHYS  480 // To be adapted to x-screen size
#define YSIZE_PHYS  800 // To be adapted to y-screen size
void LCD_X_Config(void) {
  // Set display driver and color conversion
  //
 GUI_DEVICE_CreateAndLink(&GUIDRV_Template_API, GUICC_M565, 0, 0);
  //
  // Display driver configuration, required for Lin-driver
  //
  LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
  LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
  //
  // Orientation
  //
    GUI_TOUCH_Calibrate(GUI_COORD_X,0,lcddev.height-1,0,lcddev.height-1);
    GUI_TOUCH_Calibrate(GUI_COORD_Y,0,lcddev.width-1,0,lcddev.width-1);      
 }
LCD_X_DisplayDriver
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
	printf("LCD_X_DisplayDriver \r\n");
  int r;
  (void) LayerIndex;
  (void) pData;
  
  switch (Cmd) {
  case LCD_X_INITCONTROLLER: {
    //
    // Called during the initialization process in order to set up the
    // display controller and put it into operation. If the display
    // controller is not initialized by any external routine this needs
    // to be adapted by the customer...
    //
		LCD_Init();
		tp_dev.init();

    // ...
    return 0;
  }
  default:
    r = -1;
  }

  return r;
}
GUIDRV_Template.c
_SetPixelIndex
static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
    //
    // Convert logical into physical coordinates (Dep. on LCDConf.h)
    //
    #if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
      int xPhys, yPhys;

      xPhys = LOG2PHYS_X(x, y);
      yPhys = LOG2PHYS_Y(x, y);
    #else
      #define xPhys x
      #define yPhys y
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    GUI_USE_PARA(PixelIndex);
    {
      //
      // Write into hardware ... Adapt to your system
      //
			LCD_Fast_DrawPoint(x,y,PixelIndex);
      // TBD by customer...
      //
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
      #undef xPhys
      #undef yPhys
    #endif
}
 _GetPixelIndex
static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
  unsigned int PixelIndex;
    //
    // Convert logical into physical coordinates (Dep. on LCDConf.h)
    //
    #if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
      int xPhys, yPhys;

      xPhys = LOG2PHYS_X(x, y);
      yPhys = LOG2PHYS_Y(x, y);
    #else
      #define xPhys x
      #define yPhys y
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    {
      //
      // Write into hardware ... Adapt to your system
      //
      // TBD by customer...
      //
    PixelIndex = LCD_ReadPoint(x,y);
  PixelIndex = 0;
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
      #undef xPhys
      #undef yPhys
    #endif
  return PixelIndex;
}
_FillRect
static void _FillRect(GUI_DEVICE * pDevice, int x0, int y0, int x1, int y1) {
  LCD_PIXELINDEX PixelIndex;
  int x;

  PixelIndex = LCD__GetColorIndex();
  if (GUI_pContext->DrawMode & LCD_DRAWMODE_XOR) {
    for (; y0 <= y1; y0++) {
      for (x = x0; x <= x1; x++) {
        _XorPixel(pDevice, x, y0);
      }
    }
  } else {
    LCD_Fill(x0,y0,x1,y1,PixelIndex);
  }
}
GUI_X_Touch_Analog.c
#include "GUI.h"
#include "touch.h"
#include "stdio.h"


void GUI_TOUCH_X_ActivateX(void){

}


void GUI_TOUCH_X_ActivateY(void){

}

int GUI_TOUCH_X_MeasureX(void){
  tp_dev.scan(0);
  return tp_dev.x[0];
}

int GUI_TOUCH_X_MeasureY(void){
	return tp_dev.y[0];
}






注意在修改的这些文件中添加头文件touch.c和tftlcd.c

在freertos中添加测试代码

void Touch_Task(void const * argument)
{
  /* init code for LWIP */
//  MX_LWIP_Init();
  /* USER CODE BEGIN Touch_Task */
//	
//  MX_FATFS_Init();
//	printf("fatfs is running\r\n");
char buf[]="hello world";
	MX_FSMC_Init();

	LCD_Init();           			//初始化LCD
	tp_dev.init();				    //触摸屏初始化 	
	GUI_Init();
	printf("GUI init ok\r\n");
	GUI_SetBkColor(GUI_BLUE);
	GUI_SetFont(GUI_FONT_32_1);
	GUI_SetColor(GUI_YELLOW);
	GUI_Clear();
	GUI_PID_STATE State;
  for(;;)
  {
		GUI_TOUCH_Exec();
		GUI_TOUCH_GetState(&State);
		if(State.Pressed){
		
			GUI_DispStringAt("X:",0,0);
			GUI_DispDecAt(State.x,32,0,4);
			
			GUI_DispStringAt("Y:",0,26);
			GUI_DispDecAt(State.y,32,26,4);
			
			GUI_DispStringAt("L:",0,52);
			GUI_DispDecAt(State.Layer,32,52,4);
			
			GUI_DispStringAt("P:",0,78);
			GUI_DispDecAt(State.Pressed,32,78,4);
			 printf("Touch detected at (%d, %d)\n", State.x, State.y);
		}
    osDelay(20);

	}
}

 结果,屏幕会打印触摸位置坐标

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HAL库是针对STM32F407微控制器开发的一个软件库,用于简化软件开发过程。而LCD是液晶显示器的缩写,是一种常见的显示设备。 使用HAL库来驱动STM32F407微控制器上的LCD可以实现图形和文本的显示。首先,我们需要初始化LCD引脚的配置,设置为输出模式,并根据LCD的特性选择合适的通信接口(如SPI或I2C)。 接下来,我们可以使用HAL库提供的函数来控制LCD的显示,比如写入数据或命令。HAL库可以为我们提供一个便捷的方式来设置LCD的显示模式、清除屏幕、打印文本和绘制图形等。 例如,我们可以使用HAL库的函数来设置LCD的显示模式,比如设置为单行或多行显示,选择字符显示格式(如5x7或8x8),以及光标闪烁等。 我们还可以使用HAL库的函数来清除屏幕,比如使用填充函数将屏幕上的所有像素点清零,或使用擦除函数将屏幕上的特定区域清除。 当需要显示文本时,我们可以使用HAL库的函数来设置文本的字体大小、颜色和位置,并使用打印函数将文本显示在LCD上的指定位置。 如果需要在LCD上绘制图形,我们可以使用HAL库提供的函数来设置图形的类型(如线、矩形、圆形等)、位置和颜色,并使用绘制函数将图形绘制在LCD上。 综上所述,使用HAL库可以简化STM32F407微控制器上LCD的驱动过程,帮助我们更方便地实现图形和文本的显示,并为开发者提供了丰富的函数库来满足各种显示需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值