PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : interrupt ein/ausschaltprobleme



mat-sche
03.09.2009, 20:39
Hallo,

ich detektiere über int0 eine steigende Flanke und will dies Auswerten:


Int0_isr:
Portd.7 = 1
Disable Int0
Return


Nach einmaligem Sprung in die Interruptroutine soll der Interrupt ausgeschalten werden, das Funktioniert so weit.
In:


If Portd.7 = 1 Then Set Relon
If Pinc.2 = 0 And Portd.7 = 1 Then
Portd.7 = 0
Irq_z = 0 'Netzspannung wieder da? Or Batmin = 0
Enable Int0
Reset Relon
End If


soll der Interrupterkennung wieder eingeschalten werden. Nach dem einmal die Interruptroutine angesprungen wurde wird diese aber leider nicht wieder "aktiviert".
Kompletter Code.


$regfile = "m644pdef.dat"
$crystal = 14745600

$include "MyTWI.bas"

$baud = 19200

$hwstack = 100
$swstack = 100
$framesize = 100

Ddrb = &B00000000 'PortB als Eingang für die Funksensorüberwachung
Portb = &B11111111 'PullUp's einschalten
Ddrc = &B00000000 'PortB als Eingang
Portc = &B00000100
Ddrd = &B11111000
Portd = &B00000100

Config Adc = Single , Prescaler = Auto , Reference = Off
Start Adc

Config Timer1 = Timer , Prescale = 1024 'Timer1 (16bit, 65535) läuft mit Quarztakt/1024
Const Timervorgabe = 36735 'Anfangswert ab der der Timer1 beginnen soll zu zählen (von 58336=>65535)
Enable Timer1 ' Schalte Überlaufinterupt von Timer1 ein
On Timer1 Timer_irq ' 1secint => Sprungmarke an die gesprungen wird, wenn timer1 übergelaufen ist => danach weiter Start ADC

Config Int0 = Rising 'Interrupt zur Netzspannungsdedektion
On Int0 Int0_isr 'Sprungmarke interrupt nach dem infrarot Signal anliegt
Enable Int0
Enable Interrupts
Dim Irq_z As Byte

'------------------------------------------------------------------------------- Programmvariablen
Dim Relon As Bit



'------------------------------------------------------------------------------- Config TWI
Dim Batterie As Word
Dim Batspannung As Single
Dim Tuerkontakt As Byte
Dim Absender As Byte

Declare Sub Twi_show_state(byref State As Byte) ' Fehleranzeige für TWI übertragung
Const Mn1_adr = &H5A 'lokale I2C Adresse (als Slave)
Dim Twi_mst_buff(24) As Byte 'Buffer für Masterfunktionen
Dim Twi_slv_buff(24) As Byte 'Buffer für Slavefunktionen

Dim Temp As Byte

Dim Slave_adress As Byte , Send_byte As Byte , Speicherpointer As Byte
Declare Sub Master_transmit(byref Slave_adress As Byte , Byref Send_byte As Byte , Byref Speicherpointer As Byte) 'Declarierung der Sub =>mit byref wird immer nur ein Zeiger auf die Speicherstelle
' verwiesen und nicht ein Wert übergeben
Twi_slv_addr = Mn1_adr 'lokale I2C-Adresse
Twi_sr_data = Varptr(twi_slv_buff(1)) 'datenbuffer empfang
Twi_st_data = Varptr(batspannung) 'datenbuffer senden, von dort holt sich der Master die Daten

Twar = Twi_slv_addr + 1 'I2C Adress Mega32 + GCA
Config Twi = 100000 'I2C Speed
On Twi Twi_mst_slv_isr , Nosave 'ISR f. TWI
Gosub Twi_sense 'Aktivieren Slave-Funktion
Enable Interrupts 'Generell



'################################################# ############################## Programmstart

Do


If Portd.7 = 1 Then Set Relon
If Pinc.2 = 0 And Portd.7 = 1 Then
Portd.7 = 0
Irq_z = 0 'Netzspannung wieder da? Or Batmin = 0
Enable Int0
Reset Relon
End If

'************************************************* ****************************** Überwachung Batteriespannung
Batterie = Getadc(1)

