Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

printf sur un afficheur LCD

10 réponses
Avatar
noone
Bonsoir,


je programme actuellement un microcontr=F4leur (ATMEL AVR ATmega128 avec
WinAVR gcc et VMLAB comme IDE)

J'utilise une biblioth=E8que pour utiliser un afficheur LCD caract=E8re
parall=E8le (type HD44780).
C'est la biblioth=E8que de Peter Fleury
http://homepage.hispeed.ch/peterfleury/

Elle contient par exemple la fonction tr=E8s utile

void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
register char c;

while ( (c =3D *s++) ) {
lcd_putc(c);
}

}/* lcd_puts */


donc en faisant lcd_puts("hello")
=E7a affiche hello sur le LCD.


Le probl=E8me c'est que j'ai besoin de faire des sorties format=E9es

exemple :
printf("%02i:%02i:%02i:%03u",t->hh,t->mm,t->ss,t->xx/((int)
pow(10,CHR_PRECISION-CHR_DISPLAY)));


Comment cr=E9er ma fonction propre fonction printf (disons lcd_printf) ?
Cette fonction appelerai =E9videmment lcd_puts(...)


Merci d'avance

10 réponses

Avatar
Pierre Maurette
Bonsoir,


je programme actuellement un microcontrôleur (ATMEL AVR ATmega128 avec
WinAVR gcc et VMLAB comme IDE)

J'utilise une bibliothèque pour utiliser un afficheur LCD caractère
parallèle (type HD44780).
C'est la bibliothèque de Peter Fleury
http://homepage.hispeed.ch/peterfleury/

Elle contient par exemple la fonction très utile

void lcd_puts(const char *s)
/* print string on lcd (no auto linefeed) */
{
register char c;

while ( (c = *s++) ) {
lcd_putc(c);
}

}/* lcd_puts */


donc en faisant lcd_puts("hello")
ça affiche hello sur le LCD.


Le problème c'est que j'ai besoin de faire des sorties formatées

exemple :
printf("%02i:%02i:%02i:%03u",t->hh,t->mm,t->ss,t->xx/((int)
pow(10,CHR_PRECISION-CHR_DISPLAY)));


Comment créer ma fonction propre fonction printf (disons lcd_printf) ?
Cette fonction appelerai évidemment lcd_puts(...)


Vous utilisez sprintf(), par exemple ?

--
Pierre Maurette

Avatar
noone
Comment créer ma propre fonction printf (disons lcd_printf) ?
Cette fonction appelerai évidemment lcd_puts(...)


Vous utilisez sprintf(), par exemple ?


