大彩医用级串口屏lua应用-龙8客户端下载

文件读写演示视频


一、适用范围


本文档适合大彩m系列医用级的串口屏产品使用。




二、开发环境版本


1.visualtft软件版本:v3.0.0.1111及以上的版本。

版本查看:

1)打开visualtft软件启动页面如图2-1软件版本,右上角会显示的软件版本号;

图片

图2-1软件版本


2) 打开visualtft,在软件右下角可以查看软件版本图2-2软件版本,最新版本可登录http://www.gz-dc.com/进行下载。

图片

图2-2软件版本


2.串口屏硬件版本:v6.3.249.0 及以上的版本

版本查看:

1) 查看屏幕背面版本号贴纸;

2) visualtft与屏幕联机成功后,右下角显示的版本号。




、概述


本例程中,介绍lua系统函数中的文件api读写,其中f系列和m系列仅支持对sd卡读写,物联型系列支持对屏内及sd卡、u盘的读写。




四、参考资料


1



《lua 脚本api v1.4》可通过以下链接下载物联型开发包获取:

http:/www.gz-dc.com/index.php?s=/list/index/cid/19.html

2



《lua基础学习》可通过以下链接下载物联型开发包获取:

http:/www.gz-dc.com/index.php?s=/list/index/cid/19.html

3



lua脚本初学者可以通过下面链接进行学习。

http://www.runoob.com/lua/lua-arrays.html

4



at指令,可以通过下面子连接了解

http://www.openluat.com/




五、教程实现


本文主要将以下2点进行说明:

1. 准备工程素材;

2. 配置串口屏工程;







5.1 准备工程素材

5.1.1 准备工程素材

在实现例程前需要作以下3个准备:

1. 硬件平台;

2. 软件平台;

3. ui素材;

该例程使用大彩m系列7寸串口屏dc80480m070_1111_0t为验证开发平台。如图5-1所示;

图片

图5-1 m系列7寸串口屏


其他尺寸、系列的串口屏均可借鉴此教程。


5.1.2 软件平台

使用大彩自主研发的上位机软件visualtft配置工程,登录http://www.gz-dc.com/下载。如图5-2所示;

图5-2下载软件







5.2 配置串口屏工程

本文的文件主要介绍以下2点:

(1) 读文件

(2) 写文件

5.2.1 读文件

本例程中的读文件,是读取sd根目录下的‘1.txt’文件,并用数据记录控件显示出来,用户可滑动数据记录控件,查看‘1.txt’里面的内容。


 1. 画面配置 

在画面id1中,添加1个数据记录控件(控件id1)和一个按钮控件(控件id2),其中控件id1用于显示‘1.txt’文件的内容。控件id2 用于触发读取‘1.txt’文件的按钮。画面配置如图5-3所示:

注意:其他非关键控件不在一一介绍,下文不在累述

图5-3 画面配置


 2. lua脚本编辑 

本例程中,用户点击按钮控件id2后,将读取sd目录下载的‘1.txt’文件,并添加到数据记录控件中显示;若文件不存在,则弹框提示。代码如程序清单1所示:


程序清单 1 读文件

--get the type and length of the variable
--@data: 'string' or 'table'
--@return: len and type of data
function my_getdatalen_type(data)
    my_debug_print('---------- my_getdatalen_type ----------')
    local datalen = -1
    --获取数据类型
    local data_type = type(data)
    --计算数据长度
    if data_type == 'string'
    then
        datalen = string.len(data)
    elseif data_type == 'table'
    then
        datalen = #(data)
    end
    my_debug_print('lua_debug data type and len: '..data_type..' /'..datalen)
    return datalen,data_type
