STM32F407移植Little vGL系统,freeRTOS系统,FATFS文件系统

11 篇文章 3 订阅
  • 准备freeRTOS源码和一个简单的工程

链接:https://pan.baidu.com/s/1hgyQqoDqDuETEHr_I80M8Q 
提取码:e890

另外还需要准备一个简单的工程,这里使用一个空工程来完成移植

已移植好的stm32f407例程下载链接:

https://download.csdn.net/download/mygod2008ok/12315598

开始移植

在工程中新建一个文件夹,并命名为freeRTOS

2.将准备好的freeRTOS库中的源码全部复制

3. 粘贴到工程中的freeRTOS文件夹中,并将portable中的文件仅保留以下4个 

4.在工程中创建两个文件组freeRTOS_sourcet和freeRTOS_portable,并加入以下文件到工程,注意port.c选择M4里面的,因为stm32f407是m4系列

 5. 另外要添加freeRTOS相关的文件路径到工程中

 

6.先编译一下,出现如下错误

7.少了FreeRTOSConfig.h文件,可以去下载一个,也可以到freeRTOS提供的Demo中复制一份过来,这里从DEMO中寻找,没有stm32f407 demo,用stm32f103中的代替

8.找到FreeRTOSConfig.h文件复制

9.粘贴到工程中的FreeRTOS中的include文件夹内

10.再次编译一下工程,会出现以下错误

11.按住CTRL+F键,输入xTaskGetCurrentTaskHandle后进行全局搜索

12.搜索结果如下

13.在FreeRTOSConfig.h中加入如下宏后再次编译一下

#define INCLUDE_xTaskGetCurrentTaskHandle 1

14.对port.c中的三个函数进行适配,也就是让启动文件分别能够指向这三个函数

15.再次编译一下,会出现以下错误

16.将stm32f10x_it.c中的SVC_Handler,PendSV_Handler,SysTick_Handler三个函数屏蔽掉,重新编译一下工程  

17.在main文件中加入头文件task.h,然后编译一下,出现如下错误

18.双击跳转到出错处,并加入FreeRTOS.h头文件再次编译一下,编译通过 

 

19.创建任务
 



//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
	
	  
   
    // 创建其它任务		
								
	
								
    vTaskDelete(NULL); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

20.main中启动调度器

 int main(void)
{
        xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )128,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )3,       //任务优先级
                (TaskHandle_t*  )0);   //任务句柄   
  
	vTaskStartScheduler();
	
      /* Infinite loop */
      for (;;)
      {      
		
      }
}
  • Fatfs移植

  1. 准备好flash spi驱动,这里以w25qxx系列flash为例来挂载fatfs文件系统

   2.准备好fatfs文件,这里使用fatfs_014版本文件系统,下载链接如下

链接:https://pan.baidu.com/s/1l6gcODXHpMhx4AIwA1xSsg 
提取码:zvsr 
    3.添加文件到工程

  4.添加路径到C++路径选项中

5.在ffconf.h中配置如下


#define FF_USE_MKFS		1
#define FF_USE_LABEL	        1
#define FF_CODE_PAGE	        437
#define FF_USE_LFN		2
#define FF_LFN_UNICODE    	2
#define FF_STRF_ENCODE	        3
#define FF_VOLUMES		1
#define FF_FS_REENTRANT	1
#define FF_FS_TIMEOUT	1000
#define FF_SYNC_t		SemaphoreHandle_t

 6.在ffconf.h中加入头文件

  #include "semphr.h"

7.在ffsystem.c中加入头文件

#include "queue.h"

8.以下函数中使用freeRTOS中的信号量


int ff_cre_syncobj (	/* 1:Function succeeded, 0:Could not create the sync object */
	BYTE vol,			/* Corresponding volume (logical drive number) */
	FF_SYNC_t* sobj		/* Pointer to return the created sync object */
)
{
	/* Win32 */
//	*sobj = CreateMutex(NULL, FALSE, NULL);
//	return (int)(*sobj != INVALID_HANDLE_VALUE);

	/* uITRON */
//	T_CSEM csem = {TA_TPRI,1,1};
//	*sobj = acre_sem(&csem);
//	return (int)(*sobj > 0);

	/* uC/OS-II */
//	OS_ERR err;
//	*sobj = OSMutexCreate(0, &err);
//	return (int)(err == OS_NO_ERR);

	/* FreeRTOS */
	*sobj = xSemaphoreCreateMutex();
	return (int)(*sobj != NULL);

	/* CMSIS-RTOS */
//	*sobj = osMutexCreate(&Mutex[vol]);
//	return (int)(*sobj != NULL);
}


