8 Flash API读写

大彩串口用户Flash掉电存储空间一共128K,地址范围为0~131072(10进制,128*1024),其中和modbus掉电存储、历史曲线、数据记录控件、LUA API Flahs掉电存储、大彩指令Flash 指令均是共用这128K存储地址,使用flash掉电存储需要注意以下问题

1.地址重叠:在这128K的存储中,以下情况需要两两排查是否重叠

  • 历史曲线开启存储(非块地址存储):应排查历史曲线控件所占用的存储大小,以免和Lua脚本中的 Flash 操作冲突
  • 数据记录控件开启存储(非块地址存储):应排查数据记录控件所占用的存储大小,以免和Lua脚本中的 Flash 操作冲突
  • modbus协议:开启存储,Lua脚本中的 Flash 存储地址需要避开0~2047
  • 大彩协议指令存储:排查主板发送Flash存储指令的地址,以免和Lua脚本中的 Flash 操作冲突

2.擦写次数:

  • 此区域的擦写次数为10W次左右,使用存储的时候应该斟酌使用,忌讳变量每秒存储一次的操作。建议存储一些关键变量,在变量变化存储,以延长Flash的寿命

3.虚拟屏不支持‘掉电存储’,请在实体屏运行、测试


Flash API 如下所示

1 write_flash(addr,data)

写用户FLASH数据,addr写入地址,data字节数组,下标从0开始。

2 read_flash(addr,length)

读用户FLASH数据,addr写入地址,length读取字节数,返回类型为字节数组,下标从0开始

3 write_flash_string(addr,str)

写字符串到指定FLASH地址

4 read_flash_string(addr)

从指定FLASH地址读取字符串,成功返回字符串,失败返回nil

5 flush_flash()

系统会对NAND FLASH写入操作进行缓存优化,以提高写入效率

flush_flash操作会立即把数据写入FLASH

6 flush_nor()

系统会对NOR FLASH写入操作进行缓存优化,以提高写入效率

flush_nor操作会立即把数据写入FLASH


本例程主要讲述以下几点存储方式

  1. 字节数组存储
  2. 字符串存储
  3. 字符串JSON格式存储

适用范围:M系列、W系列、X系列、F系列(固件版本 >= V4.2.401.0)

例程下载链接:《Flash API读写》(点击跳转)

8.1 字节数组存储

假设从0地址开始存储两个变量A,B,其中变量A的范围为0~255,变量B的范围为0~65535,则存储共需要3个字节,假设A=80,B=1000,为了方便理解,此处value用16进制表示,内部存放如下所示

addr 0 1 2
value 0x50 0x03 0xE8

根据上表可知,每一个地址只存储一个字节,即相对于字符串,对比而言存在以下优缺点

优点:省空间

缺点:变量连续地址存储不利于读写、需要对数组下标操作

  • 变量为整形:若value >= 255, 读写过程需要对数值移位操作,如下所示
--写操作
local wA = 80
local wB = 1000
local wdata = {}
wdata [0] = A
wdata [1] = (B >> 8) & 0xFF    --移位赋值字节数组
wdata [2] = (B >> 0) & 0xFF    --移位赋值字节数组
write_flash(0, wdata)

假设已知存储的A、B变量在地址0,共3个字节:

--读操作
local rdata = read_flash(0,3)
lcoal rA = rdata[0]
lcoal rB = (rdata[1] << 8) | rdata[2]    --拼接字节数组
  • 变量为字符串:读取出来的数值需要转为字符拼接,如下所示
--写操作
local wString = "中国"
lcoal wdata = {}
for i = 1,string.len(wString)
do
    wdata [i-1] = string.byte(wString, i, i)    --转为字节,并赋值到数组
end
write_flash(0, wdata[0]) 
-- wdata[0] = 0xD6 
-- wdata[1] = 0xD0 
-- wdata[2] = 0x87 
-- wdata[3] = 0xEB

假设已知存储字符串变量为“中国”,共4个字节:

--读操作
local rdata = read_flash(0,4)
local rString = ‘’
for i = 0,#(rdata)
do
    rString = rString..string.char(rdata[i])    --转为字符,并拼接
end
--rString = '中国'

画面配置

画面中添加以下控件

文本控件ID3、ID5:输入方式为键盘输入,其中ID3的数值限定为0~255,ID5的数值限定为0~65535

文本控件ID8、ID10:输入方式为用户主机输入

按钮控件ID1:作为写操作的触发按钮

按钮控件ID6:作为读操作的触发按钮,如下所示