end
--write data to the end of the file
--@file:file path
--@data:the type of '@data' only be [string] or [byte array]
--@open_mode:open file mode
function my_write_filedata(file, data, open_mode)
    my_debug_print('---------- my_write_filedata ----------')
    my_debug_print('lua_debug: file -> '..file..' / data -> '..type(data)..' / open_mode -> '..open_mode)
    local count     = 0
    local write_cnt = 0
    local offset    = 0
    local all_byte  = 0
    --获取待写入数据的数据类型和长度
    local wrire_len, data_type = my_getdatalen_type(data)
    local write_byte_tb = {}
    local open_state = file_open(file, open_mode)
    if open_state == true
    then
        --获取当前文件大小,仅在追加文件末尾写入执行
        if open_mode == add_write
        then
            all_byte = file_size()
        end
        if wrire_len > 0
        then
            --计算'@data'要写多少次
            write_cnt =  math.modf(wrire_len / writeoncesize)
            if wrire_len % writeoncesize > 0
            then
                write_cnt = write_cnt   1
            end
            my_debug_print('lua_debug: need write allcnt -> '..write_cnt)
            for i = 1, write_cnt
            do
                --复位写字节数组
                write_byte_tb = {}
                --计算写的位置
                offset = (i - 1) * writeoncesize  all_byte
                local offst_result = file_seek(offset)
                --文件偏移失败
                if offst_result == false 
                then
                    set_text(sc_prompt, 1, 'when reading the file, an offset error occurred. please try again! ! !')
                    set_text_roll(sc_prompt, 1, 50)
                    change_child_screen(sc_prompt)
                    break
                end
                my_debug_print('lua_debug: cur offset  -> '..offset)
                --计算本次写的个数
                count = writeoncesize
                if i == write_cnt
                then
                    if wrire_len % writeoncesize > 0
                    then
                        count = wrire_len % writeoncesize
                    end
                end
                my_debug_print('lua_debug: cur write  -> '..write_cnt..'th /wrire count '..count)
                --填充写入flash的字节数组
                for j = 1, count 
                do
                    if data_type == 'string'
                    then
                    --字符串类型,将每个字符转换为字节数组
                    write_byte_tb[j - 1] = tonumber(string.byte(data, ((i - 1) * writeoncesize   j), ((i - 1) * writeoncesize   j)))
                    elseif data_type == 'table'
                    then
                        --数组类型,字节赋值
                        write_byte_tb[j - 1] = 
                        data[((i - 1) * writeoncesize   j)]
                    end
                end
                local iswriteok = file_write(write_byte_tb)
                if iswriteok == false
                then
                    i = i - 1
                end    
            end
        end
    else
        set_text(sc_prompt, 1, 'the file don`t exist, please check the contents of the sd car! ! !')
        set_text_roll(sc_prompt, 1, 50)
        change_child_screen(sc_prompt)    
    end
    --关闭文件
    file_close()
end
--用户通过触摸修改控件后,执行此回调函数。
--点击按钮控件,修改文本控件、修改滑动条都会触发此事件。
function on_control_notify(screen,control,value)
    ......
    --追加写
    elseif screen == sc_writefile and control == 3 and value == 0
then
        sc_showrecord = sc_writefile
        --已插入sd卡
        if isinsertsd == 1
        then
            record_clear(sc_writefile, 1)
            local str = 'n'..get_text(sc_writefile, 2)    
            my_write_filedata(sd_dir..'/'..'1.txt', str, add_write)
            my_read_filedata(sd_dir..'/'..'1.txt')
            local allrecordcnt = record_get_count(sc_writefile, 1)
            record_setoffset(sc_writefile, 1, allrecordcnt - 1)
            record_select(sc_writefile   , 1, allrecordcnt - 1)
        --未插入sd卡
        else
            set_text(sc_prompt, 1, 'please insert the sd card, or check if the sd is compatible! ! !')
            set_text_roll(sc_prompt, 1, 50)
            change_child_screen(sc_prompt)
        end
    --覆盖写
    elseif screen == sc_writefile and control == 5 and value == 0
    then
        sc_showrecord = sc_writefile
        --已插入sd卡
        if isinsertsd == 1
        then
            record_clear(sc_writefile, 1)
            cnt = cnt   1
            local str = (cnt   1)..'th write -> '..get_text(sc_writefile, 4) 
            my_write_filedata(sd_dir..'/'..'newtxtfile.txt',str,over_write)
            my_read_filedata(sd_dir..'/'..'newtxtfile.txt')
        --未插入sd卡
        else
            set_text(sc_prompt, 1, 'please insert the sd card, or check if the sd is compatible! ! !')
            set_text_roll(sc_prompt, 1, 50)
            change_child_screen(sc_prompt)
        end
    ......
    end
end

▲下滑查看


 核心api函数 

1) file_open(path,mode)

打开文件,成功返回true,失败false


  • path-文件路径
  • mode-打开模式,如下组合方式:



打开模式

fa_open_existing

0x00

fa_read

0x01

fa_write

0x02

fa_create_new

0x04

fa_create_always

0x08

fa_open_always

0x10

例如:

打开文件用于读取file_open(path, 0x01) 

创建文件用于写入file_open(path, 0x02|0x08)


2) file_size()

获取当前文件大小,返回字节数

例如:all_byte = file_size()


3) file_seek(offset)

定位文件读取位置,成功返回true,失败false


  • offset-文件偏移位置


例如:定位到第2048个字节,file_seek(2048)


4) file_read(count)

读取文件内容,成功返回table数组,失败返回nil


  • count-读取字节数,最大读取2048个字节


例如:读取2048个字节,read_byte_tb = file_read(2048)


5) file_close()

关闭文件,成功返回true,失败false 


