Archives mensuelles : septembre 2014

image_pdfimage_print

Use a DAC MCP4822 with the ARIA G25

On the ARIA G25, I use the following C code to control the MCP4822 using the SPI interface :

#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 ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

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

static const char *device = « /dev/spidev0.0 »;
static uint8_t mode = 3;
static uint8_t bits = 8;
static uint32_t speed = 1000000;
static uint16_t delay;

void affichebin16(unsigned n)
{
unsigned bit = 0 ;
unsigned mask = 1 ;
int i;
for (i = 0 ; i < 16 ; ++i)
{
bit = (n & mask) >> i ;
printf(« %d », bit) ;
mask <<= 1 ;
}
printf(« \n »);
}

void affichebin8(unsigned n)
{
unsigned bit = 0 ;
unsigned mask = 1 ;
int i;
for (i = 0 ; i < 8 ; ++i)
{
bit = (n & mask) >> i ;
printf(« %d », bit) ;
mask <<= 1 ;
}
printf(« \n »);
}

static void transfer(int fd, int sortie, int val)
{
int ret;

affichebin16(val);

uint16_t A;
if ( sortie == 1)
A=( val & 0b0000111111111111) | 0b0011000000000000;
else
A=( val & 0b0000111111111111) | 0b1011000000000000;
affichebin16(A);

uint8_t SH = (A & 0xFF00) >> 8; // MSB (bits 9 à 16)
uint8_t SL = A & 0x00FF; // LSB (bits 1 à 8)

printf(« bits 1 à 8 =\n »);
affichebin8(SL);
printf(« bits 9 à 16 =\n »);
affichebin8(SH);

uint8_t tx[] = {
//5V
SH,SL
// 2048 2.5
//0x38,0x00
//0V
//0x30,0x00
};

uint8_t rx[ARRAY_SIZE(tx)] = {0, };

struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = 0,
.bits_per_word = 0,
};

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret == 1)
pabort(« can’t send spi message »);

for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
if (!(ret % 6))
puts(«  »);
printf(« %.2X « , rx[ret]);
}
puts(«  »);
}

int main(int argc, char *argv[])
{
int ret = 0;
int fd;

int val=atoi(argv[2]);
int sortie=atoi(argv[1]);

printf(« val=%d\tsortie=%d\n »,val,sortie);

fd = open(device, O_RDWR);
if (fd < 0)
pabort(« can’t open device »);

ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort(« can’t set spi mode »);

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort(« can’t get spi mode »);

ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort(« can’t set bits per word »);

ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort(« can’t get bits per word »);

ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort(« can’t set max speed hz »);

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort(« can’t get max speed hz »);

printf(« spi mode: %d\n », mode);
printf(« bits per word: %d\n », bits);
printf(« max speed: %d Hz (%d KHz)\n », speed, speed/1000);

transfer(fd,sortie,val);

close(fd);

return ret;
}

Once compiled the parameters are the output (0 or 1) and the byte to convert.