PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Erste Versuche mit AD7799 und SPI


SN

Ökoelektrik
13.11.2011, 14:19
Ich übe mich gerade an dem 24 Bit AD Wandler von Analog Devices.
Bekomme es aber nicht so richtig hin...

1. Frage wie bekomme ich die 24 bits in eine 32 Bit Variable?
Ich lese ja 3 mal 8 bits, oder?

2. wie bekomme ich die Richtige Clock rate (SCK) heraus? Werde da aus dem Datenblatt nicht schlau. Daran knüpft sich die Frage wie ich die SPI richtig für den Chip einstelle.

Hier mal mein Code mit dem ich bisher so rumübe...


$regfile = "m1280def.dat"
$crystal = 16000000 '$crystal = 14745600
$hwstack = 380
$swstack = 380
$framesize = 380
$loadersize = 2024
$baud = 57600
Const Build = "Version 1111.01" 'Versionsnummer JJMM.VV




Dim Spvalue(3) As Byte
Dim I As Byte
Dim Adwert(3)as Word

Dim Wert(4) As Byte
Dim Ergebnis As Long At Wert(4) Overlay

Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 128 , Noss = 1

Spi_cs Alias Portb.0 : Ddrb.0 = 1 'Config Spi_cs = Output chipselect SS-Pin

'Spi_sdo Alias Pinb.3 ' MISO-PIN
Set Spi_cs
Spiinit





Do
Reset Spi_cs

Spvalue(1) = &B010100000 'Readout Dataregister Command
Spiout Spvalue(1) , 1

Waitms 150

Spiin Wert(1) , 3

Print Wert(1)

Print Ergebnis

Set Spi_cs
Wait 3

Loop


End


Wenn ich die 1.Frage beantwortet bekomme würde ich schon ein Stück weiter kommen. So bin ich mir nie sicher was da überhaupt zurück kommt aus dem AD

Gruß

Jörg

BehindBlueEyes
13.11.2011, 14:50
Hallo Jörg,
du musst das Overlay für Ergebnis auf jeden Fall auf Wert(1) setzen, ansonsten liegt die Long Variable Wert(4) und dahinter.
Wenn die Bytes in der falschen Reihenfolge kommen, kannst du mal schauen, ob du bei der Übertragung zwischen MSB-first und LSB-first wechseln kannst.

Galahat
13.11.2011, 15:44
Hallo Jörg

2. wie bekomme ich die Richtige Clock rate (SCK) heraus? Werde da aus dem Datenblatt nicht schlau. Daran knüpft sich die Frage wie ich die SPI richtig für den Chip einstelle.


Hab mir das DB mal angesehen. Eine direkte Aussage zum Clockspeed gibt es nicht, jedoch findest du unter Timing-Characteristics Angaben zu SCLK High/Low pulse width mit je 100ns minimum.

Daraus ergib sich für mich ein Maximum Fmax = 1/200ns.

Die restlichen Einstellungen unter Config SPI scheinen zu stimmen.
MSB, Phase und Polarität.


Grüße
Galahat

Ökoelektrik
13.11.2011, 16:12
Danke schon mal für die Antworten.
An Galahat daraus ergibt sich dann eine Clockrate = ??? bei 16 MHz
Das mit den 100 ns hatte ich auch gelesen. Wie rechnet man das dann aber um???

Ökoelektrik
13.11.2011, 16:32
Ich habe mir das mit dem Overlay noch mal genau angeschaut.

Wenn ich


Dim Wert(4) As Byte
Dim Ergebnis As Long At Wert(1) Overlay


fangen die Variable Ergebnis und Wert(1) in der selben Speicherzelle an.