/*------------------------------------------------------------------------*/
/* Delete a Synchronization Object                                        */
/*------------------------------------------------------------------------*/
/* This function is called in f_mount() function to delete a synchronization
/  object that created with ff_cre_syncobj() function. When a 0 is returned,
/  the f_mount() function fails with FR_INT_ERR.
*/

int ff_del_syncobj (	/* 1:Function succeeded, 0:Could not delete due to an error */
	FF_SYNC_t sobj		/* Sync object tied to the logical drive to be deleted */
)
{
	/* Win32 */
//	return (int)CloseHandle(sobj);

	/* uITRON */
//	return (int)(del_sem(sobj) == E_OK);

	/* uC/OS-II */
//	OS_ERR err;
//	OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
//	return (int)(err == OS_NO_ERR);

	/* FreeRTOS */
  vSemaphoreDelete(sobj);
	return 1;

	/* CMSIS-RTOS */
//	return (int)(osMutexDelete(sobj) == osOK);
}


/*------------------------------------------------------------------------*/
/* Request Grant to Access the Volume                                     */
/*------------------------------------------------------------------------*/
/* This function is called on entering file functions to lock the volume.
/  When a 0 is returned, the file function fails with FR_TIMEOUT.
*/

int ff_req_grant (	/* 1:Got a grant to access the volume, 0:Could not get a grant */
	FF_SYNC_t sobj	/* Sync object to wait */
)
{
	/* Win32 */
//	return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);

	/* uITRON */
//	return (int)(wai_sem(sobj) == E_OK);

	/* uC/OS-II */
//	OS_ERR err;
//	OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
//	return (int)(err == OS_NO_ERR);

	/* FreeRTOS */
	return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);

	/* CMSIS-RTOS */
//	return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
}


/*------------------------------------------------------------------------*/
/* Release Grant to Access the Volume                                     */
/*------------------------------------------------------------------------*/
/* This function is called on leaving file functions to unlock the volume.
*/

void ff_rel_grant (
	FF_SYNC_t sobj	/* Sync object to be signaled */
)
{
	/* Win32 */
//	ReleaseMutex(sobj);

	/* uITRON */
//	sig_sem(sobj);

	/* uC/OS-II */
//	OSMutexPost(sobj);

	/* FreeRTOS */
	xSemaphoreGive(sobj);

	/* CMSIS-RTOS */
//	osMutexRelease(sobj);
}

9.修改freeRTOS中的配置

#define configUSE_RECURSIVE_MUTEXES				1  
#define configUSE_COUNTING_SEMAPHORES			        1 
#define configUSE_MUTEXES					1   

10.在main.c中加入头文件

#include "w25qxx.h"  
#include "ff.h"  

11.在diskio.c中适配flash spi驱动,以下内容引用正点原子的例程

 a.) 定义flash相关宏

#define EX_FLASH 0	//外部flash,卷标为1

#define FLASH_SECTOR_SIZE 	512			  
//对于W25Q128
//前12M字节给fatfs用,12M字节后,用于存放字库,字库占用3.09M.	剩余部分,给客户自己用	 			    
uint16_t	    FLASH_SECTOR_COUNT=2048*12;	//W25Q1218,前12M字节给FATFS占用
#define FLASH_BLOCK_SIZE   	8     	//每个BLOCK有8个扇区

 b.) disk_status函数直接返回0

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	return 0;
}

 c.) disk_initialize函数初时化flash

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	uint8_t res=0;	    
	switch(pdrv)
	{
		
		case EX_FLASH://外部flash
			W25QXX_Init();
			FLASH_SECTOR_COUNT=2048*12;//W25Q1218,前12M字节给FATFS占用 
 			break;
		default:
			res=1; 
	}		 
	if(res)return  STA_NOINIT;
	else return 0; //初始化成功 
}

d.) disk_read读数据函数

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	LBA_t sector,	/* Start sector in LBA */
	UINT count		/* Number of sectors to read */
)
{
	uint8_t res=0; 
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误		 	 
	switch(pdrv)
	{
		
		case EX_FLASH://外部flash
			for(;count>0;count--)
			{
				W25QXX_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
				sector++;
				buff+=FLASH_SECTOR_SIZE;
			}
			res=0;
			break;
		default:
			res=1; 
	}
   //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res==0x00)return RES_OK;	 
    else return RES_ERROR;	 
}

