单片机很好玩9,ADC介绍,使用电脑测量电压值

在第 7 节,我们讨论了借助于单片机和传感器,电脑也能获取环境参数,例如室内的温度和湿度等信息。

不过不知道大家注意到没有,环境的温湿度应该是无时无刻都在变化的,而我们使用单片机采集的温湿度值却是离散的(大约1秒个温度值),这其实就是将模拟信息数字化的过程。

相当一部分单片机都带有 ADC 外设,ADC 的功能就是将模拟信息数字化。恰好我使用的这款 51 单片机就有 ADC 功能,本节将介绍该模块。目的是让我们的电脑具备测量电压的能力。

ADC 的全称是 Analog-to-Digital Converter,即“模拟到数字转换器”,它可以将连续不断变化的模拟信号转换为离散的数字信号,供计算机进一步处理。

将模拟信号数字化之后,才能使用计算机处理之,因为计算机本身就是数字电路组成的运算机器。

其实说将模拟信号“转换”为离散信号并不合适,更恰当的说法应该是 ADC 从模拟信号中取出“一部分”信息,请看下面右图的黑点即为 ADC 采集的数字信号。

这么看来,ADC的重要参数有两个:采样频率和精度。采样频率决定了 ADC 从模拟信号中取数据的“密集”程度,一般来说肯定越密集越好,因为这样更能还原信号的特性。精度则决定了取数据的时的精确性。

以我的 51 单片机为例,它有 8 路 10 位的 ADC,采样频率为 250K/s。所以它能从每秒的模拟信号中取出 25 万个数字信号,也就相当于在坐标系中用 25 万个点描绘出 1 秒的信号。

精度为 10 位,也就是说它利用 1~1024(2的十次方)的数字表示信号,我的 51 单片机 ADC 的参考电压信号为 5V,所以它能够表示的最小电压为 5V/1024 约为 5mV。

C语言编程单片机,实现ADC采样

现在知道了什么是 ADC,怎么使用它呢?请继续往下看。我使用的这款 51 单片机自带的 ADC 模块结构如下图所示:

可以看出,最终得到的数字信号其实是经过逐次比较的来的。下图是 ADC 相关寄存器的信息:

所以,在 keil4 中可以写出如下C语言代码:

sfr     ADC_CONTR  = 0xbc;
sfr     ADC_RES    = 0xbd;      // 高 8 位结果
sfr     ADC_LOW2   = 0xbe;      // 低 2 位结果
sfr     P1ASF      = 0x9d;      // 

我的这款 51 单片机的 ADC 转换通道与 P1 口复用,上电复位后 P1 口为弱上拉型 IO 口,我们可以通过 C语言编程设置这 8 路的任意一路做 ADC 转换。

void adc_init()
{
    P1ASF = 0xff;       // 8 个通道都开
    ADC_RES = 0;
    ADC_CONTR = ADC_POWER|ADC_SPEEDLL;
    delay_about_100ms(2);
}

上面的C语言代码中,我们将 P1ASF 赋值为 0xff,表示 P1 的 8 个 IO 口都可以作为 ADC 采样口。然后延时一段时间,等待 ADC 模块初始化。

因为我使用的这款 51 单片机是一个 8 位单片机,传送 10 位的 ADC 值需要两次,当 AUXR1.1/ADRJ = 0 时,ADC 转换结果寄存器格式如下:

当 AUXR1.1/ADRJ = 1 时,ADC 转换结果寄存器格式如下:

这么看来,获取一次 ADC 的采样值高 8 位的 C语言代码可以如下写:

// 获取高 8 位的 adc 值
BYTE get_adc_h8bit(BYTE ch)
{
    ADC_CONTR = ADC_POWER|ADC_SPEEDLL|ADC_START|ch;
    _nop_();_nop_();_nop_();_nop_();        // 等待转换完成

    while(!(ADC_CONTR & ADC_FLAG));
    ADC_CONTR &= ~ADC_FLAG;

    return ADC_RES;
}

然后将之与余下 2 位 ADC 值组合一下,就得到了一次完整的ADC采样值:

// 获取 10 位 adc
WORD get_adc_res(BYTE ch)
{
    WORD res = 0;
    res = get_adc_h8bit(ch);
    res <<= 2;
    res |= ADC_LOW2;

    return res;
}

使用电脑测量电压值

上面一小部分介绍了单片机的 ADC 模块使用方法,结合之前介绍的单片机的串口 printf,我们已经能够把外界的电压值转换为 1~1024 之间的数值并传送到电脑了,但是如何将之转换为电压值呢?

其实很简单,我的这款单片机 ADC 模块的参考电压为 5V,假设 ADC 采集的数值为 n,那么对应的电压值为:

U = n*5V / 1024

如此一来,C语言控制程序可以如下写:

void main()
{
    init_uart(9600);
    adc_init();

    while(1){
        delay_about_100ms(2);
        printf("adc: %0.2f\r\n", 5.0*((float)get_adc_res(0))/1024.0);
    }
}

使用电脑测量电压


如上图,为了方便测试,将可变电阻和定电阻串联,将单片机的 P10 口与中间相连,即可在电脑端的串口调试助手得到电压信息:

使用电压表测量该点的电压值,发现的确在 3.05V 附近:

现在调节可变电阻,发现串口传来的电压值也随之改变:

至此就实现了使用电脑测量电压,相信大家也应该明白了 ADC 的功能。

阅读更多:   单片机
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif