www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI mit 12 Bit A/D Wandler


Autor: unwissend (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

für eine Entfernungsmessung mit einen Lasertriangulationssensor möchte 
ich den 12Bit A/D Wandler vom TYP ADS7816 verwenden.
Leider kriege ich es einfach nicht mit der SPI hin.

Hier mal der Code:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "lcd.h"
#include <util/delay.h>
#include<avr/interrupt.h>


#define MOSI PB5
#define MISO PB6
#define SCK PB7


void SPI_MasterInit(void)
  {
  DDRB = (1<<PB5)|(1<<PB7)|(1<<PB4);          /* Set MOSI,SS and SCK output, all others input */
  PORTB=  (1<<PB5)|(1<<PB7)|(1<<PB4);  
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPIE);    /* Enable SPI, Master, set clock rate fck/16 */
  }  

void SPI_MasterTransmit(char cData)
  {  
  SPDR = cData;                    /* Start transmission */
  while(!(SPSR & (1<<SPIF)));            /* Wait for transmission complete */
  }



int main(void)
{
  
  
  SPI_MasterInit();
  lcd_init(LCD_DISP_ON);          
  DDRD|=0xff;//Anschluss für Display
  sei();
  
  uint16_t dwert;
   char puffer[7];
  uint8_t MSB;
  uint8_t LSB;
  

  while(1){
  
    _delay_ms(500);
  
    lcd_clrscr();

  
    MSB&=0x00;
    LSB&=0x00;
  
    PORTB|=(1<<MOSI);//fallende Flanke startet AD
    _delay_us(2);  /* Time the ADC needs to convert. */
    SPI_MasterTransmit(0);
  
    MSB=SPSR;
    MSB=SPDR;
  
    
    SPI_MasterTransmit(0);
    LSB=SPSR;
    LSB=SPDR;

  PORTB&=~ (1<<MOSI);// AD Wandler aussachlten

  
  
  
  itoa( MSB , puffer, 2);
  lcd_puts(puffer);
  lcd_putc(':');
  itoa( LSB,puffer, 2);
  lcd_puts(puffer);


;

  

  }
}  

Der A/D wandelt zwar irgendwas wenn ich die Spannung (Entfernung ändere) 
aber nicht das was er soll bzw ist das MSB immer gleich dem LSB. Warum 
geht mir das LSB verloren?

Weiß jemand Rat? Ich bin am verzweifeln....

Achso: Datenblatt des ADS7816 findet ihr hier:
http://focus.ti.com/lit/ds/sbas061/sbas061.pdf

Vielen Dank

Gruß

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>    MSB=SPSR;
>    MSB=SPDR;

>aber nicht das was er soll bzw ist das MSB immer gleich dem LSB.

Du hast SPI nicht verstanden.

    SPI_MasterTransmit(0);
    LSB=SPSR;
    SPI_MasterTransmit(0);
    LSB=SPDR;