e.) disk_write写数据函数

DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	LBA_t sector,		/* Start sector in LBA */
	UINT count			/* Number of sectors to write */
)
{
	uint8_t res=0;  
    if (!count)return RES_PARERR;//count不能等于0,否则返回参数错误		 	 
	switch(pdrv)
	{
		
		case EX_FLASH://外部flash
			for(;count>0;count--)
			{										    
				W25QXX_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
				sector++;
				buff+=FLASH_SECTOR_SIZE;
			}
			res=0;
			break;
		default:
			res=1; 
	}
    //处理返回值,将SPI_SD_driver.c的返回值转成ff.c的返回值
    if(res == 0x00)return RES_OK;	 
    else return RES_ERROR;	
}

f.) disk_ioctl磁盘控制函数

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
DRESULT res;						  			     
	if(pdrv==EX_FLASH)	//外部FLASH  
	{
	    switch(cmd)
	    {
		    case CTRL_SYNC:
				res = RES_OK;  //同步操作
		        break;	 
		    case GET_SECTOR_SIZE:
		        *(WORD*)buff = FLASH_SECTOR_SIZE;  //返回扇区大小,这里为512
		        res = RES_OK;
		        break;	 
		    case GET_BLOCK_SIZE:
		        *(WORD*)buff = FLASH_BLOCK_SIZE; //返回块大小,这里为8,
		        res = RES_OK;
		        break;	 
		    case GET_SECTOR_COUNT:
		        *(DWORD*)buff = FLASH_SECTOR_COUNT; //返回扇区数量
		        res = RES_OK;
		        break;
		    default:
		        res = RES_PARERR;
		        break;
	    }
	}else res=RES_ERROR;//其他的不支持
    return res;
}

上面的扇区大小为512,这个是fatfs系统的扇区大小,块大小是8,两数相乘刚好是4096,对应flash的1个扇区大小 

e.) get_fattime时间函数,这里返回0,如果有时间系统,可以返回对应的时间,这个时间格

式参考文件系统的相关说明

DWORD get_fattime (void)
{				 
	return 0;
}	

f.) 在main函数中加挂载文件系统

        uint8_t res=f_mount(&fs,"0:",1); 				//挂载FLASH.	
	BYTE work[512];
	if(res==0X0D)//FLASH磁盘,FAT文件系统错误,重新格式化FLASH
	{
		
		res=f_mkfs("0:",0,work,sizeof(work));//格式化FLASH,1,盘符;1,不需要引导区,8个扇区为1个簇
		if(res==0)
		{
			f_setlabel((const TCHAR *)"0:ALIENTEK");	//设置Flash磁盘的名字为:ALIENTEK
			NRF_LOG_INFO("set disk name");
			
		}else{NRF_LOG_INFO("format fail");}   //格式化失败
		
	}		
  • 移植little vGL系统

准备好little vGL相关文件,下载地址如下

链接:https://pan.baidu.com/s/1DjwtXUzXerw9Yb0Am9nxhw 
提取码:1htd 
解压文件,将lvgl-master文件重新命名成lvgl后复制到工程目录下

 进入lvgl文件夹将lv_conf_template.h复制到与lvgl同目录下,并重新命名成lv_conf.h

添加路径到C++路径选项中 

将lvgl下的源文件全部加到工程中

配置lv_conf.h文件,其它在以下未列出的将保持原值


/* Maximal horizontal and vertical resolution to support by the library.*/
#define LV_HOR_RES_MAX          (480)
#define LV_VER_RES_MAX          (320)

/* Color depth:
 * - 1:  1 byte per pixel
 * - 8:  RGB233
 * - 16: RGB565
 * - 32: ARGB8888
 */
#define LV_COLOR_DEPTH     16

/* Swap the 2 bytes of RGB565 color.
 * Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP   0


/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
#define LV_ANTIALIAS        1


/*1: Enable the Animations */
#define LV_USE_ANIMATION        1

#define LV_USE_GPU              0

适配LCD显示,这里以3.5寸电阻屏的MCU屏为例,驱动引用正点原子开发板的例程