Da ich ja aber nur 3 Byte bekomme müsste ich doch das Erste Byte (Wert(1) leer lassen, oder ???

Ich hole den Wert ja mit



Spiin Wert(1) , 3


Kann ich stattdessen



Spiin Wert(2) , 3


schreiben

oder muss ich die Werte eins nach hinten shiften?

BehindBlueEyes
13.11.2011, 16:53
Die Variablen werden von Bascom mit LSB in der untersten und MSB in der obersten Speicherzelle abgelegt.
Wenn du also die drei Bytes in Wert(1) - Wert(3) ablegst, sind sie in den unteren drei Byte der Long Variablen, also wahrscheinlich so wie gewünscht. Wert(4) setzt du dann einfach nie, sondern lässt es auf 0.
Wichtiger ist, in welcher Reihenfolge der Chip die daten zurückgibt. Das solltest du dir im datenblatt einmal ansehen oder einfach ausprobieren.

Galahat
13.11.2011, 17:04
An Galahat daraus ergibt sich dann eine Clockrate = ??? bei 16 MHz
100ns (high)+ 100ns(low) = 200ns 1/200ns =5 MHz maximaler Clockspeed.


So with 4 you will have a clock rate of 4.000000 / 4 = 1 MHz , when a 4 MHZ XTAL is used.

Mit 16Mhz / (Clockrate=4) liegst du damit dann wohl ganz gut.

Galahat

Ökoelektrik
23.11.2011, 12:05
Bin immer noch am üben :(
Bis heute habe ich noch keinen brauchbaren Wert dem Ad entlocken können. Prinzipiell funktioniert die Kommunikation über SPI aber so wirklich nicht.
Im Netz gibt es einen C Code wo der AD7794/7795 erfolgreich angesprochen wird. Dort wurde aber eine Art Software SPI programmiert...

Hier mal der Code, vielleicht kann mir da ja jemand bei der Übersetzung helfen?


volatile unsigned char uc_aderror=0; /* Fehlerzähler für den AD 7795 */


volatile unsigned int ui_7795[6]; /* Speicher für 6 A/D Werte vom AD7795 */
volatile unsigned int ui_old7795[6]; /* Speicher für 6 A/D alte Werte vom AD7795 */



#pragma savereg-
// Einen Taktimpuls erzeugen
void clockpulse(void)
{
#asm
nop
nop
nop
sbi portb,sck ;Clock Port auf 1 setzen
nop
nop
nop
nop
nop
nop
cbi portb,sck ;Clock Port auf 0 setzen
nop
nop
nop


#endasm
}

/* re-enable register saving for the other interrupts */
#pragma savereg+















/* 8Bit in den AD7795 schreiben */
void write_ad7795 (unsigned char uc_byte)
{
unsigned char i=0;
for(i=0;i<8;i++)
{
if((uc_byte&(1<<7))==(1<<7))
{
ad7795_din=1;
}
else
{
ad7795_din=0;
}
clock_ad7795();
uc_byte=uc_byte<<1;
}
ad7795_din=1;
}

/* AD Wandlerwert holen AD7795 */
unsigned int read_ad7795 (unsigned char uc_channel)
{
unsigned char uc_i;
unsigned int ad_value=0;

uc_channel=uc_channel&0b00000111; /* Höherwertige Bits abtrennen */

// Init Configutation Register for Channel X
ad7795_din=1;
ad7795_cs=0;
write_ad7795(0b00010000); /* Write to Configutation Register */
write_ad7795(0b00011000); /* Write value to Configutation Register high = VBIAS=OFF, Unipolar=1, Boost=On, Gain=1,*/
write_ad7795((0b10010000|uc_channel)); /* Write value to Configutation Register low = RefSel=1,17V int, Buf=ON, CH=X */
ad7795_cs=1;
#asm("nop");

// Init Mode Register = Read selected AD Channel
ad7795_cs=0;
write_ad7795(0b00001000); /* Write to Mode Register */
write_ad7795(0b00100000); /* Write value to Mode Register high = Single Conversation=On, AMP_CM=OFF*/
write_ad7795(0b00000100); /* Write value to Mode Register low = CLK=int 64kHz,CHOP=en,UPD_Rate=62Hz*/



delay_ms(40); /* Auf A/D Wandler warten - Wegen Tastaturabfrage auf 40ms verkürzt normal 50!*/
if (ad7795_dout==1)
{
delay_ms(50); /* Nochmal warten */
}
if (ad7795_dout==1)
{
ad_value=0; /* Fehlerzähler hochzählen */
uc_aderror++;
}
else /* A/D Wandler auslesen */
{
write_ad7795(0b01011000); /* Readout Dataregister Command */
for (uc_i=0;uc_i<16;uc_i++)
{
if (ad7795_dout==1)
{
ad_value=ad_value|0x0001;
};
ad_value=(ad_value<<1);
clock_ad7795();
}
};

ad7795_cs=1;
#asm("nop");

return (ad_value);
}

/* Reset für den AD7795 */
void reset_ad7795 (void)
{
unsigned char uc_i;
ad7795_cs=0;
#asm("nop");
ad7795_din=1;
for(uc_i=0;uc_i<34;uc_i++) /* eigentlich 32 */
{
clock_ad7795();
}
ad7795_cs=1;
#asm("nop");
}


/* Initialisieren des AD7795 */
void init_ad7795 (void)
{
volatile unsigned char uc_i;
for(uc_i=0;uc_i<4;uc_i++)
{
// Init Configutation Register Ch X
ad7795_cs=0;
write_ad7795(0b00010000); /* Write to Configutation Register */
write_ad7795(0b00011000); /* Write value to Configutation Register high = VBIAS=OFF, Unipolar=1, Boost=On, Gain=1,*/
write_ad7795(0b10010000|uc_i); /* Write value to Configutation Register low = RefSel=1,17V int, Buf=ON, CH=AIN X */
ad7795_cs=1;
#asm("nop");

// Init Mode Register = Init Zero Calibration Ch X
ad7795_cs=0;
write_ad7795(0b00001000); /* Write to Mode Register */
write_ad7795(0b10000000); /* Write value to Mode Register high = Zero Calibration=On, AMP_CM=OFF*/
write_ad7795(0b00000100); /* Write value to Mode Register low = CLK=int 64kHz,CHOP=en,UPD_Rate= 62Hz */
delay_ms(50);
if (ad7795_dout==1)
{
delay_ms(100);
uc_aderror++;
}
ad7795_cs=1;
#asm("nop");

// Init Mode Register = Init Full Scale Calibration Ch X
ad7795_cs=0;
write_ad7795(0b00001000); /* Write to Mode Register */
write_ad7795(0b10100000); /* Write value to Mode Register high = Full Scale Calibration=On, AMP_CM=OFF*/
write_ad7795(0b00000100); /* Write value to Mode Register low = CLK=int 64kHz,CHOP=en,UPD_Rate=62Hz*/
delay_ms(50);
if (ad7795_dout==1)
{
delay_ms(100);
uc_aderror++;
}

ad7795_cs=1;
#asm("nop");
}
};

/* 6 A/D Werte aus dem AD7795 auslesen und abspeichern */
void read6_ad7795 (void)
{
unsigned char uc_i;
for (uc_i=0;uc_i<6;uc_i++)
{
ui_old7795[uc_i]=ui_7795[uc_i];
ui_7795[uc_i]=read_ad7795(uc_i);
}

}




// AD7795 Initialisieren
ad7795_cs=1; /* /CS abschalten */
ad7795_clock=1; /* CLK auf ruheposition =1 setzen */
ad7795_din=1; /* DIN auf Ruheposition =1 setzen */
reset_ad7795(); /* AD 7795 resetten */
delay_ms(1); /* 1ms warten */
init_ad7795(); /* Initialisierungsroutine aufrufen */


Das sind die für den AD7795 relevanten Teile. Stammt aus "lipo_voltmeter.c"

Darüber lässt das sich auch googln ;)

Grüße

Jörg

BehindBlueEyes
24.11.2011, 22:25
Hallo Jörg,
mit dem C-Code kann ich dir leider nicht weiterhelfen.

Wenn wir noch mal in deinen Bascom Code schauen, dann steht dort
Spvalue(1) = &B010100000 'Readout Dataregister Command
Das sind 9 Bit, hast du das bewusst so gemacht? die führende 0 wird dabei ignoriert, da das Array vom Typ Byte ist.
Wenn ich das Datenblatt S.13 richtig lese, dann sollte der AD bei dem Kommando &B01011100 zum kontinuierlichen Auslesen des Data Register verwenden. Das scheint mir die einfachste und damit robusteste Art zu sein. Ansonsten sind zu viele Fehlermöglichkeiten.

Ökoelektrik
25.11.2011, 11:40
Kein Problem, ich habe das mit dem AD7799/Ad7795 auch erst mal zurück gestellt. Falls jemand Interesse hat kann er die Muster bekommen (auf Adapter gelötet) und damit weiter üben ;) Kurze PN mit Adresse genügt...