FlashAPI01

LUA脚本

已知道上小节画面配置了控件ID3占用一个字节,控件ID5的值占用2个字节,当点击按钮控件ID1的时候,获取文本控件ID3、ID5的值,并写入flash。当点击按钮控件6,读取Flash里的数据,并显示出来

local sc_byte     = 0
local byte_addr   = 0x00000000

--用户通过触摸修改控件后,执行此回调函数
--点击按钮控件,修改文本控件、修改滑动条都会触发此事件
function on_control_notify(screen,control,value)  
    if screen == sc_byte
    then
        if control == 1 and value == 0
         then
            local write_byte_data = {}
            write_byte_data[0] = get_value(sc_byte,3)

            write_byte_data[1] = ( get_value(0,5) >> 8) & 0xFF
            write_byte_data[2] =  get_value(0,5) & 0xFF

            flush_flash()
            write_flash(0,write_byte_data)

        elseif control == 6 and value == 0
        then
            local read_byte_data  = {}
            read_byte_data = read_flash(byte_addr,3)

            set_text(0,  8, read_byte_data[0])
            set_text(0, 10, (read_byte_data[1]<<8) | read_byte_data[2])
        end

    ......
end

运行预览

该Flash掉电存储需要在实体屏体验,本例程中,通过修改文本值点击write按钮保存,然后断电重启后,点击read按钮,将数据读取出来显示。本例程为了方便演示、说明,实际应用中,把读flash操作放在on_init()中,屏幕上电自动读取

8.2 字符串读写

假设从0地址开始存储两个变量sA,sB,其中变量A=‘abc’,变量B=‘中国’,则将变量A、B拼接起来,并用分隔符隔开,即是

w_AB = A .. ‘,’ .. ’B’  -–w_AB = ‘abc,中国’

为了方便理解,此处value用16进制表示,内部存放如下所示

addr 0 1 2 3 4 5 6 7
value 0x61 0x62 0x63 0x2C 0xD6 0xD0 0x87 0xEB

根据上表可知,每一个地址只存储一个字节,即相对于字节存储,对比而言存在以下优缺点

优点:对字符串存储友好

缺点:对数值存储占用空间,如A=200(0<=A<255),字节存储仅占一个字节,0xC8,若字符串需要占用3个字节,0x32 0x30 0x30

画面配置

画面中添加以下控件

文本控件ID3、ID5:输入方式为键盘输入,用于修改要保存的到Flash的数据

文本控件ID8、ID10:输入方式为用户主机输入,用于显示从Flash读取的数据

按钮控件ID1:作为写操作的触发按钮

按钮控件ID6:作为读操作的触发按钮,如下所示

FlashAPI02

LUA脚本

已知道上小节画面配置了控件ID3、控件ID5均用于输入字符串,当点击按钮控件ID1的时候,获取文本控件ID3、ID5的值,拼接“,”后写入flash。当点击按钮控件6时,读取Flash里的数据,检索“,”并调用split()[自定义函数]分割,最后显示在对应文本控件ID8、ID10中,代码如下所示

local sc_str     = 1
local str_addr   = 0x00000064
local token      = ','

-- 切割字符串,遇到pat符号就切割
-- 自定义函数(非回调函数,可以修改)
-- str 需要切割的字符串
-- pat 遇到此字符切割
function split(str, pat)

    local t = {}
    local last_end = 0
    local s, e = string.find(str, pat, 1)    --  第一个分割号的位置

    while s 
    do    
        -- 找出分割符的前的参数
        table.insert(t, string.sub(str, last_end + 1, last_end + s - last_end - 1))
        last_end = e
        s, e = string.find(str, pat, last_end + 1)
    end

    if last_end <= #str then
        cap = string.sub(str, last_end + 1)
        table.insert(t, cap)
    end

    return t  
end

--用户通过触摸修改控件后,执行此回调函数。
--点击按钮控件,修改文本控件、修改滑动条都会触发此事件。
function on_control_notify(screen,control,value)

    ......
    elseif screen == sc_str
    then
        if control == 1 and value == 0
        then
            local write_Jsonstr_data = {}

            write_Jsonstr_data[0] = get_text(sc_str, 3)
            write_Jsonstr_data[1] = get_text(sc_str, 5)

            local write_str = write_Jsonstr_data[0]..token..write_Jsonstr_data[1]
            print("Dbug : write_str ->  "..write_str)
            flush_flash()
            write_flash_string(str_addr,write_str) 

        elseif control == 6 and value == 0
        then
            local read_str = ''
            local read_str_data  = {}

            read_str =  read_flash_string(str_addr) 
            print("Dbug : read_str ->  "..read_str)

            read_str_data = split(read_str, token)

            set_text(sc_str,  8, read_str_data[1])
            set_text(sc_str, 10, read_str_data[2])
        end
        ......
    end
 end

