anywill 发表于 2016-10-10 08:36:02

转发:ARM®mbed OS入门开发(三 A)GPIO

本帖最后由 anywill 于 2016-10-12 12:01 编辑

ARM®mbed OS入门开发(三)2016-09-14 Summerain 小白学嵌入式
【管脚定义】上一期介绍了简单的数字输入输出,我们知道了mbed API对底层的高度封装。程序开发者想要知道可以使用哪些管脚,例如上一期的Blinky例子中Pin名称LED1的使用,可以查看mbed.org对这款开发板的Nucleo features的介绍,也可以在mbed library目录下targets/hal/对应开发板下面的PinNames.h的头文件下查看:
typedef enum {    ... ... ...
    // Arduino connector namings
    ... ... ...// 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   = PB_3,
    // Not connected
    NC = (int)0xFFFFFFFF
} PinName;可以看到LED1,LED2,LED3,LED4其实都是同一个管脚PA_5,所以使用任何一个名称均是对PA_5进行操作。
【二】Analog Input and Output由于手头没有电位器(可变电阻器)调节输入电压,没有示波器观察输出波形,这部分就只有理论学习。1. ADC: Analog ---> Digital即:Voltage---> Binary Output对于输入电压范围0~3.3V, 12-bit的ADC,其精度为3.3/(2^12), 约0.8mV。那么最坏情况下的量化误差为0.4mV。采样频率:Nyquist
AnalogIn API:
AnalogIn(PinName pin);//构造函数,指定作为模拟输入的pin口float read();
//读取输入电压,返回0.0~1.0之间的float值,其中,0代表0V,1代表3.3V
unsigned short read_u16();
//返回unsigned short in the range ,范围在0到65535之间
例:
AnalogIn analog_value(A0);
float meas;
meas = analog_value;//等同于meas=analog_value.read();2. DAC: Digital--->AnalogAnalogOut API:AnalogOut(PinName pin);
void write(float value);
//写入 范围之间的值,按照百分比设置输出电压,0.25对应输出电压值为0.25×3.3Vvoid write_u16(unsigned short value);//unsigned short in the range
【三】Pulse width modulation(PWM)脉宽调制1. 设置PWM周期period,决定PWM波形的频率。
2. 设置PWM波形的占空比duty-cycle,从而调平均电压。duty_cycle=100% * (pulse on time) / (pulse period)PWM API:PwmOut(PinName pin);//把管脚pin设成PwmOut输出管脚void write(float value);//设置输出 duty-cycle,范围在0到1之间,0表示在一个时钟周期内全部都是低电平,1表示全部都是高电平float read();
void period(float seconds);//设置PWM period,即时钟周期,单位秒
void period_ms(int ms);
void period_us(int us);
void pulsewidth(float seconds);//设定PWM输出的脉宽,相当于设定PWM的输出值,假设时钟周期period是10ms,脉宽是5ms,那就相当于输出占空比(duty-cycle)为0.5,这里的单位是秒void pulsewidth_ms(int ms);
void pulsewidth_us(int us);请看下面的例子:#include "mbed.h"
PwmOut PWM1(LED1);//创建PWM1对LED1端口调制
int main() {PWM1.period(0.010);// PWM period = 10 ms 即输出频率为100Hz pulse;
PWM1=0.5;
// duty cycle= 50%,相当于平均电压为3.3×0.5V(或者是理论上的LED1=0.5); }
【四】GPIO Interrupt学过微机原理的同学都知道,可以通过查询和中断方式传送数据和处理事件。而查询方式传送数据占用CPU大量时间,所以中断方式判断引脚状态处理事件效率较高。GPIO中断是微处理器中断系统中最简单最常用的中断类型,它可以让用户在某个管脚状态发生特定的变化(边沿触发)时执行相应的代码。需要注意的是,并不是所有的GPIO管脚都具备中断处理能力。GPIO Interrupt API:InterruptIn(PinName pin);
//把pin管脚设成中断处理管脚int read();
//读取管脚的当前状态void rise(void (*fptr)(void));
//上升沿触发 InterruptFunction
void fall(void (*fptr)(void));
//下降沿触发InterruptFunction
void mode(PinMode pull);
//设置管脚模式,上升沿设置为 Pulldown, 下降沿 PullUp
__disable_irq();//禁止所有可屏蔽中断;
__enable_irq();//允许所有未屏蔽中断;
void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority):
//设置中断的优先级,IRQn表示需要设置的中断号,后面表示优先级,数字越小表示优先级越高。
下面是实例:#include "mbed.h"
Serial pc(USBTX,USBRX);
InterruptIn btn(USER_BUTTON);
Timer mytimer;
int falltime;
int risetime;
void fallfunc()
{
    falltime=mytimer.read_us();
}
void risefunc()
{
    risetime=mytimer.read_us();
    pc.printf("You press button for %d us \n",risetime-falltime);
}
int main() {
    mytimer.start();
    btn.fall(&fallfunc);    //按键上升沿读取当前时间    btn.rise(&risefunc);    //下降沿再次读取当前时间并输出时间间隔    while (1);
}
Tip: 使用GPIO中断的时候要确认pin端口默认接上拉电阻还是下拉电阻,如果是上拉电阻,那么默认就是高电平,此时则选择下降沿触发。反之则使用上升沿触发。



stary666 发表于 2016-10-10 09:07:23

顶一下,,,,,,

zhangdaijin 发表于 2016-10-10 09:32:31

:D:D:D:D:D:D:D

slotg 发表于 2016-10-10 09:42:06

很不错的帖子,感谢分享。

xyx365 发表于 2016-10-10 10:54:52

不错的教程

andypanfan 发表于 2016-10-23 00:16:14

很好的东西!!!!:D:D:D:D

fdsfdsf344 发表于 2018-9-15 16:05:07

谢谢分享

zhyanglyuee 发表于 2019-5-13 11:21:40

感谢分享

幻影21 发表于 2019-5-14 10:18:55


谢谢分享

ksadk155 发表于 2019-5-18 11:44:19

楼主请问mbed 通过什么确定按键按钮是否按下

Jaason 发表于 2020-3-22 11:31:28

很不错的帖子,感谢分享。
页: [1]
查看完整版本: 转发:ARM®mbed OS入门开发(三 A)GPIO