Jacob2
28.06.2011, 19:18
Hallo!
Ich habe vier Taster an einem PCF8574AP angeschlossen (Taster nach GND), welcher wiederum an einem ATmega48 hängt (I2C). Nun nutze ich diese Funktionen (http://www.mikrocontroller.net/articles/Port-Expander_PCF8574#Software) (s. unten) von Mikrocontroller.net. Um die Vorgänge zu überwachen lasse ich Kurznachrichten auf einem LCD anzeigen.
Der Interruptausgang des Portexpanders löst einen Pin-Change-Interrupt aus, was auch wunderbar funktioniert:
ISR(PCINT2_vect)//PCINT20 -> Ein Taster wurde gedrückt
{
cli();
//Welche Taste?
lcd_clrscr();
lcd_puts("Vorher...");
_delay_ms(500);
uint8_t Taste = pcf8574_get_inputs(0);//Adresse = 0 (alle auf GND)
lcd_clrscr();
lcd_puts("Nachher!");
sei();
};
Das Problem ist, dass sich der Controller bei der Get-Inputs-Funktion resettet, d.h. auf dem LCD bleibt "Vorher..." stehen. Den Neustart kann ich auch mithilfe des LCD erkennen (Mitteilung am Anfang der main()-Funktion).
Mit dem Oszilloskop habe ich schon so gut es geht überprüft, dass weder die Betriebsspannung einbricht noch der Reset-Pin auf low gezogen wird...
Hier die Funktionen von Mikrocontroller.net, die ich verwende:
#include "pcf8574.h"
void pcf8574_init (void)
{
/*set bus speed*/
TWBR = 0x10;
}
unsigned char pcf8574_send_start (void)
{
/*writing a one to TWINT clears it, TWSTA=Start, TWEN=TWI-enable*/
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
/*wait, until start condition has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}
void pcf8574_send_stop (void)
{
/*writing a one to TWINT clears it, TWSTO=Stop, TWEN=TWI-enable*/
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}
unsigned char pcf8574_send_add_rw (unsigned char address, unsigned char rw)
{
/*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/
unsigned char addr_byte = 0;
/*shift address one bit left*/
addr_byte = address << 1;
/*set RW-Bit, if necessary*/
addr_byte |= rw;
/*0b0111xxx0 --> address of Expander*/ //für PCF8574AP angepasst (0b0100xxx0 --> 0b0111xxx0)
addr_byte |= 0b01110000;
/*TWDR contains byte to send*/
TWDR = addr_byte;
/*send content of TWDR*/
TWCR = (1<<TWINT) | (1<<TWEN);
/*wait, until address has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}
unsigned char pcf8574_send_byte (unsigned char byte)
{
/*TWDR contains byte to send*/
TWDR = byte;
/*send content of TWDR*/
TWCR = (1<<TWINT) | (1<<TWEN);
/*wait, until byte has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}
unsigned char pcf8574_read_byte (void)
{
/*send content of TWDR; TWEA = enable ACK*/
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
/*wait, until byte has been received --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWDR;
}
unsigned char pcf8574_get_inputs (unsigned char address)
{
pcf8574_init ();
pcf8574_send_start ();
pcf8574_send_add_rw (address, 1);
unsigned char input = pcf8574_read_byte ();
pcf8574_send_stop ();
return input;
}
void pcf8574_set_outputs (unsigned char address, unsigned char byte)
{
pcf8574_init ();
pcf8574_send_start ();
pcf8574_send_add_rw (address, 0);
pcf8574_send_byte (byte);
pcf8574_send_stop ();
}
Was könnte den Reset verursachen?
Vielen Dank im Voraus!
PS: Hier ist noch der Schaltplan:
19205
Ich habe vier Taster an einem PCF8574AP angeschlossen (Taster nach GND), welcher wiederum an einem ATmega48 hängt (I2C). Nun nutze ich diese Funktionen (http://www.mikrocontroller.net/articles/Port-Expander_PCF8574#Software) (s. unten) von Mikrocontroller.net. Um die Vorgänge zu überwachen lasse ich Kurznachrichten auf einem LCD anzeigen.
Der Interruptausgang des Portexpanders löst einen Pin-Change-Interrupt aus, was auch wunderbar funktioniert:
ISR(PCINT2_vect)//PCINT20 -> Ein Taster wurde gedrückt
{
cli();
//Welche Taste?
lcd_clrscr();
lcd_puts("Vorher...");
_delay_ms(500);
uint8_t Taste = pcf8574_get_inputs(0);//Adresse = 0 (alle auf GND)
lcd_clrscr();
lcd_puts("Nachher!");
sei();
};
Das Problem ist, dass sich der Controller bei der Get-Inputs-Funktion resettet, d.h. auf dem LCD bleibt "Vorher..." stehen. Den Neustart kann ich auch mithilfe des LCD erkennen (Mitteilung am Anfang der main()-Funktion).
Mit dem Oszilloskop habe ich schon so gut es geht überprüft, dass weder die Betriebsspannung einbricht noch der Reset-Pin auf low gezogen wird...
Hier die Funktionen von Mikrocontroller.net, die ich verwende:
#include "pcf8574.h"
void pcf8574_init (void)
{
/*set bus speed*/
TWBR = 0x10;
}
unsigned char pcf8574_send_start (void)
{
/*writing a one to TWINT clears it, TWSTA=Start, TWEN=TWI-enable*/
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
/*wait, until start condition has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}
void pcf8574_send_stop (void)
{
/*writing a one to TWINT clears it, TWSTO=Stop, TWEN=TWI-enable*/
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN);
}
unsigned char pcf8574_send_add_rw (unsigned char address, unsigned char rw)
{
/*address can be 0 .. 8; rw=0 --> write, rw=1 --> read*/
unsigned char addr_byte = 0;
/*shift address one bit left*/
addr_byte = address << 1;
/*set RW-Bit, if necessary*/
addr_byte |= rw;
/*0b0111xxx0 --> address of Expander*/ //für PCF8574AP angepasst (0b0100xxx0 --> 0b0111xxx0)
addr_byte |= 0b01110000;
/*TWDR contains byte to send*/
TWDR = addr_byte;
/*send content of TWDR*/
TWCR = (1<<TWINT) | (1<<TWEN);
/*wait, until address has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}
unsigned char pcf8574_send_byte (unsigned char byte)
{
/*TWDR contains byte to send*/
TWDR = byte;
/*send content of TWDR*/
TWCR = (1<<TWINT) | (1<<TWEN);
/*wait, until byte has been sent --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWSR;
}
unsigned char pcf8574_read_byte (void)
{
/*send content of TWDR; TWEA = enable ACK*/
TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
/*wait, until byte has been received --> ACK*/
while (!(TWCR & (1<<TWINT)));
return TWDR;
}
unsigned char pcf8574_get_inputs (unsigned char address)
{
pcf8574_init ();
pcf8574_send_start ();
pcf8574_send_add_rw (address, 1);
unsigned char input = pcf8574_read_byte ();
pcf8574_send_stop ();
return input;
}
void pcf8574_set_outputs (unsigned char address, unsigned char byte)
{
pcf8574_init ();
pcf8574_send_start ();
pcf8574_send_add_rw (address, 0);
pcf8574_send_byte (byte);
pcf8574_send_stop ();
}
Was könnte den Reset verursachen?
Vielen Dank im Voraus!
PS: Hier ist noch der Schaltplan:
19205