上半年利用业余时间使用国产芯片-合宙Air101 做了个小玩具,有点小成果,奈何现在忙带娃,基本没有时间继续了,已经吃灰了一段时间,做个总结,送有缘人。

XT-E804是阿里平头哥的MCU,属于CSKY架构(与RISC-V接近),合宙Air101芯片是XT-E804的QFN32封装,4mm*4mm封装大小。具有32位高性能内核,主频最高可达240MHz。内置UART、SPI、I2C、GPIO、ADC、PWM等外设接口,内置2MB Flash,作为一般的IOT设备开发足够。

部分原理图如下:

使用的嘉立创EDA 专业版,布线图如下:

背面接口见下图,采用常用的PH2.0卧式,3pin和4pin;供电使用常用的6pin TYPE-C;按键采用3*4*2.5轻触按键。屏幕采用1.14寸TFT显示屏,135*240分辨率,ST7789V驱动。同接口规格的还可以使用0.96寸显示屏,80*160分分辨率,ST7735驱动。板子整体尺寸为40mm*20mm。

CN1做输入口可接单总线传感器(ds18b20)或NTC热敏电阻;CN2输出口可接5v继电器或MOS管模块,输出PWM信号和开关信号;CN3为usart接口,用于下载程序和通信;CN4为模拟I2C接口(硬件I2C被ADC占用),接传感器。

开始显示屏使用了8PIN插接款,后来发现接头有一定高度,后来改为焊线款,屏幕可以贴合到mcu上,更紧凑。

3D效果图(开始显示屏使用了8PIN插接款,后来发现接头有一定高度,后来改为焊线款,屏幕可以贴合到mcu上,更紧凑):

换个角度看 : 

软件部分,开发采用vscode,安装LuatIDE插件,采用合宙推荐的LuatOS开发,图形界面采用LVGL库。


