ad7689在arm Linux imx6ul上的使用
ad7689 是一款8通道adc采集芯片,使用spi接口通信。
移植到Linux上使用用的是内核的spidev驱动,找到 /dev/spidev1.0 设备是我们 用的总线接口。
ad7689 直接读取数据便是1-8的通道。
在读取ad7689的数据时需要配置spi 的,这里配置成默认的0模式 10MHZ
将第0路接地
打印
in0 get = 0
in1 get = 1bb
in2 get = 2079
in3 get = 9b
in4 get = 20a2
in5 get = 20a3
in6 get = 2059
in7 get = 94
源码如下
#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
#define SPI_DEVICE "/dev/spidev1.0"
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=%d,speed=%d,bits=%d\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] >> 2);
// printf("in%d get = %x \n",i,data[i]);
}
printf("\n");
sleep(2);
}
close(fd);
}