LVGL 文件系统移植
文件系统介绍
在 LVGL 里可以将图像以文件的形式存储在 SPI Flash 或 SD 卡上,但是必须存储在 LVGL 的文件系统里,因此实践移植了 LVGL 文件系统。
LVGL 的文件系统可以适配任何其他的文件系统,只要实现相应的回调函数即可。该文件系统有一个驱动字符(drive letter)用于识别不同设备,例如 SD 卡可以与驱动字符 'S' 相关联,这样可以通过路径 "S:/path/to/file.txt" 来访问一个文件。
添加驱动
为了添加文件系统的驱动,需要初始化一个 lv_fs_drv_t 的结构体,类似下列示例代码:
lv_fs_drv_t drv;
lv_fs_drv_init(&drv); /*Basic initialization*/
drv.letter = 'S'; /*An uppercase letter to identify the drive */
drv.file_size = sizeof(my_file_object); /*Size required to store a file object*/
drv.rddir_size = sizeof(my_dir_object); /*Size required to store a directory object (used by dir_open/close/read)*/
drv.ready_cb = my_ready_cb; /*Callback to tell if the drive is ready to use */
drv.open_cb = my_open_cb; /*Callback to open a file */
drv.close_cb = my_close_cb; /*Callback to close a file */
drv.read_cb = my_read_cb; /*Callback to read a file */
drv.write_cb = my_write_cb; /*Callback to write a file */
drv.seek_cb = my_seek_cb; /*Callback to seek in a file (Move cursor) */
drv.tell_cb = my_tell_cb; /*Callback to tell the cursor position */
drv.trunc_cb = my_trunc_cb; /*Callback to delete a file */
drv.size_cb = my_size_cb; /*Callback to tell a file's size */
drv.rename_cb = my_rename_cb; /*Callback to rename a file */
drv.dir_open_cb = my_dir_open_cb; /*Callback to open directory to read its content */
drv.dir_read_cb = my_dir_read_cb; /*Callback to read a directory's content */
drv.dir_close_cb = my_dir_close_cb; /*Callback to close a directory */
drv.free_space_cb = my_free_space_cb; /*Callback to tell free space on the drive */
drv.user_data = my_user_data; /*Any custom data if required*/
lv_fs_drv_register(&drv); /*Finally register the drive*/
上述的任何一个回调函数都可以为 NULL 表明该操作不支持。
举例说明一些这些回调函数是如何被使用的,如果我们执行操作:
lv_fs_open(&file, "S:/folder/file.txt", LV_FS_MODE_WR);
LVGL 会依次
检查已经注册的驱动其驱动字节是否为 's' 。
检查 open_cb 回调函数是否被实现(不为 NULL)。
调用 open_cb,其中 path 参数为 "folder/file.txt" 。
使用示例
以下代码演示了如何读取文件:
lv_fs_file_t f;
lv_fs_res_t res;
res = lv_fs_open(&f, "S:folder/file.txt", LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) my_error_handling();
uint32_t read_num;
uint8_t buf[8];
res = lv_fs_read(&f, buf, 8, &read_num);
if(res != LV_FS_RES_OK || read_num != 8) my_error_handling();
lv_fs_close(&f);
lv_fs_open 里的 mode 参数也可以是 LV_FS_MODE_WR 或 LV_FS_MODE_WR | LV_FS_MODE_RD 。
下面的例子展示了如何读取一个目录里的内容。由驱动程序决定如何标记目录,类似 Unix 风格,最好在目录名称前面插入 '/' 表明根目录。
lv_fs_dir_t dir;
lv_fs_res_t res;
res = lv_fs_dir_open(&dir, "S:/folder");
if(res != LV_FS_RES_OK) my_error_handling();
char fn[256];
while(1) {
res = lv_fs_dir_read(&dir, fn);
if(res != LV_FS_RES_OK) {
my_error_handling();
break;
}
/*fn is empty, if not more files to read*/
if(strlen(fn) == 0) {
break;
}
printf("%s\n", fn);
}
lv_fs_dir_close(&dir);
图像所使用的驱动程序
LVGL 的 image 对象可以从文件里打开(另一种方式是