TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Pchuqui_1 en 26 de Abril de 2010, 21:00:11
-
Hola a todos. Estoy tratando de utilizar las interrupciones por cambio de estado en la pata RB0 y por recepción en el bus rs232, pero al compilar me da un error que no puedo entender de que se trata. Estoy definiendo mal las interrupciones? Adjunto el error. Muchas gracias.
#include <16F887.h>
#device adc=10
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
//Definiciones pines LCD
#define _FLEX_LCD
#define LCD_DB4 PIN_B3
#define LCD_DB5 PIN_B4
#define LCD_DB6 PIN_B5
#define LCD_DB7 PIN_B6
#define LCD_RS PIN_C0
#define LCD_RW PIN_C1
#define LCD_E PIN_B2
///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
#include <flex_lcd.c>
#include <EEPROM_24512.c> //Ficheros driver de los periféricos
#include <eeprom_interna_16bits.c>
#include <floatee.c>
int dat_in;
int16 address=0,address1,address2;
float dato,dato1,dato2;
void up (void); // Lectura de EEprom
void down (void); // Escritura de EEprom
//void write_eeprom_16bits(void);
//void read_eeprom_16bits(void);
#int_ext
ext_isr()
{
lcd_putc("\f RB0");
}
#int_rda //Interrupción para el puerto serie
rda_isr()
{
dat_in=getc(); //Lee el puerto serie
if (dat_in=='2') //Si es "2" se visualizan los primeros datos de la eeprom
{
printf("%lu",555);
}
return(dat_in);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main() {
lcd_init();
enable_interrupts(int_rda);
enable_interrupts(int_ext); //Habilita la interrupción RBO...
ext_int_edge(L_TO_H); //Por flanco de subida
enable_interrupts(global);
address=0;
-
Hola.
El error es porque el programa es muy grande para ese micro y no alcanza la ROM.
Saludos
-
No puede ser.. le quite una de las interrupciones, lo compile, y me da que estoy usando un 31 % de la rom... :?
-
Hola Pchuqui_1.
Lo que te esta indicando es que la rutina MAIN, es demasiado grande para el banco de memoria, probablemente el CCS no gestione correctamente el cambio de banco, prueba a reducir el tamaño de la función MAIN, usando llamadas a funciones en vez de crearlo todo en su interior, de todas formas postea el resto del código del MAIN e intentare revisarlo a ver que se puede hacer.
-
Hola bmfranky. Gracias por contestar. Este es el programa y no creo que se haya llenado la ROM, porque cuando le quito algunas intrucciónes lo compila perfectametne y me dice que estoy usando un 30 % de ROM. Gracias.
#include <16f887.h>
#device adc=10
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7,disable_ints)
#use i2c(Master,sda=PIN_C4,scl=PIN_C3)
//Definiciones pines LCD
#define _FLEX_LCD
#define LCD_DB4 PIN_B3
#define LCD_DB5 PIN_B4
#define LCD_DB6 PIN_B5
#define LCD_DB7 PIN_B6
#define LCD_RS PIN_C0
#define LCD_RW PIN_C1
#define LCD_E PIN_B2
///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
#include <flex_lcd.c>
#include <EEPROM_24512.c> //Ficheros driver de los periféricos
#include <eeprom_interna_16bits.c>
#include <floatee.c>
int dat_in;
int16 address=0,address1,address2;
float dato,dato1,dato2;
void up (void); // Lectura de EEprom
void down (void); // Escritura de EEprom
#int_rda //Interrupción para el puerto serie
rda_isr()
{
dat_in=getc(); //Lee el puerto serie
if (dat_in=='2') //Si es "2" se visualizan los primeros datos de la eeprom
{
// printf("%lu",555);
}
return(dat_in);
}
#int_ext
ext_isr()
{
write_eeprom_16bits(0x00,address);
output_low(PIN_D2);
delay_ms(20);
output_high(PIN_C5); //led on
do{ //bucle...
} while(1);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main() {
lcd_init();
enable_interrupts(int_rda);
enable_interrupts(int_ext); //Habilita la interrupción RBO...
ext_int_edge(L_TO_H); //Por flanco de subida
enable_interrupts(global);
address=0;
do{ //bucle...
if(!input(PIN_D1)) //¿switch abierto?
up(); //SI -> Lectura de EEprom
else
down(); //NO -> Escritura de EEprom
} while(1);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
//MODO LECTURA
void up (void)
{
// lcd_putc("\up\n");
output_high(PIN_D2); //Leed confirmación
do{
// if(kbhit())
if(dat_in=='9'){
goto sigue;
}
}while(1);
sigue:
output_low(PIN_D2);
// lcd_putc("\fpaso");
address=read_eeprom_16bits(0x00);
address2=(address/4);
printf("%lu",address2);
address1=0;
arriba:
do{
output_high(PIN_D2);
//if(kbhit())
if(dat_in=='3') //Si es "2" se visualizan los primeros datos de la eeprom
{
// lcd_putc("\fConfirmo");
dat_in=0;
dato=READ_FLOAT_EXT_EEPROM(address1); //Guarda 4 bytes del FLOAT
address1=address1+4;
delay_ms(50);
if (address1==address) {
do{
goto termino;
}while(1);
}
dato1=READ_FLOAT_EXT_EEPROM(address1); //Guarda 4 bytes del FLOAT
address1=address1+4;
delay_ms(50);
if (address1==address) {
do{
goto termino;
}while(1);
}
dato2=READ_FLOAT_EXT_EEPROM(address1); //Guarda 4 bytes del FLOAT
address1=address1+4;
delay_ms(50);
if (address1==address) {
do{
goto termino;
}while(1);
}
termino:
printf("/%4.0f" "/%4.0f" "/%4.0f",dato,dato1,dato2);
if (address1==address) {
printf("/%c",'1');
do{
output_low(PIN_D2);
delay_ms(20);
output_high(PIN_C5);
}while(1);
}
goto arriba;
}
} while(1);
}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
void down (void)
{
address=0; //Variables globales
setup_adc_ports(sAN0|sAN1|sAN3 ); //configuración adc
setup_adc (adc_clock_internal); //enciende adc
setup_adc(ADC_CLOCK_DIV_8 ); //configurando la frecuencia de lectura del ADC a 12Mhz
delay_us(10);
output_high(PIN_D2); //Leed confirmación
lcd_putc("Modo Escritura"); //Visualiza en LCD la hora
delay_ms(2000);
lcd_putc('\f');
do {
set_adc_channel(0); //elige canal a medir RA1
dato=read_adc();
WRITE_FLOAT_EXT_EEPROM(address,dato); //Guarda 4 bytes del FLOAT
address=address+4; //Incrementa 4 posiciones la ADDRESS
lcd_gotoxy(1,1);
printf(lcd_putc,"%4.0f",dato); //Visualiza en LCD
delay_ms(100);
if (address==32760) {
lcd_putc("\fMEMORIA LLENA\n");
write_eeprom_16bits(0x00,address);
do{
}while(1);
}
set_adc_channel(1); //elige canal a medir RA1
dato=read_adc();
WRITE_FLOAT_EXT_EEPROM(address,dato); //Guarda 4 bytes del FLOAT
address=address+4; //Incrementa 4 posiciones la ADDRESS
lcd_gotoxy(1,2);
printf(lcd_putc,"%4.0f",dato); //Visualiza en LCD
delay_ms(100);
if (address==32760) { //32760
lcd_putc("\fMEMORIA LLENA\n");
write_eeprom_16bits(0x00,address);
do{
}while(1);
}
set_adc_channel(3); //elige canal a medir RA1
dato=read_adc();
WRITE_FLOAT_EXT_EEPROM(address,dato); //Guarda 4 bytes del FLOAT
address=address+4; //Incrementa 4 posiciones la ADDRESS
lcd_gotoxy(10,2);
printf(lcd_putc,"%4.0f",dato); //Visualiza en LCD f=flotante con truncado
delay_ms(100);
if (address==32760) {
lcd_putc("\fMEMORIA LLENA\n");
write_eeprom_16bits(0x00,address);
do{
}while(1);
}
}while(1);
}
-
Podés probar con la sentencia "#separete" (creo que era así) eso obliga al compilador a "meter" el código en otra página de la memoria de programa.
Probá usándolo antes de la definición y también antes de la implementación de la función down.
Eso obligaría a que toda la función down quede en otro banco.
-
Hola, gracias por responder. Pero el ccs c no se encarga solo de cambiar de banco cuando uno ya se ha llenado?? La verdad que no sabia. Voy a intentar probar con esa funcion ("#separete). Tengo que definirla como cualquier otra y nada mas? Gracias.
-
Hola otra ves. Busque la instrucción en la ayuda del ccs c y dice que ahora espacion en la ROM pero aumenta el uso del stack... :?. No se si realmente esta directiva pasa el codigo exedente a otro banco de la ROM. Gracias otra ves.
-
El CCS efectivamente no hace el cambio de banco automáticamente. En cuanto a la pérdida del stack, todo depende de cuanto use tu programa el stack.
Si no llamas a muchas funciones anidadas (una dentro de otra, y luego otra y otra y así...) no vas a tener problemas con el stack.
-
No consigo usar esa instrucción, me dá error. Existe otra forma de hacer un cambio de banco?
-
Te sigue dando el mismo error que antes o ahora es distinto. Yo la había usado en un programa ya funcionó bien. Ahora estoy usando HiTech como compilador.
-
Perdon, me ha funcionado. He puesto esa directiva arriba de la función main y no me da más los errores, cuando lo usaba en los otros void me daba un error. Igual no me queda claro, como se si el banco A realmente se lleno y ahora me esta guardando todo en el B u otro? Eso se puede saber? Gracias.
Porque cambiaste a HiTech?
-
Una forma de saber sería viendo el .asm o .list generado y ver en que direcciones de memoria va quedando todo.
Lo que hace "separete" es forzar la separación aunque el banco no esté lleno del todo.
Cambié a HiTech porque CCS no trabaja exactamente con ANSI C (hay cosas que son únicas de CCS) por lo tanto el código es menos portable.
Además, la versión Lite de HiTech es Free y la puedo usar sin problemas y ahora que estoy usando Linux también hay una versión para dicho OS y la estoy usando con PIKLAB.
Es cierto que CCS tiene funciones cómodas como son la forma de configurar y leer el ADC y la forma de habilitar y deshabilitar las interrupciones.
Para eso me hice mis propias rutinas en Hitech y se manejan de las misma forma así que me fue bastante sencilla la migración.