以下是初时化lvgl显示屏,触摸屏,Fatfs系统适配lvgl系统



void lv_disp_drv_flush_simple_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{

  u16 height,width;
	u16 i,j;
	width=area->x2-area->x1+1; 			//得到填充的宽度
	height=area->y2-area->y1+1;			//高度
 	for(i=0;i<height;i++)
	{
 		LCD_SetCursor(area->x1,area->y1+i);   	//设置光标位置 
		LCD_WriteRAM_Prepare();     //开始写入GRAM
		for(j=0;j<width;j++)
		{
			TFTLCD->LCD_RAM=color_p->full; 
			color_p++;	
		}
	}	
	 lv_disp_flush_ready(disp_drv); 
}


//读点函数实现
bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data)
{
   static lv_coord_t last_x = 0;
   static lv_coord_t last_y = 0;
   
   /*Save the state and save the pressed coordinate*/

	
   data->state = tp_dev.sta & TP_PRES_DOWN ?  LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; 
	
  if(data->state == LV_INDEV_STATE_PR)            //触摸屏被按下
	 {   
		    NRF_LOG_DEBUG("x=%d,y=%d\n",tp_dev.x[0],tp_dev.y[0]);
			 if((tp_dev.x[0] < LV_HOR_RES_MAX) && (tp_dev.y[0]<LV_VER_RES_MAX))
			 {   
					 last_x = tp_dev.x[0];//将触摸的点的位置告诉littlevGL
					 last_y = tp_dev.y[0];
			 }
	 }
   /*Set the coordinates (if released use the last pressed coordinates)*/
   data->point.x = last_x;
   data->point.y = last_y;

   return false; /*Return `false` because we are not buffering and no more data to read*/
}

	FATFS fs;
bool my_ready_cb(struct _lv_fs_drv_t * drv)
{
	
	return disk_status(0)==0;
}


lv_fs_res_t my_open_cb(struct _lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode)
{

	return f_open(file_p, path, mode);
	
}

lv_fs_res_t my_close_cb(struct _lv_fs_drv_t * drv, void * file_p)
{
	return f_close(file_p);
}

lv_fs_res_t my_read_cb(struct _lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br)
{
  
	return  f_read(file_p,buf,btr,br);
}

lv_fs_res_t my_write_cb(struct _lv_fs_drv_t * drv, void * file_p, const void * buf, uint32_t btw, uint32_t * bw)
{
	return f_write(file_p,buf,btw,bw);
}

 lv_fs_res_t my_seek_cb(struct _lv_fs_drv_t * drv, void * file_p, uint32_t pos)
 {
	 
	 return f_lseek(file_p,pos);
	 
 }
 
lv_fs_res_t my_trunc_cb(struct _lv_fs_drv_t * drv, void * file_p)
{
	
	return f_truncate(file_p);
}

lv_fs_res_t my_tell_cb(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p)
{
	return f_tell((FIL*)file_p);
}

lv_fs_res_t my_size_cb(struct _lv_fs_drv_t * drv, void * file_p, uint32_t * size_p)
{
	
	
    *size_p = f_size((FIL*)file_p);
	
	return  LV_FS_RES_OK; 
	
}

lv_fs_res_t my_rename_cb(struct _lv_fs_drv_t * drv, const char * oldname, const char * newname)
{
	return f_rename(oldname,newname);
}

lv_fs_res_t my_free_space_cb(struct _lv_fs_drv_t * drv, uint32_t * total_p, uint32_t * free_p)
{
	
	lv_fs_res_t result;
	uint32_t fre_clust = 0;
	uint32_t fre_sect = 0;
	uint32_t tot_sect = 0;
	FATFS *fs1 = &fs;
	result = f_getfree((const TCHAR*)&drv->letter,&fre_clust,&fs1);
	if(result == 0)
	{
		tot_sect = (fs1->n_fatent-2)*fs1->csize; // total sector
		fre_sect = fre_clust * fs1->csize;
#if FF_MAX_SS != 512
		 tot_sect*=fs1->ssize/512;
		 tot_sect*=fs1->ssize/512;
#endif
		*total_p = tot_sect >> 1;  // unit in kb
		*free_p = fre_sect >> 1;   // unit in kb
	}
	return result;
	
}