merci pour sprintf (que je n'ai jamais utilisé)

mais comment faire pour créer ma fonction lcd_printf
qui prend les même arguments que printf (en nombre variable)
et qui contient une initialisation de la chaine tampon (de quelle
taille d'ailleurs ?)
ainsi qu'un appel de lcd_puts(tampon)


Avatar
Eric Levenez
Le 23/09/06 20:40, dans
,
«  » a écrit :

mais comment faire pour créer ma fonction lcd_printf
qui prend les même arguments que printf (en nombre variable)
et qui contient une initialisation de la chaine tampon (de quelle
taille d'ailleurs ?)
ainsi qu'un appel de lcd_puts(tampon)


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

extern void lcd_printf(const char *msg, ...);
#define lcd_putc putchar

int main(void)
{
lcd_printf("Hello world %dn", 42);
return EXIT_SUCCESS;
}

void lcd_printf(const char *msg, ...)
{
va_list ap;
char c;
char tmp[80];
char * s;

va_start(ap, msg);
vsnprintf(tmp, sizeof tmp, msg, ap);
va_end(ap);

s = tmp;
while ((c = *s++))
lcd_putc(c);
}


--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.

Avatar
noone
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

extern void lcd_printf(const char *msg, ...);
#define lcd_putc putchar

int main(void)
{
lcd_printf("Hello world %dn", 42);
return EXIT_SUCCESS;
}

void lcd_printf(const char *msg, ...)
{
va_list ap;
char c;
char tmp[80];
char * s;

va_start(ap, msg);
vsnprintf(tmp, sizeof tmp, msg, ap);
va_end(ap);

s = tmp;
while ((c = *s++))
lcd_putc(c);
}




Merci beaucoup !

Que se passe-t'il si on dépasse les 79 caractères + ?

Avatar
noone

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

extern void lcd_printf(const char *msg, ...);
#define lcd_putc putchar

int main(void)
{
lcd_printf("Hello world %dn", 42);
return EXIT_SUCCESS;
}

void lcd_printf(const char *msg, ...)
{
va_list ap;
char c;
char tmp[80];
char * s;

va_start(ap, msg);
vsnprintf(tmp, sizeof tmp, msg, ap);
va_end(ap);

s = tmp;
while ((c = *s++))
lcd_putc(c);
}




Merci beaucoup !

Que se passe-t'il si on dépasse les 79 caractères + ?


il y a quelque chose d'améliorable là dedans...

si printf ne contient qu'un seul paramètre (la chaine de caractère)
exemple : printf("hello")
lcd_printf() devrait directement appeler lcd_putc(c) sans avoir besoin
de réserver

char tmp[80];

pour un microcontrôleur ça peut avoir son importance... non ?

le problème c'est que je ne sais comment récupérer ce nombre de
paramètre (je ne suis pas habitué au paramètre "..."

Merci encore (vous m'avez fait économiser un temps précieux ;-) )


Avatar
Eric Levenez
Le 23/09/06 21:22, dans
,
«  » a écrit :

char tmp[80];
vsnprintf(tmp, sizeof tmp, msg, ap);


Que se passe-t'il si on dépasse les 79 caractères + ?


"vsnprintf" retourne normalement la taille écrite dans le buffer (hors le
0). En cas de débordement, il va retourner la taille qu'il aurait eu besoin,
mais il n'aura rien écrit. Il suffit donc de tester le code de retour de
vsnprintf par rapport à la taille du buffer pour tester ce cas.

ret = vsnprintf(tmp, sizeof tmp, msg, ap);
it (ret >= sizeof tmp)
erreur();

Mais dans ton cas ou tu connais la taille de ton affichage LCD et la taille
que tu veux afficher, cela ne devrait pas poser de problème.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.


Avatar
Eric Levenez
Le 23/09/06 21:43, dans
,
«  » a écrit :

vsnprintf(tmp, sizeof tmp, msg, ap);



il y a quelque chose d'améliorable là dedans...

si printf ne contient qu'un seul paramètre (la chaine de caractère)
exemple : printf("hello")
lcd_printf() devrait directement appeler lcd_putc(c) sans avoir besoin
de réserver

char tmp[80];

pour un microcontrôleur ça peut avoir son importance... non ?


La taille est dans la pile (enfin normalement), donc allouée et libérée
dynamiquement. De toute façon vsnprintf est une grosse fonction (en taille),
et si tu l'utilises en embarqué, alors la taille de tmp est négligeable.

Si tu veux faire bien les choses, alors il faut allouer dynamiquement le
buffer en appelant une première fois vsnprintf avec une taille de 0. Tu
alloues ensuite la taille retournée + 1 pour le 0. Et enfin tu appelles une
seconde fois vsnprintf avec la taille que tu viens d'allouer. Ensuite tu
libère le buffer alloué.

le problème c'est que je ne sais comment récupérer ce nombre de
paramètre (je ne suis pas habitué au paramètre "..."


Ce n'est pas les arguments variables qui importent ici, mais la façon dont
printf traite ses arguments. Il suffit donc de compter le nombre de % (non
suivi d'un second %) pour connaître le nombre d'arguments.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.



Avatar
Pierre Maurette
Comment créer ma propre fonction printf (disons lcd_printf) ?
Cette fonction appelerai évidemment lcd_puts(...)


Vous utilisez sprintf(), par exemple ?


merci pour sprintf (que je n'ai jamais utilisé)

mais comment faire pour créer ma fonction lcd_printf
qui prend les même arguments que printf (en nombre variable)
et qui contient une initialisation de la chaine tampon (de quelle
taille d'ailleurs ?)
ainsi qu'un appel de lcd_puts(tampon)


Pourquoi dans votre contexte faire une "belle" fonction
lcd_printf(const char* format, ...) ? Il me semble que vous allez
gaspiller de la ressource, sans nécessairement vous simplifier la
programmation.
Avec un afficheur LCD, vous êtes obligé de contrôler précisément ce que
vous envoyez à l'affichage(*). Vous savez afficher un caractère, vous
savez afficher une chaîne. Il vous reste à obtenir une chaîne formatée.
La taille du buffer n'est-elle pas déterminée par les caractéristiques
de l'afficheur (ajouter le '' quand même) ? Pourquoi ne pas réserver
cette mémoire une fois pour toute en static, dans la mémoire la moins
"chère" ?
A partir de là, vous auriez soit des:
lcd_puts(const char*);
soit des:
sprintf(staticBouffeur, etc.);
lcd_puts(bouffeur);
Vous pourriez faire une macro PRINTF(), mais je ne vois pas l'avantage
d'une telle obfuscation.

(*) C'est éventuellement faux dans le cas où vous gèreriez un buffer et
des touches de défilement.

--
Pierre Maurette



Avatar
noone
Pourquoi dans votre contexte faire une "belle" fonction lcd_printf(const
char* format, ...) ?


Parce que je trouve élégant de remplacer mes printf qui m'ont servi à
tester mon code par des lcd_printf

C'est à priori la seule raison


Merci à tous les deux

Avatar
noone
Comment créer ma fonction propre fonction printf (disons lcd_printf) ?
Cette fonction appelerai évidemment lcd_puts(...)


j'ai envoyé les réponses fournit ici à l'auteur de la lib
je me suis un peu fais renvoyer ch...


1ère réponse

<quote>
You are wrong, it makes NO sense to addd lcd_printf().

Please study AVRlibc manual, stdio functions !
</quote>


2ième réponse

<quote>
#include <stdio.h>
#include "lcd.h"

static FILE lcdout = FDEV_SETUP_STREAM( (void *)lcd_putc, NULL,
_FDEV_SETUP_WRITE );
stdout = &lcdout;

/* initialize display, cursor off */
lcd_init(LCD_DISP_ON);

printf("Output to LCDn");
</quote>


bon c'est vrai que ce qu'il propose est plus joli...


Merci