TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Galdos en 07 de Mayo de 2008, 08:29:46
-
Buenas, tras mucho leer vuestros hilos, me decidi a programar mi primer pic, pero el caso es que no funciona bien, h e utilizado el program Pic-C Compiler con el siguiente código:
#include <16F73.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES
#use delay(clock=20000000)
#byte port_b=6
#byte port_c=7
void leds_encendidos(void)
{
output_c(0xff);
delay_ms(10000);
}
void leds_parpadeantes(void)
{
signed char i = 0;
while(i<20)
{
output_c(0xff);
delay_ms(200);
output_c(0x00);
delay_ms(200);
i++;
}
}
void leds_fantastico(void)
{
int pos_luz = 0x1;
int i = 0;
for(i = 0; i < 10; i++)
{
do{
output_c(pos_luz);
delay_ms(200);
rotate_left(pos_luz, 1);
}while(pos_luz != 0b00001000);
do{
output_c(pos_luz);
delay_ms(200);
rotate_right(pos_luz, 1);
}while(pos_luz != 0b00000001);
}
}
void led_num(void)
{
int pos_luz = 0x1;
int i;
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001}; //BCD 0-9
for(i = 0; i < 10; i++)
{
output_b(tabBCD[i]);
do{
output_c(pos_luz);
delay_ms(200);
rotate_left(pos_luz, 1);
}while(pos_luz != 0b00001000);
do{
output_c(pos_luz);
delay_ms(200);
rotate_right(pos_luz, 1);
}while(pos_luz != 0b00000001);
}
}
void main()
{
signed char i = 1;
int parp = 0;
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001}; //BCD 0-9
// Ni idea de lo que hace
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
set_tris_a(0xff); // Puerto A como entrada
set_tris_b(0x00); // Puerto B como salida
set_tris_c(0x00); // Puerto C como salida
while(true) // Bucle infinito
{
port_b = 0x00; // Apaga todos los bits del puerto B
port_c = 0x00; // Apaga todos los bits del puerto C
output_b(tabBCD[i]); // Fijamos el valor del BCD
if(!input(PIN_A0)) // ¿Se ha pulsado el primer botón?
{
delay_ms(151); // Sí -> Retardo para evitar rebotes
i++; // Incrementamos el contador
if(i>4) // Comprobamos si se ha mostrado el valor máximo
i=0; // Sí -> Volvemos al inicio (0)
}
if(!input(PIN_A1)) //¿Se ha pulsado el segundo botón?
{
delay_ms(151); // Sí -> Retardo para evitar rebotes
output_b(0x00);
for(parp = 0; parp < 5; parp++)
{
delay_ms(100);
output_b(tabBCD[i]);
delay_ms(100);
}
switch(i){
case 1:
leds_encendidos();
break;
case 2:
leds_parpadeantes();
break;
case 3:
leds_fantastico();
break;
case 4:
led_num();
break;
}
}
};
}
Hay una parte que la puso el programa que no sé lo que hace, otra cosa que tampoco entiendo muy bien es lo de los 'fuses' y tampoco he sido capaz de encontrar una información clara en internet, ahora tengo la problemática de que no sé si es que no se ha programado bien, no he hecho bien las conexiones o si no es correcto el código.
-
Hola!
Esto es lo que tengo sobre "fuses":
#FUSE
Permite modificar el valor de los fuses del microcontrolador que estamos empleando. Los valores posibles dependen de cada microcontrolador en particular, y los valores posibles se cargan al utilizar #INCLUDE seguido del archivo correspondiente. La forma de #FUSE es la siguiente:
#FUSE opciones
donde opciones es una lista de las opciones posibles separadas mediante comas. Antes de seguir, recuerda que puedes ver dentro del archivo con extensión .h correspondiente cuales son los valores posibles para ese microcontrolador. Están al comienzo del archivo, en forma de comentarios.
Algunos valores comunes son
* Tipo de oscilador: LP, XT, HS, RC
* Wach Dog Timer: WDT, NOWDT
* Protección de código: PROTECT, NOPROTECT
* Power Up Timer: PUT, NOPUT
* Brown Out Reset: BROWNOUT, NOBROWNOUT
Espero te sea de ayuda como para empezar.
Saludos!
-
Saca a:
port_b = 0x00; // Apaga todos los bits del puerto B
port_c = 0x00; // Apaga todos los bits del puerto C
del while, de lo contrario los vas a ver siempre apagados
-
pocher probaré con eso.
¿aitopes sabes que ocurre si no pones ningún 'Fuse'?
-
buena pregunta, no lo he probado, habría que ver que hace el compilador, en caso contrario se ajusta a la configuración por defecto del micro ( y eso lo ves en el software del programador)
-
El compilador compilará sin errores, de hecho con PROTEUS casi que nunca uso los fuses y el archivo .hex sí que lo ha generado.
Los fuses sí ó sí hay que ponerlos de lo contrario pone los fuses que le dá la gana. Sobretodo el oscilador lo suele dejar en RC (mal rollo)
-
Saludos! :-)
La parte que no sabes qué hace:
setup_adc_ports(NO_ANALOGS); // No hay entradas analógicas
setup_adc(ADC_OFF); // No se usará conversión analógico / digital (está en off)
setup_spi(FALSE); // Coloca 0x00 en el registro de configuración SPI, lo deshabilita
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); // Activa el timer 0 con pre-escala 1:1 (sin pre-escala)
setup_timer_1(T1_DISABLED); // Deshabilita timer 1
setup_timer_2(T2_DISABLED,0,1); // Deshabilita timer 2
Ok nos leemos! :mrgreen:
-
Muchas gracias por tu respuesta Firepic.
Probaré a reprogramarlo poniendo los fuses.
Otra duda que tengo es que no si se me va a estar reseteando el Pic constantemente, le he puesto una R de 10 K conectada a Vdd al pin MCLR, supongo que ahí no podrá estar el fallo.
-
Saludos amigo Galdos! :-)
La resistencia de 10K a +5V está bien... por allí no te reseteará...
Yo lo he hecho así muchas veces sin problemas...
Sin embargo, si quieres saber cómo hacer un circuito reset más decente, puedes revisar este hilo (http://www.todopic.com.ar/foros/index.php?topic=21525.0) .
Ok nos leemos! :mrgreen:
-
Nada, aun no soy capaza de hacerlo funcionar.
Le he programado el siguiente código:
// Encendemos todos los led's
void leds_encendidos(void)
{
PORTC = 0xff;
delay_ms(1000);
}
// Hacemos parpadear los led's
void leds_parpadeantes(void)
{
signed char i = 0;
while(i<20)
{
PORTC = 0xff;
delay_ms(100);
PORTC = 0x00;
delay_ms(100);
i++;
}
}
// Hacemos el efecto del coche fantástico
void leds_fantastico(void)
{
int pos_luz = 0x1;
int i = 0;
for(i = 0; i < 10; i++)
{
do{
PORTC = pos_luz;
delay_ms(100);
pos_luz << 1;
}while(pos_luz != 0b00001000);
do{
PORTC = pos_luz;
delay_ms(100);
pos_luz >> 1;
}while(pos_luz != 0b00000001);
}
}
// Sacamos todos los números
void led_num(void)
{
int pos_luz = 0x1;
int i;
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001}; //BCD 0-9
for(i = 0; i < 10; i++)
{
PORTB = tabBCD[i];
do{
PORTC = pos_luz;
delay_ms(100);
pos_luz << 1;
}while(pos_luz != 0b00001000);
do{
PORTC = pos_luz;
delay_ms(100);
pos_luz >> 1;
}while(pos_luz != 0b00000001);
}
}
void main()
{
signed char i = 1;
int parp = 0;
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001}; //BCD 0-9
TRISA = 0xff; // Puerto A como entrada
TRISB = 0x00; // Puerto B como salida
TRISC = 0x00; // Puerto C como salida
PORTB = 0x00; // Apaga todos los bits del puerto B
PORTC = 0x00; // Apaga todos los bits del puerto C
PORTB = tabBCD[i]; // Fijamos el valor del BCD
while(1) // Bucle infinito
{
// Comprobamos si se ha pulsado el primer botón
if(button(&PORTA, 0, 100, 0))
{
i++; // Incrementamos el contador
if(i>4) // Comprobamos si se ha mostrado el valor máximo
i=1; // Sí -> Volvemos al inicio (0)
PORTB = tabBCD[i];
}
// Comprobamos si se ha pulsado el segundo botón
if(button(&PORTA, 1, 100, 0))
{
// Hacemos parpadear el 7seg antes de entrar en la función
for(parp = 0; parp < 5; parp++)
{
delay_ms(10);
PORTB = tabBCD[i];
delay_ms(10);
};
switch(i){
case 1:
leds_encendidos();
break;
case 2:
leds_parpadeantes();
break;
case 3:
leds_fantastico();
break;
case 4:
led_num();
break;
}
}
};
}
Tengo un cristal de 20 Mhz, lo único que no tengo una C de 33 pf, asi que he probado con una configuración RC con una R de 4,7 K y una C de 30 pF; por ver si fallaba en eso pero sigue sin funcionar.
Lo conecto, lo activo y me saca el nº 1 por el 7seg, pasado un tiempo saca el 2 y se queda ahí pillado; da igual que en A0 y A1 haya un 0, o un 1, falla igual.
Ya no se si lo que falla es el programador que tengo, es un JDM y he programado el el micro con el WinPic, en principio parece que funciona pero no se que puede estar fallando, he intentado programar un 18F2550, pero no he podido me daba error al grabar.
El código lo he compilado con mikroC, ¿alguna idea de que puede estar fallando?
-
¿No lo estabas compilando con CCS? ¿Lo has probado con PROTEUS?
Si lo deseas pon el programa completo y pruebo a simularlo.
-
Empece utilizando el Pic-C compilerl, pero como me parecia un poco 'soso' y no me dejaba depurar, he terminado utilizando el MikroC, lo que pasa que encontrar info en inet del MikroC es más dificil, probaré a hacerlo con el Pic-C haber si funciona.
Os pongo el código en CCS por si veís algún problema:
#include <16F73.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES RC
#use delay(clock=20000000)
#byte port_b=6
#byte port_c=7
void leds_encendidos(void)
{
// Encendemos los led's durante 5 segundos
output_c(0xff);
delay_ms(5000);
}
void leds_parpadeantes(void)
{
// Hacemos parpadear todos los led's
signed char i = 0;
while(i<20)
{
output_c(0xff);
delay_ms(200);
output_c(0x00);
delay_ms(200);
i++;
}
}
void leds_fantastico(void)
{
// Hacemos el efecto del coche fantástico
int pos_luz = 0x1;
int i = 0;
for(i = 0; i < 10; i++)
{
do{
output_c(pos_luz);
delay_ms(200);
rotate_left(pos_luz, 1);
}while(pos_luz != 0b00001000);
do{
output_c(pos_luz);
delay_ms(200);
rotate_right(pos_luz, 1);
}while(pos_luz != 0b00000001);
}
}
void led_num(void)
{
// Vamos sacando todos los números por el 7seg.
int pos_luz = 0x1;
int i;
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001}; //BCD 0-9
for(i = 0; i < 10; i++)
{
output_b(tabBCD[i]);
do{
output_c(pos_luz);
delay_ms(200);
rotate_left(pos_luz, 1);
}while(pos_luz != 0b00001000);
do{
output_c(pos_luz);
delay_ms(200);
rotate_right(pos_luz, 1);
}while(pos_luz != 0b00000001);
}
}
void main()
{
signed char i = 1;
int parp = 0;
int tabBCD[10]={0b0000,0b0001,0b0010,0b0011,0b0100,0b0101,0b0110,0b0111,0b1000,0b1001}; //BCD 0-9
setup_adc_ports(NO_ANALOGS); // Desactivamos las entradas analógicas
setup_adc(ADC_OFF); // Conversión ADC desactivada
setup_spi(FALSE); // Desactiva el SPI
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); // Activa el Timer0 sin prescala (1:1)
setup_timer_1(T1_DISABLED); // Desactiva el Timer1
setup_timer_2(T2_DISABLED,0,1); // Desactiva el Timer0
set_tris_a(0xff); // Puerto A como entrada
set_tris_b(0x00); // Puerto B como salida
set_tris_c(0x00); // Puerto C como salida
port_b = 0x00; // Apaga todos los bits del puerto B
port_c = 0x00; // Apaga todos los bits del puerto C
while(true) // Bucle infinito
{
output_b(tabBCD[i]); // Fijamos el valor del BCD
if(!input(PIN_A0)) // ¿Se ha pulsado el primer botón?
{
delay_ms(151); // Sí -> Retardo para evitar rebotes
i++; // Incrementamos el contador
if(i>4) // Comprobamos si se ha mostrado el valor máximo
i=0; // Sí -> Volvemos al inicio (0)
}
if(!input(PIN_A1)) //¿Se ha pulsado el segundo botón?
{
delay_ms(151); // Sí -> Retardo para evitar rebotes
output_b(0x00);
for(parp = 0; parp < 5; parp++)
{
delay_ms(100);
output_b(tabBCD[i]);
delay_ms(100);
}
switch(i){
case 1:
leds_encendidos();
break;
case 2:
leds_parpadeantes();
break;
case 3:
leds_fantastico();
break;
case 4:
led_num();
break;
}
}
};
}
Por cierto, ¿que IDE utilizaís?
-
Yo para escribir el código y corregir los errores uso simplemente el Ultraedit.
Puedes usar el entorno integrado de CCS.
También puedes usar el MPLAB.
Voy a ver si simulo el código, ya te cuento.
Un saludo
-
En el PROTEUS no esta el 16F73 así que he puesto un 16F876.
Varias cosas. Si vas a usar un cristal de 20Mhz quita el fuse RC y pon HS.
El primer "juego" de luces que va a ejecutar es el bucle for, donde teóricamente debieran de salir en el 7 segmentos los números del 0 al 9. No te funciona porque debes de incrementar en el for el valor del índice para que te recorra toda la tabla, es decir "parp" lo debes de meter en lugar de la variable i. Si pones parp<5 solo te va a recorrer 5 valores del 0 al 4.
Con esto solucionarás el primer juego, a ver si eres capaz de seguir tú solo con los siguientes juegos.
PD. Veo que utilizas la variable i en muchas funciones, cuidado a ver si esto te va a dar problemas.
-
La función for con parp la uitlizaba para hacer parpadear el número para indicar que entra dentro de la función, pero me acabo de dar cuenta de que no hace nada, vaya fallo más tonto, para hacerlo parpadear tendría que sacar un cable al pin LT creo que era del 74LS73.
El fuse de RC lo he puesto porque tengo un cristal de 20 Mhz, pero no tengo los condensadores de 33 pf que hacen falta, esta tarde los comprare y probare poniendo el fuse en HS y os cuento.
Otra cosa, me he bajado el MPLAB del Microchip pero no compila C, ¿es de pago el compilador de C de Microchip?
-
Microchip posee el compilador de C, C18, escrito específicamente para programación de PICs de la serie 18. No he usado nunca el C18, creo que el MPLAB lleva una miniversión incluida gratuita de este compilador, la completa sí que es de pago.
El MPLAB no es ningún compilador ni ensamblador, tán solo y no es poco, es un un entorno IDE para poder escribir programas y poder depurarlos usando simulación paso a paso (tiene además otros 2 tipos de simulaciones). El MPLAB es un "contenedor" de programas, es decir que desde él se llaman a otros compiladores que pueden pertenecer a empresas distintas de la misma Microchip.
En la última versión del MPLAB (v8) ya incluye el acceso al compilador de CCS, solo tienes que darle la ruta del compilador (en versiones anteriores tenías que ejecutar un plugin).
El fuse RC solo debes usarlo si usas como oscilador una red RC, formada por un condensador y una resistencia (no se usa cristal).
Sin en el bucle for haces output_b(tabBCD[parp]), te irá mostrando secuencialmente todos los números del 0 al 9 (después de haberte leido, me parece que no es eso lo que quieres).
Reeescribe de nuevo el código y ponle comentarios para que te lo pueda corregir.
El código tiene más fallos, pero haz que funcione un "juego" e iremos avanzando.
Es muy sencillo!!! Animo!!!