lv_fs_res_t my_dir_open_cb(struct _lv_fs_drv_t * drv, void * rddir_p, const char * path)
{
	return f_opendir(rddir_p,path);
}
lv_fs_res_t my_dir_read_cb(struct _lv_fs_drv_t * drv, void * rddir_p, char * fn)
{
	FILINFO info;
	lv_fs_res_t result = f_readdir(rddir_p,&info);
	
	return 	result;
}
lv_fs_res_t my_dir_close_cb(struct _lv_fs_drv_t * drv, void * rddir_p)
{
	return f_closedir(rddir_p);
}


//閬嶅巻鏂囦欢
 //path:璺緞
 //杩斿洖鍊?鎵ц缁撴灉
uint8_t mf_scan_files(uint8_t * path,char *file_res,char *dir_res)
{
    FRESULT res;   
    char *fn;   /* This function is assuming non-Unicode cfg. */
    DIR dir;
    FILINFO fileinfo; //鏂囦欢淇℃伅
//#if FF_USE_LFN
//  fileinfo.fsize = FF_MAX_LFN * 2 + 1;
// fileinfo.lfname = malloc(SRAMIN,fileinfo.lfsize);
//#endif    
 char *p = file_res;
 res = f_opendir(&dir,(const TCHAR*)path); //鎵撳紑涓€涓洰褰?
 if (res == FR_OK) 
 { 
//			NRF_LOG_DEBUG("\r\n"); 
			while(1)
			{
						 res = f_readdir(&dir, &fileinfo);                   //璇诲彇鐩綍涓嬬殑涓€涓枃浠?
						 if (res != FR_OK || fileinfo.fname[0] == 0) break;  //閿欒浜?鍒版湯灏句簡,閫€鍑?
						 //if (fileinfo.fname[0] == '.') continue;             //蹇界暐涓婄骇鐩綍
		#if _USE_LFN
						 fn = *fileinfo.lfname ? fileinfo.lfname : fileinfo.fname;
		#else          
						 fn = fileinfo.fname;
		#endif            
                                   /* It is a file. */
				 NRF_LOG_DEBUG("attr=%d,%s\r\n",fileinfo.fattrib,fileinfo.fname);//鎵撳嵃鏂囦欢鍚? 
	   if(fileinfo.fattrib ==  AM_DIR)
		 {
			 while(*fn)
			 {
				 *dir_res++ = *fn++;
			 }
			 *dir_res++ = '\n'; 
		 }
			while(*fn)
			{
				*p++ = *fn++;
				 
			}
			 *p++ = '\n';//			 NRF_LOG_DEBUG("%s/", path);//鎵撳嵃璺緞 
			 
			} 
  }   
// myfree(SRAMIN,fileinfo.lfname);
    return res;   
}



/**
* @brief ivgl相关初时化
*/
static void lvgl_config_init(void)
{
	//--------------------------lvgl初时化--------------------------------------------------
    lv_init();

// 显示缓冲初时化
    static lv_disp_buf_t disp_buf;
    static lv_color_t buf[LV_HOR_RES_MAX * 10];                     /*Declare a buffer for 10 lines*/
    lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);    /*Initialize the display buffer*/
//===================================================================================================

// 注册显示回调函数
    lv_disp_drv_t disp_drv;               /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);          /*Basic initialization*/
    disp_drv.flush_cb = lv_disp_drv_flush_simple_cb;    /*Set your driver function*/
    disp_drv.buffer = &disp_buf;          /*Assign the buffer to the display*/
    lv_disp_drv_register(&disp_drv);      /*Finally register the driver*/   

 //===============================================================================================
	
	//触摸输入注册
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);             /*Descriptor of a input device driver*/
    indev_drv.type = LV_INDEV_TYPE_POINTER;    /*Touch pad is a pointer-like device*/
    indev_drv.read_cb = my_touchpad_read;      /*Set your driver function*/
    lv_indev_drv_register(&indev_drv);         /*Finally register the driver*/

 //------file system------------------------------
 lv_fs_drv_t drv;
 lv_fs_drv_init(&drv);
 drv.letter = '0';
 drv.file_size = sizeof(FIL);
 drv.rddir_size = sizeof(DIR);
 drv.ready_cb = my_ready_cb;
 drv.open_cb = my_open_cb;
  drv.close_cb = my_close_cb;
  drv.read_cb = my_read_cb;
 drv.write_cb = my_write_cb;
 drv.seek_cb = my_seek_cb;
 drv.tell_cb = my_tell_cb;
 drv.trunc_cb = my_trunc_cb;
 drv.size_cb = my_size_cb;
 drv.rename_cb = my_rename_cb;
 drv.dir_open_cb = my_dir_open_cb;
 drv.dir_read_cb = my_dir_read_cb;
 drv.dir_close_cb = my_dir_close_cb;
 drv.free_space_cb = my_free_space_cb;
