【学习计划】
为了上手使用mbed OS,可以采取如下的学习路线:
1. Digital input and output
2. Analog input and output
3. Pulse width modulation(PWM)
4. GPIO Interrupt
5. Timer
6. UART Communication
7. SPI Communication
8. I2C Communication
9. mbed RTOS
9.1 Thread synchronization
9.2 Thread communication
9.3 ISR
10. Bluetooth Low Energy (BLE)
11. mbed network
12. TCP application
... ...
【一】Digital Input and Output
这部分主要是熟悉一下如何使用mbed OS的API,基本的数字输入输出。相当于第一个程序“Hello word!”。
进入IDE,在使用的开发板(NUCLEO-F103RB)下面选择New新建项目,可以选择模板 "Blinky LED Hello Word"
接着就会导入mbed目录和main.cpp.
关于mbed目录的内容上一期已经提到,项目中的结构也一一对应:
我们重点看一下这个Blinky LED的main.cpp:
#include "mbed.h"
DigitalOut myled(LED1);
int main() {
while(1) {
myled = 1; // LED is ON
wait(0.2); // 200 ms
myled = 0; // LED is OFF
wait(1.0); // 1 sec
}
}
上面的程序是基于mbed API写的,可以看到非常简洁。首先建立DigitalOut的对象myled,并指定LED1作为数字输出口,在main函数的while循环里分别将对象值赋值为1和0,来控制灯的亮灭。
实际上,mbed API是对mbed HAL API的进一步封装,如果读者对上一期的【mbed library的层次结构】还有印象的话,HAL API这一层是“MCU无关层”的最底层,它的接口定义对于不同的开发板是一样的,但是其HAL API的实现(mbed HAL implementation)是"MCU相关层"。为了对比上面使用mbed API接口的程序,我使用HAL层的接口写了如下具有同样功能的一段程序:
#include "mbed.h"
int main()
{
gpio_t obj;
gpio_init(&obj,LED1);
if(LED1!=NC) {
gpio_write(&obj,0);
gpio_dir(&obj,PIN_OUTPUT);
gpio_mode(&obj,PullNone);
}
while(1) {
gpio_write(&obj,1);
uint32_t start1=us_ticker_read();
while((us_ticker_read()-start1)<(uint32_t)(0.2*1000000.0f));
gpio_write(&obj,0);
uint32_t start2=us_ticker_read();
while((us_ticker_read()-start2)<(uint32_t)(1*1000000.0f));
}
}
看到上面的程序依然没有直接读取寄存器,但是比起使用mbed API,代码行数增加很多,可见mbed对底层可以说是极致的封装。至于CMSIS-CORE,则是直接对硬件进行抽象,并提供了处理器和外围寄存器之间的接口。芯片厂商提供设备的同时都会包含CMSIS-CORE和CMSIS设备特定文件的源包。因此每一个MCU都有独立的CMSIS文件。如果有兴趣,还可以使用CMSIS CORE写一个Blinky程序。
总结:mbed API对底层的封装目的就是使得程序更大限度的“MCU无关”。也就是说,不需要使用CMSIS甚至是HAL API,而是直接通过mbed API设计程序就可以了。当然仍然有一些比较少见的情况需要使用CMSIS函数,例如__disable_irq()或者NVIC_SystemReset()。
附:【mbed API中部分数字输入输出接口函数和使用方法】
(1)数字输入:DigitalIn(PinName pin);
//Create a DigitalIn connected to the specified pin
例: DigitalIn Switchinput(USER_BUTTON);
//Setting the pin USER_BUTTON as Digital input.
if(Switchinput==1)
... ...;
else
... ...;
DigitalIn(PinName pin, PinMode mode);
//其中,mode有:PullUp, PullDown, PullNone, OpenDrain
int read(); //Read the input, represented as 0 or 1 (int)
(2)数字输出:DigitalOut(PinName pin);
DigitalOut(PinName pin, PinMode mode); 其他同理。
(3)DigitalInOut(PinName pin); 数字复用口。
(4)BusOut(PinName p0, PinName p1, PinName p2, PinName p3, PinName p4, PinName p5, PinName p6, PinName p7, PinName p8, PinName p9, PinName p10, PinName p11, PinName p12, PinName p13, PinName p14, PinName p15);
BusOut(PinName pins[16]);
(6)BusIn(PinName pins[16]);
(7)BusInOut(PinName pins[16]);