PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pinkompatibel zu ATTiny2313 mit mehr Flash?



Bumbum
26.04.2011, 13:25
Hallo,

ich habe ein kleines Projekt mit 3 Tasten, 3 Leds und 8 Relais. Der Zustand soll im EEPROM gespeichert werden. Ich habe dazu einen ATTiny 2313 verwendet. Nur leider ist jetzt schon mein Flash-Speicher voll und ich wollte noch eine IR-Bedienung hinzufügen.

Weiß jemand aus dem Stegreif, ob es einen Pinkompatiblen Chip von Atmel gibt, der mehr Flash Speicher hat?
Vielen Dank!

Viele Grüße
Andreas

TobiKa
26.04.2011, 15:13
Wüsste so keinen, wird auch keiner erwähnt.
Aber bei 3 Tastern und 8Relais ist der 2Kb Speicher schon voll?! Vielleicht solltest du deinen Code mal überarbeiten!

Bumbum
26.04.2011, 15:18
Ich habe mich selbst gewundert. Aber sooo verschwenderisch ist der Code gar nicht geschrieben. Ich hänge ihn mal hinten an. (Was noch an Info fehlt: Die Relais hängen an einem Schiebe-Register) Sicher könnte man noch einiges optimieren, aber ich habe hier gelesen, dass der Code für den IR-Empfang zwischen 600 und 900 Bytes des Flash inanspruch nimmt. Ich denke soweit kann man den Code dann doch nicht optimieren:



#define AVRGCC
#include <avr/io.h>
#include <compiler.h>
#include <avr/eeprom.h>
/**
Der AVR übernimmt die Steuerung der Relais für die Kanalwahl und Phase.
IO's:
PB0 OUT Relais Strobe
PB1 OUT Relais Data
PB2 OUT Relais CLK
PB3 OUT Power-LED
PB4 OUT Power-LED
PB5 SPI
PB6 SPI
PB7 SPI
PD0 IN Sub1
PD1 IN Sub2
PD2 IN IR Empfänger
PD3 IN Set
PD4 IN Power Supply On
PD5 ---
PD6 ---
Speaker-Relais:
Links = Sub 1
Rechts = Sub 2
**/

U8 ShiftByte = 0;
U8 PowerState = 255;
U8 ActiveSub = 1;
U8 Phase_1L = 0;
U8 Phase_1R = 0;
U8 Phase_2L = 0;
U8 Phase_2R = 0;
#define RelSigLinks 7
#define RelSigRechts 6
#define RelPhaseLinks 5
#define RelPhaseRechts 4
#define RelSubLinks 3
#define RelSubRechts 2
#define LEDSub1 1
#define LEDSub2 0