// drv.user_data = my_user_data;
 lv_fs_drv_register(&drv); 
 
}

fatfs文件系统和lvgl文件接口的读写定义的值不匹配,为了使其匹配,这里更改lv_fs.h中的Filesystem mode的定义值,修改如下(也可以不修改,匹配open_cb的接口时对mode进行相应的匹配)

/**
 * Filesystem mode.
 */
enum {
	  LV_FS_MODE_EXISTING = 0,
      LV_FS_MODE_RD = 0x01,
	  LV_FS_MODE_WR = 0x02,
	  LV_FS_MODE_CREATE_NEW	= 0x04,
	  LV_FS_MODE_CREATE_ALWAYS = 0X08,
	  LV_FS_MODE_OPEN_ALWAYS = 0X10,
	  LV_FS_MODE_OPEN_APPEND = 0X30,
	  
};

在port.c中加入lv_tick_inc函数,并将freeRTOS节拍设成200Hz

创建1个任务运行lvgl任务调度

注册lvgl打印函数,这里使用RTT打印

RTT打印配置请参考 https://blog.csdn.net/mygod2008ok/article/details/90036720

lvgl打印配置请参考https://blog.csdn.net/mygod2008ok/article/details/105060696

freeRTOS打印配置

最后main函数中调用相关

int main(void)
{

	RTT_INIT();
	delay_init();
  TFTLCD_Init();           //初始化LCD FSMC接口

	tp_dev.init();				//触摸屏初始化
	
  uint8_t res=f_mount(&fs,"0:",1); 				//挂载FLASH.	
	BYTE work[512];
	if(res==0X0D)//FLASH磁盘,FAT文件系统错误,重新格式化FLASH
	{
		
		res=f_mkfs("0:",0,work,sizeof(work));//格式化FLASH,1,盘符;1,不需要引导区,8个扇区为1个簇
		if(res==0)
		{
			f_setlabel((const TCHAR *)"0:ALIENTEK");	//设置Flash磁盘的名字为:ALIENTEK
			NRF_LOG_INFO("set disk name");
			
		}else{NRF_LOG_INFO("format fail");}   //格式化失败
		
	}		
	res = f_open(&fil, "0:touch.txt", FA_OPEN_ALWAYS|FA_READ);

	if (res==0)
	{

			memset(work,0x0,50);
      uint32_t bw1;
			res = f_read(&fil,work,1,&bw1);

			if (work[0] != 'o')
			{
				LCD_Clear(WHITE);	//清屏
		    TP_Adjust();  		//屏幕校准 
			  TP_Save_Adjdata();	 
			  Load_Drow_Dialog();
				f_close(&fil);
				res = f_open(&fil,"0:touch.txt", FA_CREATE_ALWAYS|FA_WRITE);
				if(res==0)
				{
					work[0] = 'o';
					work[1] = 0;
					f_write(&fil,work,1,&bw1);
				}
			}
		
	}	
	f_close(&fil);
			
  
 	Load_Drow_Dialog();	 	
	
	
	
	
	lvgl_config_init();

	

	
	lv_log_register_print_cb(my_printf);
	
	lvgl_demo();

//	lv_test_theme_1(lv_theme_nemo_init(210, NULL));
	
	 xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )128,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )3,       //任务优先级
                (TaskHandle_t*  )0);   //任务句柄   
  
	vTaskStartScheduler();
	
  /* Infinite loop */
  for (;;)
  {      
		
  }
}

    lvgl_demo函数实现lvgl的简单显示demo


static lv_obj_t * mbox;

static void mbox_event_handler(lv_obj_t * obj, lv_event_t event)
{

    if(event == LV_EVENT_VALUE_CHANGED) {

        NRF_LOG_DEBUG("Button: %s\n", lv_mbox_get_active_btn_text(obj));
				lv_obj_del_async(lv_obj_get_parent(obj));
    }

}

