Kampi
03.10.2012, 15:50
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:
/*
* 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:
/*
* 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!
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:
/*
* 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:
/*
* 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!