#define RelSigLinks0 ShiftByte = ~(~ShiftByte | (1<<RelSigLinks))
#define RelSigLinks1 ShiftByte = (ShiftByte | (1<<RelSigLinks))
#define RelSigRechts0 ShiftByte = ~(~ShiftByte | (1<<RelSigRechts))
#define RelSigRechts1 ShiftByte = (ShiftByte | (1<<RelSigRechts))
#define RelPhaseLinks0 ShiftByte = ~(~ShiftByte | (1<<RelPhaseLinks))
#define RelPhaseLinks1 ShiftByte = (ShiftByte | (1<<RelPhaseLinks))
#define RelPhaseRechts0 ShiftByte = ~(~ShiftByte | (1<<RelPhaseRechts))
#define RelPhaseRechts1 ShiftByte = (ShiftByte | (1<<RelPhaseRechts))
#define RelSubLinks0 ShiftByte = ~(~ShiftByte | (1<<RelSubLinks))
#define RelSubLinks1 ShiftByte = (ShiftByte | (1<<RelSubLinks))
#define RelSubRechts0 ShiftByte = ~(~ShiftByte | (1<<RelSubRechts))
#define RelSubRechts1 ShiftByte = (ShiftByte | (1<<RelSubRechts))
#define LEDSub1_0 ShiftByte = ~(~ShiftByte | (1<<LEDSub1))
#define LEDSub1_1 ShiftByte = (ShiftByte | (1<<LEDSub1))
#define LEDSub2_0 ShiftByte = ~(~ShiftByte | (1<<LEDSub2))
#define LEDSub2_1 ShiftByte = (ShiftByte | (1<<LEDSub2))
#define RelaisStrobe0 PORTB = ~(~PORTB | (1<<PB0))
#define RelaisStrobe1 PORTB = (PORTB | (1<<PB0))
#define RelaisData0 PORTB = ~(~PORTB | (1<<PB1))
#define RelaisData1 PORTB = (PORTB | (1<<PB1))
#define RelaisCLK0 PORTB = ~(~PORTB | (1<<PB2))
#define RelaisCLK1 PORTB = (PORTB | (1<<PB2))
#define PowerLED1_0 PORTB = ~(~PORTB | (1<<PB3)) // rot
#define PowerLED1_1 PORTB = (PORTB | (1<<PB3))
#define PowerLED2_0 PORTB = ~(~PORTB | (1<<PB4)) // grün
#define PowerLED2_1 PORTB = (PORTB | (1<<PB4))
#define TasteSub1 ((PIND & (1<<PD0)) == 0)
#define TasteSub2 ((PIND & (1<<PD1)) == 0)
#define TasteSet ((PIND & (1<<PD3)) == 0)
#define PowerSupplyOn ((PIND & (1<<PD4)) == 0)

#define Wait_Shift 30

void Wait (U16 Time)
{
U16 i1;
for (i1 = 0; i1 < Time; i1++)
asm volatile ("NOP");
}
void ShiftOut (void)
{
U8 Temp = ShiftByte;
U8 i1;
RelaisStrobe0;
RelaisCLK1;
Wait (Wait_Shift);
for (i1 = 0; i1 < 8;i1++)
{
if ((Temp & 1) == 0)
RelaisData0;
else
RelaisData1;

Wait (Wait_Shift);
RelaisCLK0;
Wait (Wait_Shift);
RelaisCLK1;
Wait (Wait_Shift);
Temp = (Temp>>1);
}
RelaisStrobe1;
}

void SetOutputs (U8 showPhase)
{
switch (ActiveSub)
{
case 1: { RelSigLinks0;
RelSigRechts0;
if (Phase_1L == 0)
RelPhaseLinks0;
else
RelPhaseLinks1;
if (Phase_1R == 0)
RelPhaseRechts0;
else
RelPhaseRechts1;
RelSubLinks0;
RelSubRechts0;
LEDSub1_1;
LEDSub2_0;
break;
}
case 2: { RelSigLinks1;
RelSigRechts1;
if (Phase_2L == 0)
RelPhaseLinks0;
else
RelPhaseLinks1;
if (Phase_2R == 0)
RelPhaseRechts0;
else
RelPhaseRechts1;
RelSubLinks1;
RelSubRechts1;
LEDSub1_0;
LEDSub2_1;
break;
}
}
if (showPhase == 1)
{
U8 tmpShiftByte = ShiftByte;
U8 tmpFlashByte;
LEDSub1_0;
LEDSub2_0;
PowerLED1_1;
PowerLED2_0;
ShiftOut ();
Wait (5000);
switch (ActiveSub)
{
case 1: { if (Phase_1L == 1)
LEDSub1_1;
if (Phase_1R == 1)
LEDSub2_1;
break;
}
case 2: { if (Phase_2L == 1)
LEDSub1_1;
if (Phase_2R == 1)
LEDSub2_1;
break;
}
}
ShiftOut ();
tmpFlashByte = ShiftByte;
Wait (1000);
ShiftByte = tmpShiftByte;
LEDSub1_0;
LEDSub2_0;
ShiftOut ();
Wait (1000);
ShiftByte = tmpFlashByte;
ShiftOut ();
Wait (5000);
PowerLED1_0;
PowerLED2_1;
ShiftByte = tmpShiftByte;
}
ShiftOut ();
}