Ökoelektrik
02.12.2011, 22:38
Inzwischen habe ich den jetzt von mir favorisierten AD bekommen. Ein MCP3903. Link zum Datenblatt http://ww1.microchip.com/downloads/en/DeviceDoc/25048B.pdf

Ich versuche jetzt mit folgenden Code:


$regfile = "xm256a3def.dat"
$crystal = 32000000
$hwstack = 84
$swstack = 80
$framesize = 80



' xmega128 is running on 32 MHz

$lib "xmega.lib" : $external _xmegafix_clear : $external _xmegafix_rol_r1014 ' add a reference to this lib

'first enabled the osc of your choice
Config Osc = Enabled , 32mhzosc = Enabled 'internal 2 MHz and 32 MHz enabled

'configure the systemclock
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1 ' we will use 32 MHz and divide by 1 to end up with 32 MHz

'configure the priority
Config Priority = Static , Vector = Application , Lo = Enabled
Config Com1 = 57600 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Open "COM1:" For Binary As #1
Waitms 2

Ddrd = &B1011_0000

Spi_cs Alias Portd.4
Set Spi_cs

Config Spid = Hard , Master = Yes , Mode = 0 , Clockdiv = Clk8 , Data_order = Msb , Ss = Auto




Open "SPID" For Binary As #12


