发 帖  
张飞软硬开源基于STM32 BLDC直流无刷电机驱动器开发视频套件, 👉戳此立抢👈

[经验] 【XNUCLEO-F030R8试用体验】之三:mbed开发之数字输入输出

2016-5-26 13:45:05  3038
分享
1
【XNUCLEO-F030R8试用体验】之三:mbed开发之数字输入输出
这一节来讲一下数字输入输出。
首先是数字输入输出,上一节的测试例程就是一个数字输入输出的例子,可以看到相比于库函数,mbed的库更加简洁和好用,用户不需要关心底层的代码是怎么实现的,操作了哪些寄存器,只需要关注应用本身,大大提高了开发速度,所以后面所有的程序我们都会用官方提供的库来进行开发。
来看看官方提供的数字输入输出部分的库函数:

1.png
mbed中有三个类和数字输入输出相关,分别是DigitalIn(数字管脚输入类)、DigitalOut(数字管脚输出类)、DigitalInOut(数字管脚输入输出类),学过STM32库函数的话应该明白这三个类提供的方法相当于GPIO库函数的功能,但是更简洁。
看完这些类和方法,我们试着点亮开发板上的一个LED灯。
还记得第二节用到的Keil mbed工程吗?我们从mbed官网将在线工程导出为keil 4工程,就得到了一个模板,这样就不用自己建立工程,做各种复杂的工程配置了,是不是很简单呢?至于为什么不用SMeshStudio,上节提到过,XNUCLEO的ST-LINK不支持。
现在我们打开一个空的工程,main.cpp内容很简单,如下:
#include "mbed.h"
int main()
{
}
注意不同的mbed.h文件所包含的芯片型号是不一样的,具体取决于你从在线工程导出时选择的开发板型号。
现在将main.cpp改成下面这样:
#include "mbed.h"
DigitalOut myled(LED1);  //构造DigitalOut类的一个对象myled,并初始化
int main()
{
  while(1)
  {
    myled=1;           //点亮LED
    wait(1);            //延时1s
    myled=0;            //熄灭LED
    wait(1);
  }
}
下载程序到开发板,可以看到LED1每1s闪烁一次。现在我们来分析一下代码。程序首先构造DigitalOut类的一个对象myled,初始化参数为LED1,我们从mbed API看到,构造函数形式为:DititalOut(PinName Pin);也就意味着LED1是某个引脚名,我们打开PinNames.h文件可以看到下面的定义:
typedef enum {
    PA_0 = 0x00,
    PA_1 = 0x01,
    PA_2 = 0x02,
    PA_3 = 0x03,
    PA_4 = 0x04,
    PA_5 = 0x05,
    PA_6 = 0x06,
    PA_7 = 0x07,
    PA_8 = 0x08,
    PA_9 = 0x09,
    PA_10 = 0x0A,
    PA_11 = 0x0B,
    PA_12 = 0x0C,
    PA_13 = 0x0D,
    PA_14 = 0x0E,
    PA_15 = 0x0F,
    PB_0 = 0x10,
    PB_1 = 0x11,
    PB_2 = 0x12,
    PB_3 = 0x13,
    PB_4 = 0x14,
    PB_5 = 0x15,
    PB_6 = 0x16,
    PB_7 = 0x17,
    PB_8 = 0x18,
    PB_9 = 0x19,
    PB_10 = 0x1A,
    PB_11 = 0x1B,
    PB_12 = 0x1C,
    PB_13 = 0x1D,
    PB_14 = 0x1E,
    PB_15 = 0x1F,
    PC_0 = 0x20,
    PC_1 = 0x21,
    PC_2 = 0x22,
    PC_3 = 0x23,
    PC_4 = 0x24,
    PC_5 = 0x25,
    PC_6 = 0x26,
    PC_7 = 0x27,
    PC_8 = 0x28,
    PC_9 = 0x29,
    PC_10 = 0x2A,
    PC_11 = 0x2B,
    PC_12 = 0x2C,
    PC_13 = 0x2D,
    PC_14 = 0x2E,
    PC_15 = 0x2F,
    PD_2 = 0x32,
    PF_0 = 0x50,
    PF_1 = 0x51,
    PF_4 = 0x54,
    PF_5 = 0x55,
    PF_6 = 0x56,
    PF_7 = 0x57,
    // Arduino connector namings
    A0         = PA_0,
    A1         = PA_1,
    A2         = PA_4,
    A3         = PB_0,
    A4         = PC_1,
    A5         = PC_0,
    D0         = PA_3,
    D1         = PA_2,
    D2         = PA_10,
    D3         = PB_3,
    D4         = PB_5,
    D5         = PB_4,
    D6         = PB_10,
    D7         = PA_8,
    D8         = PA_9,
    D9         = PC_7,
    D10        = PB_6,
    D11        = PA_7,
    D12        = PA_6,
    D13        = PA_5,
    D14        = PB_9,
    D15        = PB_8,
    // Generic signals namings
    LED1       = PA_5,
    LED2       = PA_5,
    LED3       = PA_5,
    LED4       = PA_5,
    USER_BUTTON = PC_13,
    SERIAL_TX  = PA_2,
    SERIAL_RX  = PA_3,
    USBTX      = PA_2,
    USBRX      = PA_3,
    I2C_SCL    = PB_8,
    I2C_SDA    = PB_9,
    SPI_MOSI   = PA_7,
    SPI_MISO   = PA_6,
    SPI_SCK    = PA_5,
    SPI_CS     = PB_6,
    PWM_OUT    = PC_7,
    // Not connected
    NC = (int)0xFFFFFFFF
} PinName;
这里定义了这块开发板所用芯片的所有用户可以使用的引脚,还定义了mbed接口引脚(A0~D15),还定义了功能引脚(LED1~PWM_OUT)。LED1连接的引脚是MCU的PA_5,LED2~LED4引脚也是PA_5。事实上,初始化参数也可以是LED2~LED5,当然也可以是引脚名称。那为什么要把4个LED定义到同一个引脚呢?因为这是我们从mbed官网导出的工程,它是以NUCLEO板为原型定义的,而NUCLEO板上只有一个用户LED(通常是LED1)。我们的XNUCLEO板上有4个用户LED,分别是LED1~LED4,分别接到了不同的引脚,可以看看电路图
2.png
如果我们初始化的时候参数改为LED2~LED4,那么实际上点亮的还是LED1,这个应该明白了吧?
为了保持程序的兼容性,官方提供的代码我们尽量不要改动,实际在初始化的时候,我们可以用引脚号作为参数。下面的程序初始化开发板上的4个LED,并组成流水灯效果。
#include "mbed.h"
DigitalOut myled1(LED1);        //初始化LED1
DigitalOut myled2(PC_9);        //初始化LED2
DigitalOut myled3(PC_8);        //初始化LED3
DigitalOut myled4(PC_5);        //初始化LED4
void mode1(void);         //模式1函数声明
void blink_mode(DigitalOuts,int n);  //闪烁模式函数声明
int main()
{
   while(1)
   {
        mode1();
   }      
}
//模式1函数,每个LED亮1s,循环点亮
void mode1(void)
{
    myled1 = 1;
    //wait(1);
    blink_mode(myled1,5);
    myled1 = !myled1;
    myled2 = 1;
    wait(1);
    myled2 = !myled2;
    myled3 = 1;
    wait(1);
    myled3 = !myled3;
    myled4 = 1;
    wait(1);
    myled4 = !myled4;
}
//LED快速闪烁n次
void blink_mode(DigitalOuts,int n)
{
    for(int i=0;i<n;i++)
    {
        s = 0;
        wait_ms(30);
        s = !s;
        wait_ms(30);
    }
}
数字输出就讲到这里,接下来看一下数字输入。
数字输入一般用于读取外部数字信息,比如按键、开关的状态。
下面写一个简单的程序,功能是当按键按下的时候,LED1状态改变,代码如下:
#include "mbed.h"
DigitalOut myled1(LED1);
DigitalIn button(USER_BUTTON,PullDown);        //这里用到了内部上拉电阻,
int main()
{
    myled1 = 1;
    while(1)
    {
        IF(button == 0)               //检测按键是否按下
            myled1 = !myled1;
    }
}
开发板上的按键接在PC_13引脚,在PinNames.h中有定义,电路图中,按键连接了外部上拉电阻,按下时会检测到低电平。如果用户需要外接按键,可以把Pin Mode改为PullUp(内部上拉)、PullDown(内部下拉)、PullNone(悬空)、OpenDrain(开漏)四种模式,这样在外接按键时就可以简化电路设计。
实际上当我们下载程序后发现,有时候按下一次,LED1的状态改变多次,有时没有改变,这主要是由于按键抖动造成的,我们可以考虑加上按键消抖,效果会好很多。下面是按键消抖的代码,在检测时加了10ms的延时。
int main()
{
    myled1 = 1;
    while(1)
    {
        if(button == 0)
        {
          wait_ms(10);
            if(button == 0)
              myled1 = !myled1;
        }
    }
}
上面的程序采用查询的方式,比较占用MCU资源,可以改成中断的形式,关于中断的部分我们后面再讲。
下节带来mbed模拟输入输出讲解。

评分

参与人数 1积分 +10 收起 理由
elecfans跑堂 + 10 您的帖子很精彩,期待您分享的下一个帖子!.

查看全部评分

rongzc 2017-5-27 16:39:33
楼主做过hexiwear手表的开发没?刚接触到mbed想请教些问题。
回复

举报

只有小组成员才能发言,加入小组>>

21个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /8 下一条

快速回复 返回顶部 返回列表