void loadSettings (void)
{
ActiveSub = eeprom_read_byte (1);
Phase_1L = eeprom_read_byte (2);
Phase_1R = eeprom_read_byte (3);
Phase_2L = eeprom_read_byte (4);
Phase_2R = eeprom_read_byte (5);
if (ActiveSub < 1) ActiveSub = 1;
if (ActiveSub > 2) ActiveSub = 2;
if (Phase_1L > 1) Phase_1L = 0;
if (Phase_1R > 1) Phase_1R = 0;
if (Phase_2L > 1) Phase_2L = 0;
if (Phase_2R > 1) Phase_2R = 0;
}
void saveSettings (void)
{
eeprom_write_byte (1, ActiveSub);
eeprom_write_byte (2, Phase_1L);
eeprom_write_byte (3, Phase_1R);
eeprom_write_byte (4, Phase_2L);
eeprom_write_byte (5, Phase_2R);
}

int main(void)
{
DDRB = 0b00011111;
PORTB = 0b00000000;
DDRD = 0b00000000;
PORTD = 0b00011011;
RelaisStrobe1;
RelaisCLK1;
loadSettings ();

ShiftOut ();


while (1)
{
if (PowerSupplyOn)
{
if (PowerState != 0)
{
PowerLED1_0;
PowerLED2_1;
PowerState = 1;
SetOutputs (0);
}

if (PowerState == 1)
{
if (TasteSub1)
{
ActiveSub = 1;
SetOutputs (0);
saveSettings ();
Wait (1000);
while (TasteSub1)
Wait (1000);
}
if (TasteSub2)
{
ActiveSub = 2;
SetOutputs (0);
saveSettings ();
Wait (1000);
while (TasteSub2)
Wait (1000);
}
if (TasteSet)
{
switch (ActiveSub)
{
case 1: { if (Phase_1L == 0)
{
if (Phase_1R == 0)
{
Phase_1R = 1;
}
else
{
Phase_1L = 1;
Phase_1R = 0;
}
}
else
{
if (Phase_1R == 0)
{
Phase_1R = 1;
}
else
{
Phase_1L = 0;
Phase_1R = 0;
}
}
break;
}
case 2: { if (Phase_2L == 0)
{
if (Phase_2R == 0)
{
Phase_2R = 1;
}
else
{
Phase_2L = 1;
Phase_2R = 0;
}
}
else
{
if (Phase_2R == 0)
{
Phase_2R = 1;
}
else
{
Phase_2L = 0;
Phase_2R = 0;
}
}
break;
}
}
SetOutputs (1);
saveSettings ();

Wait (1000);
while (TasteSet)
Wait (1000);
}
}
}
else
{
if (PowerState != 0)
{
ShiftByte = 0;
ShiftOut ();
PowerLED1_1;
PowerLED2_0;
PowerState = 0;
}
}
}
return(0);
}


Viele Grüße
Andreas

TobiKa
26.04.2011, 15:36
Habs grad mal getestet.
Ohne optimierung 2006 Bytes, mit Optimierung 1296 Bytes.
Man müsste nur gucken ob er nichts wichtiges, besonders Pausen, weg optimiert hat.

Besserwessi
26.04.2011, 18:05
Selbst 1296 Bytes kommen mir für das Programm noch recht viel vor, kann aber Täuschen wegen der vielen #Define.

Falls es wirklich gebraucht wird, gibt es relativ neu den ATiny4313 als Version mit dem doppelten Speicher.

Bumbum
26.04.2011, 20:30
Hallo Besserwessi,

der 4313 ist der richtige Tipp. Danke! Die zwei teilen sich ja mittlerweile sogar das gleiche Datenblatt. Nur ich habe leider keine Bezugsquelle dafür gefunden. (Brauche ja nur einen...)
Hast du noch einen Tipp, wo man den 4313 kaufen kann?

