-         

Ergebnis 1 bis 3 von 3

Thema: Xmega I²C PCF8547

  1. #1
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    28
    Beiträge
    3.517
    Blog-Einträge
    9

    Xmega I²C PCF8547

    Anzeige

    Hallo Forum,

    ich möchte über den I²C einen PCF8574 ansteuern.
    Zu Testzwecken habe ich den XMega128A1 mit dem PCF verbunden und an P0 vom PCF hängt eine LED die aufleuchten soll sobald der Pin gegen GND schaltet.
    Ich verwende folgenden Code:

    Main:
    Code:
    /*
     * XMega_I2C.c
     *
     * Created: 02.10.2012 15:47:40
     *  Author: Daniel
     */ 
    
    
    
    
    
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <string.h>
    #include <stddef.h>																										// Makro "offsetof" einbinden
    #include <avr/pgmspace.h>																								// Funktionen zum auslesen
    #include <stdlib.h>
    #include "PCF8574.h"
    
    
    void PCF8574_SetOutput(char adress, char data);
    																								
    int main(void)
    {
    	Clock_init();
    	Int_init();	
    	TimerC0_init();
    	UART_init();	
    	Port_init();		
    
    
        while(1)
        {
            //TODO:: Please write your application code 
        }
    }
    
    
    void Clock_init(void)
    {	
    	OSC.CTRL |= OSC_RC32MEN_bm;																							// Oszillator auf 32Mhz stellen
    	while(!(OSC.STATUS & OSC_RC32MEN_bm));																				// Warten bis der Oszillator bereit ist
    	CCP = CCP_IOREG_gc;
    	CLK.CTRL = CLK_SCLKSEL_RC32M_gc;																					// Clock auf 32MHz stellen																							// Prescaler A = CLK/2, Prescaler B/C = CLK/1
    }
    
    
    void Int_init(void)
    {
    	PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;													// Interrupts (Highlevel, Mediumlevel und Lowlevel freigeben)
    	sei();																												// Globale Interruptfreigabe
    }
    
    
    void TimerC0_init()
    {
    	TCC0.CTRLA = TC_CLKSEL_DIV1024_gc;																					// Vorteiler einstellen
    	TCC0.CTRLB = 0x00;																									// Timer in Normalmodus stellen
    	TCC0.INTCTRLA = 0x03;																								// Interrupt konfigurieren  
    }
    
    
    void UART_init(void)
    {
    	USARTC0.BAUDCTRLB = 0;																								// BSCALE = 0 
    	USARTC0.BAUDCTRLA = 0x68;																							// Baudrate 19200 @ 41MHz
    	USARTC0.CTRLA = USART_RXCINTLVL_HI_gc;																				// Interrupts mit Highlevel aktivieren
    	USARTC0.CTRLB = USART_TXEN_bm | USART_RXEN_bm;																		// RX+TX Enable CLK
    	USARTC0.CTRLC = USART_CHSIZE_8BIT_gc; 																				// Async, no parity, 8 bit data, 1 stop bit 	
    }
    
    
    void Port_init(void)
    {
    	PORTC.DIR = 0x08;																									// Pins für den UART C0 einstellen																								
    }
    
    
    void Send_UART(char data[])
    {
    	char Counter;
    	char lenght = 0x00;			
    	
    	lenght = strlen(data);
    	
    	while(Counter < lenght)
    	{
    		while (!(USARTC0.STATUS & USART_DREIF_bm));
    		USARTC0.DATA = data[Counter];	
    		Counter++;
    	}
    				
    	Counter = 0x00;	
    	while (!( USARTC0.STATUS & USART_DREIF_bm));
    	USARTC0.DATA = 0x0A;	
    	while (!( USARTC0.STATUS & USART_DREIF_bm));
    	USARTC0.DATA = 0x0D;	
    }
    
    
    ISR(TCC0_OVF_vect)
    {
    	PCF8574_send_byte (&TWIF, 0);
    }
    
    
    void PCF8574_SetOutput(char address, char data)
    {
    	TWI_MasterInit(&TWIF); 
    	PCF8574_send_add_rw (&TWIF, 0x20, 0);
    	PCF8574_send_byte (&TWIF, 1);
    }
    PCF8574.h:
    Code:
    /*
     * TWI_Master.h
     *
     * Created: 02.10.2012 23:34:10
     *  Author: Daniel
     */ 
    
    
    #ifndef TWI PCF8574_H_
    #define TWI PCF8574_H_
    
    
    #define CPU_SPEED 32000000
    #define BAUDRATE    400000
    #define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)
    #define TWI_BAUDSETTING TWI_BAUD(CPU_SPEED, BAUDRATE) 
    
    
    void TWI_MasterInit(TWI_t *twi)
    {
        twi->MASTER.BAUD = TWI_BAUDSETTING; 
        twi->MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
        twi->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
    }
    
    
    void PCF8574_send_add_rw(TWI_t *twi, unsigned char Adresse, unsigned char RW)
    {
    	char PCF8574_Add = 0x00;
    
    
    	PCF8574_Add = Adresse << 1;
    	PCF8574_Add |= RW;																										// RW setzen
    		
    	_delay_ms(5);
    	
    	twi->MASTER.ADDR = PCF8574_Add;
    	
    	_delay_ms(5);
    }
    
    
    PCF8574_send_byte (TWI_t *twi, unsigned char byte)
    {
    	twi->MASTER.DATA = byte;
    }
    
    
    #endif /* PCF8574_H_ */
    Nur leider passiert da nichts, sprich die LED bleibt dunkel.
    Als Pull-Up Widerstände verwende ich 3,3k und bei dem Board handelt es sich um ein AVR XPlained128.
    Kann mir einer sagen wo ich den Fehler gemacht habe?
    Danke schonmal!
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.03.2011
    Beiträge
    1.401
    Der Code ist ziemlich unübersichtlich. Ich kann nicht wirklich erkennen, was passieren soll. Da die Mainloop leer ist, muß es wohl im Interrupt sein. Für einen ersten Versuch ist das unglücklich, weil wesentlich schwerer zu verstehen und zu debuggen. Ein paar Kommentare wären nützlich. Noch eine Anmerkung, Code gehört nur in Ausnahmefällen in einen Header-File.

    Für das Schreiben vom I2C Master zum Slave braucht man einen Ablauf noch folgendem Muster

    i2c-Start
    write AddressByte
    write DataByte // möglicherweise mehrmals
    i2c-Stop

    Das kann ich aber nicht finden.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  3. #3
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    28
    Beiträge
    3.517
    Blog-Einträge
    9
    Hey,

    ja da hast du nicht ganz unrecht....hab ihn mal etwas verschönert und schon funktionierte es ^-^
    Hab mich wohl irgendwie verrannt....
    Danke trotzdem für die Hilfe
    Hier ist der funktionierende Code:

    Code:
    /*
     * XMega_I2C.c
     *
     * Created: 02.10.2012 15:47:40
     *  Author: Daniel
     */ 
    
    
    #define F_CPU 32000000
    #define CPU_SPEED 32000000
    #define BAUDRATE    400000
    #define TWI_BAUD(F_SYS, F_TWI) ((F_SYS / (2 * F_TWI)) - 5)
    #define TWI_BAUDSETTING TWI_BAUD(CPU_SPEED, BAUDRATE) 
    
    
    #define PCF8574 0x20                                                                                                    // PCF8574 Adresse definieren
    
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <string.h>
    #include <stddef.h>                                                                                                        // Makro "offsetof" einbinden
    #include <avr/pgmspace.h>                                                                                                // Funktionen zum auslesen
    #include <stdlib.h>
                                                                                                    
    int main(void)
    {
        Clock_init();                                                                                                        // Clock mit 32MHz initialisieren
        Int_init();                                                                                                            // Interrupts aktivieren
        TimerC0_init();
        UART_init();    
        Port_init();
        TWI_MasterInit(&TWIF);                                                                                                 // TWI initialisieren
    
    
        while(1)
        {
           PCF8574_send_byte(&TWIF, 0);                                                                                        // Eine 0 zum PCF senden
           _delay_ms(1000);                                                                                                    // 1 Sekunde warten
           PCF8574_send_byte(&TWIF, 1);
           _delay_ms(1000);
        }
    }
    
    
    void Clock_init(void)
    {    
        OSC.CTRL |= OSC_RC32MEN_bm;                                                                                            // Oszillator auf 32Mhz stellen
        while(!(OSC.STATUS & OSC_RC32MEN_bm));                                                                                // Warten bis der Oszillator bereit ist
        CCP = CCP_IOREG_gc;
        CLK.CTRL = CLK_SCLKSEL_RC32M_gc;                                                                                    // Clock auf 32MHz stellen                                                                                            // Prescaler A = CLK/2, Prescaler B/C = CLK/1
    }
    
    
    void Int_init(void)
    {
        PMIC.CTRL |= PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;                                                    // Interrupts (Highlevel, Mediumlevel und Lowlevel freigeben)
        sei();                                                                                                                // Globale Interruptfreigabe
    }
    
    
    void TimerC0_init()
    {
        TCC0.CTRLA = TC_CLKSEL_DIV1024_gc;                                                                                    // Vorteiler einstellen
        TCC0.CTRLB = 0x00;                                                                                                    // Timer in Normalmodus stellen
        TCC0.INTCTRLA = 0x03;                                                                                                // Interrupt konfigurieren  
    }
    
    
    void UART_init(void)
    {
        USARTC0.BAUDCTRLB = 0;                                                                                                // BSCALE = 0 
        USARTC0.BAUDCTRLA = 0x68;                                                                                            // Baudrate 19200 @ 41MHz
        USARTC0.CTRLA = USART_RXCINTLVL_HI_gc;                                                                                // Interrupts mit Highlevel aktivieren
        USARTC0.CTRLB = USART_TXEN_bm | USART_RXEN_bm;                                                                        // RX+TX Enable CLK
        USARTC0.CTRLC = USART_CHSIZE_8BIT_gc;                                                                                 // Async, no parity, 8 bit data, 1 stop bit     
    }
    
    
    void Port_init(void)
    {
        PORTC.DIR = 0x08;                                                                                                    // Pins für den UART C0 einstellen                                                                                                
    }
    
    
    void TWI_MasterInit(TWI_t *twi)
    {
        twi->MASTER.BAUD = TWI_BAUDSETTING; 
        twi->MASTER.CTRLA = TWI_MASTER_ENABLE_bm;
        twi->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
    }
    
    
    void Send_UART(char data[])
    {
        char Counter;
        char lenght = 0x00;            
        
        lenght = strlen(data);
        
        while(Counter < lenght)
        {
            while (!(USARTC0.STATUS & USART_DREIF_bm));
            USARTC0.DATA = data[Counter];    
            Counter++;
        }
                    
        Counter = 0x00;    
        while (!( USARTC0.STATUS & USART_DREIF_bm));
        USARTC0.DATA = 0x0A;    
        while (!( USARTC0.STATUS & USART_DREIF_bm));
        USARTC0.DATA = 0x0D;    
    }
    
    
    ISR(TCC0_OVF_vect)
    {
        
    }
    
    
    void Send_Address(TWI_t *twi, unsigned char Adresse, unsigned char RW)
    {
        char Add = 0x00;
    
    
        Add = Adresse << 1;                                                                                                        // Adresse um eine Stelle nach links schieben
        Add |= RW;                                                                                                                // RW setzen
        twi->MASTER.ADDR = Add;                                                                                                    // Adresse in das Adressregister schreiben
        
        _delay_ms(5);
    }
    
    
    void PCF8574_send_byte(TWI_t *twi, unsigned char byte)
    {
        Send_Address(&TWIF, PCF8574, 0);
        twi->MASTER.DATA = byte;                                                                                                // Byte ins Datenregister schreiben
    }
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

Ähnliche Themen

  1. Serialin mit XMEGA
    Von Che Guevara im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 22.03.2012, 22:56
  2. Xmega mit LCD-Controller
    Von Roboternetz-News im Forum Neuigkeiten / Technik-News / Nachrichten / Aktuelles
    Antworten: 0
    Letzter Beitrag: 21.11.2011, 14:30
  3. Xmega auf MAC?
    Von Snow Wolf im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 1
    Letzter Beitrag: 18.09.2011, 02:18
  4. Bascom xMega ?
    Von rauf81 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 17.04.2011, 21:37
  5. XMega alle ADC
    Von Frettchen im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 31.03.2011, 00:08

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •