luat对较为严格的IO口时序问题目前只能依靠单片机解决,比如之前项目用到了编码器,我就为AIR202外挂了一片STM8S003。用stm8专用的编码器引脚IO捕捉信号。stm8的确便宜...
luat对较为严格的IO口时序问题目前只能依靠单片机解决,比如之前项目用到了编码器,我就为AIR202外挂了一片STM8S003。用stm8专用的编码器引脚IO捕捉信号。stm8的确便宜,才1块钱,小应性能也还可以。还省去了外置看门狗,让003做看门狗,串口喂狗。
剩下的问题就是远程升级了,怎么能没有远程升级功能囊。于是乎我做了针对STM8S003的程序烧录脚本。并写了个相适配的单片机的BOOTLOADER程序。(额,其实是烧录脚本适配BOOTLOADER,因为单片机flash只有8k,我们要让引导程序尽量的小)最终引导程序做到了600多字节,并且带有中断向量表,是全功能的。APP部分程序可以从0x8300地址开始烧录,详细后面说。先上脚本代码:
连接:McuUpdata.lua
原文:
--- 模块功能:STM8S003串口升级
-- @author dingzaiquan
-- @module MCUupdata
-- @license MIT
-- @release 2019.09.27 V1.0
module(...,package.seeall)
--[[
如果项目使用了STM8S003单片机
--加载单片机升级功能模块
require "McuUpData"
McuUpData.McuFlashLoader()
在串口接收中断函数适当位置加入
。。。
if McuUpdata.isDownloading() then
sys.publish("UART_RXD",data)
。。。
]]
require "pins"
-- 单片机程序保存路径(通过烧写软件烧写默认路径)
local STM8_FILE_PATH = "/ldata/app.bin"
local UART_ID = 1
local sDownloading = false
--[[函数名:UpData
功能 :STM8S003程序烧写
]]
local function UpData()
sDownloading = true
local err_dog = 0--错误计数
log.info("STM8_UpData","start")
--复位单片机//可以操作单片机复位引脚,也可以通过APP程序中加入串口复位指令复位单片机这里使用的是拉单片机复位引脚
pins.setup(pio.P0_2,0) --初始化单片机复位引脚底电平
sys.wait(100)
pins.setup(pio.P0_2,nil,pio.PULLUP)
sys.wait(10)
uart.write(UART_ID,0xa5)--发送烧录识别:a5
local result, data = sys.waitUntil("UART_RXD", 1000)
if data == "R" then --是否收到准备接收应答
--开始准备工作
local fileSize = io.fileSize(STM8_FILE_PATH) --取出程序文件字节数
local body = io.readFile(STM8_FILE_PATH) --读取文件并返回文件的内容
if fileSize%64>0 then --补足字节数到64的倍数
local replenish =""
for n=1,64-(fileSize%64) do
replenish= replenish..string.char(0x00)
end
body=body..replenish
fileSize = string.len(body)
end
log.info("STM8_UpData","fileSize:",fileSize) --打印烧录字节总数
sys.wait(10)
local i=0 --计数
--开始烧写工作
while i < fileSize do
uart.write(UART_ID,i/64)--发送包地址
local verify=0 --校验和
for j=i+1,i+64 do --计算校验和
verify = verify + string.byte(body,j)
end
--log.info("STM8_UpData","checksum:",string.toHex(string.char(verify%256)))--打印十六进制校验和
uart.write(UART_ID,string.byte(body,i+1,i+64))--发送64字节数据
--等待收到效验数据
result, data = sys.waitUntil("UART_RXD", 1000)
if result == true then
if data == string.char(verify%256) then --校验正确
i=i+64
log.info("STM8_UpData","Done:",i)--打印已完成烧录字节数
else
err_dog = err_dog + 1
if err_dog >=10 then
err_dog =0
log.info("STM8_UpData","error")
break
end
end
else
log.info("STM8_UpData","mcu no reply")
break
end
end
--烧录结束
uart.write(UART_ID,0x88)--发送0x88地址示意让单片机退出烧录
result, data = sys.waitUntil("UART_RXD", 1000)
if data == "F" then
log.info("STM8_UpData","finish")
sDownloading = false
return true
end
end
log.info("STM8_UpData","defeated")
sDownloading = false
return false
end
function McuFlashLoader()
sys.taskInit(UpData)
end
function isDownloading()
return sDownloading
end
我觉得注释写的很详细了,就不多废话了。
自制的boot:boot.bin
app程序从0x8300地址开始写入,对了很重要的波特率:115200。
也没仔细捣鼓,可能还有许多可以再继续优化的地方,欢迎指正。如果有需求就拿去用吧,希望能帮助到大家。