Viele Grüße
Andreas

Besserwessi
26.04.2011, 20:42
Bei dem Code kann man vermutlich noch einiges Optimieren. Es ist aber durch die vielen Defines etwas schlecht zu sehen.

Ein mögliche Quelle wäre:
http://www.tme.eu/de/katalog/#idp%3D1%26search%3Dtiny4313

Angeblich haben die jetzt auch eine Niederlassung in Deutschland, also kleine Polnische Mwst. mehr.

TobiKa
26.04.2011, 20:45
Es gibt ihn auch noch bei Farnell, 2,85€ der IC und 7,95€ Versand :D

Bumbum
19.05.2011, 18:42
Hallo,

ich habe gerade was herausgefunden. Wenn ich die Defines der IO's tausche von



#define RelaisStrobe0 PORTB = ~(~PORTB | (1<<PB0))
#define RelaisStrobe1 PORTB = (PORTB | (1<<PB0))
#define RelaisData0 PORTB = ~(~PORTB | (1<<PB1))
#define RelaisData1 PORTB = (PORTB | (1<<PB1))
#define RelaisCLK0 PORTB = ~(~PORTB | (1<<PB2))
#define RelaisCLK1 PORTB = (PORTB | (1<<PB2))
#define PowerLED1_0 PORTB = ~(~PORTB | (1<<PB3)) // rot
#define PowerLED1_1 PORTB = (PORTB | (1<<PB3))
#define PowerLED2_0 PORTB = ~(~PORTB | (1<<PB4)) // grün
#define PowerLED2_1 PORTB = (PORTB | (1<<PB4))


zu



#define RelaisStrobe0 asm volatile ("cbi 0x18, 0")
#define RelaisStrobe1 asm volatile ("sbi 0x18, 0")
#define RelaisData0 asm volatile ("cbi 0x18, 1")
#define RelaisData1 asm volatile ("sbi 0x18, 1")
#define RelaisCLK0 asm volatile ("cbi 0x18, 2")
#define RelaisCLK1 asm volatile ("sbi 0x18, 2")
#define PowerLED1_0 asm volatile ("cbi 0x18, 3") // rot
#define PowerLED1_1 asm volatile ("sbi 0x18, 3")
#define PowerLED2_0 asm volatile ("cbi 0x18, 4") // grün
#define PowerLED2_1 asm volatile ("sbi 0x18, 4")


spart mir das fast 10% Platz im AVR. Ist dies eventuell auch mit den Variablen möglich? Kann man z.B. Eine Variable in C direkt an ein Register binden und dann auch solche Optimierungen mit cbr und sbr durchführen:



U8 ShiftByte = 0;

#define RelSigLinks0 ShiftByte = ~(~ShiftByte | (1<<RelSigLinks))
#define RelSigLinks1 ShiftByte = (ShiftByte | (1<<RelSigLinks))
#define RelSigRechts0 ShiftByte = ~(~ShiftByte | (1<<RelSigRechts))
#define RelSigRechts1 ShiftByte = (ShiftByte | (1<<RelSigRechts))
#define RelPhaseLinks0 ShiftByte = ~(~ShiftByte | (1<<RelPhaseLinks))
#define RelPhaseLinks1 ShiftByte = (ShiftByte | (1<<RelPhaseLinks))
#define RelPhaseRechts0 ShiftByte = ~(~ShiftByte | (1<<RelPhaseRechts))
#define RelPhaseRechts1 ShiftByte = (ShiftByte | (1<<RelPhaseRechts))
#define RelSubLinks0 ShiftByte = ~(~ShiftByte | (1<<RelSubLinks))
#define RelSubLinks1 ShiftByte = (ShiftByte | (1<<RelSubLinks))
#define RelSubRechts0 ShiftByte = ~(~ShiftByte | (1<<RelSubRechts))
#define RelSubRechts1 ShiftByte = (ShiftByte | (1<<RelSubRechts))
#define LEDSub1_0 ShiftByte = ~(~ShiftByte | (1<<LEDSub1))
#define LEDSub1_1 ShiftByte = (ShiftByte | (1<<LEDSub1))
#define LEDSub2_0 ShiftByte = ~(~ShiftByte | (1<<LEDSub2))
#define LEDSub2_1 ShiftByte = (ShiftByte | (1<<LEDSub2))