Dim Wert(3) As Byte
Dim Ergebnis As Long At Wert(1) Overlay


Declare Sub Mcp_init




Do

Call Mcp_init

Print #1 , "AD " ; " " ; Ergebnis

Wait 1

Loop

End


Sub Mcp_init
Ergebnis = 0
Reset Spi_cs
Waitms 10
Print #12 , &B01010100
Waitms 10
Print #12 , &B00000000
Waitms 10
Print #12 , &B00001111
Waitms 10
Print #12 , &B11010000
Waitms 10
Set Spi_cs

Waitms 10

Reset Spi_cs
Waitms 10
Print #12 , &B01010101
Waitms 10
Input #12 , Wert(1)
Waitms 10
Input #12 , Wert(2)
Waitms 10
Input #12 , Wert(3)
Waitms 10

Set Spi_cs

End Sub


das Config Register zu schreiben und dann wieder auszulesen.

Funktioniert aber leider nicht und ich finde nicht was ich was falsch mache.

Das Control byte setzt sich aus

A6 - A5 welche festgelegt sind mit 0 1

der Adresse ( Configregister = 0x0A = 1010)

A4-A3-A2-A1-A0 = 01010

und dem R/W bit zusammen.

daraus resultiert dann 01010100 zum schreiben und 01010101 zum lesen.

Richtig?
nachdenken#-###---#

Ökoelektrik
03.12.2011, 19:47
So langsam komme ich der Sache näher. Der XM128A1 und XM256A3 scheinen wohl mehr Unterschiede zu haben als ich angenommen hatte. Jetzt werde ich wohl mal die Datenblätter genauer studieren müssen...