运行预览

该Flash掉电存储需要在实体屏体验

8.3 字符串存储-JSON格式

对象可以包含多个 key/value(键/值)对,key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null),JSON同时具有自我描述性,更易理解,一般声明数组,通过函数压缩成JSON字符串,或将JSON字符串解压成数组,常见声明有以下方式:

--声明一个数组
local addNewPrj_Tb = {
    addPercentage    = 0,
    description      = "水果",
    duration         = 0,
    name             = "苹果",
    percentage       = 0,
    price            = 11,
    selectPercentage = 0,
    type             = 1,
    wechatShow       = false
}

若引用name的值,其中“name”为key,“苹果”为value

print(jsonTest[name])
print(jsonTest.name)

>大彩
>大彩
  • 表压缩为JSON字符串
local newPrj = cjson.encode(addNewPrj_Tb)
print(newPrj)

> {"selectPercentage":0,"addPercentage":0,"description":"水果","name":"苹果","duration":0,"wechatShow":true,"type":1,"price":11,"percentage":0}
  • JSON字符串解压成表,即是“jsonStr”字符串被解压成“newTb”表,就可以引用里面成员,如newTb[price]
--JSON字符串解压成
local jsonStr = {"selectPercentage":0,"addPercentage":0,"description":"水果","name":"苹果","duration":0,"wechatShow":true,"type":1,"price":11,"percentage":0}

local newTb = cjson.dncode(jsonStr)
print(newTb[price])

>11

根据上表可知,每一个地址只存储一个字节,即相对于上述字节存储、字符串存储,对比而言,字符串存储-JSON格式存在以下优缺点

优点:对字符串存储友好,对于连续变量无需分割,API一键压缩/解压,更方便引用成员,拥有自我描述性,项目中的代码可读性更强,更易理解

缺点:因为存在键值对,占用内存比上述两者方式都大

画面配置

画面中添加以下控件

文本控件ID3、ID5:输入方式为键盘输入,用于键潘修改后保存的到Flash

文本控件ID8、ID10:输入方式为用户主机输入,用于显示从Flash读取的数据

按钮控件ID1:作为写操作的触发按钮

按钮控件ID6:作为读操作的触发按钮,如下所示

FlashAPI03

LUA脚本

已知道上小节画面配置了控件ID3、控件ID5均用于输入字符串,当点击按钮控件ID1的时候,获取文本控件ID3、ID5的值,赋值给表压缩成JSON格式,在写入Flash。当点击按钮控件6时,读取Flash里的数据,通过解压JSON字符串,生成一个新的表,最后显示在对应文本控件ID8、ID10中,代码如下所示

local sc_Jsonstr = 2
local jsonstr_addr= 0x000000C8


--用户通过触摸修改控件后,执行此回调函数。
--点击按钮控件,修改文本控件、修改滑动条都会触发此事件。
function on_control_notify(screen,control,value)

    ......
        elseif screen == sc_Jsonstr
    then
        if control == 1 and value == 0
        then
            local write_Jsonstr_data = {}

            write_Jsonstr_data["data1"] = get_text(sc_Jsonstr, 3)
            write_Jsonstr_data["data2"] = get_text(sc_Jsonstr, 5)

            local write_jsonStr = cjson.encode(write_Jsonstr_data)

            flush_flash()
            write_flash_string(jsonstr_addr, write_jsonStr)

        elseif control == 6 and value == 0
        then
            local read_Jsonstr_flash = {}
            local read_Jsonstr = read_flash_string(jsonstr_addr)


            read_Jsonstr_flash = cjson.decode(read_Jsonstr) 

            print(read_Jsonstr_flash["data1"])
            print(read_Jsonstr_flash["data2"])

            set_text(sc_Jsonstr,  8, read_Jsonstr_flash["data1"])
            set_text(sc_Jsonstr, 10, read_Jsonstr_flash["data2"])
        end
    end
 end

运行预览

该Flash掉电存储需要在实体屏体验

Copyright ©Dacai all right reserved,powered by Gitbook该文件修订时间: 2023-03-30 11:39:27

results matching ""

    No results matching ""