-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = "lvgldemo"
VERSION = "1.0.0"log.info("main", PROJECT, VERSION)-- sys库是标配
_G.sys = require("sys")--添加硬狗防止程序卡死
if wdt thenwdt.init(15000)--初始化watchdog设置为15ssys.timerLoopStart(wdt.feed, 10000)--10s喂一次狗
end-- UI带屏的项目一般不需要低功耗了吧, 设置到最高性能
if mcu thenmcu.setClk(240)
endlog.info("main", "ask for help", "https://wiki.luatos.com/")--air101 v2 13pin
spi_lcd = spi.deviceSetup(0,pin.PB08,0,0,8,10*1000*1000,spi.MSB,1,1)
lcd.init("st7789",{port = "device",pin_dc = pin.PB10, pin_rst = pin.PB09,direction = 2,w = 240,h = 135,xoffset = 40,yoffset = 53},spi_lcd)SignalOn = false
function getSignalState(t)if heatingMode == 1 thenif SignalOn == false and t < trigerValue then SignalOn = truegpio.set(pin.PB01,1)endif SignalOn == true and t > trigerValue+returnDifference thenSignalOn = falsegpio.set(pin.PB01,0)endelseif SignalOn == false and t > trigerValue then SignalOn = truegpio.set(pin.PB01,1)endif SignalOn == true and t < trigerValue-returnDifference thenSignalOn = falsegpio.set(pin.PB01,0)endendreturn SignalOn
endfunction f0(v)if sensorID == 0 then--vcc voltage in mVlvgl.gauge_set_value(gauge,0,v//100)elseif sensorID == 2 then-- external voltagelvgl.gauge_set_value(gauge,0,v//100)elseif sensorID == 3 or sensorID == 4 then--external tempreturelvgl.gauge_set_value(gauge,0,math.floor(v))if getSignalState(v) == true thenlvgl.switch_on(sw1, lvgl.ANIM_ON)elselvgl.switch_off(sw1, lvgl.ANIM_ON)endend
end
function drawGauge()--0local val = 30sensorOn = truesw1 = lvgl.switch_create(lvgl.scr_act())lvgl.obj_align(sw1, nil, lvgl.ALIGN_CENTER, 96, -51)--lvgl.obj_set_size(sw1, 20, 20)lvgl.switch_off(sw1, lvgl.ANIM_ON)gauge = lvgl.gauge_create(lvgl.scr_act())lvgl.obj_align(gauge, nil, lvgl.ALIGN_CENTER, -21, 30)lvgl.obj_set_size(gauge, 238, 238)lvgl.gauge_set_range(gauge, -20, 100)lvgl.gauge_set_scale(gauge,180,31,7)--lvgl.gauge_set_needle_count(g1, 1, lvgl.color_hex(0xFF0000))lvgl.gauge_set_critical_value(gauge, 80)sys.subscribe("value",f0)while true dolocal r,k = sys.waitUntil("key")if k=="3" thensys.unsubscribe("value",f0)lvgl.obj_clean(gauge)lvgl.obj_del(gauge)lvgl.obj_clean(sw1)lvgl.obj_del(sw1)log.info("key",k)return 2elseif k == "4" thensys.unsubscribe("value",f0)lvgl.obj_clean(gauge)lvgl.obj_del(gauge)lvgl.obj_clean(sw1)lvgl.obj_del(sw1)log.info("key",k)return 3elseif k=="5" thensys.unsubscribe("value",f0)lvgl.obj_clean(gauge)lvgl.obj_del(gauge)lvgl.obj_clean(sw1)lvgl.obj_del(sw1)log.info("key",k)return 1endend
endfunction f1(v)if sensorID == 0 thenlvgl.chart_set_next(chart, ser1, v//100)elseif sensorID == 2 thenlvgl.chart_set_next(chart, ser1, v//100)elseif sensorID == 3 thenlvgl.chart_set_next(chart, ser1, math.floor(v))elseif sensorID == 4 thenlvgl.chart_set_next(chart, ser1, math.floor(v))endlvgl.chart_refresh(chart)
end
function drawChart()--1chart = lvgl.chart_create(lvgl.scr_act(), nil)lvgl.obj_set_size(chart, 240, 135)lvgl.obj_align(chart, nil, lvgl.ALIGN_CENTER, 0, 0)--lvgl.obj_set_stype_local_value_str(chart,lvgl.CONT_PART_MAIN,lvgl.STATE_DEFAULT,"                                                                     ")lvgl.chart_set_type(chart, lvgl.CHART_TYPE_LINE)-- 设置 Chart 的显示模式 (折线图)lvgl.chart_set_range(chart,-20,100)lvgl.chart_set_div_line_count(chart,5,8)lvgl.chart_set_point_count(chart,20)--lvgl.chart_set_y_tick_length(chart,0,0)--lvgl.chart_set_y_tick_texts(chart, "100\n80\n60\n40\n20\n0\n-20", 3, lvgl.CHART_AXIS_DRAW_LAST_TICK);ser1 = lvgl.chart_add_series(chart, lvgl.color_hex(0xFF0000))--ser2 = lvgl.chart_add_series(chart, lvgl.color_hex(0x008000))sys.subscribe("value",f1)while true dolocal r,k = sys.waitUntil("key")if k == "3" thensys.unsubscribe("value",f1)lvgl.obj_clean(chart)lvgl.obj_del(chart)return 0elseif k == "4" thenlog.info("key",k)sys.unsubscribe("value",f1)lvgl.obj_clean(chart)lvgl.obj_del(chart)return 3elseif k == "5" thensys.unsubscribe("value",f1)lvgl.obj_clean(chart)lvgl.obj_del(chart)return 2endend
endfunction f2(v)lvgl.obj_clean(text)if sensorID == 0 thenlvgl.label_set_text(text, string.format("%d mV",v))elseif sensorID == 2 thenlvgl.label_set_text(text, string.format("%d mV",v))elseif sensorID == 3 thenlvgl.label_set_text(text, string.format("%.1f °C",v))elseif sensorID == 4 thenlvgl.label_set_text(text, string.format("%.1f °C",v))end
end
function drawText()--2local label1 = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(label1, nil, lvgl.ALIGN_CENTER, -40, -40)if sensorID == 0 thenlvgl.label_set_text(label1, "VCC Voltage:")elseif sensorID == 3 thenlvgl.label_set_text(label1,"DS18B20:")elseif sensorID == 4 thenlvgl.label_set_text(label1,"NTC 10K B2950:")elselvgl.label_set_text(label1, "label1:")            endtext = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(text, nil, lvgl.ALIGN_CENTER, -40, 10)sys.subscribe("value",f2)while true dolocal r,k = sys.waitUntil("key")if k == "3" thensys.unsubscribe("value",f2)lvgl.obj_clean(label1)lvgl.obj_del(label1)lvgl.obj_clean(text)lvgl.obj_del(text)log.info("key",k)return 1elseif k == "4" thensys.unsubscribe("value",f2)lvgl.obj_clean(label1)lvgl.obj_del(label1)lvgl.obj_clean(text)lvgl.obj_del(text)log.info("key",k)return 3elseif k == "5" thensys.unsubscribe("value",f2)lvgl.obj_clean(label1)lvgl.obj_del(label1)lvgl.obj_clean(text)lvgl.obj_del(text)log.info("key",k)return 0endend
endsensorID = 0
function setSensor()--3sensorOn = falselocal i = sensorIDlocal label1 = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(label1, nil, lvgl.ALIGN_CENTER, -90, -40)lvgl.label_set_text(label1, "Data Source:")local dd = lvgl.dropdown_create(lvgl.scr_act(), nil)lvgl.dropdown_set_options(dd, [[VCC VoltageChip TempretureExternal VoltageDS18b20NTC 10k B:2950]])lvgl.obj_align(dd, nil, lvgl.ALIGN_CENTER, -40, 0)lvgl.obj_set_width(dd,180)lvgl.dropdown_set_selected(dd, i)while true dolocal r,k = sys.waitUntil("key")if k == "3" theni = (i+4)%5lvgl.dropdown_set_selected(dd, i)endif k == "4" thensensorID = lvgl.dropdown_get_selected(dd)log.info("sensorID",sensorID)lvgl.obj_clean(dd)lvgl.obj_del(dd)lvgl.obj_clean(label1)lvgl.obj_del(label1)return 4endif k == "5" theni = (i+1)%5lvgl.dropdown_set_selected(dd, i)endend
endheatingMode = false --1 for heating, 0 for refrigerating mode
function setHeatingMode()local i = 0if heatingMode == true theni = 1endlocal label1 = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(label1, nil, lvgl.ALIGN_CENTER, -90, -40)lvgl.label_set_text(label1, "Application Mode:")local dd = lvgl.dropdown_create(lvgl.scr_act(), nil)lvgl.dropdown_set_options(dd, [[Refrigerating ModeHeating Mode]])lvgl.obj_align(dd, nil, lvgl.ALIGN_CENTER, -40, 0)lvgl.obj_set_width(dd,200)lvgl.dropdown_set_selected(dd, i)while true dolocal r,k = sys.waitUntil("key")if k == "4" theni = lvgl.dropdown_get_selected(dd)if i == 1 then heatingMode = trueelseheatingMode = falseendlog.info("heatingMode",heatingMode)lvgl.obj_clean(dd)lvgl.obj_del(dd)lvgl.obj_clean(label1)lvgl.obj_del(label1)return 5elsei = (i+1)%2lvgl.dropdown_set_selected(dd, i)endend
endsignalMode = 1 --5
function setSignalMode()--0 for PWM mode 1 for Relay Modelocal i=signalModelocal label1 = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(label1, nil, lvgl.ALIGN_CENTER, -90, -40)lvgl.label_set_text(label1, "Signal:")local dd = lvgl.dropdown_create(lvgl.scr_act(), nil)lvgl.dropdown_set_options(dd, [[ON/OFFPWM ON/OFF]])lvgl.obj_align(dd, nil, lvgl.ALIGN_CENTER, -40, 0)lvgl.obj_set_width(dd,180)lvgl.dropdown_set_selected(dd, i)while true dolocal r,k = sys.waitUntil("key")if k == "4" thensignalMode = lvgl.dropdown_get_selected(dd)log.info("signalMode",signalMode)lvgl.obj_clean(dd)lvgl.obj_del(dd)lvgl.obj_clean(label1)lvgl.obj_del(label1)return 6elsei = (i+1)%2lvgl.dropdown_set_selected(dd, i)endend
endtrigerValue = 30.0
function setTrigerValue()--6local label1 = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(label1, nil, lvgl.ALIGN_CENTER, -90, -40)lvgl.label_set_text(label1, "Trigger Value:")local sb1 = lvgl.spinbox_create(lvgl.scr_act(),nil)lvgl.obj_set_width(sb1,120)lvgl.obj_align(sb1, nil, lvgl.ALIGN_CENTER, 0, 0)lvgl.spinbox_set_digit_format(sb1, 4, 3)lvgl.spinbox_set_range(sb1, -200, 1000)lvgl.spinbox_set_value(sb1,math.floor(trigerValue*10))while 1 dolocal r,k = sys.waitUntil("key")if k == "3" thenlvgl.spinbox_decrement(sb1)elseif k == "4" thentrigerValue = lvgl.spinbox_get_value(sb1)/10log.info("trigerValue",trigerValue)lvgl.obj_clean(sb1)lvgl.obj_del(sb1)lvgl.obj_clean(label1)lvgl.obj_del(label1)return 7elseif k == "5" thenlvgl.spinbox_increment(sb1)endend
endreturnDifference = 5.0
function setReturnDifference()--7local label1 = lvgl.label_create(lvgl.scr_act())lvgl.obj_align(label1, nil, lvgl.ALIGN_CENTER, -90, -40)lvgl.label_set_text(label1, "Return Difference:")local sb2 = lvgl.spinbox_create(lvgl.scr_act(),nil)lvgl.obj_set_width(sb2,80)lvgl.obj_align(sb2, nil, lvgl.ALIGN_CENTER, 0, 0)lvgl.spinbox_set_digit_format(sb2, 3, 2)lvgl.spinbox_set_range(sb2, 0, 1000)lvgl.spinbox_set_value(sb2,math.floor(returnDifference*10))while 1 dolocal r,k = sys.waitUntil("key")if k == "3" thenlvgl.spinbox_decrement(sb2)elseif k == "4" thenreturnDifference = lvgl.spinbox_get_value(sb2)/10log.info("returnDifference",returnDifference)lvgl.obj_clean(sb2)lvgl.obj_del(sb2)lvgl.obj_clean(label1)lvgl.obj_del(label1)return 8elseif k == "5" thenlvgl.spinbox_increment(sb2)endend
endfunction screen(n)if n == 0 thenreturn drawGauge()--仪表盘endif n == 1 thenreturn drawChart()--折线图endif n==2 thenreturn drawText()--输出模式,只用文字输出endif n==3 thenreturn setSensor()--下拉选项框,传感器选择endif n==4 thenreturn setHeatingMode()--下拉选项框,工作模式 加热 降温endif n==5 thenreturn n+1  --不选PWM 模式--return setSignalMode()--下拉选项框,信号模式,0 pwm mode 1 继电器模式endif n==6 thenreturn setTrigerValue()--下拉选项框,触发值endif n==7 thenreturn setReturnDifference()--下拉选项框,回差值endif n==8 then--创建表格return n+1end--触发值if n==9 thenreturn n+1end--回差if n==10 thenreturn n+1end--回差if n==11 thenreturn n+1end--回差if n==12 thenreturn n+1end--回差if n==13 thenreturn n+1end--回差if n==14 thenreturn n+1end--回差if n==15 thenreturn 0end
end--------------------------------------
function getVccVolt()adc.open(11) -- VCC电压,最新代码才支持local v1,v2 = adc.read(11)adc.close(11)log.info("vccVolt",v1)return v1
end
function getChipTemp()adc.open(10) -- CPU温度local t1,t2 = adc.read(10)adc.close(10)return t1
end
function getPortVolt()adc.open(1) -- 模块上的ADC1脚-PA4, 0~2.4v,不要超过范围使用!!!local value,volt = adc.read(1)adc.close(1)log.info("adc",volt)return volt
end
function getDs18b20()while true dolocal value,status = sensor.ds18b20(4,false)if status == true thenreturn valueendend
end
function getNtcTemp()adc.open(1) -- 模块上的ADC1脚-PA4, 0~2.4v,不要超过范围使用!!!local value,volt = adc.read(1)adc.close(1)adc.open(11) -- VCC电压,最新代码才支持local v1,v2 = adc.read(11)adc.close(11)local resistant = 10000*volt/(v1-volt)local temp = 1/(1/298.15 + math.log(resistant/10000)/3950) - 273.15log.info("ntc",temp)return temp
end
-------------------get sensor value-------------------
sys.taskInit(function()while true dosys.wait(1000)if sensorOn == true thenif sensorID == 0 thensys.publish("value",getVccVolt())endif sensorID == 1 thenlog.debug("value","chip_temp","not support")endif sensorID == 2 then--检测分压电压sys.publish("value",getPortVolt())endif sensorID == 3 then--DS18B20sys.publish("value",getDs18b20()/10)endif sensorID == 4 thensys.publish("value",getNtcTemp())endendend
end)----按键检测
sys.taskInit(function()gpio.setup(pin.PB11, nil, gpio.PULLUP)--27,upgpio.setup(pin.PB04, nil, gpio.PULLUP)--20,centergpio.setup(pin.PB00, nil, gpio.PULLUP)--16,downgpio.setup(pin.PB01,0)                --PWM Signalwhile true doif gpio.get(27) == gpio.LOW thensys.publish("key","3")endif gpio.get(20) == gpio.LOW thensys.publish("key","4")endif gpio.get(16) == gpio.LOW thensys.publish("key","5")endsys.wait(150)end
end)--SCREEN WINDOWS
sys.taskInit(function()sys.wait(100)log.info("lvgl", lvgl.init())-- ("default")("mono")("empty")("material_light")material_dark--lvgl.theme_set_act("mono")-- ("material_no_transition")("material_no_focus")scr = lvgl.scr_act()local font_20 = lvgl.font_load("/luadb/20_test_fonts.bin")lvgl.obj_set_style_local_text_font(lvgl.scr_act(), lvgl.LABEL_PART_MAIN, lvgl.STATE_DEFAULT, font_20)local screen_n = 0while true doscreen_n = screen(screen_n)end
end)-- 用户代码已结束---------------------------------------------
-- 结尾总是这一句
sys.run()
-- sys.run()之后后面不要加任何语句!!!!!

实物效果图两张:

合宙Air101的软硬件开发相关推荐

  1. 使用合宙air101系统板DIY一个小船

    这个故事还得从在校园湖边散步说起--水面上遥控船吸引了我-- 视频演示:[划水的瓶子-哔哩哔哩] 材料清单: 合宙air101小板:9.9元 航模有刷电机:5元左右 L298N电机驱动板:6元左右 蓝 ...

  2. 合宙Air101 的LCD怎么用Arudino IDE驱动

    屏幕怎么驱动 有个官方的资料,可以了解到是ST7735,屏幕的分辨率 https://doc.openluat.com/wiki/21?wiki_page_id=2672 有个库但是这个库是LuatO ...

  3. 合宙首款MCU芯片——Air101上市

    Air101的诞生背景 ● 传统MCU行业痛点 传统的MCU不同厂家之间开发环境.接口命名.寄存器都不一样,因此切换一款芯片需要付出很大的学习成本,同时项目验证周期长. 基于上述原因,缺芯浪潮下即便某 ...

  4. 最新动态 | 合宙MCU新品即将发布,LuatOS-SoC软硬件齐发力

    合宙在9月初首发推出MCU产品线Air101系列,搭载LuatOS开发助力快速量产,在业界引发广泛反响. 今天合宙正式发布MCU新品--Air103及其配套开发板,更多引脚将满足更丰富的需求 未来,还 ...

  5. 新品上市 | 合宙MCU新品Air103【芯片+开发板+拓展板】火爆来袭

    深耕嵌入式操作系统LuatOS和主控CPU组合发展应用,提升开发效率,切实解决工程师痛点.合宙9月份推出国产MCU系列Air101之后,不少工程师朋友问:IO可不可以再多些,功耗可不可以再低些? 工程 ...

  6. 合宙Air103 LuatOS开发小试

    一.简介  使用LuatOS开发Air103,先点个灯熟悉流程.可以使用官方建议的vs code的LuatIDE进行开发会比较方便:  但是由于用Lua脚本语言开发,编辑器显得不那么重要了,随便用都一 ...

  7. 日志中出现乱码_合宙Luat | 乱码搞得一团糟?开源神器帮你轻松修复

    鎰熸仼鐩搁亣 缇庡ソ鐨勬椂鍏変笌澶у鐩镐即 2021锛屾柊骞村揩涔愶紒 相信大家在日常生活中,都见过类似上面的字符串.这些看起来不明所以的内容,通常被称作乱码. 那么乱码是如何产生的,并且如何修复呢 ...

  8. 小熊派开发实践丨小熊派+合宙Cat.1接入云服务器

    摘要:使用小熊派开发板,以合宙的AIR724为通信模组(Cat.1),以AT指令方式,通过mqtt协议接入云服务器. 本贴使用小熊派开发板+合宙的Air724(Cat.1模组),接入自己搭建的EMQ服 ...

  9. 小熊派开发板移植emwin_小熊派开发实践丨小熊派+合宙Cat.1接入云服务器

    摘要:使用小熊派开发板,以合宙的AIR724为通信模组(Cat.1),以AT指令方式,通过mqtt协议接入云服务器. 本贴使用小熊派开发板+合宙的Air724(Cat.1模组),接入自己搭建的EMQ服 ...

最新文章

  1. centos7 中搭建gitlab
  2. Oracle簇表介绍 (clustered table)
  3. 【CentOS Linux 7】【Linux网络配置基础】
  4. win10启动项_科普:为什么重装Win7系统后,速度比Win10系统慢很多?
  5. 集合还有这么优雅的运算法?
  6. mongo基本使用方法
  7. 课堂上老师不讲的有趣物理知识,才是孩子最感兴趣的!
  8. 模式匹配算法----KMP算法以及next数组的解法
  9. PulseAudio多线程通信:pthread_cond_broadcast/pthread_cond_signal/pthread_cond_wait(九)
  10. 传智播客 C/C++学习笔记 指针3 理解指针必须与内存四区相结合
  11. 360se html怎么删除,如何卸载360浏览器?怎么彻底删除360浏览器?
  12. adobe illustrator 菜单中英文对照
  13. 中国版Second Life前途难料
  14. 计算机视觉方面的三大顶级会议:ICCV,CVPR,ECCV(统称ICE)
  15. python复利计算_python复利代码
  16. chrome与chromedriver版本对应关系以及官方下载页面
  17. 【电脑版微信文件存储在什么位置】
  18. 残差(residual)
  19. uploadify批量上传文件
  20. c++ 中map 的find 用法

热门文章

  1. ResNet随堂笔记
  2. 基于python文本挖掘实战_Python数据分析系列视频课程--学习文本挖掘
  3. android wifi 休眠策略,atheros wifi芯片ics高通平台---wifi睡眠策略分析
  4. cad-家装平面图(一)
  5. python数据分析是什么意思_利用python进行数据分析,python数据分析是什么
  6. 共享打印机出现0x00000569代码解决方案(亲测有效)
  7. 实战:直指人心的恐惧营销应如何运用
  8. python picklable
  9. python如何将多个文件夹的PNG图片批量转换为jpg图片(无损转换)
  10. 每日一书丨由浅入深解析软件自动化的痛点问题