Ich hatte mir eben die Mühe gemacht das XMega SPI Beispiel von MAK3 mal aufzubauen... das haut mit dem XM256A3 nicht hin.

Der Angepasste Code



'This is the SPI MASTER which belong to spi-slave_atmega_328_3.3V.bas

$regfile = "xm256a3def.dat"
$crystal = 32000000
$hwstack = 64
$swstack = 40
$framesize = 40

'include the following lib and code, the routines will be replaced since they are a workaround
$lib "xmega.lib" : $external _xmegafix_clear : $external _xmegafix_rol_r1014

Config Osc = Enabled , 32mhzosc = Enabled
Config Sysclock = 32mhz '--> 32MHz

'configure the priority
Config Priority = Static , Vector = Application , Lo = Enabled


Config Com1 = 57600 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Waitms 2
Open "COM1:" For Binary As #1
Print #1 ,
Print #1 , "------------SPI MASTER-Slave Test----------------"

' Master = ATXMEGA128A1 running at 3.3 Volt
' Slave = ATMEGA328P running at 3.3 Volt

'We use Port E for SPI
Ddrd = &B1011_0000
'Bit7 = SCK = Output ------> SCK ATMEGA328P (PinB.5)
'Bit6 = MISO = Input ------> MISO ATMEGA328P (PinB.4)
'Bit5 = MOSI = Output ------> MOSI ATMEGA328P (PinB.3)
'Bit4 = SS = Output ------> SS ATMEGA328P (PinB.2)
Slave_select Alias Portd.4
Set Slave_select

Dim Switch_bit As Bit

Switch Alias Pind.0 ' Switch connected to GND
Portd_pin0ctrl = &B00_011_010 ' activate Pullup



Dim Bspivar As Byte
Dim Spi_send_byte As Byte
Dim Spi_receive_byte As Byte


'SPI, Master|Slave , MODE, clock division
Config Spid = Hard , Master = Yes , Mode = 0 , Clockdiv = Clk32 , Data_order = Msb , Ss = Auto
'SS = Auto set the Slave Select (SS) automatically before a print #X or input #X command (including initialization of the pin)
'Master SPI clock = 1MHz
Open "SPId" For Binary As #12


Main:
Config Debounce = 50

Do

Debounce Switch , 0 , Switch_sub , Sub 'Switch Debouncing

If Switch_bit = 1 Then 'When Switch pressed
Reset Switch_bit

Incr Spi_send_byte
Print "Spi_send_byte = " ; Spi_send_byte

'SEND TO SLAVE
Print #12 , Spi_send_byte 'SEND ONE BYTE TO SLAVE

Waitms 3

'READ FROM SLAVE
Input #12 , Spi_receive_byte 'READ ONE BYTE FROM SLAVE

Print #1 , "Spi_receive_byte = " ; Spi_receive_byte
End If


Loop



End 'end program

'there is NO CLOSE for SPI


Switch_sub:
Set Switch_bit
Return


'

Ökoelektrik
03.12.2011, 21:34
Ich gebe es auf für heute...

Es wird am Slave ISR ausgelöst aber der SS geht nicht low..

Ökoelektrik
04.12.2011, 09:45
Nun habe ich den Sonntag Morgen damit verbracht es noch mal mit einem xmega32A4 zu probieren. Mit dem selben Ergebnis....

Hat jemand mit der aktuellen Bascom Version irgend was mit SPI am laufen??

MAK3
04.12.2011, 10:41
Hallo,


Es wird am Slave ISR ausgelöst aber der SS geht nicht low..
Der Master setzt den SS.

Hast Du es auch mit SS = NONE versucht und dann die SS Leitung manuell setzen bzw. rücksetzen ?
Pin muss als output gesetzt sein.

Hast Du auch das alles berücksichtigt ?



Multi Slave Systems - /SS pin Functionality

