单片机/MCU论坛
直播中

jf_1137202360

8年用户 1361经验值
擅长:嵌入式技术
私信 关注
[文章]

【HD-G2UL-EVM开发板体验】ADC测试-虚拟示波器实现

75a4cb24a56ec28cc200a093f8c386f1

前言
本板引出了两路12bits ADC 模拟采集通道,加上之前测的串口的通讯,可以将ADC才机制发送到上位机,通过上位机进行曲线显示,即实现了简单的虚拟示波器。
图片10.png
过程代码
两路的ADC对应设备如下,直接读对应的文件即可获取到ADC值
图片1.png
代码如下
引用: int adc_get(int ch)

{

    int channel;

    char cmd[128]={0};

    FILE *stream = NULL;

    char adc_v[1024] = {0};

    snprintf(cmd, sizeof(cmd),"cat /sys/bus/iio/devices/iio\:device0/in_voltage%d_raw",ch);

    stream = popen(cmd,"r");

    fread(adc_v,1,sizeof(adc_v),stream);

    pclose(stream);

    //printf("adc_channel%d: %s",channel,adc_v);

    return atoi(adc_v);

}

在上一篇测试串口的基础上完整代码如下
引用: #include       /* Standard input/output */

#include       /* File control definitions */

#include

#include

#include      /* POSIX terminal control definitions */

#include    /* Time structures for select() */

#include      /* POSIX Symbolic Constants */

#include

#include       /* Error definitions */

#include

#include

#include



#define  CMSPAR 010000000000  



#define SERIAL_FLUSH_TX     1      

#define SERIAL_FLUSH_RX     2



#define SERIAL_PARITY_NO        0

#define SERIAL_PARITY_ODD       1

#define SERIAL_PARITY_EVENT     2

#define SERIAL_PARITY_MARK      3

#define SERIAL_PARITY_SPACE     4



#define SERIAL_STOPBIT_ONE      1

#define SERIAL_STOPBIT_TWO      2



static int serial_fd  = -1;



struct termios old_tios;



int uart_read(uint8_t* buffer,uint32_t len,uint32_t timeout);

int uart_write(uint8_t* buffer,uint32_t len);



static void serial_print_buf(unsigned char *buf,int len) /* 打印输出 */

