一、air001芯片简介
air001是厂商合宙推出的一款tssop封装的mcu芯片。支持swd与串口烧录,多面向简单的功能简单类别的电子产品,因为官方文档齐全上手简易,所以也特别适合非专业爱好者乃至于幼儿编程。芯片内置资源:AIR001芯片数据手册1.0.4.pdf
-
arm Comtex-m0内核架构,内置集成32kB的字节寻址flash以及4kB ram,工作最高主频48Mhz,内置rc振荡器也支持外部晶振时钟
-
供电支持1.7-5.5v的宽范围供电与io口,io数量18个,但有些io需要被复用为串口下载或者swd仿真,实际无法全部使用为gpio
-
带一个1Mhz采样率12bit分11路adc外设,9外部2内部,内部可用于实现温度传感器
-
3通道DMA
-
硬件CRC校验
-
9个定时器,1个16bit高级定时器,4个16bit通用定时器,2个看门狗定时器,1个systick定时器,1个低功耗定时器
-
带2个uart跟1个iic跟2个spi通信外设,iic支持100k\400k速率。
-
2个硬件比较器
二、使用的开发板
1.开发板上下图片
2.官方开发板图片
三、开发环境
1.更推荐只是想diy不涉及商业应用的新手使用arduino平台作为开发环境
2.建议商业级应用使用keil作为开发环境
四、基于arduino的开发环境
1.工具准备
-
usb转ttl串口收发器(如果是合宙官方的开发板自带usb转ttl串口收发器,所以不需要准备转串口工具)
2.烧录与下载
- 合宙官方提供了完整的开发文档,可以多看看那些
- arduino IDE下载完了之后会给自身安装插件以及驱动,耐心等待以及一路next就好。
- 软件准备完毕之后,把下面合宙官方的测试代码复制进去
void setup() {
// put your setup code here, to run once:
pinMode(PB_0, OUTPUT);
Serial.begin(115200);
Serial.printf("Hello, Air001. \n");
}
void loop() {
// put your main code here, to run repeatedly:
static int count = 0;
if (count % 2 == 0) {
digitalWrite(PB_0, HIGH);
} else {
digitalWrite(PB_0, LOW);
}
Serial.printf("This is NO.%d print. \n", count);
count++;
delay(1000);
}
-
然后先按住板上的"boot"按钮,再给开发板插上电,再松开按钮,这样芯片就进入了串口烧录模式。值得注意的是,我的开发板不板载usb转ttl芯片,所以需要外置转串口工具,但是转串口工具的引脚"RX、TX"会反灌开发板电压,导致air001进入串口烧录模式失败,所以转串口工具不要先插电脑。
-
插上usb转ttl串口工具,将转串口工具的’RX’连接开发板的’TX’,将转串口工具的’TX’连接开发板的’RX’,将转串口工具的’GND’连接开发板的’GND’(合宙官方开发板免去这个步骤)
-
设置arduino ide,如下图
-
当然,里面的设置不会跟我的一模一样,比如第二步就因为串口收发器插入了电脑不同的端口导致有所不同,所以先在设备管理器看看自己新加入设备在哪个端口上。还有一个情况是,转串口工具是需要下载驱动安装的,这个自己去找卖给自己的usb转ttl工具的商家要,目前常用的芯片一般也就是两类:CH34x、cp210x。而第三步里软件不会直接就有“Air001 Dev chip”的选项,而是“air001”的选项,想要有“Air001 Dev chip”的选项必须先选择“air001”然后“OK”确定后软件就会开始下载支持插件以及SDK,下载完之后就会跟我图片展现的一致出现“Air001 Dev chip”的选项
-
点击arduino IDE的upload按钮开始编译以及下载
-
烧录成功后就按下rst按钮即可复位芯片,当然也有可能复位失败的情况,复位失败就直接拔掉芯片的供电再插回去也可以复位。
-
打开串口监视器
-
选择串口监视器的波特率为115200,如果设置完后发现乱码那就重新拔插一下供电或者再重复一遍烧录流程
3.到上面的这一步就已经可以开始愉快的电子diy之旅。下面我会演示点亮一块0.96寸oled屏幕
-
这个屏幕是普通的0.96寸oled屏幕,控制芯片为SSD1306,四线iic通信,兼容3.3v\5v的一块显示屏。
-
将开发板的PA5\PA6连接到显示屏的SCL\SDA(PA5—SDA, PA6—SCL),显示屏的VCC以及GND也要记得接上开发板。
-
将下面的代码复制进编辑器并按上文的编译烧录流程走一遍
#include <Arduino.h>
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ PA_6, /* data=*/ PA_5, /* reset=*/ U8X8_PIN_NONE);
void setup() {
u8g2.begin();
u8g2.home();
pinMode(PB_0, OUTPUT);
Serial.begin(115200);
Serial.printf("Hello, Air001. \n");
}
void loop() {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_ncenB10_tr);
u8g2.drawStr(10,10,"Hello World!");
u8g2.drawStr(10,30,"And air001!");
} while ( u8g2.nextPage() );
Serial.printf("Hello, Air001. \n");
delay(1000);
}
-
编译烧录完毕后按下reset按钮,等一会就可以看到显示屏显示了字体出来。
-
可以看到,虽然显示屏有数据出来,但是刷新速度太慢,这个时候可以提高系统的频率,来提高刷新率。如下面图片选择的是:使用内部振荡器时钟,工作频率为48Mhz,当然如果自己使用的开发板带外部晶振也可选择使用
"HSE ***,HCLK ***"
-
我这里演示了0.96寸oled显示屏点亮,事实上显示屏是diy中非常重要的一个功能,很多的diy设计都会需要用到显示屏显示一些运行中的数据或者用显示屏加按键实现人机交互。使用串口做数据监控离不开电脑,所以uart串口除却用于其他器件的通信外一般用于代码debug以及打log。
-
我已经演示了uart串口、oled显示、gpio控制,这三个掌握了已经可以说是掌握了diy设计要求能力的80%。一些功能复杂、代码繁复、高速、有时序要求的设计就不是arduino开发平台能搞得定的了。我对arduino的期待就是小于1000行的代码设计可以使用arduino平台做开发,如果超过就不应该使用arduino做设计开发。当然我上面讨论的是diy设计,如果是属于消费电子以及工控领域,无论如何都不应该使用arduino做开发,而是使用keil或者iar做编译,vscode做编辑的方式。商业开发要求代码稳定可移植而且工程师要对代码中的任何一个库以及环节尽可能的了然于胸(完全了解肯定是不可能的),否则就等着一个bug搞一个月最后也搞不出来项目流产。嵌入式技术总体分为单片机以及linux领域,fpga、dsp开发也在嵌入式开发中有涉及到,专业的嵌入式工程师应该在前期抓住一个领域死磕并涉猎硬件,再然后把自己的知识面扩展到其他的方面并挑一个行业扎根深入。嵌入式是很大的一个领域不能够三天打鱼两天晒网也不能东捞一网西下一笼,广但是精很重要。
五、其他常用外设示例
在合宙的应用官网上有很多的应用实例以及api手册,其中api手册很重要,因为一些arduino的常用api其实air001并没有很好的适配,所以使用官方的api开发时非常有必要的。
1、adc示例
#include <Arduino.h>
void setup() {
pinMode(PA_7, INPUT_ANALOG);//初始化adc,通道7
Serial.begin(115200);//初始化串口
Serial.printf("Hello, Air001. \n");
}
void loop() {
float volt = 3.3;
char buffer[7] = {0};
volt = analogRead(PA_7)/1024.0*3.3;//12bit的dac为什么是1024?因为合宙官方貌似底层驱动库做了处理。
Serial.print("PA7---adc0_in7 : voltal=");
//Serial.printf似乎合宙官方没有实现支持浮点,只能人工转换了
buffer[0] = (int)(volt/10)%10 + '0';//十位
buffer[1] = (int)volt%10 + '0';//个位
buffer[2] = '.';
buffer[3] = (int)(volt*10)%10 + '0';
buffer[4] = (int)(volt*100)%10 + '0';
buffer[5] = (int)(volt*1000)%10 + '0';
buffer[6] = '\0';
Serial.printf("%sV\n", buffer);
delay(1000);
}
2、pwm示例
#include <Arduino.h>
void setup() {
//不要改变下面函数的书写顺序,在48Mhz运行时钟下最低分辨率为2bit,最快速度为12Mhz,实测波形完整性50%占空比下ok,但是芯片内部貌似使用内部时钟时时钟质量会变化也就是斜率变斜导致占空比输出的波形劣化
pinMode(PA_0, OUTPUT);
analogWriteResolution(2);//设置占空比的分母2^2 = 4
analogWriteFrequency(12000000);//12Mhz
analogWrite(PA_0, 4/2);//设置占空比的分子以及输出端口
}
void loop() {
delay(1000);
}
3、iic示例
略,建议看官方的例子更加详细。–> iic例子
六、LuatOS系统开发与air001
目前air001并没有支持合宙官方的LuatOS嵌入式系统,估计是受限于紧缺的ram以及flash资源。虽然遗憾,但是我想可以使用osal做系统开发。osal是一个基于事件的前后台操作系统(不是异步也不是实时操作系统),把轮询的系统框架伪装成实时系统开发以获得更好的移植性,以及更低的资源消耗,osal一般用于蓝牙开发。值得注意,osal依旧是一个前后台系统。
七、移植osal系统进air001芯片
- 这个章节我会演示osal系统运行进air001中,但是值得注意的是,arduino硬件平台使用的是前后台代码架构(也可以放弃arduino平台本身的架构转而使用freeRTOS或者RT-thread做内核从而获得实时性,同时还可以继续使用arduino丰富的开发库,但是这样做在我眼中arduino就失去了简易的意义,还不如直接基于rt-thread、freeRtos做开发,这样就能够使用基于其上的编辑、编译开发工具链),而osal也是一个前后台系统,在前后台系统之上再搭一个前后台系统是为了更好的移植性以及可读性,arduino为了简易性考虑只给出两个函数:
void setup() {};
void loop() {};
绝大多数情况下就这样的架构是很够用的,把功能函数封装,在loop()中循环,但是在某些时候有更高要求的情况不够用。通过牺牲简易性来换取代码架构的简洁与部分可维护性是允许的,毕竟复杂的项目不能期待能够在两个函数体内就搞定。虽然是这样说,但是在arduino上引入osal架构还是一种没什么太大意义的东西,但是讲了嵌入式开发的基本却不讲系统总感觉缺了什么。
- 下面给出了osal移植进arduino的模板例程
- 使用osal运行串口例程
移植osal移植搞不定头文件识别的问题。看样子arduino这个ide真的整不出骚活。只能这样了,例程我放在下面,欢迎动手能力强的能把完整的osal移植进arduino里面
例程