The Slave Select (/SS) pin plays a central role in the SPI configuration. Depending on the mode the part is running in and the configuration of this pin, it can be used to activate or deactivate the devices. The /SS pin can be compared with a chip select pin which has some extra features. In master mode, the /SS pin must be held high to ensure master SPI operation if this pin is configured as an input pin. A low level will switch the SPI into slave mode and the hardware of the SPI will perform the following actions:



1. The master bit (MSTR) in the SPI Control Register (SPCR) is cleared and the SPI system becomes a slave. The direction of the pins will be switched according to Table 1.



2. The SPI Interrupt Flag (SPIF) in the SPI Status Register (SPSR) will be set. If the SPI interrupt and the global interrupts are enabled the interrupt routine will be executed. This can be useful in systems with more than one master to avoid that two masters are accessing the SPI bus at the same time. If the /SS pin is configured as output pin it can be used as a general purpose output pin which does not affect the SPI system.





Note: In cases where the AVR is configured for master mode and it can not be ensured that the /SS pin will stay high between two transmissions, the status of the MSTR bit has to be checked before a new byte is written. Once the MSTR bit has been cleared by a low level on the /SS line, it must be set by the application to re-enable SPI master mode.





In slave mode the /SS pin is always an input. When /SS is held low, the SPI is activated and MISO becomes output if configured so by the user. All other pins are inputs. When /SS is driven high, all pins are inputs, and the SPI is passive, which means that it will not receive incoming data.

Ökoelektrik
04.12.2011, 10:49
Hallo MAK3,
ich werde gleich noch mal weiter probieren.
Verstehe aber nicht, warum der Beispiel Code aus "ATXMEGA - kleines einmaleins - Erste Schritte mit ATxmega" nicht so funktioniert.
Ich habe ja nur andere MCU´s eingesetzt. Statt des 168ers einen 88er und des Xmega a1 einen A3 oder A3B.

Was mich auch stutzig macht, obwohl vom Slave nichts zurück gesendet wird (B ist immer 0) empfängt der Master immer was.

Ökoelektrik
04.12.2011, 12:34
Ich bin jetzt ein Schritt weiter.
Der Master (xmega) empfängt vom slave die Daten immer richtig.
Der Slave empfängt sporadisch falsche Daten.

SS habe ich jetzt auf none und setze von hand vor dem senden das ss auf low

MAK3
04.12.2011, 13:28
Evtl.liegt es noch am Takt.

Das hier funktioniert soweit.

Der Master erhält genau das zurück was zum Slave gesendet wird:
------------SPI MASTER-Slave Test----------------

Spi_send_byte = 1

Spi_receive_byte = 1

Spi_send_byte = 2

Spi_receive_byte = 2

Spi_send_byte = 3

Spi_receive_byte = 3

Spi_send_byte = 4

Spi_receive_byte = 4

Spi_send_byte = 5

Spi_receive_byte = 5

Spi_send_byte = 6

Spi_receive_byte = 6

Spi_send_byte = 7

Spi_receive_byte = 7

Spi_send_byte = 8

Spi_receive_byte = 8


'This is the SPI MASTER which belong to spi-slave_atmega_328_3.3V.bas
$regfile = "xm256a3bdef.dat"
$crystal = 32000000
$hwstack = 64
$swstack = 40
$framesize = 80
'include the following lib and code, the routines will be replaced since they are a workaround
$lib "xmega.lib" : $external _xmegafix_clear : $external _xmegafix_rol_r1014
Config Osc = Disabled , 32mhzosc = Enabled
Config Sysclock = 32mhz '--> 32MHz
'configure the priority
Config Priority = Static , Vector = Application , Lo = Enabled , Med = Enabled
Enable Interrupts

