C UART String überschreitet Programmspeicher?

Folienkondensator

Neues Mitglied
28. Mai 2012
89
0
0
Sprachen
  1. ANSI C
  2. Assembler
Hallo

Ich hab heute mal versucht unsere Heizung via RS232 an zu steuern. Soweit kein Problem und alles funktioniert einwandfrei.
Aber wenn ich einen bestimmten zyklus abfahren will brauche ich natürlich mehrere Strings. Und dann fängt das problem an.
Der Programmspeicher ist überfüllt und es funktioniert nichtsmehr so wie es soll. :(
Ich hab schon den ganzen tag gegooglet und versucht alles aus dem String raus zu nehmen was ich nicht dringend brauche. Es wiord viel geschrieben dass man die Strings in den Flash Speicher schreiben soll. das macht evtl Sinn, aber wie das funktioniert kann niemand so wirklich erklären.
Kann mir das jemand verständlich und praktisch umsetzbar erklären?

Gruß

Hier mal die Strings damit man mal siht welche Datenfluten das sind.
Code:
	while (1)
	{
				switch (Zeit)
				{		
					case 10:
					_delay_ms(500);
					uart_putstring("\n$01E 0010.0 0080.0 0080.0 0000.0 0000.0 0000.0 0000.0 011 00000000000000000000000000000\r");		
					_delay_ms(500);
					uart_putstring("\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 011 00000000000000000000000000000\r");		
					_delay_ms(100);
					break;
					
					case 30:
					_delay_ms(500);
					uart_putstring("\n$01E 0020.0 0040.0\r");	
					_delay_ms(500);
					uart_putstring("\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 010 00000001010000000000000000000\r");		
					_delay_ms(100);
					break;
					
					case 50:
					_delay_ms(1000);
					uart_putstring("\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 010 00000001000000000000000000000\r");		
					_delay_ms(100);
					break;
					
					case 70:		
					uart_putstring("\n$01E 0070.0 0012.0\r");		
					_delay_ms(1000);
					uart_putstring("\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 010 00000000000000000000000000000\r");		
					_delay_ms(100);
					break;
					
					case 90:	
					_delay_ms(1000);
					uart_putstring("\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 010 00000000010000000000000000000\r");		
					_delay_ms(100);
					break;
					
					case 110:
					uart_putstring("\n$01E 0060.0 0020.0\r");		
					_delay_ms(600);
					uart_putstring("\n$02E 0060.0 0020.0 0056.0 0000.0 0000.0 0000.0 0000.0 010 00000000010000000000000000000\r");
					_delay_ms(500);						
					break;
					
					case 130:
					_delay_ms(500);			
					uart_putstring("\n$01E 0020.0 0040.0 0080.0 0000.0 0000.0 0000.0 0000.0 000 00000000000000000000000000000\r");		
					_delay_ms(500);
					uart_putstring("\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 000 00000000000000000000000000000\r");		
					_delay_ms(100);
					break;

					

					case 800:
					Zeit=0;
					cnt=0;
					Sekunden=0;
					Minuten=0;
					Stunden=0;
					break;		
		}
			Lumpensammler=0;		
	}
	
	
	
	return 0;
}
 
Ähem... Program Flash = Programmspeicher

Bei einem ASCII-String entspricht halt jedes Zeichen einem Byte (und ein weiteres Byte als Stringende). Andere Codierungen brauchen mehr, klar. Deine Frage ist also eher, wie Du mehrfach verwendete Teilstrings wiederverwerten kannst. Üblicherweise definierst Du Dir Konstanten (meinetwegen im Flash), und setzt den ganzen zu sendenden String dann aus den Konstanten zusammen.
 
Hi
Danke für die schnelle Antwort.
Wie genau ruf ich den String wieder auf?

Ich habe diese wie folgt bisher angelegt:
Code:
const char FlashString1[] PROGMEM = "\nHello World\r";
//usw..
char* FlashStringArray[]={FlashString1,FlashString2,FlashString3,...}

Wie muss ich meinen alten Aufruf
Code:
uart_putstring("sdfsdfsd")
anpassen?

Am besten jemand hat für mich ein einfaches Beispiel?

Gruß
 
Eigentlich ganz einfach:

Code:
const char FlashString1[] PROGMEM = "\nHello World\r";

void uart_putstring(const char *str);

void uart_putstring(const char *str) {
     while (pgm_read_byte(str) != 0x00)
     USART_Tx(pgm_read_byte(str++)); // hier wird das Zeichen in den USART-Puffer geschoben.
}

Interessant ist an der Stelle pgm_read_byte().
 
Hi
Hat geklapt! :)

