Ik heb een probleempje bij het weergeven van tekst op mijn HD44780 LCD (met ATmega8). Afzonderlijke karakters lukt wel, maar wanneer ik
char words[] = "foo";
lcd_string(words);
probeer, dan krijg ik blokjes en andere vreemde karakters. Het volgende lukt trouwens wel:
char words[] = {'f', 'o', 'o', '\0'};
lcd_string(words);
Na wat googlen krijg ik de indruk dat het iets te maken heeft met RAM versus flash geheugen, maar ik heb nog geen concrete oplossing gevonden.
#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#define RS 4
#define E 5
void sbi(mask){
PORTC |= (1 << mask);
}
void cbi(mask){
PORTC &= ~(1 << mask);
}
void e_toggle(){
sbi(E);
_delay_us(1);
cbi(E);
}
void lcd_cmd(unsigned char letter){
PORTC = (letter >> 4);
cbi(RS);
e_toggle();
PORTC = letter;
cbi(RS);
e_toggle();
_delay_ms(1);
}
void lcd_char(char letter){
PORTC = (letter >> 4);
sbi(RS);
e_toggle();
PORTC = letter;
sbi(RS);
e_toggle();
_delay_ms(1);
}
void lcd_init(){
cbi(RS);
PORTC = 0x03;
e_toggle();
_delay_ms(50);
PORTC = 0x03;
e_toggle();
_delay_ms(50);
PORTC = 0x03;
e_toggle();
_delay_ms(50);
PORTC = 0x02;
e_toggle();
_delay_ms(50);
lcd_cmd(0x28); // 4-bit mode - 2 line - 5x7 font.
lcd_cmd(0x0D); // Display no cursor - no blink.
lcd_cmd(0x06); // Automatic Increment - No Display shift.
lcd_cmd(0x01);
}
void lcd_line1(){
lcd_cmd(0x80);
}
void lcd_line2(){
lcd_cmd(0xc0);
}
void lcd_string(char *senpoint)
{
while(*senpoint != '\0'){
lcd_char(*senpoint);
senpoint++;
}
}
int main(void){
DDRC = 0xff;
_delay_ms(50);
cbi(E);
lcd_init();
lcd_line1();
//char words[] = {'f', 'o', 'o', '\0'};
char words[] = "foo";
lcd_string(words);
//lcd_char(0x41);
//lcd_char(65);
//lcd_char((char)'A');
while(1);
}
Bedankt!
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
char words[] = "foo";
char words[] = {'f', 'o', 'o', '\0'};
Da's net hetzelfde.
Maar:
void sbi(mask){ ...
Komt avr-gcc niet in opstand tegen zoiets! Er wordt van je verwacht, dat je opgeeft welk soort argument de subroutine kan verwachten. Doe je dat niet, dan moet je iets te zien krijgen als:
JeBroncode.c:11: warning: function declaration isn't a prototype
Wat je dus moet doen, is:
void sbi(char mask){ ...
void e_toggle(void){ ...
Dat levert bij mij een hex-file op, die 33 karakters minder telt dan de oorspronkelijke versie.
Voor zulke 1-regel subroutines kan je overigens beter een "#define" gebruiken. Maar dat is niet de oorzaak van je probleem.
Op 22 juni 2009 21:22:37 schreef pros:
char words[] = "foo"; char words[] = {'f', 'o', 'o', '\0'};Da's net hetzelfde.
In principe wel, maar toch werkt het ene wel en het ander niet. Vandaar mijn vraag dus...
Probleem opgelost dmv PROGMEM:
void lcd_string(char *entrypoint)
{
while(pgm_read_byte(entrypoint) != '\0'){
lcd_char(pgm_read_byte(entrypoint));
entrypoint++;
}
}
lcd_string(PSTR("testing..."));
zie http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&am…
pros
Prosper, yop la boum, c'est le roi du macadam (aldus Maurice Chevalier)
Op 22 juni 2009 22:12:43 schreef pieterprovoost:
In principe wel, maar toch werkt het ene wel en het ander niet. Vandaar mijn vraag dus...
Er is toch iets raars mee.
Als [char words[] = "foo";] binnen de main()-routine staat, levert dat een hex-bestand van 1335 bytes op.
Met [char words[] = {'f', 'o', 'o', '\0'};] binnen de main()-routine wordt dat 1290 bytes.
Plaats je de string buiten de main()-routine, dan zakt de grootte van het hex-bestand tot 1090 bytes. Welk van de twee varianten je gebruikt, maakt dan geen verschil meer.
Het gebruik van PROGMEM is uiteraard ideaal als het om data gaat die niet gewijzigd hoeft te worden door het programma.