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

  • 準備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)
{
	
	return f_size((FIL*)file_p);
	
}

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); 
 
}

在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);
   
}

最後運行效果如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章