Autor: unwissend (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und dann mit dem MSB das ganze nochmal??

Warum ist das so? Im datenblatt steht doch nur dass man beide Register 
lesen muss und nicht das man nachdem man SPSR gelesen hat nochmal ein 
Dummybyte schicken muss. Oder irre ich mich da ?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>und dann mit dem MSB das ganze nochmal??

Hast du es ausprobiert?
SPI braucht 8 Takte Clock für ein Byte.

>    LSB=SPSR;

Wo kommen hier noch 8 Takte?

>    LSB=SPDR;

Autor: unwissend (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, ich kann es erst morgen auf der Arbeit ausprobieren. Da steht das 
ganze Zeusch. Habe vorher noch nie mit SPI gearbeitet, bin neu auf dem 
Gebiet.

Ist es so dann richtig ?

    SPI_MasterTransmit(0);
    MSB=SPSR;
    SPI_MasterTransmit(0);
    MSB=SPDR;

    SPI_MasterTransmit(0);
    LSB=SPSR;
    SPI_MasterTransmit(0);
    LSB=SPDR;

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nabend,

schau dir bitte nochmal die Doku im DB an!!!
Wenn du es nicht verstehst, siehe hier in der Artikelsammlung unter SPI 
nach.
http://www.mikrocontroller.net/articles/Serial_Per...
spezial hier die APP: AVR151

Im DB deines MCs stehen auch Code-Schnipsel die du mal durch arbeiten 
könntest.

Denn so wüsstest du, das dieses Register "SPSR" das "SPI Status 
Register" ist und nichts mit Nutzdaten zu tun hat.

Stephan

Autor: unwissend (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stephan W. schrieb:
> Im DB deines MCs stehen auch Code-Schnipsel die du mal durch arbeiten
> könntest.
>
> Denn so wüsstest du, das dieses Register "SPSR" das "SPI Status
> Register" ist und nichts mit Nutzdaten zu tun hat.

Soweit klar, aber im DB des Mikrocontrollers (übrigens ich verwende den 
AtMega16) steht folgendes:

• Bit 7 – SPIF: SPI Interrupt Flag
When a serial transfer is complete, the SPIF Flag is set. An interrupt 
is generated if SPIE in
SPCR is set and global interrupts are enabled. If SS is an input and is 
driven low when the SPI is
in Master mode, this will also set the SPIF Flag. SPIF is cleared by 
hardware when executing the
corresponding interrupt handling vector. Alternatively, the SPIF bit is 
cleared by first reading the
SPI Status Register with SPIF set, then accessing the SPI Data Register 
(SPDR).

Autor: Stephan W. (sir_wedeck)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja, ist ja auch richtig!
Dafür haste ja auch die Sendefunktion:
void SPI_MasterTransmit(char cData)
  {  
  SPDR = cData;                    /* Start transmission */
  while(!(SPSR & (1<<SPIF)));            /* Wait for transmission complete */
  }

Die legt cData in Datenregister und die SPI gibs raus.
Du wartest bis das SPIF Bit gesetzt ist und verlässt die Funktion.
Alles soweit in Ordnung, nur warum dann noch mal im Hauptprogramm????
SPI_MasterTransmit(0);
MSB=SPSR;
Das hat da nichts zu suchen!!!!
Stephan

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was hast du eigentlich mit deiner CS Leitung gemacht?

Du musst die bedienen! Siehe das Diagramm auf Seite 9 des Datenblattes 
unten. Der ADC beginnt zu arbeiten wenn CS auf 0 geht. Das kann ich in 
deinem Code nicht erkennen.

Ich bin mir jetzt nicht sicher, ob du bei eingeschaltetem SPI den MOSI 
Pin noch vom Programm aus schalten kannst. Ganz abgesehen davon, dass

       PORTB|=(1<<MOSI);//fallende Flanke startet AD

sowieso keine fallende Flanke erzeugt, sondern eine steigende (ausser du 
hast noch einen Inverter da dazwischen)

Aber wie gesagt: Ich bin mir nicht sicher, ob das überhaupt geht.




   char puffer[7];

das ist zu kurz für

  itoa( MSB , puffer, 2);

Autor: unwissend (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm also irgendwie funzt das ned. der AD wandelt zwar, geht auch auf null 
wie er soll aber ansonsten sind die Bytes immer gleich.
Ich weiß eifnach nicht was ich noch tun könnte.
Ich habe nun den Code wie folgt:
#include <stdlib.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "lcd.h"
#include <util/delay.h>
#include<avr/interrupt.h>


#define MOSI PB5
#define MISO PB6
#define SCK PB7


void SPI_MasterInit(void)
  {
  DDRB = (1<<PB5)|(1<<PB7)|(1<<PB4);          /* Set MOSI,SS and SCK output, all others input */
  PORTB=  (1<<PB5)|(1<<PB7)|(1<<PB4);  
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)/*|(1<<SPIE)*/;    /* Enable SPI, Master, set clock rate fck/16 */
  }  

void SPI_MasterTransmit(char cData)
  {  
  SPDR = cData;                    /* Start transmission */
  while(!(SPSR & (1<<SPIF)));            /* Wait for transmission complete */
  }



int main(void)
{
  
  
  SPI_MasterInit();
  lcd_init(LCD_DISP_ON);          /* initialize display, cursor off */
  DDRD|=0xff;
  sei();
  
  uint16_t dwert;
   char puffer[15];
  uint8_t MSB;
  uint8_t LSB;
  PORTB|=(1<<MOSI);//MOSI(CS AUF DEF. PEGEL)

  while(1){
  
    _delay_ms(500);
  
    lcd_clrscr();

  
    MSB&=0x00;
    LSB&=0x00;
  
    PORTB&=~(1<<MOSI);
    _delay_ms(2);  /* Time the ADC needs to convert. */
    SPI_MasterTransmit(0);
    MSB=SPDR;
  
  
    SPI_MasterTransmit(0);
    LSB=SPDR;

  PORTB|= (1<<MOSI);
  dwert=MSB*LSB;  
  
  
  itoa( MSB , puffer, 16);
  lcd_puts(puffer);
  lcd_putc(':');
  itoa( LSB,puffer, 16);
  lcd_puts(puffer);


  lcd_putc('\n');
  lcd_puts("Dwert:");
  itoa( dwert , puffer, 10);
  lcd_puts(puffer);
  
  

  }
}  



Hat noch jdm. einen Tip?

Autor: Spätzünder (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hier geht's schon schief
PORTB|=(1<<MOSI);//MOSI(CS AUF DEF. PEGEL)
Das CS bzw SS und MOSI sind zwei total verschiedene Dinge.

Schaut man sich diese Zeile an
  DDRB = (1<<PB5)|(1<<PB7)|(1<<PB4);          /* Set MOSI,SS and SCK 
output, all others input */

Ist SS offensichtlich auf PB4, wird aber nicht bedient. wird also jetzt 
an MOSI "rumgespielt", kann beim AD-Wandler auch nichts rechtes mehr 
ankommen.

Und was soll daraus werden ?:  dwert=MSB*LSB;

Schöne Grüße

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.