基本思路:当按钮控件id2按下的时候,触发触摸控件回调函数on_control_notify(),在调用自定义函数my_read_filedata()。

1) 打开文件:以只读的方式fa_read(0x01)打开指定文件。
2) 获取文件大小:文件打开成功后,调用file_size() api函数获取该文件的大小。
3) 计算读取次数:根据文件大小,得出读取的次数。本例程采取一次读取2048个字节(注意:屏幕一次读取最大字节 <= 2048)
4) 计算读取偏移量:每次读取需要调用file_seek(offset)定位读取位置,offset相当于已读取的字节数
5) 读出数据:本文读取的数据,转换成字符拼接字符串显示出来,详细应用根据实际情况出来。

6) 关闭文件:文件读取完毕,将该文件关闭。


5.2.2 写文件

常用的写文件操作主要有以下两种:

1) 追加写:写在文件末尾。本例程是写在sd根目录下的‘1.txt’文件末尾,并用数据记录控件显示出来。

2) 覆盖写:清空在写入数据。本例程在sd卡目录下,每次写入创建一个新的newfile.txt,并写入数据。


追加写和覆盖写的功能实现区别:

1) 打开方式:file_open(path,mode)。


  • 追加写:mode = fa_write|fa_read;
  • 覆盖写:mode = fa_create_always|fa_write;


2) 写入位置:file_seek(offset)。


  • 追加写:offset = file_size() (i - 1) * writeoncesize;其中writeoncesize为一次写入数据的大小,i为循环写入的次数。
  • 覆盖写:offset = 0;



 1. 画面配置 

在画面id2中,添加1个数据记录控件、2个文本控件(控件id2、控件id4)和2个按钮控件(控件id3、控件id5),其中数据记录控件仅做显示文件内容效果。按钮控件3用于体现追加写功能,按钮控件5用于覆盖写功能。画面配置如图5-4所示:

图片

图5-4 画面配置


2. lua脚本编辑 

按钮控件id3按下时候,将文本控件id2的内容写在sd根目录下的‘1.txt’文件末尾(追加写);按钮控件id5按下时候,将文本控件id4的内容写在sd根目录下的‘newfile.txt’文件(覆盖写)代码如程序清单 2所示。


程序清单 2 写文件

--get the type and length of the variable
--@data: 'string' or 'table'
--@return: len and type of data
function my_getdatalen_type(data)
    my_debug_print('---------- my_getdatalen_type ----------')
    local datalen = -1
    --获取数据类型
    local data_type = type(data)
    --计算数据长度
    if data_type == 'string'
    then
        datalen = string.len(data)
    elseif data_type == 'table'
    then
        datalen = #(data)
    end
    my_debug_print('lua_debug data type and len: '..data_type..' /'..datalen)
    return datalen,data_type
end
--write data to the end of the file
--@file:file path
--@data:the type of '@data' only be [string] or [byte array]
--@open_mode:open file mode
function my_write_filedata(file, data, open_mode)
    my_debug_print('---------- my_write_filedata ----------')
    my_debug_print('lua_debug: file -> '..file..' / data -> '..type(data)..' / open_mode -> '..open_mode)
    local count     = 0
    local write_cnt = 0
    local offset    = 0
    local all_byte  = 0
    --获取待写入数据的数据类型和长度
    local wrire_len, data_type = my_getdatalen_type(data)
    local write_byte_tb = {}
    local open_state = file_open(file, open_mode)
    if open_state == true
    then
        --获取当前文件大小,仅在追加文件末尾写入执行
        if open_mode == add_write
        then
            all_byte = file_size()
        end
        if wrire_len > 0
        then
            --计算'@data'要写多少次
            write_cnt =  math.modf(wrire_len / writeoncesize)
            if wrire_len % writeoncesize > 0
            then
                write_cnt = write_cnt   1
            end
            my_debug_print('lua_debug: need write allcnt -> '..write_cnt)
            for i = 1, write_cnt
            do
                --复位写字节数组
                write_byte_tb = {}
                --计算写的位置
                offset = (i - 1) * writeoncesize  all_byte
                local offst_result = file_seek(offset)
                --文件偏移失败
                if offst_result == false 
                then
                    set_text(sc_prompt, 1, 'when reading the file, an offset error occurred. please try again! ! !')
                    set_text_roll(sc_prompt, 1, 50)
                    change_child_screen(sc_prompt)
                    break
                end
                my_debug_print('lua_debug: cur offset  -> '..offset)
                --计算本次写的个数
                count = writeoncesize
                if i == write_cnt
                then
                    if wrire_len % writeoncesize > 0
                    then
                        count = wrire_len % writeoncesize
                    end
                end
                my_debug_print('lua_debug: cur write  -> '..write_cnt..'th /wrire count '..count)
                --填充写入flash的字节数组
                for j = 1, count 
                do
                    if data_type == 'string'
                    then
                    --字符串类型,将每个字符转换为字节数组
                    write_byte_tb[j - 1] = tonumber(string.byte(data, ((i - 1) * writeoncesize   j), ((i - 1) * writeoncesize   j)))
                    elseif data_type == 'table'
                    then
                        --数组类型,字节赋值
                        write_byte_tb[j - 1] = 
                        data[((i - 1) * writeoncesize   j)]
                    end
                end
                local iswriteok = file_write(write_byte_tb)
                if iswriteok == false
                then
                    i = i - 1
                end    
            end
        end
    else
        set_text(sc_prompt, 1, 'the file don`t exist, please check the contents of the sd car! ! !')
        set_text_roll(sc_prompt, 1, 50)
        change_child_screen(sc_prompt)    
    end
    --关闭文件
    file_close()
