ELFboard学习(六):ADC

ADC简介

模数转换器(ADC)是数字电子设备中不可或缺的组件,它能够将模拟信号转换为数字信号,以便于计算机或微处理器进行处理。ADC的作用是将连续的模拟信号转换为离散的数字信号,这一过程涉及到对信号进行采样、量化以及编码三个步骤。采样是将连续时间信号转换为离散时间信号的过程,量化是将离散幅度值进行近似取整的过程,而编码则是将量化后的结果转换为二进制码。ADC的性能指标包括分辨率、量化误差、动态范围、采样速率等。随着科技的不断发展,ADC的应用越来越广泛,不仅应用于音频、视频等消费电子产品中,还涉及到通信、医疗、工业控制等领域。
ELFboard上板载了一个可调电阻,可用于测试 ADC 功能。

shell命令查看ADC原始值

shel
从图中可以看出,当前ADC采集到的数值为1153,通过调节滑动变阻器,能够改变ADC采集到的数值,但该数值并不是电压值,若要获取电压值则还需要进行一定的转换。

C编程读取ADC原始值并转换为电压值

在/sys/bus/iio/devices/iio:device0/文件夹下,其中in_voltage5_raw 文件中存储的是ADC采集到的原始值, in_voltage_scale 文件中存储的是电源规模值。若要获取实际的电压值(V),只需将两者相乘再除以1000即可。

这里我们分别使用了系统调用函数和C语言标准库函数进行了编程实现,并使用利用 atoi 和 atof 库函数进行数据类型转换,具体代码如下:

  • 系统调用函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fcntl.h>
#include <unistd.h>

#define voltage5_raw "/sys/bus/iio/devices/iio:device0/in_voltage5_raw"
#define voltage_scale "/sys/bus/iio/devices/iio:device0/in_voltage_scale"

int main(int argc, char *argv[])
{
    int raw_fd, scale_fd;
    int res;
    char buff[20];
    int raw;
    double scale;

    while(1){
        /* 1.打开文件 */
        raw_fd = open(voltage5_raw, O_RDONLY);
        if(raw_fd < 0){
            printf("open raw_fd failed!\n");
            return -1;
        }

        scale_fd = open(voltage_scale, O_RDONLY);
        if(scale_fd < 0){
            printf("open scale_fd failed!\n");
            return -1;
        }

        /* 2.读取文件 */
        // rewind(raw_fd);   // 将光标移回文件开头
        res = read(raw_fd, buff, sizeof(buff));
        raw = atoi(buff);

        memset(buff, 0, sizeof(buff));
        // rewind(scale_fd);   // 将光标移回文件开头
        res = read(scale_fd, buff, sizeof(buff));
        scale = atof(buff);

        printf("ADC原始值:%d,电压值:%.3fV\r\n", raw, raw * scale / 1000.f);

        close(raw_fd);
        close(scale_fd);
        sleep(1);
    }

    return 0;
}
  • 标准库函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>

#define voltage5_raw "/sys/bus/iio/devices/iio:device0/in_voltage5_raw"
#define voltage_scale "/sys/bus/iio/devices/iio:device0/in_voltage_scale"

int main(int argc, char *argv[])
{
    FILE *raw_fd, *scale_fd;
    int len1, len2, res;
    char data[20];
    int raw;
    double scale;

    while(1){
        /* 1.打开文件 */
        raw_fd = fopen(voltage5_raw, "r");
        if(raw_fd == NULL){
            printf("open raw_fd failed!\n");
            return -1;
        }

        scale_fd = fopen(voltage_scale, "r");
        if(scale_fd == NULL){
            printf("open scale_fd failed!\n");
            return -2;
        }

        /* 2.读取文件 */
        // rewind(raw_fd);   // 将光标移回文件开头
        res = fscanf(raw_fd, "%s", data);
        raw = atoi(data);

        memset(data, 0, sizeof(data));
        rewind(scale_fd);   // 将光标移回文件开头
        res = fscanf(scale_fd, "%s", data);
        scale = atof(data);


        printf("ADC原始值:%d,电压值:%.3fV\r\n", raw, raw * scale / 1000.f);

        fclose(raw_fd);
        fclose(scale_fd);
        sleep(2);
    }

    return 0;
}

在程序中,我们首先分别读取了in_voltage5_raw和in_voltage_scale中的数据,并分别使用atoi和atof将读取到的ADC原始数据和电源规模值转换成int类型和double类型的数据,之后通过计算得到ADC采集到的电压值。实验效果如下:
在这里插入图片描述

微信公众号:MrFeng的学习笔记
关注可了解更多的嵌入式教程及技巧。问题或建议,请公众号留言。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
这两个Verilog代码可以放在一个.v文件中吗:1.`timescale 1ns / 1ps module Top(clk,sw,led,flag, ADC_sdata, ADC_sclk,ADC_csn,slec_wei,slec_duan); input clk; input [3:0]sw; output reg [7:0] led; input flag; input ADC_sdata; output ADC_sclk,ADC_csn; output [7:0] slec_wei; output [7:0] slec_duan; wire [11:0] adc_res; wire adc_valid; wire [19:0]cout; always@(posedge clk)if(adc_valid) led<=adc_res[11:4]; PmodAD1 U0( .clk(clk), .rst(1’b0), .ADC_sdata(ADC_sdata), .ADC_sclk(ADC_sclk), .ADC_csn(ADC_csn), .adc_res(adc_res), .adc_valid(adc_valid) ); data_ad_pro U1( .sys_clk(clk), .rst_n(1’b1), .pre_data(adc_res[11:4]), .cout(cout) ); display U2( .sys_clk(clk), .rst_n(1’b1), .cout(cout), .sw(sw), .flag(flag), .slec_wei(slec_wei), .slec_duan(slec_duan) ); endmodule ———————2.module PmodAD1( clk,rst, ADC_sdata,ADC_sclk,ADC_csn,adc_res,adc_valid); input clk,rst, ADC_sdata; output reg ADC_sclk,ADC_csn; output reg [11:0] adc_res; output reg adc_valid; reg [7:0] cntr; always@(posedge clk) if(rst)cntr<=0;else if(cntr==34)cntr<=0;else cntr<=cntr+1; always@(posedge clk) case (cntr) 0: ADC_csn<=0; 33: ADC_csn<=1; endcase always@(posedge clk) case(cntr) 34,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,33:ADC_sclk<=1; default ADC_sclk<=0; endcase always@(posedge clk) case(cntr) 8: adc_res[11]<= ADC_sdata; 10:adc_res[10]<= ADC_sdata; 12:adc_res[9]<= ADC_sdata; 14:adc_res[8]<= ADC_sdata; 16:adc_res[7]<= ADC_sdata; 18:adc_res[6]<= ADC_sdata; 20:adc_res[5]<= ADC_sdata; 22:adc_res[4]<= ADC_sdata; 24:adc_res[3]<= ADC_sdata; 26:adc_res[2]<= ADC_sdata; 28:adc_res[1]<= ADC_sdata; 30:adc_res[0]<= ADC_sdata; endcase always@(posedge clk)adc_valid<=cntr==32; endmodule
06-01

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxfeng~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值