7 years ago.

Sending variable information via SPI

Hello, I want to send variable values via SPI communication and i wanted to know how to do this. In my programm, i already have a part where the integer (0-65535) is converted into hexadecimal. But the adress has to be modifiable to, and i really don't know how to write it, as i need to seperate instructions into 4 x 8 bits .

Here is the code:, hoping you can help me. Yann :)

#include "mbed.h"
#include "limits.h"
Serial pc(USBTX, USBRX);
SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
DigitalOut cs(PA_4);

int main()
{
    int rep =0;
    int bit32[32];
    int ch;
    int choix;
    int registre;
    int value;
    int z=0;
    // Chip must be deselected


    // Setup the spi for 8 bit data, high steady state clock,
    // second edge capture, with a 1MHz clock rate
    spi.format(32,1);
    spi.frequency(1000000);


//-----------------------Conversion de l'entier en 16 bits----------------------
    long int decimalNumber,remainder,quotient;
    int i=1,j,temp;
    char hexadecimalNumber[100];


    while(1) {
//Affichage du menu principal
        pc.printf("Ecrire dans le registre ADC(1)\n\n");
        pc.printf("Mettre a jour le registre ADC(2)\n\n");
        pc.printf("Ecrire et mettre a jour le registre ADC(3)\n\n");
        pc.printf("Mise sous tension ou hors tension(4)\n\n");
        pc.printf("Reinitialiser la mise sous tension (5)\n\n");
        scanf("%d",&ch);


    
//---------------------------------------Switch case----------------------------
        switch(ch) {

//-----------------------------------------Ecrire dans un registre--------------
            case 01:
            pc.printf("Which value do you want to set ?\n");
                cs = 0;
                spi.write(0x00);
                spi.write(0x5F);
                spi.write(0xA5);
                spi.write(0x20);
                cs= 1;
                //  pc.printf("Quel pourcentage de voltage (0-65535) ?\n");
                // scanf("%d",&value);
                /*scanf("%ld",&decimalNumber);

                quotient = decimalNumber;

                while(quotient!=0) {
                    temp = quotient % 16;

                    //To convert integer into character
                    if( temp < 10)
                        temp =temp + 48;
                    else
                        temp = temp + 55;

                    hexadecimalNumber[i++]= temp;

                    quotient = quotient / 16;
                }

                pc.printf("Equivalent hexadecimal value of decimal number %d: ",decimalNumber);
                for(j = i -1 ; j> 0; j--) {
                    pc.printf("%c",hexadecimalNumber[j]);
                    valeur[z]= hexadecimalNumber[j];
                    z++;

                } */

                break;
//--------------------------------Update le registre----------------------------
            case 02:
                pc.printf("Quel registre souhaitez-vous update mettre a jour ? \n");
                pc.printf(" Registre A (1)\n Registre B (2)\n Registre C (3)\n Registre D (4)\n Registre E (5)\n Registre F (6)\n Registre G (7)\n Registre H (8)\n Tous les registres (9)\n");

                scanf("%d",&registre);
                if (registre == 1) { //Affichage dans le premier registre 

                    cs = 0;
                    spi.write(0x01);
                    spi.write(0x0F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC A mis a jour \n");

                } else if (registre ==2) { //Affichage dans le deuxieme registre
                    cs = 0;
                    spi.write(0x01);
                    spi.write(0x1F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs=1;
                    pc.printf("DAC B mis a jour \n");
                } else  if (registre ==3) { //Affichage dans le troisieme registre

                    cs = 0;
                    spi.write(0x01);
                    spi.write(0x2F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC C mis a jour \n");
                } else  if (registre ==4) { //Affichage dans le quatrième registre 
                    cs=0;
                    spi.write(0x01);
                    spi.write(0x3F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC D mis a jour \n");
                } else if (registre == 5) { //Affichage dans le cinquième registre
                    cs=0;
                    spi.write(0x01);
                    spi.write(0x4F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC E mis a jour \n");
                } else if  (registre ==6) { //Affichage dans le sixieme registre

                    cs=0;
                    spi.write(0x01);
                    spi.write(0x5F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC F mis a jour \n");
                } else  if (registre == 7) { //Affichage dans le septieme registre
                    cs=0;
                    spi.write(0x01);
                    spi.write(0x6F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC G mis a jour \n");
                } else  if (registre ==8) { //Affichage dans le huitieme registre
                    cs=0;
                    spi.write(0x01);
                    spi.write(0x7F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC H mis a jour \n");
                } else  if (registre ==9) { //Affichage dans TOUS les registres
                    cs=0;
                    spi.write(0x01);
                    spi.write(0xFF);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("Tous les DAC mis a jour \n");//affichage du message définitif
                } else {
                    pc.printf("Commande non reconnue\n");
                }
                break;
                
//------------Ecriture et update du registre en meme temps----------------------
            case 03:
                pc.printf("Quel pourcentage de voltage (0-65535) ?\n");
                /*scanf("%ld",&decimalNumber);

                quotient = decimalNumber;

                while(quotient!=0) {
                    temp = quotient % 16;

                    //To convert integer into character
                    if( temp < 10)
                        temp =temp + 48;
                    else
                        temp = temp + 55;

                    hexadecimalNumber[i++]= temp;
                    quotient = quotient / 16;
                }

                pc.printf("Equivalent hexadecimal value of decimal number %d: ",decimalNumber);
                for(j = i -1 ; j> 0; j--) {
                    pc.printf("%c",hexadecimalNumber[j]);
                }*/


                // Select the device by seting chip select low
                cs = 0;
                spi.write(0x03);
                spi.write(0x52);
                spi.write(0xAF);
                spi.write(0x80);

                //wait(0.5);
                cs=1;

                break;

//---------------------------Power Down ou Power up l'ADC-----------------------
            case 04:
                pc.printf("Souhaitez vous une mise en tension(1) ou hors tension (2) ?\n");
                scanf("%d",&choix); //En fonction du choix
                if (choix == 1) {
                    pc.printf("bien recu m\n"); //Affichage de message OK
                } else if (choix == 2) {
                    pc.printf("bien recu h\n");
                } else {
                    pc.printf("Commande non reconnue\n"); //IDEM
                }
                break;
                
            default:
                break;
        }


        ch =0;
        registre =0;
    } //while 1


}

1 Answer

7 years ago.

I'm not sure exactly what your question is but your code that does this...

.....
            scanf("%d",&registre);
                if (registre == 1) { //Affichage dans le premier registre 
 
                    cs = 0;
                    spi.write(0x01);
                    spi.write(0x0F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs= 1;
                    pc.printf("DAC A mis a jour \n");
 
                } else if (registre ==2) { //Affichage dans le deuxieme registre
                    cs = 0;
                    spi.write(0x01);
                    spi.write(0x1F);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs=1;
                    pc.printf("DAC B mis a jour \n");
                } else  if (registre ==3) { //Affichage dans le troisieme registre
.....

Would be far neater as:

void writeReg(char address) {
                    cs = 0;
                    spi.write(0x01);
                    spi.write(address);
                    spi.write(0xFF);
                    spi.write(0xF0);
                    cs=1;
}

....
                if (registre == 1) { //Affichage dans le premier registre 
                    writeReg(0x0f);
                    pc.printf("DAC A mis a jour \n");
 
                } else if (registre ==2) { //Affichage dans le deuxieme registre
                    writeReg(0x1f);
                    pc.printf("DAC B mis a jour \n");
                } else  if (registre ==3) { //Affichage dans le troisieme registre
....

or if you don't mind dropping the printf lines then all 9 possible values can be covered in a few lines...

....
                if (registre >= 1) && (registre <= 8) { //Affichage dans le premier registre 
                    writeReg(0x0f + (registre -1)*16);
                } else if (registre == 9) { //Affichage dans le deuxieme registre
                    writeReg(0xff);
                }
....

Are you thinking that values have to be specified in hex for some reason? That is not the case.

spi.write(0x10);
spi.write(16);
spi.write(1<<4);
x=4; spi.write(4*x);

will all do exactly the same. You can use whichever way of specifying the value is most convenient.When setting registers hex is normally easiest but it is up to you how you do it.

You could even do spi.write('0'); to write 48 (the ascii value of '0') on the SPI bus if you really wanted to.

Thank you very much for your answer. I understand better now, the way the DAC reads the information. A last question: how would you write to the DAC with a lot of variable ? Is it possible to do so ?

spi.write(0x0);
spi.write(commande); //(4 bits of instruction)
spi.write(adress); // 4 bits of adress
spi.write(instruction); //16 bits of instruction
spi.write(0x0);  ? 
posted by Yann De Baudus 15 Mar 2017

Something like:

void writeCommand(uint8_t commande, uint8_t adress, uint16_t instruction) {

  uint8_t commandAddressByte = (commande<<4) | (adress & 0x0f);
  spi.write(0);
  spi.write(commandAddressByte);
  spi.write(instruction>>8);
  spi.write(instruction & 0x0ff);
  spi.write(0);
}

All SPI writes should be the same size, it looks like 8 bits in your code, so I've assumed that since command and address are both 4 bits that they should be sent as a single byte with the command as the 4 most significant bits of the byte and the address as the least significant 4 bits.

The data is then sent as two bytes, most significant byte first (watch out for this, some thing want the bytes in the other order).


I just checked you code, your comments say "Setup the spi for 8 bit data" but then you have spi.format(32,1); which is setting it up for 32 bit transfers. That means if you do something like spi.write(0xff) what will actually get sent is 0x000000ff since it will treat each write as a 32 bit transfer.

posted by Andy A 15 Mar 2017

Ok ! Though, i didn't get why you put (adress & 0x0f) and (instruction & 0x0ff) ? So to use what you've just written, i need to put the 8 bits format ? I tried this programm, and the voltage changed, but not ase expected so i guess an instruction is not understood weel. The voltage changed to 3.6 volts (for 65535 the maximum value) instead of 58 volts. Do you have an idea of what's wrong ? Thanks, Yann

#include "mbed.h"
#include "limits.h"
Serial pc(USBTX, USBRX);
SPI spi(PA_7, PA_6, PA_5); // mosi, miso, sclk
DigitalOut cs(PA_4);
int value;



void writeCommand(uint8_t commande, uint8_t adress, uint16_t instruction)
{

    uint8_t commandAddressByte = (commande<<4) | (adress & 0x0f);
    spi.write(0);
    spi.write(commandAddressByte); //
    spi.write(instruction>>8);
    spi.write(instruction & 0x0ff);
    spi.write(0);
}



int main()
{
    spi.format(8,1);
    spi.frequency(1000000);
    int rep1;
    int rep2;
    int rep3;
    pc.printf("Quelle valeur ?\n");
    scanf("%d",&rep3);
    while(1) {
//Fonction 1: Ecrire dans un fichier

        pc.printf("enclencher registre\n");
        scanf("%d",&rep1);
        if(rep1 == 1) {
            pc.printf("Ecriture dans le registre\n");
            cs=0;
            writeCommand(0,0,rep3);
            cs=1;
        } else {}
        pc.printf("enclencher update\n");
        scanf("%d",&rep2);
        if (rep2 == 1) {
            pc.printf("Update du registre\n");
            cs=0;
            writeCommand(1,0,rep3);
            cs=1;
        } else {}
rep1=0;
rep2=0;
    }


}

posted by Yann De Baudus 16 Mar 2017