Config Com7 = 57600 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Waitms 2
Open "COM7:" For Binary As #1
Print #1 ,
Print #1 , "------------SPI MASTER-Slave Test----------------"
' Master = ATXMEGA128A1 running at 3.3 Volt
' Slave = ATMEGA328P running at 3.3 Volt
'We use Port E for SPI
Config Pind.7 = Output
Config Pind.6 = Input
Config Pind.5 = Output
Config Pind.4 = Output
'Bit7 = SCK = Output ------> SCK ATMEGA328P (PinB.5)
'Bit6 = MISO = Input ------> MISO ATMEGA328P (PinB.4)
'Bit5 = MOSI = Output ------> MOSI ATMEGA328P (PinB.3)
'Bit4 = SS = Output ------> SS ATMEGA328P (PinB.2)
Slave_select Alias Portd.4
Set Slave_select
Portd_pin4ctrl = Bits(3 , 4) ' Enalbe Pullup

Dim Bspivar As Byte
Dim Spi_send_byte As Byte
Dim Spi_receive_byte As Byte

'SPI, Master|Slave , MODE, clock division
Config Spid = Hard , Master = Yes , Mode = 0 , Clockdiv = Clk32 , Data_order = Msb , Ss = auto
'SS = Auto set the Slave Select (SS) automatically before a print #X or input #X command (including initialization of the pin)
'Master SPI clock = 32MHz/Clk32 = 1MHz
Open "SPID" For Binary As #12

Main:

Do
Wait 3 'Every 3 seconds
Incr Spi_send_byte
Print #1 , "Spi_send_byte = " ; Spi_send_byte
'SEND TO SLAVE
Print #12 , Spi_send_byte 'SEND ONE BYTE TO SLAVE
Waitms 3
'READ FROM SLAVE
Input #12 , Spi_receive_byte 'READ ONE BYTE FROM SLAVE
Print #1 , "Spi_receive_byte = " ; Spi_receive_byte

Loop

End 'end program
'there is NO CLOSE for SPI

'


Mit diesem Slave:


' This is the SPI Slave which belong to XMEGA256A3B Master
$regfile = "m328pdef.dat"
$crystal = 16000000 '= overclocking at 3.3 Volt
$hwstack = 64
$swstack = 40
$framesize = 40
$baud = 19200
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Dim B As Byte , Rbit As Bit
Dim My_byte As Byte
Dim Spi_status As Byte

'First configure the MISO pin
Config Pinb.4 = Output ' MISO
Config Pinb.2 = Input 'Slave Select
Config Pinb.0 = Output 'LED

'Then configure the SPI hardware SPCR register
Config Spi = Hard , Interrupt = on , Data Order = Msb , Master = No , Polarity = Low , Phase = 0 , Clockrate = 16
'Clock = 16MHz/16 = 1MHz
'Then init the SPI pins directly after the CONFIG SPI statement.
Spiinit
'specify the SPI interrupt
On Spi Spi_isr
'enable spi --> already enabled with Interrupt = on in Config spi
Enable Interrupts
Print "Start Slave"

Do
If Rbit = 1 Then
Reset Rbit
My_byte = B 'Save B in My_byte
Print "My_byte = " ; My_byte 'This is what we Receive from SPI Master
Spdr = My_byte 'This is what we want to send back to SPI MASTER
End If
Loop

'Interrupt routine
Spi_isr:
Spi_status = Spsr ''Read Status Register before reading SPI Data to clear SPIF
B = Spdr
Set Rbit
Return

Ökoelektrik
04.12.2011, 13:57
Danke, das haut jetzt soweit hin... Clk64. Der Atmega läuft ja auch nur auf knapp 4 MHZ

Ökoelektrik
04.12.2011, 15:23
Und die Verbindung zum MCP3903 funktioniert jetzt auch ;D;D

dj1yr
11.12.2011, 09:23
Hallo,

das klingt alles sehr interessant, hast du eine Quelle für den MCP3903
Könntest du vieleicht einen funktionierenden Beispielcode posten?

mfg René

Ökoelektrik
11.12.2011, 13:49
Quelle für den Chip? mouser.com Ab 70 Euro Versandkostenfrei. DE UST allerdings erforderlich. Ich habe allerdings 25 Stück davon da. Adapterplatinen von TSOP auf DIP auch. Weiteres dazu per PM.

