Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Controller als I2C Slave mit Bascom
BasCom verfügt ja schon über eingebaute I2C-Befehle. Eigentlich feine Sache.
Kann man damit irgendwie einen Controller als Slave betreiben so das er von anderm Controller per I2C angesprochen wird? Ich suche ein paar Beispiele.
Judgeman
16.02.2004, 14:34
Beim Ultraschallsensor SFR04 und SFR08, sowie dem Kompass CMPS03 werden PICs für die Auswertung und Aufbereitung der Sensordaten verwendet. Diese sind über den I2C-Bus (als Slave) auslesbar.
Mit Code kann ich leider nicht dienen.
Ich hab einige Zeilen gefunden
'
' SLAVE-Adresse 100
' nur Daten empfangen möglich/erforderlich --> MASTER-WRITE
' 5 Servos
' Im Feld Daten wird die Nr. des Servo's und dessen Laufrichtung verschlüsselt übergeben
'
'******************************************
Servo1 Alias Portb.1
Servo2 Alias Portb.2
Servo3 Alias Portb.3
Servo4 Alias Portb.4
Servo5 Alias Portb.5
Dim Daten As Byte
Dim I As Byte
$baud = 9600
On Int0 Ext_int0
On Ovf0 Tim0_ovf
Goto Reset
$asm
;************************************************* **************************
;* Refers to the application note AVR302 documentation for more
;* detailed description.
;*
;* USAGE
;* Insert user code in the two locations marked "insert user code here".
;*
;* NOTES
;* Minimum one instruction will be executed between each interrupt.
;*
;* STATISTICS
;* Code Size : 160
;* Register Usage : 5 High, 0 Low
;* Interrupt Usage : EXT_INT0 and TIM0_OVF
;* Port Usage : PD4(T0) and PD2(INT0)
;* XTAL : - I2C Fast Mode : min 16.0MHz
;* - I2C Standard Mode : min 3.0MHz
;*
;************************************************* **************************
;**** Includes ****
.include "2313def.inc"
;**** Global I2C Constants ****
;.def Devadr = 0x50 ; Slave Device Address geändert
;.def Devadrm = 0x7f ; Slave Multi Address Mask geändert
;.def Pinmaskx = 0x14 ; <=>(1 << Pd4) +(1 << Pd2) geändert
;**** Global Register Variables ****
.def Temp = R16 ; Temporary Variable
.def Etemp = R17 ; Extra Temporary Variable
.def I2cdata = R18 ; I2c Data Register
.def I2cadr = R19 ; I2c Address And Direction Register
.def I2cstat = R20 ; I2c Temporary Sreg Storage
;**** Interrupt Vectors ****
; Anpassung wegen Umstellung von 1200 auf 2313 !!!
; rjmp RESET ;Reset handle
; rjmp EXT_INT0 ;INT0 handle
; rjmp Xxx ;int_1 eingefügt
; rjmp Xxx ;time1_capt eingefügt
; rjmp xxx ;time1_compa eingefügt
; rjmp xxx ;time1_compb eingefügt
; Rjmp Xxx ;Time1_ovfl eingefügt
; rjmp TIM0_OVF ;Timer 0 overflow handle
;
; ( rjmp ANA_COMP ) ; ( Analog comparator handle )
;
;Xxx:
;************************************************* **************************
;*
;* INTERRUPT
;* EXT_INT0 / i2c_wakeup
;*
;* DESCRIPTION
;* Detects the start condition and handles the data transfer on
;* the I2C bus.
;*
;* Received data is stored in the r0 register and r0 is transmitted
;* during a master read transfer.
;*
;* NOTE
;* This interrupt code, in some cases, jumps to code parts in the
;* TIM0_OVF / i2c_skip section to reduce code size.
;*
;************************************************* **************************
Ext_int0:
in i2cstat,SREG ; store SREG
;*************************
;* Get I2C Slave Address *
;*************************
I2c_get_adr:
ldi i2cadr,1 ; initialize address register
Wlo_ga0:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ga0
rjmp first_ga
Do_ga:
; Do
Wlo_ga:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ga
mov temp,i2cadr ; test address
;orginal andi temp,Devadrm ; mask register full floating bit
andi R16,0x7f ;geändert
;orginal cpi temp,devadr ; if device addressed
;************************************************* ****************************
;************************************************* ****************************
cpi R16,0x32 ;dig.Adresse (RR&Co) = 100 geändert
;0x32 = binär 0110010 + 0 (R/W-Bit)
;100 = binär 01100100
;************************************************* ****************************
;************************************************* ****************************
in temp,SREG ; set T flag ("T = Z")
bst temp,1
First_ga:
sec ; set carry
Whi_ga:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_ga
sbis PIND,PIND2 ; if SDA low
clc ; clear carry
rol i2cadr ; shift carry into address register
brcc do_ga ; while register not full
Wlo_ca:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ca
;**** Check Address ****
; if T flag set (device addressed)
brts i2c_adr_ack ; acknowledge address
; else
rjmp i2c_adr_miss ; goto address miss handle
;**** Acknowledge Address ****
I2c_adr_ack:
sbi DDRD,DDD2 ; assert acknowledge on SDA
Whi_aa:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_aa
;**** Check Transfer Direction ****
lsr i2cadr ; if master write
brcc i2c_master_write; goto master write handle
;*******************************
;* Transmit Data (master read) *
;*******************************
I2c_master_read:
;**** Load Data (handle outgoing data) ****
;!INSERT USER CODE HERE !
;!NOTE! If the user code is more than ONE instruction then wait
; states MUST be inserted as shown in description.
mov i2cdata,r0 ; insert data in "serial"
; register (user code example)
sec ; shift MSB out and "floating empty flag" in
rol i2cdata
Wlo_mr:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr
;**** Transmitt data ****
brcc fb_low_mr ; if current data bit high
cbi DDRD,DDD2 ; release SDA
rjmp fb_mr ; goto read loop
Fb_low_mr:
; Else
sbi DDRD,DDD2 ; force SDA
Fb_mr:
Lsl I2cdata ; If Data Register Not Empty
Loop_mr:
Whi_mr:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mr
Wlo_mr2:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr2
brcc b_low_mr ; if current data bit high
cbi DDRD,DDD2 ; release SDA
lsl i2cdata ; if data register not empty
brne loop_mr ; loop
rjmp done_mr ; done
B_low_mr:
; Else
sbi DDRD,DDD2 ; force SDA
lsl i2cdata ; if data register not empty
brne loop_mr ; loop
Done_mr:
Whi_mr2:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mr2
Wlo_mr3:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mr3
cbi DDRD,DDD2 ; release SDA
;**** Read Acknowledge from Master ****
Whi_ra:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_ra
sec ; read acknowledge
sbis PIND,PIND2
clc
brcc i2c_master_read ; if ack transfer (next) data
Wlo_ra:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_ra
rjmp i2c_wait_cond ; goto wait condition (rep. start or stop)
;*******************************
;* Receive Data (master write) *
;*******************************
I2c_master_write:
Wlo_mw0:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_mw0
cbi DDRD,DDD2 ; remove acknowledge from SDA
Whi_mw:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_mw
in temp,PIND ; sample SDA (first bit) and SCL
;orginal: andi temp,pinmask
andi R16,0x14 ; mask out SDA and SCL geändert
Do_mw:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask
andi R17,0x14 ; mask out SDA and SCL geändert
cp etemp,temp
breq do_mw ; while no change
sbrs etemp,PIND4 ; if SCL changed to low
rjmp receive_data ; goto receive data
sbrs etemp,PIND2 ; if SDA changed to low
rjmp i2c_get_adr ; goto repeated start
; else
rjmp i2c_stop ; goto transfer stop
Receive_data:
ldi i2cdata,2 ; set i2cdata MSB to zero
sbrc temp,PIND2 ; if SDA sample is one
ldi i2cdata,3 ; set i2cdata MSB to one
Do_rd:
; Do
Wlo_rd:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_rd
sec ; set carry
Whi_rd:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_rd
sbis PIND,PIND2 ; if SDA low
clc ; clear carry
rol i2cdata ; shift carry into data register
brcc do_rd ; while register not full
;**** Acknowledge Data ****
I2c_dat_ack:
Wlo_da:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_da
sbi DDRD,DDD2 ; assert acknowledge on SDA
Whi_da:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_da
; (acknowledge is removed later)
;**** Store Data (handle incoming data) ****
; insert wait states here if nessesary
Sbi Ddrd , Ddd4 ;(start Wait State) aktiviert
;!INSERT USER CODE HERE !
;!NOTE! If the user code is more than TWO instruction then wait
; states MUST be inserted as shown in description.
mov r0,i2cdata ; Store data receved in "serial"
; register (user code example)
Gosub Bearbeitung
cbi DDRD,DDD4 ; (end wait state) aktiviert
cbi DDRD,DDD2 ; remove acknowledge from SDA
;Rjmp I2c_master_write ; Start On Next Transfer geändert / nur Datenempfang
rjmp I2c_stop
;************************************************* **************************
;*
;* INTERRUPT
;* TIM0_OVF / i2c_skip
;*
;* DESCRIPTION
;* This interrupt handles a "address miss". If the slave device is
;* not addressed by a master, it will not acknowledge the address.
;*
;* Instead of waiting for a new start condition in a "busy loop"
;* the slave set up the counter to count 8 falling edges on SCL and
;* returns from the current interrupt. This "skipping" of data
;* do not occupies any processor time. When 8 egdes are counted, a
;* timer overflow interrupt handling routine (this one) will check
;* the next condition that accure. If it 's a stop condition
;* the transfer ends, if it 's a repeated start condition a jump
;* to the i2c_wakeup interrupt will read the new address. If a new
;* transfer is initiated the "skipping" process is repeated.
;*
;************************************************* **************************
Tim0_ovf:
; (timer 0 Overflow Handle )
in i2cstat,SREG ; store SREG
I2c_adr_miss:
;**** Drop Acknowledge ****
Whi_dac:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_dac
Wlo_dac:
Sbic Pind , Pind4 ; Wait For Scl Low
rjmp wlo_dac
; disable timer 0 overflow interrupt
;orginal: ldi temp,(0<<TOIE0)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Timsk , Temp
; enable external interrupt request 0
;orginal: ldi temp,(1<<INT0)
clr temp ; eingefügt
sbr temp,&b01000000 ; geändert
Out Gimsk , Temp
;************************
;* Wait for a Condition *
;************************
I2c_wait_cond:
Whi_wc:
Sbis Pind , Pind4 ; Wait For Scl High
rjmp whi_wc
in temp,PIND ; sample SDA (first bit) and SCL
;orginal:andi temp,pinmask ; mask out SDA and SCL
andi R16,0x14 ; geändert
Do_wc:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask ; mask out SDA and SCL
andi R17,0x14 ; geändert
cp etemp,temp
breq do_wc ; while no change
sbrs etemp,PIND4 ; if SCL changed to low
rjmp i2c_skip_byte ; goto skip byte
sbrs etemp,PIND2 ; if SDA changed to low
rjmp i2c_get_adr ; goto repeated start
; else
; goto transfer stop
;*************************
;* Handle Stop Condition *
;*************************
I2c_stop:
;! Set INT0 to generate an interrupt on low level,
;! then set INT0 to generate an interrupt on falling edge.
;! This will clear the EXT_INT0 request flag.
;orginal: ldi temp,(0<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Mcucr , Temp
;orginal: ldi temp,(1<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Mcucr , Temp
Out Sreg , I2cstat ; Restore Sreg
reti ; return from interrupt
;****************
;* Skip byte(s) *
;****************
I2c_skip_byte:
; set counter initial value
ldi temp,-7
Out Tcnt0 , Temp
; enable timer 0 overflow interrupt
;orginal: ldi temp,(1<<TOIE0)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Timsk , Temp
; disable external interrupt request 0
;orginal: ldi temp,(0<<INT0)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Gimsk , Temp
Out Sreg , I2cstat ; Restore Sreg
reti
;************************************************* **************************
;*
;* FUNCTION
;* i2c_init
;*
;* DESCRIPTION
;* Initialization of interrupts and port used by the I2C interface
;* and waits for the first start condition.
;*
;* USAGE
;* Jump to this code directly after a reset.
;*
;* RETURN
;* none
;*
;* NOTE
;* Code size can be reduced by 12 instructions (words) if no transfer
;* is started on the I2C bus (bus free), before the interrupt
;* initialization is finished. If this can be ensured, remove the
;* "Wait for I2C Start Condition" part and replace it with a "sei"
;* instruction.
;*
;************************************************* **************************
Reset:
I2c_init:
;**** PORT Initialization ****
; Initialize PD2 (INT0) for open colector operation (SDA in/out)
;orginal: ldi temp,(0<<DDD4)+(0<<DDD2)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Ddrd , Temp
; Initialize PD4 (T0) for open colector operation (SCL in/out)
;orginal: ldi temp,(0<<PD4)+(0<<PD2)
clr temp ; eingefügt
sbr temp,&b00000000 ; geändert
Out Portd , Temp
;**** Interrupt Initialization ****
; Set INT0 to generate an interrupt on falling edge
;orginal: ldi temp,(1<<ISC01)+(0<<ISC00)
clr temp ; eingefügt
sbr temp,&b00000010 ; geändert
Out Mcucr , Temp
; Enable INT0 -> Freigeben INT0 !!!
clr temp
sbr temp,&b01000000 ;setzt bit 6 des Reg. Gimsk ( = INT0) auf 1 / on
Out Gimsk , Temp
; Set clock to count on falling edge of T0
;orginal: ldi temp,(1<<CS02)+(1<<CS01)+(0<< CS00)
clr temp ; eingefügt
sbr temp,&b00000110 ; geändert
Out Tccr0 , Temp
;************************************************* **
;* Wait for I2C Start Condition (13 intstructions) *
;************************************************* **
Do_start_w:
; Do
in temp,PIND ; sample SDA & SCL
com temp ; invert
;orginal: andi temp,pinmask ; mask SDA and SCL
andi R16,0x14 ; geändert
brne do_start_w ; while (!(SDA && SCL))
in temp,PIND ; sample SDA & SCL
;orginal: andi temp,pinmask ; mask out SDA and SCL
andi R16,0x14 ; geändert
Do_start_w2:
; Do
in etemp,PIND ; new sample
;orginal: andi etemp,pinmask ; mask out SDA and SCL
andi R17,0x14 ; geändert
cp etemp,temp
breq do_start_w2 ; while no change
sbrc etemp,PIND2 ; if SDA no changed to low
rjmp do_start_w ; repeat
rcall i2c_get_adr ; call(!) interrupt handle (New transfer)
;************************************************* **************************
;*
;* PROGRAM
;* main - Test of I2C slave implementation
;*
;************************************************* **************************
Main:
Rjmp Main ; Loop Forever
;**** End of File ****
$end Asm
Bearbeitung:
Daten = Peek(0)
Config Portb = Output
Portb = &B11111111 'alle LED aus
If Daten = 1 Or Daten = 11 Then Gosub Servo_1
If Daten = 2 Or Daten = 12 Then Gosub Servo_2
If Daten = 3 Or Daten = 13 Then Gosub Servo_3
If Daten = 4 Or Daten = 14 Then Gosub Servo_4
If Daten = 5 Or Daten = 15 Then Gosub Servo_5
Return
Servo_1:
If Daten = 11 Then Goto Servo_1_links
'-----------------------------------------------
Servo_1_rechts:
For I = 1 To 18 'nach rechts
Portb.1 = 0
Waitms 20
Portb.1 = 1
Waitms 1
Next I
Portb.1 = 0
Return
Servo_1_links:
For I = 1 To 18 'nach links
Portb.1 = 1
Waitms 20
Portb.1 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_2:
If Daten = 12 Then Goto Servo_2_links
For I = 1 To 18 'nach rechts
Portb.2 = 0
Waitms 20
Portb.2 = 1
Waitms 1
Next I
Portb.2 = 0
Return
Servo_2_links:
For I = 1 To 18 'nach links
Portb.2 = 1
Waitms 20
Portb.2 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_3:
If Daten = 13 Then Goto Servo_3_links
For I = 1 To 18 'nach rechts
Portb.3 = 0
Waitms 20
Portb.3 = 1
Waitms 1
Next I
Portb.3 = 0
Return
Servo_3_links:
For I = 1 To 18 'nach links
Portb.3 = 1
Waitms 20
Portb.3 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_4:
If Daten = 14 Then Goto Servo_4_links
For I = 1 To 18 'nach rechts
Portb.4 = 0
Waitms 20
Portb.4 = 1
Waitms 1
Next I
Portb.4 = 0
Return
Servo_4_links:
For I = 1 To 18 'nach links
Portb.4 = 1
Waitms 20
Portb.4 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Servo_5:
If Daten = 15 Then Goto Servo_5_links
For I = 1 To 18 'nach rechts
Portb.5 = 0
Waitms 20
Portb.5 = 1
Waitms 1
Next I
Portb.5 = 0
Return
Servo_5_links:
For I = 1 To 18 'nach links
Portb.5 = 1
Waitms 20
Portb.5 = 0
Waitms 20
Next I
Return
'-----------------------------------------------
Gottfreak
21.04.2004, 10:50
Irgendwie hilft mir dieser Quelltext beim I2C-Bus nicht sonderlich weiter.
1. Kann das Programm nur ein PWM-Signal für die Maximalausschläge machen? Also lässt sich keine Position sondern nur eine Richtung angeben und die tatsächliche Servoposition muss gemessen und dann das Servo in die richtige Richtung gedreht werden? Wozu dann ein Co-Controller?
2. Zu den I2C-Befehlen: Wie ist das mit denen, die Bascom schon hat? Brauch ich diesen Assebler-Kram trotzdem? Eingentlich will ich nur einzelne Werte übertragen und an einem anderen µC empfangen.
Wenn Du Controller als Slave benutzen willst dann kommst du an Assembler nicht ganz vorbei. Außer du nimmst die I2C-Slave Libary (5 Euro) vom Bascom-Hersteller.
Wenn es um Servos geht, dann kannst Du ja nun Kjions Servo-Programm in den Atmel Controller 90S2313 laden (im Download Bereich). Zum Beispiel beim Board RNBFRA (ich glaub das hast Du ja). Momentan kann dieser allerdings nicht mit Bascom I2C-Befehlen angesteuert werden da Kjions Software noch nicht die volle I2C Bus-Geschwindigkeit unterstützt (soll aber später noch optimiert werden). Ich hab aber eine kleine Engine geschrieben die neue I2C-Befehle, Servo-Befehl, Port-Befehle etc. für RNBFRA beinhaltet. Ist noch nicht ganz fertig weil ich derzeit selten dazu komme. Werde aber in Kürze schon mal die erste Version posten. Man kann dann einfach per Include die Datei in sein Basic Programm einbinden und kann dann alle wichtigen Funktionen des RNBFRA-Boards bequem per Basic-Subroutine steuern und muß nicht als mit den I2C-Befehlen hantieren. Das schreiben von Programmen wird dann noch ne ganze Ecke einfacher
Gruß Frank
Gottfreak
21.04.2004, 13:39
Erstmal danke, Frank: Die Bascom-Befehle sind also nur zum Senden...
Einen 90S2313, der Servos stellen kann, hab' ich mir schon gebastelt (ne, ähm das RNBFRA-Board hab' ich nicht, sondern 'nen Eigenbau).
Ich würde jetzt gern die gewünschte Servostellung (insgesamt ca. 10byte für die maximal vorgesehene Anzahl) von einer anderen Quelle entgegennehmen.
Was ist mit dem Befehl "I2creceive" von Bascom? Kann ich dem Empfänger nicht über einen Interupt oder so mitteilen, dass es neue Werte gibt und der empfängt die dann (oder der Servo-AVR "fragt" regelmäßig bei dem anderen die neuen Werte ab?)? Oder geht der Befehl auch nur mit der extra-Library?
PS: Wie lange dauert so ein Zyklus dann (die Servos sind ja solange ohne Ansteuerung.)?
Kann ich das PWM Signal innerhalb eines Modulationsintervalls einfach abbrechen(zum Empfangen der neuen Stellung und dann neu senden) oder ändert das noch die Stellung, wenn der letzte Pulz zu kurz ist?
Gottfreak
21.04.2004, 13:58
Ach ja: Was passiert eigentlich, wenn während des Sendens mit Bascom-I2C-Befehl ein Interupt 'reinkommt?
Hi,
ja sicher man könnte Baustein über einen Port ode IRQ darauf aufmerksam machen das es neue Servodaten gibt und er die quasi als Master abrufen soll. Aber dann hättest du ja das Problem mit dem anderen COntroller - denn der müsste nu als Slave programmiert werden :-) Außerdem wäre es Murks :-) wenn ich es mal so sagen darf.
Nö ich würde baustein dann schon vernünftig als Slave programmieren, entweder mit der genannten Libary die du für 5 Euro bekommst oder halt mit oberer Assembler Routine (die hab ich aber nicht ausprobiert).
Das heißt der Hauptcontroller spricht den Servobaustein per I2C an und überträgt ihm die neuen Servo Positionen. Die IC2 Libary nutzt dazu auch einen Interruptfähigen Eingang als I2C-Port.
Ein Problem besteht dann darin das vermutlich deine Servosteuerung kurz unterbrochen wird (während der I2C Übertragung). Inwieweit das deine Servosteuerung beeinflußt mußt du selbst wissen, mit der genauen Impulsgenerierung für die Servos hab ich mich nicht beschäftigt. Da kann Kjion sicher was zu sagen, denn er kennt das Problem. Er sperrt Interrupts während der Servo-Signalgenerierung soweit ich mich erinnere. Dadurch ist aber dann die volle I2C Geschwindigkeit nicht mehr möglich (es würden Takte verpaßt werden).
Wozu I2creceive ist weiß ich aus dem stehgreif garnicht. Ich nehme aber an das er die I2C-Grundfunktionen I2CSTART , I2CSTOP , I2CRBYTE
einfach zusammenfaßt und einige Bytes liest. Abrufen und senden von Bytes ist ja als Master möglich.
Das Beispiel hab ich gefunden:
Example
Config Sda = Portb.5
Config Scl = Portb.7
Dim X As Byte , Slave As Byte
X = 0 'reset variable
Slave = &H40 'slave address of a PCF 8574 I/O IC
I2creceive Slave , X 'get the value
Print X 'print it
Das gleiche geht auch mit I2CSTART , I2CSTOP , I2CRBYTE .
Hi,
PS: Wie lange dauert so ein Zyklus dann (die Servos sind ja solange ohne Ansteuerung.)?
Beliebig, das ist ja das Problem. Es kann ganz schnell sein, aber theoretisch auch einen Takt pro Stunde...
Kann ich das PWM Signal innerhalb eines Modulationsintervalls einfach abbrechen(zum Empfangen der neuen Stellung und dann neu senden)
Kann ab und zu funktionieren, in den meisten Fällen werden allerdings die Servos wild umherzucken.
ändert das noch die Stellung, wenn der letzte Pulz zu kurz ist?
Das würde auf jeden Fall passieren...
Ein Problem besteht dann darin das vermutlich deine Servosteuerung kurz unterbrochen wird (während der I2C Übertragung). Inwieweit das deine Servosteuerung beeinflußt mußt du selbst wissen, mit der genauen Impulsgenerierung für die Servos hab ich mich nicht beschäftigt. Da kann Kjion sicher was zu sagen, denn er kennt das Problem. Er sperrt Interrupts während der Servo-Signalgenerierung soweit ich mich erinnere. Dadurch ist aber dann die volle I2C Geschwindigkeit nicht mehr möglich (es würden Takte verpaßt werden).
Bei mir ists im Moment so, dass der Empfang der I2C Befehle im Hauptprogramm passiert. Die Servoansteuerung erfolgt über Timerinterrupts im Hintergrund. Das heißt allerdings, dass die Timerinterrupts zu jedem beliebigen Zeitpunkt auftreten können und damit das schöne Timing vermasseln...
Ohne die Servoansteuerung funktionierts auch mit vollen Geschwindigkeit ( hab mir zum Testen mal ein kleines I2C Display gebastelt )
Von dem Code der Oben für die Servoansteuerung gepostet wurde hat übrigens noch ein paar größere Fehler:
Die Servos werden nur angesteuert wenn ein Signal empfangen wurde. Das heißt man muss ständig die Positionen neu senden wenn man das Servo irgendwie belasten will. Des weiteren kann man keine Befehle empfangen während die Servos angesteuert werden. Das heißt man muss nach dem Senden eines Befehls erst eine Pause von mindestens 22 ms einhalten...
Ach ja: Was passiert eigentlich, wenn während des Sendens mit Bascom-I2C-Befehl ein Interupt 'reinkommt?
Als Master ist das ja egal, da man da beliebig viel Zeit zum Senden hat. Ansonsten wird halt die Senderoutine kurz unterbrochen und der Interrupt abgearbeitet...
MfG Kjion
Gottfreak
21.04.2004, 18:12
Abrufen und senden von Bytes ist ja als Master möglich.
Als Master ist senden und Empfangen möglich?
Was spricht dann gegen zwei als Master configurierte AVRs?
Der Haupt-AVR löst einen Interupt beim Servobaustein aus, wenn sich die Positionswerte verändert haben. Der macht dann noch sein Signal fertig und unterbricht dann kurz und führt I2CReceive oder I2CRBYTE aus. Der sendende AVR wartet dann einfach so lange, bis das Servosignal auf jeden Fall fertig ist (max. 2ms) und schickt dann die neue Position (wenn der Servo-AVR früher schon versucht zu empfangen, sollte dem das nix machen oder?).
Dass dann ganz kurz garkein Signal zu den Servos kommt, wird denen nix machen (wenn ich die Modellfernsteuerung ausmache, bleiben die ja auch einfach stehen.).
Du bringst Master/Slave und Empfangen/Senden durcheinander.
Der Master unterscheidet sich vom Slave dadurch das nur er die Verbindung auslösen kann. Ein Slave muss ständig die I2C-Ports kontrollieren ob der Master was von ihm will.
man könnte natürlich abwechselnd mal den und mal den als Master verwenden, aber dann wäre immer gleichzeitig der andere SLave. Der Master gibt ja die i2c Taktraten vor - der Slave muss nur antworten. Wenn der Maste reinen Sendebefehl schickt, muß der Slave die Bits im Takt des Masters annehmen. Gibt der Master einen Empfangsbefehl vor, dann muß der Slave einen Wert (im Takt des Masters) senden.
Der Matser ist halt der Chef - zwei Chef´s vertragen sich nicht im Büro. Abwechseln dürfen sie sich aber in der Chefrolle, wenn der andere die Arbeit des Mitarbeiters macht.
Gottfreak
21.04.2004, 20:40
ok, dass mehr als ein Master nicht geht, hätt ich mir echt denken können.
Des weiteren kann man keine Befehle empfangen während die Servos angesteuert werden. Das heißt man muss nach dem Senden eines Befehls erst eine Pause von mindestens 22 ms einhalten...
Das heist also, dass das Assembleprogramm so eine Art Endlosschleife ist, die nur unterbrochen wird, wenn eine Position empfangen wurde. Wenn ich das Programm also derart anpassen würde, dass es ohne neues Daten Via I2C sein Signal wiederholt, wäre ein ordentliches Empfangen garnicht mehr sichergestellt.
Die IC2 Libary nutzt dazu auch einen Interruptfähigen Eingang als I2C-Port.
Also braucht die I2C-Lösung mit der Libary dann einen der INT-Pins? Oder beide?
PS: Ein Äquivalent zum Input-Befehl, mit dem man in Bascom die Serielle Schnittstelle abfragen kann, wäre ideal. Dann könnte das Programm, wenn ein neuer Wert kommt, ggf. noch die Impulse für die Servos fertigmachen und dann zwischendurch (der Abstand zwischen denen ist nicht so wichtig.) auf Empfang schalten(und automatisch zurückkehren, wenn sagen wir mal zwei Bytes empfangen sind). Kann man das Programm von oben so anpassen?
Bei der Libary muß nur ein Pin Interrupt fähig sein. Hier Auszug aus der Beschreibung
'This program shows how you could use the I2C slave library to create a PCF8574
'The PCF8574 is an IO extender chip that has 8 pins.
'The pins can be set to a logic level by writing the address followed by a value
'In order to read from the pins you need to make them '1' first
'This program uses a AT90S2313, PORTB is used as the PCF8574 PORT
'The slave library needs INT0 and TIMER0 in order to work.
'SCL is PORTD.4 (T0)
'SDA is PORTD.2 (INT0)
'Use 10K pull up resistors for both SCL and SDA
'The Slave library will only work for chips that have T0 and INT0 connected to the same PORT.
'These chips are : 2313,2323, 2333,2343,4433,tiny22, tiny12,tiny15, M8
'The other chips have build in hardware I2C(slave) support.
Gottfreak
22.04.2004, 09:12
'The other chips have build in hardware I2C(slave) support.
Kann man bei den AVRs mit Hardware I2C(slave) die Funktionen einfacher nutzen? Mancher AVR ist ja schon günstiger als diese Libary.
Würde mich auch interessieren wie dies in bascom oder C abläuft
Hab im Netzt zum Hardware i2c in Verbindung mit bascom nichts gefunden. Ich hab mal beim Bascom Hersteller nachgefragt. Die wollen sich der Sache mal annehmen und ein Mega 8 Demo Prg. basteln. Werde es posten wenn es fertig ist
Gruß Frank
Ich hab jetzt mal die Software I2C Libary (noch die Software Version des I2C) für Bascom ausgetestet! Funktioniert eigentlich ganz gut. Nur offenbar verbraucht die alle Resourcen an Rechenleistung. Das heißt man kann offenbar nicht mehr nebenher ein anderes Hauptprogramm in dem Slave Chip ablaufen lassen. Offenbar wird es von einen Interrupt so oft unterbrochen das dafür keine Rechenzeit mehr zur Verfügung steht.
Habt ihr die gleichen Erfahrungen?
Gottfreak
06.05.2004, 22:45
Meinst du die kostenpflichtige Version? Die wäre damit ja vollkommen unbrauchbar (ein Glück, dass ich die nicht gekauft hab').
Ist das eigentlich unabhängig vom Takt?
PS: Zum HW I2C hast du auch nix gefunden? Ich auch nicht(mein Servobaustein läuft jetzt über den Serialport *g).
Ja die kostenpflichtige! Na ja, kosten halten sich mit 5 Euro ja in Grenzen. Für manche Anwendungen mag es ja ohne Hauptprogramm gehen, wenn man z.B. an Portbausteine denkt. Die müssen ja nur was machen wenn der Master was abfragt oder was übergibt.
Aber mir wäre auch ne Variante lieber wo ich ich ein vernünftiges Hauptprogramm nebenbei abaufen lassen kann. Mir ist auch noch nicht ganz verständlich warum das mit der Libary nicht geht. Wenn nix auf I2C-Bus übertragen wird , dann müsste doch Rechenzeit bereitstehen.
Hoffe nur das das mit der Implementierung der Hardware I2C Routinen besser wird. Da wollte Mark (Bascom Autor) noch Demo schreiben.
Mit Takt hat es sicherlich nichts zu tun, hab es auf Mega8 mit 8 Mhz ausprobiert.
Hi
Ich muß mein gesagtes etwas revidieren! Mit der Software I2C LIB von Bascom kann sehr wohl ein Hauptprogramm nebenher laufen.
Es gibt da nur ein paar Dinge die man beachten muß. So müssen alle am Bus befindlichen I2C Teilnehmer auch das I2C Protokoll korrekt beherrschen. Und das ist leider bei selbst gebastelten Routinen nicht immer der Fall. Beispielsweise ist vielen (auch bis vor kurzem mir) nicht bekannt, das der SLAVE den Master bei der Übertragung anhalten kann indem er von sich aus das Clock Signal auf Masse hält. Der Master muß also immer kontrollieren ob das Clock Signal auch wirklich High ist wenn er es nicht auf Low zieht. Das wird von vielen Routinen offenbar nicht berücksichtigt weshalb es dann zu Problemen kommt. Das war auch der Grund warum das Hauptprogramm bei mir nicht weiter lief, es lag an einer i2C Routine für den Serbobaustein (wird inzwischen geändert). Dadurch ist die Bascom LIB nicht mehr aus dem Interrrupt raus gekommen.
Bei der Bascom Lib ist es generell so das das Clock Signal vom Slave auf Low gelegt wird bis die Bearbeitung der Basic-Routine 'I2c_master_has_data' abgeschlossen ist. Wenn dies also zu lange dauert, dann muß der Master warten. Wenn das Protokoll richtig verwendet wird, ist das auch kein Problem. Das Hauptprogramm stoppt dann nur, während die Funktion 'I2c_master_has_data' abgearbeitet wird.
Aber wie gesagt, wenn der Master nicht wartet, dann gibt es ein Problem!
Das witzige daran ist, das selbst die I2C-bascom Funktionen sich offenbar nicht korrekt daran halten. Zwar kommt es hier nicht zu einem "hängenbleiben", aber es werden I2C-Übertragungen übergangen (kommen also nicht beim Slave an).
Offenbar hat der Bascom Entwickler selbst nicht daran gedacht, was er später in der Libary dokumentiert hat.
Ich gehe mal davon aus das dies bald korrigiert wird.
Im Augenblick bleibt einem also nichts anders übrig als in der Funktion 'I2c_master_has_data' nicht so zeitaufwendige Dinge zu machen. Wenn man sich daran hält, dann gibts keine Probleme!
Gruß frank
Noch zur Info: Die Bascom I2C-Lib kommt offenbar nicht mit dem I2CSEND Befehl zurecht, welcher mehrere Bytes überträgt!
Erst das positive: Habe dem Bascom Entwickler darüber informiert das seine I2C Befehle nicht auf den Slave warten! Er hat sogar schon innerhalb von Stunden Bugfix geschickt! Das nenne ich Support!
Jetzt das negative: Bugfix funktioniert noch nicht richtig :-) Bleibe aber am Ball und poste das noch sobald es 100% geht!
So noch eine Berichtigung: Das die I2C-Slave Lib nicht mit dem I2CSEND Befehl zurecht kam, lag auch an einem Bug in den normalen I2C-Befehlen von Bascom.
Ich hab den letzten Fehler in der Bascom Libary i2c.lib nun selbst gefunden und korrigiert. Zusammen mit dem Patch vom Bascom Entwickler funktioniert nun alles bestens. Ich habe das an den Bascom-Entwickler weitergegeben, denke er wird die korrigierte Lib zum download bereitstellen.
Wer sie dringend braucht kann Email hier posten, ich erläutere dann Korrektur! Wie gesagt, normalerweise hat man mit den Bascom I2C-Befehlen keine Probleme, mit den meisten Bausteinen kommt Bascom problemlos klar. Aber es gibt auch Slaves die den Master zum warten zwingen um die Daten gleich bearbeiten zu können. In einem solchen Fall gibt es derzeit oft Probleme mit Bascom. Diese können mit der neuen Libary behoben werden.
Hier kann nun die korrigierte I2C-Libary geladen werden:
http://www.mcselec.com/download/avr/beta/i2clib.zip
Einfach in das Unterverzeichnis LIB des bascom-Compilers kopieren (egal ob Vollversion oder Demo).
Gruß Frank
Nachtrag:
Leider geht der LInk derzeit oben nicht. Abe rin Kürze kommt die neue bascom Version wo die korrigierte Lib enthalten ist
Hat den jemand zwischenzeitlich mit dem HW I2C slave z.B. des M8 gearbeitet?
Gruss Peter
Hi!
Bei Atmel direkt gabs ein paar Infos, die Reste findest du unter
http://www.avrfreaks.net/Tools/showtools.php?ToolID=77
mfg
nollsen
Dieser Code auf der AVR Seite ist bekannt. Es ist aber eine Software-Impementation. Diese entspricht in etwa der Bascom-I2C Slave Lib, wobei die von Bascom noch etwas verbessert ist.
Gesucht wird aber mehr eine Hardware I2C Slave Implementation. Aber dazu hat MCS bald was fertig.
Hallo Freunde (Hellmut)
Dieses Thread ist nun schon eine Weile still, hier meine Aufgabenstellung. Meine RN-Mega8 soll die Impulslaengen an den Servosteckplaetzen eines 8-Kanal-Empfaengers meiner F14 Fernsteuerung von robbe messen, die gemessene Laenge einer von 256 moeglichen Laengen zuordnen und dann wenn er feststellt das sich die Impulslaenge veraendert hat diese Aenderung an die RN-Control ueber I2C melden.
Ich teile die Impulslaengen zwischen 1ms und 2ms in 256 Schritte und trage in einer Tabelle fuer alle 8 Steckplaetze den aktuellen Wert ein, falls dieser sich geaendert hat. Da der Empfaenger die Impulse an die Servos 1 bis 8 sequentiell und direkt nach einander anlegt, muss ich im laengsten Fall mit 8x 2ms = 16ms plus einem Puffer fuer Variationen einer speziellen Hardware fuer die Impulslaenge reservieren. Das heisst ich habe in diesem Fall nur gute 3ms fuer sonstiges wie den I2C-Verkehr zur Verfuegung.
Wenn ich diesen Thread richtig lese, so muesste die RN-mega8 als I2C slave den I2C-Clock alle 20ms solange auf low halten um so sicherzustellen das die I2C Kommunikation steht bis die RN-mega8 Zeit hat? Ausserdem muesste der I2C Master durch diesen Vorgang nicht eingefroren werden.
Das macht fuer mein System keinen Sinn, da dadurch mein verteiltes System vermutlich lahm gelegt wird. Ich plane eine RN-Control und 3 der Fahrtregler von stupsi plus 2 mega8 Minimalsysteme zur Impulslaengenmessung plus 1x i2c zur Displaysteuereinheit alle ueber einen I2C Bus verbunden! Ich muss aber sicherstellen, dass alle 20ms Aenderungen an den Servosteckplaetzen im System weitervermittelt werden. Das Antwortverhalten des Systems auf Steuerbefehle des Benutzers an der Fernsteuerung muss verzoegerungsfrei wirken.
Habt ihr eine Idee? Ist vielleicht I2C nicht der beste Bus um die Impulslaengen an die RN-Control zu senden? Der Datensatz der Impulslaengenuebermittlung je Kanal wird wohl 3 Byte lang sein, 2 Byte (jedes Bit einem Kanal zugewiesen) 1 Byte um die Impulslaengeninfo zu kodieren. (Ich verwende einen 8-fach Multiprop der aus einem Proportionalkanal 8 proportionale Kanaele macht, daher 16 Bit fuer (8+8-1)
Hellmut aus dem Ausland
Dieser Code auf der AVR Seite ist bekannt. Es ist aber eine Software-Impementation. Diese entspricht in etwa der Bascom-I2C Slave Lib, wobei die von Bascom noch etwas verbessert ist.
Gesucht wird aber mehr eine Hardware I2C Slave Implementation. Aber dazu hat MCS bald was fertig.
das gibts doch auch bei atmel auf der hp unter application notes: AVR311: Using the TWI module as I2C slave.
-- jetzt hab ich nur die Frage: Wie kann man diesen Code in Bascom benutzen, bzw. wie kann man eine Library einbinden (Assembler oder was auch immer), wie z.b. die i2slave lib ???
gruß Werner...
So, wenn ich nochmal zusammenfassen darf:
So noch eine Berichtigung: Das die I2C-Slave Lib nicht mit dem I2CSEND Befehl zurecht kam, lag auch an einem Bug in den normalen I2C-Befehlen von Bascom.
------
Bei der Bascom Lib ist es generell so das das Clock Signal vom Slave auf Low gelegt wird bis die Bearbeitung der Basic-Routine 'I2c_master_has_data' abgeschlossen ist. Wenn dies also zu lange dauert, dann muss der Master warten. Wenn das Protokoll richtig verwendet wird, ist das auch kein Problem. Das Hauptprogramm stoppt dann nur, während die Funktion 'I2c_master_has_data' abgearbeitet wird.
------
Aber wie gesagt, wenn der Master nicht wartet, dann gibt es ein Problem!
Das witzige daran ist, das selbst die I2C-bascom Funktionen sich offenbar nicht korrekt daran halten. Zwar kommt es hier nicht zu einem "hängenbleiben", aber es werden I2C-Übertragungen übergangen (kommen also nicht beim Slave an). .
so ich glaub das is mir auch passiert, wobei ich denke daß der master einfach nicht prüft ob der slave schon fertig ist:---->
For I = 1 To 101
adresse = I
sendebyte = 2*i
Gosub Schreibebytei2c:
Next I
Schreibebytei2c:
I2cstart
Waitms 10
I2cwbyte i2cadresse
Waitms 10
I2cwbyte adresse
Waitms 10
I2cwbyte sendebyte
Waitms 10
I2cstop
Waitms 10
Return
----------->
hier speichert er nur jeden 4 ten wert bzw wenn ich das i2cdelay auf 10 stelle jeden 2ten wert wenn man die waitms entfernt. ich denke das liegt an dem fehler in der i2clib?? er wartet wohl nicht auf meinen eeprom baustein bis er fertig ist und sendet immer weiter obwohl der i2c slave noch garnicht empfangsbereit ist. (der slave braucht 5-20ms um einen wert zu verarbeiten). ich weiß auch nicht genau ob alle waitms benötigt werden aber so funktionierts auf jedenfall.
Offenbar hat der Bascom Entwickler selbst nicht daran gedacht, was er später in der Libary dokumentiert hat.
Gruß frank
Wo kann ich das Kommentierte finden?
gruß Werner
Fehler in der Bascom Libary i2c.lib nun selbst gefunden und korrigiert. Zusammen mit dem Patch vom Bascom Entwickler funktioniert nun alles bestens.
Wer sie dringend braucht kann Email hier posten, ich erläutere dann Korrektur!
ok, dann schick mir doch mal bitte den Patch und die verbesserte lib und ne kurze erklärung wie und was wäre auch ziemlich gut.
gruß und vielen Dank Werner...
Hi,
leider hab ich noch kein I2C eeprom (oder was hast du als slave?)verwendet, daher kann ich zur Ansteuerung nix sagen. Ich denke nicht das es an dem Bug in der alten I2C-Libary liegt, vornehmlich hatte es mit I2C-Send-befehl Probleme gegeben.
Aber du kannst sicherheitshalber ja mal die neue nutzen.
Da der Link oben nicht mehr geht kannst du die ja hier laden
https://www.roboternetz.de/download/bascomi2clib.zip
Einfach entpacken und ins Libary Verzeichnis kopieren
Was ich oben mit Doku meinte weiß ich garnicht mehr, ist ja schon ewig her. Ich glaube ich meinte den Quellcode der Libary. Aber ist nicht so wichtig.
Hallo Leute. Bin neu hier und habe auch Probleme mit dem I2c Bus
Hab mich schonmal theoretisch damit beschäftigt und hier auch einiges dazu gelesen. Dies führte allerdings zu immer mehr Verwirrung.
Arbeite mit Bascom (siehe Signatur) und habe I2CSEND und I2CRECEIVE benutzt.
Der Mega8 ist der MASTER und der 8535 sollte der SLAVE sein.
Nun lese ich, dass man 2 Chips garnicht so einfach miteinander verbinden kan, weil die i2c.lib nicht vorhanden ist bzw. diese mit I2CSEND/I2CRECEIVE nicht funktioniert.
Was muss ich tun?
Hier noch ein paar konkrete Fragen dazu:
1. Ich lese immer nur was von der Arbeitsweise des MASTERS. Wie bringe ich aber einem anderen Bauteil bei, dass es ein SLAVE sein soll, woher weiß es das?
2. Ich habe eine einfache Routine zum Ausprobieren der Befehle I2CSEND/I2CRECEIVE geschrieben. Wie ich weiß, stehen Daten+Adresse im TWDR. Wenn ich mit BASCOM simuliere ändert sich allerdings rein garnix in irgend einem TW-Register. Woran kann das liegen?
(Wie kann ich hier in soeinen Post so ein Fenster mit entsprechendem Quellcode einbinden?)
Viele Fragen, ich weiß. Aber jeder muss mal klein anfangen. :)
Hier der Code vorerst in dieser "unpraktischen" Form
'Deklarationen + Initialisationen:
$regfile = "m8def.dat"
$crystal = 8000000
Config Portb = Output 'damit LEDs zur Kontrolle leuchten koennen
Config Sda = Portc.4 'laut Datenblat des mega8
Config Scl = Portc.5
Dim X As Byte
Dim Slave As Word
Portb = &H00 'alle LEDs anschalten
On Int0 Senden 'Senden=Sprungmarke
On Int1 Empfang 'empfangen = Sprungmarke
Enable Int0
Enable Int1
Enable Interrupts
X = 0
Do
Print X
Loop
Senden:
Portb.0 = Not Portb.0 'nur zur Kontrolle, das Int funktioniert
I2cinit
Slave = &H80
X = 50
I2csend Slave , X
Return
Empfang:
Portb.0 = Not Portb.0 'nur zur Kontrolle, das Int funktioniert
I2cinit
Slave = &H81
I2creceive Slave , X
If X = 50 Then Portb = Not Portb
Return
End
schonmal vorweg, ich kenne mich mit Bascom nicht aus, habe aber eine Verbindung von µC zu µC per TWI in C realisiert
der ATMEGA8 unterstützt auf jeden Fall Hardware-TWI, der 8535(AT90S oder ATMEGA ?) glaube ich überhaupt nicht (beim ATMEGA8535 bin ich mir nicht ganz sicher)
das bedeutet, den 8535 kannst du vielleicht noch zum TWI-Master machen, aber Slave würde erheblichen Programmieraufwand bedeuten, deshalb habe ich dafür ATMEGA8 verwendet, die das eben Hardwaremäßig unterstützen
wie man Master programmiert, findet man ja überall(bzw. dürfte mit Bascom kein Problem sein) und für den Slave steht im Datenblatt des ATMEGA8 ein wenig Programmcode(allerdings Assembler und C, wobei man meines Wissens nach Assembler ganz gut in Bascom eibinden kann)
das mit den TWxx-Registern könnte daran liegen, dass in früheren Versionen nicht das Hardware-TWI benutzt wurde, sondern Software-I²C und wenn du noch eine solche Version hast, ändert sich nichts in den TWxx-Registern, es müsste aber trotzdem gehen
vielleicht kann sich das noch mal ein Bascom-Programmierer anschauen?
Hallo Pascal,
Danke für die Tips. Die haben achonmal weitergeholfen. Beim 8535 handelt es sich um den AT90S8535 und Du hast recht,der hat auch kein Hardware-TWI. Ich wollte das ja auch nur zum Testen verwenden. Versuche ich es mal andersherum. (Mega8 als SLAVE)
Da ich wirklich den Hardware I2C des MEga8 verwende, wird dies der Grund der "leeren" Register sein.
Habt ihr noch Ideen, wie ich sonst noch auf einfache weise testen kann ob das SENDEN/EMPFANGEN funktioniert?
ich hatte einen PCF8574(Porterweiterungsbaustein für I²C) rumliegen, hab dann mit dessen Hilfe den Master zum Laufen gebracht und als ich sicher sein konnte, dass der geht, hab ich einen anderen ATMEGA8 als Slave hergenommen
also nehm, wenn möglich, erstmal einen "normalen" I²C-Baustein, um das Senden/Empfangen zu probieren
sebastian.heyn
17.12.2004, 10:00
Hallo, hatte ein ähnliches Problem.
Ich poste hier mal meinen Code, vielleicht hilft er ja irgendjemand. Er ist eigentlich ziemlich scmutzig programmiert aber er läuft. Dazu noch eine kurze Erklärung zu meinem I2C signal: Startbit, Adresse des Slave, Länge des Datenpackets, Daten, Stopbit. BIT 7 wird zuerst übertragen, Die software wartet auf startbedingung, ließt dann aus, gibt auf rs232 aus, macht ne kleine pause (So häufig kommen keine daten bei mir), Stopbit wird nicht beachtet, da die länge ja übermittelt wird und ich so rechtzeitig aufhören kann.
Es ging darum diese daten zu loggen (RS232) Franks mini projekt hat mir ein bisschen weitergeholfen.
$regfile = "m128def.dat"
$crystal = 16000000
$baud = 57600
Config Portd = Input
Cl Alias Pind.0 'Clock an Pind.0
Da Alias Pind.1 'SDA an Pind.1
On Int1 Startchk
Config Int1 = Falling
Enable Interrupts
Dim Adr As Byte
Dim Leng As Byte
Dim Temp As Byte
Dim C As Byte
Dim I As Byte
Dim J As Byte
Dim St(10) As Byte
For I = 1 To 8 'String leer machen zum ersten mal
St(i) = " "
Next
Enable Int1
Do
nop
Loop
End
Startchk:
If Cl = 1 Then 'Startbedingung: fallende flanke an SDA&SCL=1
Disable Int1
Gosub Rxdata
End If
Waitms 1000
Enable Int1
Return
Rxdata:
'Adresse immer 70H
Adr = 0 'Wert zurücksetzten
C = 128
For I = 1 To 8
Do
Loop Until Cl = 0
Do
Loop Until Cl = 1
If Da = 1 Then Adr = Adr + C
C = C / 2
Next
'ack überspringen
Gosub Jmpack
'Länge des strings
Leng = 0 'Wert zurücksetzten
C = 128
For I = 1 To 8
Do
Loop Until Cl = 0
Do
Loop Until Cl = 1
If Da = 1 Then Leng = Leng + C
nop
C = C / 2
Next
'ack überspringen
Gosub Jmpack
'String
For J = 1 To Leng
Temp = 0
C = 128
For I = 1 To 8
Do
Loop Until Cl = 0
Do
Loop Until Cl = 1
If Da = 1 Then Temp = Temp + C
nop
C = C / 2
Next
St(j) = Temp
'ack überspringen
Gosub Jmpack
Next
Print Chr(12);
Print "Adress: " ; Hex(adr) ; "h " ; "Length: " ; Leng ;
For I = 1 To Leng
Print Chr(st(i));
Next
Print
For I = 1 To 8 'String komplett leer machen
St(i) = " "
Next
Return
Jmpack:
'ack überspringen
Do
Loop Until Cl = 0
Do
Loop Until Cl = 1
Return
Du bringst Master/Slave und Empfangen/Senden durcheinander.
Der Master unterscheidet sich vom Slave dadurch das nur er die Verbindung auslösen kann. Ein Slave muss ständig die I2C-Ports kontrollieren ob der Master was von ihm will.
man könnte natürlich abwechselnd mal den und mal den als Master verwenden, aber dann wäre immer gleichzeitig der andere SLave. Der Master gibt ja die i2c Taktraten vor - der Slave muss nur antworten. Wenn der Maste reinen Sendebefehl schickt, muß der Slave die Bits im Takt des Masters annehmen. Gibt der Master einen Empfangsbefehl vor, dann muß der Slave einen Wert (im Takt des Masters) senden.
Der Matser ist halt der Chef - zwei Chef´s vertragen sich nicht im Büro. Abwechseln dürfen sie sich aber in der Chefrolle, wenn der andere die Arbeit des Mitarbeiters macht.
Du bringst Master/Slave und Empfangen/Senden durcheinander.
Der Master unterscheidet sich vom Slave dadurch das nur er die Verbindung auslösen kann. Ein Slave muss ständig die I2C-Ports kontrollieren ob der Master was von ihm will.
man könnte natürlich abwechselnd mal den und mal den als Master verwenden, aber dann wäre immer gleichzeitig der andere SLave. Der Master gibt ja die i2c Taktraten vor - der Slave muss nur antworten. Wenn der Maste reinen Sendebefehl schickt, muß der Slave die Bits im Takt des Masters annehmen. Gibt der Master einen Empfangsbefehl vor, dann muß der Slave einen Wert (im Takt des Masters) senden.
Der Matser ist halt der Chef - zwei Chef´s vertragen sich nicht im Büro. Abwechseln dürfen sie sich aber in der Chefrolle, wenn der andere die Arbeit des Mitarbeiters macht.
Verflixt nochmal. Sorry fuer die beiden letzten Posts. Bin mit Google irgendwie da in eine schon vorhandene "Antwort schreiben" Seite reingeraten. Und die falschen Tasten zur falschen Zeit gedrueckt.
Thomas
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.