TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Thulsa Doom en 14 de Agosto de 2010, 18:56:58
-
Hola, resulta que estoy modificando una práctica y añadiendole un LCD para ver que ocurre.
estoy trabado en una sección de la misma, ya que no consigo que se imprima la variable y no tengo ni idea de que puede ser
La práctica consiste en generar una señal PWM por hardware y por medio de un teclado matricial, cambiar el estado de la PWM, yo lo que he hecho es añadirle un LCD para ver en que estado está.
El compilador utilizado es el CCS
Expongo el código para que me digan algo
#include <16F876A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use standard_io (A)
#define use_portb_kbd TRUE //DEFINE EL USO DE UN PUERTO PARA EL TECLADO
#include <kbd.c> //INCLUYE LAS LIBRERÍAS DEL TECLADO
#define use_portb_lcd TRUE //DEFINE EL USO DE UN PUERTO PARA EL LCD
#include <lcd.c> //INCLUYE LAS LIBERÍAS DEL LCD
void main(){
char a,k,kant='0'; //INICIALIZA A CERO UN PAR DE VARIABLES
CHAR ULTIMO_TECLADO, NUEVO_TECLADO='0';
char PWMH=0,PWML=0; /*INICIALIZA DOS VARIABLES QUE VA A UTILIZAR COMO CONTADORES PARA EL NIVEL ALTO Y BAJO DE LA PWM*/
kbd_init(); //LLAMA A UNA FUNCIÓN QUE SERÍA PARA INICIALIZAR EL TECLADO
lcd_init(); //IDEM PARA EL LECTOR
port_b_pullups(TRUE); //LLAMA A UNA FUNCIÓN QUE PREPARA UN PUERTO PARA TRABAJAR EN MODO PULL UP
lcd_gotoxy(1,1); //Posicionamos lo que vamos a imprimir en la posición linea 1, fila 1
printf(lcd_putc,"\fPulse una tecla\n para comenzar"); //Imprimimos en el LCD al comienzo del programa
while (TRUE){ //BUCLE INFINITO
k=kbd_getc(); //RECOGE DATO DEL TECLADO
a=k;
NUEVO_TECLADO=a;
//***AQUÍ VA MI RUTINA************************************************************
IF (NUEVO_TECLADO != ULTIMO_TECLADO) //SÍ NUEVO_TECLADO NO ES IGUAL QUE ULTIMO_TECLADO
{
printf(lcd_putc,"\fNivel %c",a); //Escribimos en el LCD la variable a, pero en el lcd solo aparece NIVEL
/*si pongo esto:
lcd_putc(a);
si imprime el número que piso en el teclado pero un valos se suma al siguiente
por ejemplo si pulso 1 2 3 4 , aparece de esta manera en el lcd, si pulso más pues se añaden a lo que hay, no
entiendo que pasa, en teoría el %c",a devería de funcionar, lo he probado con d, con u, pero nada, es como si no
identificara la variable*/
ULTIMO_TECLADO=NUEVO_TECLADO;
}
/************************************************FIN DE RUTINA*****************************************************************/
if(K=='\0')k=kant;
if((k=='*')||(k=='#')) k='0';
kant=k; //PREPARA LAS VARIABLES DE LOS NIVELES DE LA PWM SEGÚN CÓDIGO ASKI
k=k-48;
PWMH=k*28;
PWML=255-PWMH;
for(PWMH;PWMH>0;PWMH--){ //CREA EL NIVEL ALTO DE LA PWM
output_high(PIN_A0);
}
for(PWML;PWML>0;PWML--){ //CREA EL NIVEL BAJO DE LA PWM
output_low(PIN_A0);
}
}
}
Como digo en el mismo código, solo se imprime la palabra NIVEL y el valor del caracter no se imprime, es como si el valor del caracter no estubiera.
He probado de muchas maneras y formas y no me sale, a ver si alguien ve el error y me pude orientar.
He de puntualizar que la práctica la pruebo en el proteus no se si es que el proteus falla o que.
gracias y un saludo
-
Hola no se si te podré ayudar pero creo que te falta poner el igual (=)
en : printf (lcd_putc, "\fNivel=%c",a), no estoy seguro
pero prueba es lo único que se me ocurre
-
Yo probaría a poner:
printf(lcd_putc,"\fNivel %1.0c",a);
Ya que no le indicas el número de dígitos que quieres visualizar.
Un saludo
-
El valor que retorna kbd_getc() es imprimible? Para 0x00 por ejemplo, retorna '0' o '\0'?
En la comparación que haces if(k=='\0')k=kant, da la impresion que K no es imprimible.
Podrias provar de este modo:
if(k >= 0 && c <= 9)
k+='0';
Con el IF te estas asegurando de no sumar '0' a '*' o '#'.
-
Hola, prueba a cambiar:
printf(lcd_putc,"\fNivel %c",a);
por:
printf(lcd_putc,"\rNivel %u ",a);
La \r hace un retorno de carro y luego se sobreescribe lo que haya en el LCD con la palabra Nivel y escribe el texto con el numero de tecla y un espacio para borrar la segunda cifra si el valor anteriormente mostrado era superior a 9.
saludos.
-
Hola a todos, pues he de decir que nada de lo expuesto funciona.
Lo único que consigo es que salga un 0 permanente si pongo esto
printf(lcd_putc,"\f Nivel %d", a);
Según lo que he estudiado el lenguaje C estándar, con poner
printf("\f Nivel %c", a);
Añadiendo stdio.h
Debería de funcionar sin problemas porque la variable k o a están dentro del programa pero en el CCS no funciona el printf sin el lcd_putc, eso me da muchos dolores de cabeza, habiendo un estándar, estos se lo pasan por el forro de los cojo.....
He probado con todas las combinaciones posibles, %c, %u, %d y nada hay algunos que me muestran un 0 permanente, otros caracteres raros.
No comprendo el motivo de ello, al igual es una coñada que no termino de ver pero no se que más hacer
Otra cosa que veo es que si sustituyo
printf("\f Nivel %c", a);
Por
lcd_putc(k);
Éste si funciona pero solo imprime el valor de k y se añade en la pantalla pulsación tras pulsación, ósea si pulso 1 luego 2 luego 5, aparece en el LCD 125 y así sucesivamente
Si intento borrar el LCD después de cada pulsación como por ejemplo
lcd_putc('\f'); y debajo continuo con
lcd_putc(k);
No muestra nada en la pantalla todo en blanco.
No entiendo como una cosa que se supone que es tan simple da tanto por sac.....
¿ideas?
Gracias
-
Hola Thulsa Doom, revisando tu programa veo que le falta una instrucción importante: if(k != 0). Cuando no se presiona ninguna tecla, kbd_getc(); devuelve siempre un 0, que es mandado a imprimir como char por printf, lo que muestra un caracter extraño o nada en el caso del proteus; intenta con las correcciones que te incluyo en el siguiente código:
void main()
{
char a, k, kant = '0'; //INICIALIZA A CERO UN PAR DE VARIABLES
char ULTIMO_TECLADO, NUEVO_TECLADO = '0';
char PWMH=0,PWML=0; //INICIALIZA DOS VARIABLES QUE VA A UTILIZAR COMO CONTADORES
//PARA EL NIVEL ALTO Y BAJO DE LA PWM
kbd_init(); //LLAMA A UNA FUNCIÓN QUE SERÍA PARA INICIALIZAR EL TECLADO
lcd_init(); //IDEM PARA EL LECTOR
port_b_pullups(TRUE); //LLAMA A UNA FUNCIÓN QUE PREPARA UN PUERTO PARA TRABAJAR EN MODO PULL UP
lcd_putc('\f');
lcd_gotoxy(1,1); //Posicionamos lo que vamos a imprimir en la posición linea 1, fila 1
printf(lcd_putc,"Pulse una tecla\n para comenzar"); //Imprimimos en el LCD al comienzo del programa
while (TRUE)
{ //BUCLE INFINITO
k = kbd_getc(); //RECOGE DATO DEL TECLADO
if(k != 0) // Ojo con esto! Si no se presiona ninguna tecla, k = 0
{
a = k;
NUEVO_TECLADO = a;
//***AQUÍ VA MI RUTINA******************************************************
IF (NUEVO_TECLADO != ULTIMO_TECLADO) //SÍ NUEVO_TECLADO NO ES IGUAL QUE ULTIMO_TECLADO
{
lcd_putc('\f');
printf(lcd_putc,"Nivel %c", a); //Escribimos en el LCD la variable a, pero en el lcd solo aparece NIVEL
}
/*si pongo esto:
lcd_putc(a);
si imprime el número que piso en el teclado pero un valos se suma al siguiente
por ejemplo si pulso 1 2 3 4 , aparece de esta manera en el lcd, si pulso más pues se añaden a lo que hay, no
entiendo que pasa, en teoría el %c",a devería de funcionar, lo he probado con d, con u, pero nada, es como si no
identificara la variable*/
ULTIMO_TECLADO=NUEVO_TECLADO;
}
/************************************************FIN DE RUTINA*****************************************************************/
if(k =='\0')
k = kant;
if((k=='*')||(k=='#'))
k = '0';
kant=k; //PREPARA LAS VARIABLES DE LOS NIVELES DE LA PWM SEGÚN CÓDIGO ASKI
k=k-48;
PWMH=k*28;
PWML=255-PWMH;
for(PWMH; PWMH>0; PWMH--)
{ //CREA EL NIVEL ALTO DE LA PWM
output_high(PIN_A0);
}
for(PWML; PWML>0; PWML--)
{ //CREA EL NIVEL BAJO DE LA PWM
output_low(PIN_A0);
}
}
}
Sin embargo, no me queda claro como quieres hacer funcionar el PWM. Por ejemplo las dos últimas instrucciones for no tienen ningún efecto en el programa. En los ejemplos del CCS hay uno que se llama EX_PWM.C. Te recomiendo que lo estudies detenidamente, asi como el uso de la instrucción for.
Saludos!
Editado. Causa: corrección en código y explicación...
-
Gracias por la ayuda.
Resulta que esta mañana mismo antes de ver ésta solución he resuelto el problema, es parecido a la solución que me has dado,(CREO).
Simplemente con cambiar la rutina que he añadido de posición se ha resuelto el problema.
No entendía el por qué, pero leyendo la explicación que me has dado ya más o menos lo comprendo.
Tú has utilizado if(k != 0) que creo que viene a ser lo mismo que if(k=='\0')
El programa me ha quedado así funcionando correctamente:
void main(){
char k,kant='0'; //INICIALIZA A CERO UN PAR DE VARIABLES
CHAR ULTIMO_TECLADO, NUEVO_TECLADO='0';
char PWMH=0,PWML=0; //INICIALIZA DOS VARIABLES QUE VA A UTILIZAR COMO CONTADORES PARA EL NIVEL ALTO Y BAJO DE LA PWM
kbd_init(); //LLAMA A UNA FUNCIÓN QUE PRESUPONGO (PORQUE NESTOR PASA DE ENVIÃRMELA) QUE SERà PARA INICIALIZAR EL TECLADO
lcd_init(); //IDEM PARA EL LECTOR
port_b_pullups(TRUE); //LLAMA A UNA FUNCIÓN QUE PRESUPONGO (IDEM NESTOR) QUE PREPARA UN PUERTO PARA TRABAJAR EN MODO PULL UP
lcd_gotoxy(1,1); //Posicionamos lo que vamos a imprimir en la posición linea 1, fila 1
printf(lcd_putc,"\fPulse una tecla\n para comenzar"); //Imprimimos en el teclado al comienzo del programa
while (TRUE){ //BUCLE INFINITO
k=kbd_getc(); //PRESUPONGO (IDEM0 NESTOR) QUE RECOGE DATO DEL TECLADO
NUEVO_TECLADO=k;
if(K=='\0')k=kant;
if (NUEVO_TECLADO != ULTIMO_TECLADO){ //Si es distinto de NUEVO_TECLADO se ejecuta el printf
printf(lcd_putc,"\f Nivel %c\n",k); //Escribimos en el LCD la variable K
ULTIMO_TECLADO = NUEVO_TECLADO;
}
if((k=='*')||(k=='#')) k='0';
kant=k; //PREPARA LAS VARIABLES DE LOS NIVELES DE LA PWM SEGÚN CÓDIGO ASKI
k=k-48;
PWMH=k*28;
PWML=255-PWMH;
for(PWMH;PWMH>0;PWMH--){ //CREA EL NIVEL ALTO DE LA PWM
output_high(PIN_A0);
}
for(PWML;PWML>0;PWML--){ //CREA EL NIVEL BAJO DE LA PWM
output_low(PIN_A0);
}
}
}
El ejercicio es simplemente eso, es un ejercicio que me venía en un libro y no utilizaba el LCD si no solo un teclado y yo en mi afán por aprender le quise meter un LCD a ver si yo era capaz de modificarlo, y en el transcurso de eso aprender.
En verdad el programa tal y como está funciona lo que la señal PWM varía poco del nivel 1 en el teclado al nivel 9, ahora lo que pretendo es a ver si puedo es modificar esa oscilación y por ejemplo en el nivel 1 dejarla muy baja y en el nivel 9 ponerla a tope.
Sé que lo suyo es hacerla mediante interrupciones, pero no he llegado a esa parte en el libro.
De todas maneras le echare un vistazo al ejemplo que mencionas a ver qué tal