Fertigen Code habe ich noch nicht wirklich. Die Werte floaten mir noch zu sehr. Für meine Anwendung ist das Teil wohl auch doch nicht geeignet, da für Strommessung konzipiert...



$regfile = "xm256a3bdef.dat"
$crystal = 32000000
$hwstack = 64
$swstack = 40
$framesize = 40



' xmega128 is running on 32 MHz

$lib "xmega.lib" : $external _xmegafix_clear : $external _xmegafix_rol_r1014 ' add a reference to this lib

'first enabled the osc of your choice
Config Osc = Enabled , 32mhzosc = Enabled 'internal 2 MHz and 32 MHz enabled

'configure the systemclock
Config Sysclock = 32mhz , Prescalea = 1 , Prescalebc = 1_1 ' we will use 32 MHz and divide by 1 to end up with 32 MHz

'configure the priority
Config Priority = Static , Vector = Application , Lo = Enabled
Config Com1 = 57600 , Mode = Asynchroneous , Parity = None , Stopbits = 1 , Databits = 8
Open "COM1:" For Binary As #1
Waitms 2


Spi_cs Alias Portc.4
Config Portc.4 = Output

Set Spi_cs

Config Spic = Hard , Master = Yes , Mode = 0 , Clockdiv = Clk32 , Data_order = Msb , Ss = None

Open "SPIc" For Binary As #12


On Portc_int0 Port_c_int0__isr
'Enable this Interrupt as Lo Level Interrupt
Enable Interrupts

Config Portd.0 = Output 'Output for Frequency

Config Tcd0 = Freq , Prescale = 2 , Comparea = Enabled , Resolution = 16

Tcd0_cca = 1 'F = 8 MHz




Dim Pinc_0_int_flag As Bit

Config Pinc.0 = Input


'On PINE.0 there is for this example a switch connected to GND.
'Because of the activated Pullup the PIN Level is high and there is a falling edge when switch is pressed
Portc_pin0ctrl = &B00_011_010 'Enable Pullup and reaction on falling edge at PINE.0
'^ ^
'^ Reaction on falling edge
'^
'Enable Pullup

Portc_int0mask = &B0000_0001 'include PIN0 in INT0 Mask
Portc_intctrl = &B0000_00_01


Dim Ergebnis As Long
Dim Wert(3) As Byte At Ergebnis Overlay
Dim Z As Byte
Dim Adwerte(12) As Long




Declare Sub Mcp_init
Declare Sub Mcp_lese_ads



Call Mcp_init


Do




Disable Portc_int0
If Pinc_0_int_flag = 1 Then
Reset Pinc_0_int_flag
Call Mcp_lese_ads

For Z = 1 To 1
Print #1 , "AD " ; Z ; " " ; Adwerte(z)
Next Z
End If
Enable Portc_int0 , Lo
Waitms 1000

Loop


Sub Mcp_lese_ads



Reset Spi_cs
Print #12 , &B01000001



For Z = 1 To 6

Input #12 , Wert(3)
Input #12 , Wert(2)
Input #12 , Wert(1)

Adwerte(z) = Ergebnis



Next Z

Set Spi_cs

End Sub


Sub Mcp_init

Reset Spi_cs

Print #12 , &B01010010 ' Status/Com Register
Print #12 , &B10000000
Print #12 , &B01010000
Print #12 , &B00111111

Set Spi_cs


Reset Spi_cs

Print #12 , &B01010100 ' Config Register
Print #12 , &B00000000
Print #12 , &B00000000
Print #12 , &B00000001

Set Spi_cs

Reset Spi_cs

Print #12 , &B01010000 ' Gain Register
Print #12 , &B10000100
Print #12 , &B10000100
Print #12 , &B10000100

Set Spi_cs
End Sub



Port_c_int0__isr:
Set Pinc_0_int_flag
Return