Batspannung = Batterie * 4.5 ' Potivoreinstellung 4,5V = 10V Battspannung
Batspannung = Batspannung / 920 ' Spannung auf Wandlerrate umstellen
Batspannung = Batspannung * 2.22 ' Faktor für Umrechnung in tatsächlichen Bat-Wert 10V/4,5V
If Portd.7 = 1 Then ' Unterspannungsüberwachung
If Batspannung =< 6.7 Then
Portd.7 = 0
End If
End If
If Relon = 1 Then ' Übermittlung das Netzausfall vorliegt => Meldung an Zentrale
Tuerkontakt.7 = 1
Else
Tuerkontakt.7 = 0
End If

'************************************************* ****************************** Überwachung Türkontakte


If Pinb.0 = 1 Then
Tuerkontakt.0 = 1
Else
Tuerkontakt.0 = 0
End If
If Pinb.1 = 0 Then
Tuerkontakt.1 = 1
Else
Tuerkontakt.1 = 0
End If
If Pinb.2 = 1 Then
Tuerkontakt.2 = 1
Else
Tuerkontakt.2 = 0
End If
If Pinb.3 = 1 Then
Tuerkontakt.3 = 1
Else
Tuerkontakt.3 = 0
End If
If Pinb.5 = 1 Then
Tuerkontakt.4 = 0
Else
Tuerkontakt.4 = 0
End If
If Pinb.6 = 1 Then
Tuerkontakt.5 = 1
Else
Tuerkontakt.5 = 0
End If
If Pinb.7 = 1 Then
Tuerkontakt.6 = 1
Else
Tuerkontakt.6 = 0
End If


'************************************************* ****************************** TWI Slavefunktion, hier wird gehört, ob ein andere Master etwas sendet

If Twi_slv_flag <> 0 Then 'ständige Abfrage ob als Slave Daten anliegen =>Vorsicht, der Bus ist solange blockiert

Select Case Twi_slv_flag
Case &H60 :
Print ; "Slave empfängt" ; 'es ist was empfangen worden
Print Hex(twi_slv_addr) ; " "; 'von Adresse in Hex
For Temp = 1 To Twi_sr_cntr 'Daten aus Twi_sr_cntr in den puffer schreiben
Print Hex(twi_slv_buff(temp)); 'print der Daten
Next
Case &HA8 :

Print ; "Slave sendet" ; 'es ist was abgeholt worden Spc(30)
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_st_cntr
Print Twi_slv_buff(temp); 'print der Daten Hex(twi_slv_buff(temp));
Next

Case &H70 : Print Spc(30) ; "SLAVE GCA :" ; 'ein General Call ist gekommen
Print Hex(twi_slv_addr) ; " ";
For Temp = 1 To Twi_sr_cntr
Print Hex(twi_slv_buff(temp)); 'print der Daten
Next
Case Else:
Print " Fehler als Slave " ; Chr(7) ; Hex(twi_mst_addr) ; " "; 'Irgendein Fehler
Call Twi_show_state(twi_slv_flag) 'Print status-text



End Select
Print
Twi_slv_flag = 0 'löschen marker
Twi_slv_stat = 0 'löschen marker
Gosub Twi_sense 'alles wieder enablen
'und Bus freigeben
End If
'************************************************* ******************************



Print " IRQ-Zaehler " ; Irq_z
Waitms 200
Print " Batspannung " ; Batspannung
Waitms 200
Print " Relon " ; Relon
Waitms 200
Loop
End

'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ SUBROUTINEN
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Timerschaltung für Impulse Resetbaustein Netzüberwachung
Timer_irq:
Toggle Portd.6
Timer1 = Timervorgabe
Return

'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Interruptabfrage Netzausfall
Int0_isr:
Portd.7 = 1
Disable Int0
Return


'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++
$include "Twi_show_state.bas"
'+++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++ Senderoutine TWI
Run_wait_master:
Gosub Mst_start 'aufruf LIBRARY
Select Case Twi_mst_flag 'ergebnis ?
Case Twi_m_sent: 'gesendet
Print "<<<<<<MASTER sent:" ;
Print Hex(twi_mst_addr) ; " ";
For Temp = 1 To Twi_mt_cntr
Print Hex(twi_mst_buff(temp));
Next
Print
Twi_mst_flag = 0
Case Twi_m_recv: 'geholt
Print ">>>>>>MASTER read:" ;
Print Hex(twi_mst_addr) ; " ";
For Temp = 1 To Twi_mr_cntr
Print Hex(twi_mst_buff(temp));
Next
Print
Twi_mst_flag = 0
Case Else: 'irgendein Problem
Print "Fehler als Run_wait_master " ; Chr(7) ; Hex(twi_mst_addr) ; " ";
Call Twi_show_state(twi_mst_flag)
End Select
Return



