teamohnename
18.07.2011, 13:50
Hallo,
ich möchte gerne einen 8x PWM I²C Slave mit einem ATmega8 in C programmieren. Dabei benutze ich die Soft-PWM Lib von mikrocontroller.net (http://www.mikrocontroller.net/articles/Soft-PWM) und die twislave Lib aus dem rn-wissen (http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc). Mit dem Soft-PWM funktioniert soweit alles einwandfrei, aber es gibt noch ein paar Probleme mit dem I²C Slave. Der Slave wird vom Master erkannt, wenn ich ihn unter der angegebenen Adresse anspreche, aber ich kann dann nichts in das Data Array vom Slave schreiben und auch nichts auslesen (Der Master selbst funktioniert, ich kann problemlos einen PCF8574 ansprechen). Der Master bleibt also nicht hängen, die Status LED leuchtet nicht. Die Werte von i2cdata[] im Slave bleiben aber alle 0. Ich vermute jetzt, dass das daran liegt, dass die twislave.c auf den ATmega32 abgestimmt wurde. Die einzelnen TWI Register (TWCR etc.) stimmen also vermutlich nicht alle (deshalb funktioniert nur die Hälfte). Den Buffer im twislave.c habe ich entsprechend groß gewählt. Wenn das das Problem ist: Welche Register müssen jetzt geändert werden? Durch die beiden Datenblätter steige ich nicht ganz durch. Hier mein Code:
Slave:
#include <util/twi.h> //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR
#include <avr/interrupt.h> //dient zur Behandlung der Interrupts
//#include <stdint.h> //definiert den Datentyp uint8_t
#include <stdlib.h> //nötig für Zahlumwandlung mit itoa
#include <util/delay.h>
//Software PWM:
// Defines an den Controller und die Anwendung anpassen
#define F_CPU 8000000L // Systemtakt in Hz
#define F_PWM 100L // PWM-Frequenz in Hz
#define PWM_PRESCALER 8 // Vorteiler für den Timer
#define PWM_STEPS 256 // PWM-Schritte pro Zyklus(1..256)
#define PWM_PORT PORTD // Port für PWM
#define PWM_DDR DDRD // Datenrichtungsregister für PWM
#define PWM_CHANNELS 8 // Anzahl der PWM-Kanäle
#include "twislave.c"
#include "softpwm.h"
int main (void)
{
DDRB = 0xff;
DDRD = 0xff;
DDRC = ((0 << PB0 ) | (0<<PB1) | (0<<PB2) | (0<<PB3) | (1<<PB4) | (1<<PB5));
init_software_pwm();
init_twi_slave(I2C_ADR_SLAVE); //TWI als Slave mit Adresse starten
sei();
while(1)
{
for(uint8_t i=0; i<8; i++) //Software PWM Daten aus i2cdata lesen
{
pwm_setting[i]=i2cdata[i];
}
pwm_update();
OCR1A = i2cdata[8];
OCR1B = i2cdata[9];
OCR2 = i2cdata[10];
for(uint8_t i=11; i<15; i++)
{
i2cdata[i] = ADC_Read(i-11);
}
if(i2cdata[15]==1){
PORTB |= (1<<0);}
else{
PORTB &= ~(1<<0);}
if(i2cdata[16]==1){
PORTB |= (1<<4);}
else{
PORTB &= ~(1<<4);}
if(i2cdata[17]==1){
PORTB |= (1<<5);}
else{
PORTB &= (1<<5);}
} //end.while
} //end.main
Codeausschnitt Master:
uint8_t ret = i2c_start(0x19+I2C_WRITE); // set device address and write mode
if ( ret )
{
/* failed to issue start condition, possibly no device found */
i2c_stop();
PORTD |= (1<<4); //Status LED an
}
else
{
/* issuing start condition ok, device accessible */
i2c_write(0x00); //Buffer Startadresse
i2c_write(0x0A); //10
i2c_write(0x14); //20
i2c_write(0x1E); //30
i2c_write(0x28); //40
i2c_write(0x64); //100
i2c_stop(); // set stop conditon = release bus
PORTD &= ~(1<<4); //Status LED aus
}
Ich hoffe, ihr könnt mir helfen.
Vielen Dank schonmal im Vorraus und
Viele Grüße
teamohnename
ich möchte gerne einen 8x PWM I²C Slave mit einem ATmega8 in C programmieren. Dabei benutze ich die Soft-PWM Lib von mikrocontroller.net (http://www.mikrocontroller.net/articles/Soft-PWM) und die twislave Lib aus dem rn-wissen (http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc). Mit dem Soft-PWM funktioniert soweit alles einwandfrei, aber es gibt noch ein paar Probleme mit dem I²C Slave. Der Slave wird vom Master erkannt, wenn ich ihn unter der angegebenen Adresse anspreche, aber ich kann dann nichts in das Data Array vom Slave schreiben und auch nichts auslesen (Der Master selbst funktioniert, ich kann problemlos einen PCF8574 ansprechen). Der Master bleibt also nicht hängen, die Status LED leuchtet nicht. Die Werte von i2cdata[] im Slave bleiben aber alle 0. Ich vermute jetzt, dass das daran liegt, dass die twislave.c auf den ATmega32 abgestimmt wurde. Die einzelnen TWI Register (TWCR etc.) stimmen also vermutlich nicht alle (deshalb funktioniert nur die Hälfte). Den Buffer im twislave.c habe ich entsprechend groß gewählt. Wenn das das Problem ist: Welche Register müssen jetzt geändert werden? Durch die beiden Datenblätter steige ich nicht ganz durch. Hier mein Code:
Slave:
#include <util/twi.h> //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR
#include <avr/interrupt.h> //dient zur Behandlung der Interrupts
//#include <stdint.h> //definiert den Datentyp uint8_t
#include <stdlib.h> //nötig für Zahlumwandlung mit itoa
#include <util/delay.h>
//Software PWM:
// Defines an den Controller und die Anwendung anpassen
#define F_CPU 8000000L // Systemtakt in Hz
#define F_PWM 100L // PWM-Frequenz in Hz
#define PWM_PRESCALER 8 // Vorteiler für den Timer
#define PWM_STEPS 256 // PWM-Schritte pro Zyklus(1..256)
#define PWM_PORT PORTD // Port für PWM
#define PWM_DDR DDRD // Datenrichtungsregister für PWM
#define PWM_CHANNELS 8 // Anzahl der PWM-Kanäle
#include "twislave.c"
#include "softpwm.h"
int main (void)
{
DDRB = 0xff;
DDRD = 0xff;
DDRC = ((0 << PB0 ) | (0<<PB1) | (0<<PB2) | (0<<PB3) | (1<<PB4) | (1<<PB5));
init_software_pwm();
init_twi_slave(I2C_ADR_SLAVE); //TWI als Slave mit Adresse starten
sei();
while(1)
{
for(uint8_t i=0; i<8; i++) //Software PWM Daten aus i2cdata lesen
{
pwm_setting[i]=i2cdata[i];
}
pwm_update();
OCR1A = i2cdata[8];
OCR1B = i2cdata[9];
OCR2 = i2cdata[10];
for(uint8_t i=11; i<15; i++)
{
i2cdata[i] = ADC_Read(i-11);
}
if(i2cdata[15]==1){
PORTB |= (1<<0);}
else{
PORTB &= ~(1<<0);}
if(i2cdata[16]==1){
PORTB |= (1<<4);}
else{
PORTB &= ~(1<<4);}
if(i2cdata[17]==1){
PORTB |= (1<<5);}
else{
PORTB &= (1<<5);}
} //end.while
} //end.main
Codeausschnitt Master:
uint8_t ret = i2c_start(0x19+I2C_WRITE); // set device address and write mode
if ( ret )
{
/* failed to issue start condition, possibly no device found */
i2c_stop();
PORTD |= (1<<4); //Status LED an
}
else
{
/* issuing start condition ok, device accessible */
i2c_write(0x00); //Buffer Startadresse
i2c_write(0x0A); //10
i2c_write(0x14); //20
i2c_write(0x1E); //30
i2c_write(0x28); //40
i2c_write(0x64); //100
i2c_stop(); // set stop conditon = release bus
PORTD &= ~(1<<4); //Status LED aus
}
Ich hoffe, ihr könnt mir helfen.
Vielen Dank schonmal im Vorraus und
Viele Grüße
teamohnename