Nur steh ich jetzt vor dem anderen Problem dass ich ja mehrere Strings habe und ich die alle nacheinander abrufen müsste. Das Abrufen funktioniert aber anscheinend nur direkt in der MAIN Schleife also müsste ich ja alle Strings vor der While Schleife laden. aber dann ist der Programmspeicher ja wider überfüllt oder? Aber das eigendliche Problem das ich ahbe ist ein anderes. Ich habe mal versucht die Strings hintereinander zu laden. das funktioniert aber nicht, weil beim zweiten mal Laden anscheinend "addr" nicht verlinkt ist (zumindest meckert AVR Studio)
Was hab ich da falsch gemacht?
Das siht dann so aus:


Code:
#include <avr/io.h>
#include <avr/pgmspace.h>
....
const char pgmString1[] PROGMEM = "Hello world";
const char pgmString2[] PROGMEM = "Test zwei";
....

main (void)
{

char a;
const char* addr;
addr = pgmString1;
	
char b;
const char* addr;
addr = pgmString1;


	while (1)
	{

		switch (Zeit)
		{		
			


			
		case 5:
		while (a = pgm_read_byte (addr++), a != '\0')
			{
			uart_putchar(a);
			}
		_delay_ms(2000);
		break;



					
		case 10:
		while (b = pgm_read_byte (addr++), b != '\0')
			{
			uart_putchar(b);
		_delay_ms(2000);
		break;


				
	}
}
 
Meinst Du diese Variable addr:

Code:
const char* addr;

oder irgendeine Andere?

Warum deklarierst Du die Variable addr zwei mal und warum schreibst Du zwei mal den Wert rein?

Und was meinst Du mit "zwei Mal laden"? Ich verstehe ehrlich gesagt nicht so ganz, was Du machen willst.

Grüße
Heinrich
 
Mal 'ne andere Frage dazu: In seinem ersten Beispiel hat er doch mehrfach:
Code:
uart_putstring("\n$01E 0010.0 0080.0 0080.0 0000.0 0000.0 0000.0 0000.0 011 00000000000000000000000000000\r");
verwendet (jeweils mit unterschiedlichen String-Argumenten). Werden diese String-Konstanten nicht beim Compilieren bzw danach beim "Brennen" eh im Programmflash (eben als Konstanten) abgelegt? Und zur Laufzeit von dort geladen? Der Knackpunkt ist doch eher, daß er bisher mehrfach nahezu identische Strings, bzw Strings mit relativ langen (jedes Zeichen = 1 byte) identischen Teilstrings im Flash abgelegt hat, oder? Wenn man die zu senden Strings also in "sinnige" Teilstrings zerlegt, und identische (Teil-)Strings jetzt eben nicht mehr mehrfach im Flash ablegt, müßte man den jeweiligen String vor dem Senden nur noch zusammenbauen lassen. Bietet "uart_putstring" dazu keine Konkatenation an? C ist doch 'ne Hochsprache...
 
Hi,

ich habe jetzt eine saubere Version am Laufen, jedoch durch meine Funktion ein neues Problem.
Ich arbeite nun mit der Funktion
Code:
void uart_puts_p(const char *text)
{
	char zeichen;
	
	while ((zeichen = pgm_read_byte (text)))
	{
		// so lange, wie mittels pgm_read_byte nicht das Stringende
		// gelesen wurde: gib dieses Zeichen aus
		
		uart_putchar(zeichen);
		text++;
	}
}

und rufe diese später so z.B. auf
Code:
	case 10: 
					uart_puts_p(FlashStringArray[0]);
				             break;

Die String werden zuvor angelegt:
Code:
const char pgmString1[] PROGMEM = "\n$02E 0010.0 0080.0 0056.0 0000.0 0000.0 0000.0 0000.0 011 00000000000000000000000000000\r";
char* FlashStringArray[]={pgmString1,pgmString2,usw..};

Das Problem ist nun, dass die uart_puts_p-Funktion nicht mehr meine \n und \r Befehle erkennt. Diese brauche ich später, um CR zu senden.
Wie bekomm ich das wieder hin. Ohne Flash-Speicher hatte ich diese Funktion benutzt:
Code:
void uart_putstring(char *str)
{
	unsigned char i;

	for (i=0;i<255;i++)				// Maximal 255 Zeichen ausgeben ... 
	{
		if (str[i] != 0)
			uart_putchar(str[i]);
		else
			break;					// Ende des Strings erreicht
	}
}


Weiß wer was?
Gruß :hello:
 
Ich sehe gerade, du hattest die Steuerzeichen geändert ("/r" -> "\r"). Nun müsste es wieder funktionieren?!

Dirk
 
Hi

Ja, das hab ich grade bemerkt. und ich hab bemerkt, dass es nicht funktionieren kann wenn man den falschen HEX Code auf den Chip schreibt xD
Jetzt funktionierts aber.
Danke ;)
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)