Bonjour a tous,
Pour réaliser une conversion "Digital-to-Analog", je me suis doté d'un DAC MCP4922 utilisant le Bus SPI pour communiquer.
Problème: c'est la première fois que j'utilise du SPI, je me suis donc lancer à la recherche de tuto mais cela reste peu évident à comprendre pour l'instant.
je suis tombé sur un code qui me parait fonctionnelle, et je souhaiterai que l'on m'explique ( Si possible ) quelques points afin que je puisse identifier ceux qui m'intéresse ( pour me focaliser dessus).
voici le code entier:
#define DATAOUT 11//MOSI
//#define DATAIN 12//MISO - not used, but part of builtin SPI
#define SPICLOCK 13//sck
#define SLAVESELECT 10//ss
void setup()
{
byte clr;
pinMode(DATAOUT, OUTPUT);
// pinMode(DATAIN, INPUT);
pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
digitalWrite(SLAVESELECT,HIGH); //disable device
SPCR = (1<<SPE)|(1<<MSTR);
clr=SPSR;
clr=SPDR;
//delay(10);
}
void write_value(uint16_t sample)
{
uint8_t dacSPI0 = 0;
uint8_t dacSPI1 = 0;
dacSPI0 = (sample >> 8) & 0x00FF;
dacSPI0 |= 0x10;
dacSPI1 = sample & 0x00FF;
digitalWrite(SLAVESELECT,LOW);
SPDR = dacSPI0; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
SPDR = dacSPI1;
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
digitalWrite(SLAVESELECT,HIGH);
//delay(5);
}
void playNote(int incomingByte)
{
int diff = 0;
//---------
for (diff=0; diff <= 4095; diff++){
// write_value (405) ; // 0 --->4095 12 bits 405=1.00V
write_value (diff) ; // 0 --->4095 12 bits 405=1.00V
//delay(1); run OK avec Voltmetre ana et num , signal à tester à l'oscillo
delayMicroseconds(200); //run ok mais met les Voltmetres ana et digital dans les choux, pas etonnant = oscillo a faire
}
}
//void noteOff()
//{
// write_value(0);
//}
int incomingByte = 0;
void loop()
{
playNote(incomingByte);
}
j'ai compris ce que réalise le code mais j'ai quelques questions sur les fonctions suivantes:
void write_value(uint16_t sample)
{
uint8_t dacSPI0 = 0;
uint8_t dacSPI1 = 0;
dacSPI0 = (sample >> 8) & 0x00FF;
dacSPI0 |= 0x10;
dacSPI1 = sample & 0x00FF;
digitalWrite(SLAVESELECT,LOW);
SPDR = dacSPI0; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{
};
"sample" est sur 16bits, le DAC étant de 12 bits, on coupe le mot en deux. mais comment procéder si la valeur de sample est déjà sur 12 bits ?
En suite dans cette fonction :
void playNote(int incomingByte)
{
int diff = 0;
//---------
for (diff=0; diff <= 4095; diff++){
// write_value (405) ; // 0 --->4095 12 bits 405=1.00V
write_value (diff) ; // 0 --->4095 12 bits 405=1.00V
//delay(1); run OK avec Voltmetre ana et num , signal à tester à l'oscillo
delayMicroseconds(200); //run ok mais met les Voltmetres ana et digital dans les choux, pas etonnant = oscillo a faire
}
}
int incomingByte = 0;
pourquoi créer une variable "int incomingByte"? elle reste toujours a zero !!
Enfin, je voudrais que le DAC convertisse un valeur renvoyer par un capteur:
le code suivant me permet de décoder la réponse de mon capteur ( au format numérique ):
void setup()
{
Serial.begin (115200);
noInterrupts(); // disable all interrupts
/* initialisation timer3 mode CaptureToCompare*/
TCCR3A = 0;
TCCR3B = 0;
TCNT3 = 0;
OCR3A = 125; // compare match register 16MHz/256/2Hz // interrupt every 1 ms
TCCR3B |= (1 << WGM32); // CTC mode
TCCR3B |= (1 << CS32); // 256 prescaler
TIMSK3 |= (1 << OCIE3A); // enable timer compare interrupt
/*Initialisation timer5 mode InputCompare*/
TCCR5A = 0;
TCCR5B = 0;
TCNT5 = 0;
TCCR5B |= (1 << CS50);// 8 prescaler
TCCR5B |= (1 << ICES5);// Rising
interrupts(); // enable all interrupts
}
/*Trigger*/
ISR(TIMER3_COMPA_vect) // interrupt fonction
{
TIMSK5 |= (0 << ICIE5);
DDRB = (1 << DDB4); //Pin 10 en mode OUTPUT
PORTB = (0 << PORTB4); // Pin 10 à 0
delayMicroseconds(9); // temps a l'état bas du trigger
PORTB = (1 << PORTB4); // Pin 10 à 1
// PASSEAGE EN INPUT POUR LIRE LA REPONSE DU CAPTEUR
DDRB = ( 0 << DDB4); // Pin 10 en entrée et attente de la réponse capteur
TIMSK5 |= (1 << ICIE5);//enable Input Capture interrupt
}
ISR(TIMER5_CAPT_vect)
{
TCNT5 = 0;
Buffer[ buff_index ] = (ICR5); //(48 = 3*16) 3 = prédiv capteur, et 16 clock/µs
Buffer[ buff_index ] = ((ICR5 / 43) - 11); //(48 = 3*16) 3 = prédiv capteur, et 16 clock/µs
buff_index ++;
if (buff_index == size_buff)
{
buff_index = 0;
}
}
void loop()
{
Serial.println("New trame");
for ( i = 4, j = 0; i < 8, j < 4; i++, j++)
{
Nibble [j] = Buffer [i];
val_Num_16 = (Nibble[3] + (Nibble[2] << 4) + (Nibble[1] << 8) + (Nibble[0] << 12));
}
//Serial.println (val_Num_16); // buffer reader
val_Num_12 = map(val_Num_16, 0, 65535, 0, 4095);
Serial.println (val_Num_12); // buffer reader
}
comment doit-je m'y prendre pour réaliser la conversion ?
cordialement