Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
7 years, 9 months 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",®istre); 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, 9 months ago.
I'm not sure exactly what your question is but your code that does this...
..... scanf("%d",®istre); 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); ?
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 15 Mar 2017Ok ! 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; } }