ARM40-A5应用程序——SPI应用程序(AD7689)

2017.9.15

版权声明:本文为博主原创文章,允许转载。

 

一、SPI应用程序的C语言源码

        文件名为 test_ad7689.c,代码见本文的最后。

二、交叉编译

         arm-none-linux-gnueabi-gcc -o test_ad7689 test_ad7689.c -static

三、执行程序与测试

        (1)无AD采样芯片AD7689情况下的测试

        硬件上将spidev32765.0对应的SPI_MOSI与SPI_MISO这两个信号线连接在一起,直连即可,无须串接电阻。 

        将交叉编译得到的 test_ad7689 文件拷贝到ARM40-A5板中,执行程序:

                ./test_ad7689

        可以看到打印为:

root@ARM40:~# ./test_ad7689
in0 get = 3d49 
in1 get = 3dc9 
in2 get = 3e49 
in3 get = 3ec9 
in4 get = 3f49 
in5 get = 3fc9 
in6 get = 3c49 
in7 get = 3cc9 
.....  // 会循环打印

 

        (2)有AD采样芯片AD7689情况下的测试

        有AD采样芯片AD7689情况下,将交叉编译得到的 test_ad7689 文件拷贝到ARM40-A5板中,执行程序:

                ./test_ad7689

        可以看到打印为(AD7689的IN上电压不同时,显示的数据会不同):

root@ARM40:~# ./ad7689for
in0 get = 0 
in1 get = 0 
in2 get = 0 
in3 get = 0 
in4 get = 0 
in5 get = 0 
in6 get = 0 
in7 get = 3fff 

.....  // 会循环打印

四、数据处理

        AD采样的数据往往需要经过数字滤波处理,推荐采用一阶低通滤波或者算术平均滤波。

 

参考文章:

Documentation/spi/spidev_test.c

Linux内核源码中的示例spidev_test.c

http://www.aiweibang.com/yuedu/41098585.html

【Linux公开课】用户态SPI编程

【滤波器学习笔记】一阶RC低通滤波 

https://blog.csdn.net/qq_27334499/article/details/52186336

荟聚计划:共商 共建 共享 Grant 

 

附:

(1)test_ad7689.c 的代码

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define IN0             (0x3c49 << 2)           // IN0 4.096V, AD7689 Configuration Register is 14bit
#define IN1             (0x3cc9 << 2)           // IN1 4.096V
#define IN2             (0x3d49 << 2)
#define IN3             (0x3dc9 << 2)
#define IN4             (0x3e49 << 2)
#define IN5             (0x3ec9 << 2)
#define IN6             (0x3f49 << 2)
#define IN7             (0x3fc9 << 2)
#define M               8                       // channel num

const char *device = "/dev/spidev1.0";
uint32_t speed = 10000000;                      // 10MHz
uint16_t delay = 0;
uint16_t ad7689_cfg[M] = {IN2, IN3, IN4, IN5, IN6, IN7, IN0, IN1, };

/*
 * Error termination
 */
static void pabort(const char *s)
{
        perror(s);
        abort();
}

/*
 * configure channel & get ad data
 * cfg_data is Configuration Register << 2
 * rxbuf return ad7689 Channels data
 */
uint16_t get_ad_data(int fd,int cfg_data)
{
        int ret;
        uint16_t txbuf = cfg_data;
        uint16_t rxbuf = 0;

        struct spi_ioc_transfer tr = {
                .tx_buf = (unsigned long)&txbuf,                // (n+1) channel Configuration
                .rx_buf = (unsigned long)&rxbuf,                // (n-1) channel data
                .len = sizeof(txbuf),
                .delay_usecs = delay,
                .speed_hz = speed,
                .bits_per_word = 16,
        };

        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);               // send spi_ioc_transfer to spidev
        if(ret < 1)
                pabort("can't send spi message");

        return rxbuf;
}

/*
 * open spidev and set it
 */
int spi_set(const char *dev_spi)
{
        int fd_spi;
        int ret = 0;
        uint8_t bits = 16;
        uint32_t mode = 0;

        fd_spi = open(dev_spi, O_RDWR);
        if (fd_spi < 0)
                pabort("can't open device");

        /*
         * spi mode
         */
        ret = ioctl(fd_spi, SPI_IOC_WR_MODE, &mode);
        if (ret == -1)
                pabort("can't set spi mode");

        ret = ioctl(fd_spi, SPI_IOC_RD_MODE, &mode);
        if (ret == -1)
                pabort("can't get spi mode");

        /*
         * max speed hz
         */
        ret = ioctl(fd_spi, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
        if (ret == -1)
                pabort("can't set max speed hz");

        ret = ioctl(fd_spi, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
        if (ret == -1)
                pabort("can't get max speed hz");

        /*
         * set spi bits
         */
        ret = ioctl(fd_spi, SPI_IOC_WR_BITS_PER_WORD, &bits);
        if (ret == -1)
                pabort("can't set bits per word");

        ret = ioctl(fd_spi, SPI_IOC_RD_BITS_PER_WORD, &bits);
        if (ret == -1)
                pabort("can't get bits per word");

//      printf("mode=0x%x,speed=%d,bits=0x%x\n", mode, speed, bits);

        return fd_spi;
}

int main(int argc, char *argv[])
{
        int i;
        int fd;
        uint16_t data[M];
        fd = spi_set(device);
        get_ad_data(fd, ad7689_cfg[6]);
        get_ad_data(fd, ad7689_cfg[7]);

        while(1)
        {
                for(i=0;i<M;i++) {
                        data[i] = get_ad_data(fd, ad7689_cfg[i]);       // use about 650us for 8 channels
                }

                for(i=0;i<M;i++) {
                        printf("in%d get = %x \n",i,data[i]);
                }

                printf("\n");
                usleep(50000);
        }

        close(fd);
}

 

 

 

 

 

 


 

Logo

更多推荐