Viele Grüße
Andreas

Besserwessi
19.05.2011, 19:13
In der Regel ist der Compiler bei der verwendung der Register schon nicht so schlecht - wenn man da was von Hand macht, wird es oft schlecher.

Was ist denn an Optimierung eingestellt. Ich dachte gcc mach die oben von Hand eingefügte Optimierung auch schon automatisch, wenn man mit -o2 oder -os compiliert.

BMS
19.05.2011, 21:07
Hallo,
nützt es vielleicht noch etwas, wenn du die Wait-Funktion als "inline" machst? Gerade bei so kurzen Methoden bietet sich das an. Eventuell spart das noch ein paar Bytes ein.
Kannst du vielleicht an der switch-Anweisung noch etwas kürzen?
Grüße, Bernhard

Besserwessi
19.05.2011, 22:47
Inline wird bei einer so häufig genutzen Funktion kaum einen kürzeren Code bringen. Eventuell bringt es etwas die Funktion als static zu deklarieren.

Bumbum
20.05.2011, 12:56
Hallo,

ich habe mir heute bei Farnell ein paar Tiny4313 bestellt. Aber trotzdem wollte ich das Thema Optimierung noch mal ansprechen, da ich bis jetzt nicht darauf eingegangen bin.

Ich bin davon ausgegangen, dass die Optimierungen automatisch durchgeführt werden.

@TobiKa: Wie hast du diese Optimierung aktiviert, um deine oben genannte Ersparnis zu erreichen?


Was ist denn an Optimierung eingestellt. Ich dachte gcc mach die oben von Hand eingefügte Optimierung auch schon automatisch, wenn man mit -o2 oder -os compiliert.

Scheinbar ist dies nicht der Fall. Ich habe nach den Einstellungen für die Optimierung gesucht, aber leider nichts gefunden. Die einzig für mich sinnvolle Position für deine Änderungsvorschläge war im Menü unter Project/Configure Options und dort unter Custom Options in der rechte Liste mit add -o2 oder -os einzufügen. Leider wird dadurch das Projekt gar nicht mehr kompiliert. Ich erhalte die Fehlermeldung "avr-gcc.exe: StereoSubWeiche.o: No such file or directory"

Was mache ich falsch?

Viele Grüße
Andreas

Besserwessi
20.05.2011, 15:59
Die Optimierung kann man bei AVRStudio mit GCC bei Project/Configure Options unter General einstellen. Da gibt es ein extra Feld für.

Das GCC die Optimierung so nicht erkennt, wundert mich etwas. Bei der Schreibweise PORTB |= (1<<test) tut er das angeblich schon.

Bumbum
24.05.2011, 09:04
Hallo,

meine 4313 sind gekommen. Aber ich muss noch mal auf das Thema Optimierung kommen. Die Optionen dazu habe ich jetzt gefunden, und bei beiden Einstellungen (-O2 und -Os) verringert sich der benötigte Platz Flash des 2313 auf knapp über 50%. Die Optimierung war vorher auf -O0 gestanden.

Nur leider wird, wie von TobiKa bereits vermutet, die Warteschleife ebenfalls rausoptimiert. Gibt es eine Möglichkeit trotz Optimierung die Warteschleife beizubehalten?

Viele Grüße
Andreas

Bumbum
24.05.2011, 13:48
Hallo nochmal,

ich habe jetzt die Wait-Funktion durch Funktionen aus der Delay.h getauscht, jetzt läuft das Programm wieder.

Viele Grüße
Andreas