{

    int i;

    for(i=0;i
        printf("%02X ",buf);

    printf("n");

}



char *get_serial_dev_name(char *serial_name)   /* 获取串口名称 */

{

    if (strcasecmp(serial_name, "COM2") == 0)   /* 传入参函数是COM2(不区分大小写),则返回串口对应的设备节点/dev/ttymxc1 */

        return "/dev/ttymxc1";

    else if (strcasecmp(serial_name, "COM3") == 0)

        return "/dev/ttymxc2";

    else if (strcasecmp(serial_name, "COM4") == 0)

        return "/dev/ttymxc3";

    else if (strcasecmp(serial_name, "COM5") == 0)

        return "/dev/ttymxc4 ";

    else

        //return NULL;

        return serial_name;

}



static int termios_init(struct termios *tios,int baud,int parity,int data_bits,int stop_bits) //串口 传入波特率,校验位,数据位,停止位。

{

    speed_t baud_rate;



    if (tios == NULL)

        return -1;



    tios->c_line  = 0;



    tios->c_cc[VMIN ] = 0;

    tios->c_cc[VTIME] = 0;



    /* configure the input modes... */

    tios->c_iflag =  IGNBRK | IGNPAR | INPCK;



    /* configure the output modes... */

    tios->c_oflag = 0;     /* enable implementation-defined output processing */

    /* configure the control modes... */

    tios->c_cflag = CREAD | CLOCAL;

   

    if (data_bits == 5)      //对传入的数据位进行判断

        tios->c_cflag |= CS5;

    else if (data_bits == 6)

        tios->c_cflag |= CS6;

    else if (data_bits == 7)

        tios->c_cflag |= CS7;

    else if (data_bits == 8)

        tios->c_cflag |= CS8;

    else

        return -1;



    if (stop_bits == 1)     //对传入的停止位进行判断

        tios->c_cflag &=~ CSTOPB;

    else if (stop_bits == 2)

        tios->c_cflag |= CSTOPB;

    else

        return -1;



    if(parity == 0)         //校验位: 0:无校验 1:奇校验 2:偶校验 3:mark parity 4:space parity

    { /* none */

        tios->c_cflag &=~ PARENB;

        tios->c_cflag &=~ PARODD;

    }

    else if(parity == 2)

    { /* even */

        tios->c_cflag |= PARENB;

        tios->c_cflag &=~ PARODD;

    }

    else if(parity == 1)

    { /* odd */

        tios->c_cflag |= PARENB;

        tios->c_cflag |= PARODD;

    }

    else if (parity == 3)/* 2008.12.17 add for support mark and space parity */

    {

        /* mark */

        tios->c_cflag |= PARENB;

        tios->c_cflag |= CMSPAR;

        tios->c_cflag |= PARODD;

    }

    else if (parity == 4)

    {

        /* space */

        tios->c_cflag |= PARENB;

        tios->c_cflag |= CMSPAR;

    }

    else

        return -1;



    /* configure the local modes... */

    tios->c_lflag = 0;    /* enable implementation-defined input processing   */



    /* Set the baud rate */

    switch(baud)            //对传入的波特率进行判断

    {

        case 110:

            baud_rate = B110;

            break;

        case 300:

            baud_rate = B300;

            break;

        case 600:

            baud_rate = B600;

            break;

        case 1200:

            baud_rate = B1200;

            break;

        case 2400:

            baud_rate = B2400;

            break;

        case 4800:

            baud_rate = B4800;

            break;

        case 9600:

            baud_rate = B9600;

            break;

        case 19200:

            baud_rate = B19200;

            break;

        case 38400:

            baud_rate = B38400;

            break;

        case 57600:

            baud_rate = B57600;

            break;

        case 115200:

            baud_rate = B115200;

            break;

        case 230400:

            baud_rate = B230400;

            break;

        case 460800:

            baud_rate = B460800;

            break;

        case 576000:

            baud_rate = B576000;

            break;

        case 921600:

            baud_rate = B921600;

            break;



        default:

            return -1;

    }



    if ((cfsetispeed(tios, baud_rate) < 0) ||(cfsetospeed(tios, baud_rate) < 0))

        return -1;

    return 0;

}



//return serial fd, error return -1

int serial_open(char *serial_name, int baud,int parity,int data_bits,int stop_bits,int timeout)  //打开串口

{

    struct termios settings;

    int fd;

    char *serial_dev_name;



    if (serial_fd >= 0)

        return 0;

    if (termios_init(&settings, baud,parity,data_bits,stop_bits) < 0)

        return 0;



   

    serial_dev_name = get_serial_dev_name(serial_name);

    if (serial_dev_name == NULL)

    {

        fprintf(stderr, "invalid serial name:%sn", serial_name);

        return 0;

    }



    if((fd = open(serial_dev_name, O_RDWR | O_NOCTTY | O_NDELAY))< 0)

        return 0;



    if(tcgetattr(fd, &old_tios) < 0)

    {

        close(fd);

        return 0;

    }



    if(tcsetattr(fd, TCSANOW, &settings) < 0)

    {

        close(fd);

        return 0;

    }



    serial_fd = fd;

    return 1;

}



int serial_close()      //关闭串口

{

    if (serial_fd < 0)

        return 0;

    tcsetattr(serial_fd, TCSANOW, &(old_tios));

    close(serial_fd);

    serial_fd = -1;

   

    return 1;

}



int serial_flush(int flag)

{

    if (serial_fd < 0)

        return 0;



    if (flag == SERIAL_FLUSH_TX)

        tcflush(serial_fd,TCOFLUSH);

    else if (flag == SERIAL_FLUSH_RX)

        tcflush(serial_fd,TCIFLUSH);

    else if (flag == (SERIAL_FLUSH_RX|SERIAL_FLUSH_TX) )

        tcflush(serial_fd,TCIOFLUSH);

    return 1;

}



//return 1: poll ok, 0: timeout, -1: error

int serial_poll(int timeout)

{

    int fd = serial_fd;

   

    fd_set rfds;

    struct timeval tv;

    int sel_res;



    FD_ZERO(&rfds);

    FD_SET(fd, &rfds);

    tv.tv_sec = timeout/1000;

    tv.tv_usec = (timeout % 1000)*1000;

    return select(fd + 1, &rfds, NULL,NULL,&tv);

}



int uart_read(uint8_t* buffer,uint32_t len,uint32_t timeout)

{

    while(serial_poll(timeout)>0)   //当另一端传入数据时会接收到数据

    {

        return read(serial_fd,buffer,len);

    }

}



int uart_write(uint8_t* buffer,uint32_t len)

{

    write(serial_fd,buffer,len);

}





int adc_get(int ch)

{

    int channel;

    char cmd[128]={0};

    FILE *stream = NULL;

    char adc_v[1024] = {0};



    snprintf(cmd, sizeof(cmd),"cat /sys/bus/iio/devices/iio\:device0/in_voltage%d_raw",ch);

    stream = popen(cmd,"r");

    fread(adc_v,1,sizeof(adc_v),stream);

    pclose(stream);

    //printf("adc_channel%d: %s",channel,adc_v);

    return atoi(adc_v);

}



int main(int argc, char *argv[])

{

    int fd;

    uint8_t recv_buffer[128];

    int i, ret;

    uint8_t send_buffer[128];



    if (argc != 3)    //需要传入串口对应的设备名

    {

        fprintf(stderr, "usage:serialtest com_port baudn");

        return -1;

    }



    ret = serial_open(argv[1], atoi(argv[2]), SERIAL_PARITY_NO, 8, SERIAL_STOPBIT_ONE, 1000); //调用上面封装好的打开串口函数 传入设备名,波特率,校验位,数据位,停止位以及超时时间

    if (ret == 0)   //打开失败

    {

        fprintf(stderr, "open serial failedn");

        return -1;

    }

    memset(recv_buffer,0x55,sizeof(recv_buffer));

    while(1)

    {

        //int len = 0;

        //if((len = uart_read(recv_buffer,sizeof(recv_buffer),100)) > 0)

        //{

        //  uart_write(recv_buffer,sizeof(recv_buffer));

        //}

        int adc = adc_get(1);

        snprintf(send_buffer,sizeof(send_buffer),"/* %d */rn",adc);

        uart_write(send_buffer,strlen(send_buffer));

    }

    serial_close();

   

    return 0;

}

上位机
https://serial-studio.github.io/下下载安装Serial Studio
点击JSON编辑器按如下设置
图片2.png
点击添加组别
图片3.png
添加数据集
图片4.png
按如下设置点击申请
图片5.png
连接串口
图片6.png
控制台可以看到打印的值
图片7.png
仪表盘可以看到曲线
图片8.png
测试
使用滑动变阻分压得到模拟电压,旋转旋钮可以看到电压变化曲线。
图片9.png
总结
以上测试了ADC的采集,由于没有精度较高的DAC源和电压测量设备,所以就不测试其精度了。通过上位机的曲线显示,实现了简单的虚拟示波器的功能。

更多回帖

×
20
完善资料,
赚取积分