'################################################# ############################## Sendesub
Sub Master_transmit(byref Slave_adress As Byte , Byref Send_byte As Byte , Byref Speicherpointer As Byte) 'Sub in der die Adresse des Empfängers steht und der Zeiger aus der Callprozedur

Twi_mst_addr = Slave_adress 'I2C Adresse Slave
Twi_mt_cntr = Send_byte '4 Byte senden
Twi_mt_data = Varptr(speicherpointer(1)) 'Daten senden => Varptr(Speicherpointer(1)) Speicherpointer = Zeiger auf eine
' Speicherstelle, nicht auf den Wert, aus der Callsubroutine (Temperaturbyte(1))
Twi_mr_cntr = 0

'Twi_mr_cntr = 1 ' dann 3 Byte empfangen
'Twi_mr_data = Varptr(twi_mst_buff(1)) ' empfangsbuffer

Gosub Run_wait_master ' auf gehts

End Sub
Return


Nun leider kann ich mir das nicht erklären. Kann ich den Interrupt für int0 so benutzen?

MAT

for_ro
03.09.2009, 22:11
Hallo,

ich detektiere über int0 eine steigende Flanke und will dies Auswerten:


Int0_isr:
Portd.7 = 1
Disable Int0
Return


Nach einmaligem Sprung in die Interruptroutine soll der Interrupt ausgeschalten werden, das Funktioniert so weit.
In:


If Portd.7 = 1 Then Set Relon
If Pinc.2 = 0 And Portd.7 = 1 Then
Portd.7 = 0
Irq_z = 0 'Netzspannung wieder da? Or Batmin = 0
Enable Int0
Reset Relon
End If




Da PortD.7 als Eingang konfiguriert ist, wird hiermit nur der PullUp eingeschaltet:
Portd.7 = 1
Willst du das wirklich?
In allen Abfragen musst du aber sicher den Port durch den Pin ersetzen, also so
If Pind.7 = 1 Then Set Relon

Gruß

Rolf

Edit: Ich sehe gerade, dass du D.7 als Ausgang konfiguriert hast. Das passt dann gar nicht zusammen. Das soll in den Abfragen dann doch bestimmt einer der Eingänge D.0, D.1 oder D.2 sein.

mat-sche
04.09.2009, 09:31
Hi for_ro,

gut.. dann werde ich die Abfrage, ob der Ausgang D.7 gesetzt ist, über Pind.7 = 1 machen und probieren.
Die frage ist nun, ob man in einer isr einen Interrupt ausschalten kann?

Ceos
04.09.2009, 10:14
ja das sist kein problem, wenn du das interrupt-enable an der entsprechenden stelle löscht wird der interrupt solagen nicht ausgelöst, wie du das enable-flag wieder setzt

for_ro
04.09.2009, 20:10
Hi for_ro,

gut.. dann werde ich die Abfrage, ob der Ausgang D.7 gesetzt ist, über Pind.7 = 1 machen und probieren.


Sorry, ich glaube ich hatte nicht verstanden, was du machen willst.
Du willst also abfragen, ob von deinem Programm der Ausgang D.7 gesetzt worden ist. Wenn das der Fall ist, dann musst du das tatsächlich so machen, wie in deinem Code angegeben. Zumindest geht es im Simulator so. Mit Pin wird das jedenfalls nicht gehen.
Falls dies im µC anders funktioniert, könntest du auch eine Variable benutzen, um den Zustand nachzuhalten. Oder du fragst direkt das Register ab, welches den Zustand des Int0 hält, also EIMSK.0.

Bist du denn sicher, dass C.2 = 0 kommt?

Gruß

Rolf

mat-sche
05.09.2009, 09:08
moin Rolf,

genau wie Du es erkannt hast möchte ich den Ausgang D.7 überwachen ob er geschalten wurde, so kann ich mir einen zusätzlichen Merker sparen. Das Programm läuft insoweit auch. Nur wenn ich in der ISR den Interrupt ausschalte (ne Art der Entprellung) und ihn wieder ein schalte, wird der Interrrupt nicht wieder eingeschalten. C.2 ist tatsächlich 0.
Das Programm nehme ich für eine unterbrechungsfreie Spannungsversorgung.
Die direkte Registerabfrage werde ich mir näher anschauen.
Danke für Deine Hilfe!