end
--用户通过触摸修改控件后,执行此回调函数。
--点击按钮控件,修改文本控件、修改滑动条都会触发此事件。
function on_control_notify(screen,control,value)
    ......
    --追加写
    elseif screen == sc_writefile and control == 3 and value == 0
then
        sc_showrecord = sc_writefile
        --已插入sd卡
        if isinsertsd == 1
        then
            record_clear(sc_writefile, 1)
            local str = 'n'..get_text(sc_writefile, 2)    
            my_write_filedata(sd_dir..'/'..'1.txt', str, add_write)
            my_read_filedata(sd_dir..'/'..'1.txt')
            local allrecordcnt = record_get_count(sc_writefile, 1)
            record_setoffset(sc_writefile, 1, allrecordcnt - 1)
            record_select(sc_writefile   , 1, allrecordcnt - 1)
        --未插入sd卡
        else
            set_text(sc_prompt, 1, 'please insert the sd card, or check if the sd is compatible! ! !')
            set_text_roll(sc_prompt, 1, 50)
            change_child_screen(sc_prompt)
        end
    --覆盖写
    elseif screen == sc_writefile and control == 5 and value == 0
    then
        sc_showrecord = sc_writefile
        --已插入sd卡
        if isinsertsd == 1
        then
            record_clear(sc_writefile, 1)
            cnt = cnt   1
            local str = (cnt   1)..'th write -> '..get_text(sc_writefile, 4) 
            my_write_filedata(sd_dir..'/'..'newtxtfile.txt',str,over_write)
            my_read_filedata(sd_dir..'/'..'newtxtfile.txt')
        --未插入sd卡
        else
            set_text(sc_prompt, 1, 'please insert the sd card, or check if the sd is compatible! ! !')
            set_text_roll(sc_prompt, 1, 50)
            change_child_screen(sc_prompt)
        end
    ......
    end
end

▲下滑查看


 核心api函数 

1) file_open(path,mode)

相关说明参考读文件章节,不在赘述


2) file_size()

相关说明参考读文件章节,不在赘述


3) file_seek(offset)

相关说明参考读文件章节,不在赘述


4) file_write(data)

写文件内容,成功返回true,失败返回false


  • data-待写入的table数组,索引从0开始,最大一次性写2048个字节



5) file_close()

相关说明参考读文件章节,不在赘述


基本思路:当按钮控件id3或按钮控件id5按下的时候,触发触摸控件回调函数on_control_notify(),在调用自定义函数my_write_filedata()。

1) 打开文件:


  • 追加写:以读写的方式(fa_read|fa_write:0x01|0x02)打开sd卡目录下的1.txt文件。
  • 覆盖写:以新建写入的方式(fa_create_always|fa_write:0x08|0x02)打开sd卡目录下的newfile.txt文件


2) 获取文件大小:文件打开成功后,若追加写模式,则执行file_size() api代码段。
3) 计算写入次数:根据写入数据的大小,得出读取的次数。本例程采取一次写入2048个字节(注意:屏幕一次读取最大字节 <= 2048)
4) 计算写入的偏移量:每次写入需要调用file_seek(offset)定位读取位置
5) 写入数据

6) 关闭文件:文件写完后完毕,将该文件关闭。







5.3 下载工程

工程编译成功后在输出窗口会提示编译成功,如图5-4所示。编译成功后点击菜单栏中【工具】→【量产向导】,如图5-5所示;

图片

图5-4编译成功

图片

图5-5量产向导


在弹窗中选中【sd卡下载】,然后把将文件夹中的private文件夹拷贝到sd卡中,如图5-6和图5-7所示;把sd卡接上串口屏后重新上电,等到提示烧录工程成功后,拔掉sd卡重新上电即可。

图片

图5-6量产向导

图片

图5-7拷贝到sd卡