打印
[开发工具]

MBED基础教程(3)模拟输入输出

[复制链接]
1815|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
643757107|  楼主 | 2015-12-19 13:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

现实世界大量的信号都是模拟信号,如温度、声音、加速度等,为了能够让微处理器能够处理这些信息,我们必须先把它们转换成数字信号,即完成模数转换(Anology to Digital Converter)工作,这在微处理器是由ADC组件完成的。对于用户来说,我们在ADC应用过程中需要关心ADC的采样精度(即模拟信号被量化成多大的数值空间)、参考电压(即模拟信号的电压范围,最大不能超过参考电压)、采样频率(即ADC采样的速度)。另外我们还可能关心ADC的路数和管脚数,路数表示同时可以进行的信号采样个数,管教数表示有多少个管脚可以用户ADC的输入,由于ADC采集其间会采用多路复用技术,所以可用管脚数必然会大于ADC路数,下图是ADC工作的原理图:


对于LPC1768来说,它的采用精度是12位,即ADC的数字输出范围是(0——2^12-1),最大采样频率是200kHZ,参考电压为Vdda的输入电压,建议为3.3V,一共有8个ADC管脚服用1路ADC组件。

考虑到现实世界需要的大量信号也是模拟信号,所以微处理器在完成必要的数字运算以后还需要把数字信号转换成模拟信号输出,这就是数模转换(DAC),实际上就是ADC的逆过程。对于DAC来说,我们同样需要关心转换精度、参考电压和转换频率,考虑到DAC在应用时一般都是连续输出,所以很少采用多路复用方式,即一路DAC只和一个GPIO管脚相连。对于LPC1768来说,它的DAC转换精度是10位,即DAC的数字输入范围是(0——2^10-1),参考电压也是Vdda,只有1路DAC1个GPIO管脚。

在mbed中,用AnalogIn表示ADC模拟输入,Ana**ut表示DAC模拟输出,主要API描述如下:

类名
方法
用途
AnalogIn
AnalogIn(PinName pin)
构造函数,把pin设定成模拟输入
float read()
读取ADC采样值,返回的是0-1之间的小数,即0代表0V,1代表3.3V
unsigned short read_u16()
读取ADC采样值,返回的是整数,,范围在0到65535之间
operator float()
操作符重载,相当于float read()
Ana**ut
Ana**ut(PinName pin)
构造函数,把pin设定成模拟输出
void write(float value)
设定DAC的输出值,范围为0-1之间的小数,即0代表0V,1代表3.3V
void write_u16(unsigned short value)
设定DAC的输出值,范围为0到65535之间
float read()
返回刚才DAC的0到1的输出值
Ana**ut& operator= (float percent)
操作符重载,相当于float read()
Ana**ut& operator= (Ana**ut& rhs)
操作符重载,相当于float read()
        mbed模拟输入输出初步应用

对于xbed LPC1768来说,p15,p16,p17,p18,p19,p20可以设定成模拟输入功能,而只有P18能设定成模拟输出功能。首先,我们来体验一下mbed模拟输入的使用方法,在这里,我们使用了光敏电阻来体现外部模拟信号的变化。光敏电阻是一种随着光线强度变化而变化的电阻,标准参考值为10K欧姆,但随着光线的变暗它的电阻会升高,所以可以使用下面的电路来感知环境光的变化,其采样值越高,对应电路的采样值越大。

下面是对应的ADC采样代码,顺便还实现了类似光控开关的功能,当你把光敏电阻遮住的时候,LED1会被点亮,你还可以通过串口调试工具查看具体的采样值。

AnalogIn light(p20);

DigitalOut led1(LED1);

float lvf=0;

ushort lvu=0;

int main()

{

    while(1)

    {

        lvf=(float)light;

        lvu=light.read_u16();

        printf("light adc count is %f , %d  \n",lvf,lvu);

        wait(0.5);

        if (lvf<0.7)

            led1=1;

        else

            led1=0;

    }


}

DAC模拟输出的体验相对来说比较困难,很多人都想到了LED的亮度,但实际上由于LED有导通电压,所以可以展现的亮度范围有限,所以效果并不明显,下面是对应的连接图和代码:

Ana**ut led(p18);

float ledvalue=1.0;

int main()

{

    while (1)

    {

        while(1)

        {

            led.write(ledvalue);

            wait (0.5);

            ledvalue=ledvalue-0.1;

            if (ledvalue<0.1)

                break;

        }

    }


}

当然,我们也可以直接将DAC输出与ADC输入相连,再通过串口输出查看DAC和ADC的效果,我们只需要把p18,p19相连即可,相应的代码如下:

Ana**ut ao(p18);

AnalogIn ai(p19);

float aoValue=0;

float aiValue=0;

int main()

{

    while (1)

    {

        while(1)

        {

            aoValue=aoValue+0.01;

            ao.write(aoValue);

            aiValue=ai.read();

            wait (0.5);

            printf("Aout is %f ,A in is %f, adc value is %f \n",aoValue, aiValue, aiValue*3.3);

        }

    }


}

     下面是它对应的输出片断:

Aout is 0.080000 ,A in is 0.077656, adc value is 0.256264

Aout is 0.090000 ,A in is 0.088156, adc value is 0.290916

Aout is 0.100000 ,A in is 0.107204, adc value is 0.353773

Aout is 0.110000 ,A in is 0.116484, adc value is 0.384396

Aout is 0.120000 ,A in is 0.126252, adc value is 0.416630

Aout is 0.130000 ,A in is 0.136020, adc value is 0.448864


Aout is 0.140000 ,A in is 0.137241, adc value is 0.452894  


沙发
玛尼玛尼哄| | 2015-12-20 23:58 | 只看该作者
是对所用支持的芯片都有效吗,还是只是针对这一款单片机有效。我之前试过STM32F411的,确实是很给力。

使用特权

评论回复
板凳
643757107|  楼主 | 2015-12-22 11:33 | 只看该作者
AnalogIn light(p20);
DigitalOut led1(LED1);
float lvf=0;
ushort lvu=0;
int main()
{
    while(1)
    {
        lvf=(float)light;
        lvu=light.read_u16();
        printf("light adc count is %f , %d  \n",lvf,lvu);
        wait(0.5);
        if (lvf<0.7)
            led1=1;
        else
            led1=0;
    }
就这么长就搞定了,是不是觉得很简单

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

213

主题

3784

帖子

11

粉丝