2010-11-23 33 views
2

J'ai un écran LCD, connecté à un Atmega32, en travaillant avec des caractères uniques en utilisant cette fonction:Affichage des caractères ASCII d'un tableau sur un écran LCD avec ATmega32

void send_char(uint8_t c){ 
    PORTD = c; // set the output pins to the ascii value of the char 
    PORTB |= 0x05; 
    _delay_us(1); 
    PORTB &= 0xfa; 
    _delay_us(60); 
    PORTD = 0x00; 
    update_cursor(); 
} 

je peux appeler cela avec un caractère comme argument: send_char('a'); et cela fonctionne.

Alors j'ai essayé enroulant une fonction send_string autour:

void send_string(const char * msg){ 
    while (*msg != '\0'){ 
     send_char(*msg++); 
    } 
} 

Cela met juste charabia sur mon LCD indiquant que la valeur ASCII est loin. Et quand j'essaie de passer une chaîne vide (send_string("")), un minimum de trois caractères charabia s'affiche sur l'écran LCD.

+1

L'envoi avec la chaîne vide devrait être un do-nothing, puisque '* msg == '\ 0''. Y a-t-il du code en cours d'exécution après cela qui risque de perturber votre affichage? L'affichage est-il initialisé correctement? – nmichaels

+0

l'affichage semble être initialisé correctement car je peux envoyer n'importe quel nombre de caractères en utilisant send_char() et tout va bien et rien d'autre ne sera envoyé à l'affichage sauf une mise à jour de la position du curseur de send_char. – fasseg

Répondre

3

Tout d'abord, il semble que vous utilisiez le compilateur avr-gcc. Lorsque vous faites des questions sur les périphériques intégrés, vous devez toujours indiquer le compilateur que vous utilisez.

Je vais maintenant essayer de vous aider à comprendre ce qui ne va pas avec votre code et pourquoi votre solution fonctionne. La fonction que vous avez définie:

void send_string(const char * msg); 

attend un pointeur de chaîne dans la RAM. Peu importe que vous ayez utilisé le mot clé const, le compilateur s'attend toujours à ce que la chaîne soit en RAM. Donc, si vous avez une chaîne dans la mémoire morte:

const char msg[] PROGMEM = "Test"; 

et vous essayez de le transmettre dans votre fonction:

send_string(msg); 

il passe juste une adresse invalide à elle et donc charabia sont affichés.Si au contraire vous copiez d'abord la RAM, comme vous l'avez fait dans votre solution, il fonctionne très bien:

char buf[strlen(msg)]; 
strcpy_P(buf,msg); 
send_string(buf); 

Si vous souhaitez définir une fonction qui va lire une chaîne de ROM, vous pouvez le faire comme ceci:

void send_string_P(const char *data) 
{ 
    while (pgm_read_byte(data) != 0x00) 
     send_char(pgm_read_byte(data++)); 
} 

Notez le suffixe _P. C'est la convention générale utilisée pour les fonctions distinctes qui fonctionnent sur ROM à partir de celles qui fonctionnent sur RAM.

Tout cela et bien d'autres sont bien expliqués here. Je suggère également que vous essayez le AVR Freaks forum pour ce genre de questions. Les gens là-bas seront certainement plus expérimentés dans ces questions que Stack   Les utilisateurs de débordement et sont toujours heureux d'aider.

1

Je ne vois rien de mal manifestement avec votre code (pas que je sache parler à un Atmega32). Essayez de l'exécuter sous un débogueur et imprimez c à chaque invocation à send_char, ou mettez simplement printf("%d\n", (int)c); comme première ligne à send_char.

1

Cela fonctionne pour moi:

#include <stdio.h> 
#include <stdint.h> 

void send_char(uint8_t c) 
{ 
    printf("%c", c); 
} 

void send_string(const char * msg) 
{ 
    while (*msg != '\0') 
    { 
     send_char(*msg++); 
    } 
} 

int main() 
{ 
    send_string("Stackoverflow!"); 

    return 0; 
} 

Dans votre code, insérez sleep(1); après l'appel send_char() et voir si elle modifie le comportement que vous observez.

1

Cela fonctionne sur mon contrôleur Atmel (bien que je ne sais pas pourquoi):

premier doit ajouter le littéral à la ROM par l'intermédiaire de PROGMEM <avr/pgmspace.h>:

const char msg[] PROGMEM = "Test"; 

Copiez ensuite le littéral à un tampon dans la RAM du contrôleur:

char buf[strlen(msg)]; 
strcpy_P(buf,msg); 

maintenant send_string(msg) peut être utilisé comme prévu ..

+0

vous ne nous avez pas montré comment msg a été défini à l'avance, comment vous appelez send_string() – lImbus

+0

'char buf [] =" Test ";' devrait aussi fonctionner. – caf

+0

@limubs: comme je l'ai écrit dans la question que j'appelais send_string (""). et même avec une chaîne vide j'obtiendrais des caractères brouillés ... – fasseg