void event_handler(struct _lv_obj_t * obj, lv_event_t event)
{
	 if(event == LV_EVENT_PRESSED)
	 {
	  static const char* btns[] = { "OK","" };
		lv_obj_t * back = lv_obj_create(lv_scr_act(),NULL);
	
		lv_obj_set_size(back,LV_HOR_RES_MAX,LV_VER_RES_MAX);
		
		static lv_style_t lab_style;
		lv_style_copy(&lab_style,&lv_style_plain);
		lab_style.body.main_color = LV_COLOR_WHITE;
		lab_style.body.opa = LV_OPA_100;
		lv_obj_set_style(back,&lab_style);
		
		
    mbox = lv_mbox_create(back, NULL);
    	char file_str[64]={0};
			char dir_str[64] = {0};
			mf_scan_files((uint8_t*)"0:",file_str,dir_str);
			NRF_LOG_INFO("file=%s dir=%s",file_str,dir_str);
		strcat(file_str,dir_str);
		
    lv_mbox_set_text(mbox, file_str);
    lv_mbox_add_btns(mbox, btns);
    lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
		static lv_style_t style_box;
		lv_style_copy(&style_box,&lv_style_plain);
		style_box.text.color = LV_COLOR_RED; 
		style_box.body.main_color = lv_color_hex3(0xf0f);
		style_box.body.grad_color = lv_color_hex3(0xf0f);
		lv_mbox_set_style(mbox,LV_MBOX_STYLE_BTN_PR,&style_box);
		
		lv_obj_set_event_cb(mbox, mbox_event_handler);
	}
}

void lvgl_demo(void)
{
	建立一按钮
    lv_obj_t * label;

    lv_obj_t * btn1 = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_event_cb(btn1, event_handler);//按钮按下回调函数,可以不用设置,可以多按钮同一个回调函数

		lv_obj_set_size(btn1,80,30);
    lv_obj_align(btn1, NULL, LV_ALIGN_IN_TOP_MID, 0, 40);

    label = lv_label_create(btn1, NULL);
		
    lv_label_set_text(label, "OK");


	lv_obj_t *slider = lv_slider_create(lv_scr_act(),NULL);
	lv_obj_set_size(slider,160,45);
	lv_obj_align(slider,btn1,LV_ALIGN_OUT_BOTTOM_MID,0,10);
	lv_slider_set_range(slider,0,100);
	lv_slider_set_value(slider,60,LV_ANIM_ON);
	
	
	 /*Create a style for the line meter*/

    static lv_style_t style_lmeter;

    lv_style_copy(&style_lmeter, &lv_style_pretty_color);

    style_lmeter.line.width = 3;

    style_lmeter.line.color = LV_COLOR_RED;

    style_lmeter.body.main_color = lv_color_hex(0x91bfed);

    style_lmeter.body.grad_color = lv_color_hex(0x04386c);

    style_lmeter.body.padding.left = 8;

 

    /*Create a line meter*/

    lv_obj_t* lmeter;

    lmeter = lv_lmeter_create(lv_scr_act(), NULL);

    lv_lmeter_set_range(lmeter, 0, 60);

    lv_lmeter_set_value(lmeter, 10);

    lv_lmeter_set_scale(lmeter, 360, 15);

 
   
    lv_lmeter_set_style(lmeter, LV_LMETER_STYLE_MAIN,&style_lmeter);

    lv_obj_set_size(lmeter, 80, 80);

    lv_obj_align(lmeter, slider, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);

   

    lv_task_t* t = lv_task_create(line_meter_task, 200, LV_TASK_PRIO_MID, lmeter);

    lv_task_ready(t);

    LV_FONT_DECLARE(myFont)

    lv_obj_t* label2 = lv_label_create(lv_scr_act(), NULL);

    lv_label_set_long_mode(label2, LV_LABEL_LONG_SROLL_CIRC);
		static lv_style_t red_style;
		lv_style_copy(&red_style,&lv_style_plain);
		red_style.text.color = 	LV_COLOR_RED;
		red_style.text.font = &myFont;
		lv_label_set_style(label2,LV_LABEL_STYLE_MAIN,&red_style);
    lv_obj_set_size(label2, 178,50);

  lv_label_set_text(label2,"闀块鐮存氮浼氭湁鏃剁洿鎸備簯甯嗘祹娌ф捣");

    lv_obj_align(label2, lmeter, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
   
}

最后运行效果如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 13
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风雨依依

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值