...El PROBLEMA está en la interrupción por cambio de estado en portB RB4..RB7, resulta que el compilador al salir de la interrupción baja la bandera RBIF pero no hace una lectura/escritura en el portB y estas dos cosas se deben cumplir (mirar el Datasheet) para que de nuevo no entre en la interrupción hasta que realmente haya otro cambio de estado. Si no se hace una lectura/escritura en el portB el programa se vuelve loco y está contínuamente entrando y saliendo de la interrupción.
...
#include <18F4550.h>
#fuses XTPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,NOPBADEN
#DEVICE HIGH_INTS=true
#use delay(clock=48000000) //Cristal de 4 MHz (PLL1)
#use fast_io(B)
#byte port_a = 0xF80
#byte port_b = 0xF81
//#PRIORITY int_ext,int_rb
//#PRIORITY int_rb,int_ext
#INT_TIMER0 // Interrupción externa en RB0
//#INT_TIMER0 HIGH
interrupcion_TIMER0() // Función de atención a la interrupción
{
delay_ms(3000);
output_toggle(PIN_B1);
disable_interrupts(INT_TIMER0);
}
#INT_EXT // Interrupción externa en RB0
//#INT_EXT HIGH
interrupcion_RB0() // Función de atención a la interrupción
{
delay_ms(3000);
output_toggle(PIN_A0);
}
//#INT_RB // Interrupción externa en RB4-RB7
#INT_RB HIGH
//#INT_RB FAST
interrupcion_RB4_RB7() // Función de atención a la interrupción
{
delay_ms(3000);
#asm movf port_b,0 #endasm //Hace falta leer el portb, si no va mal
output_toggle(PIN_B3);
}
main()
{
set_tris_b(0x85); // RB4 salida, RB4-RB7,RB0 entradas.
set_tris_a(0x00);
//bit_clear(port_a,0);
//bit_clear(port_b,1);
//bit_clear(port_b,3);
output_low(PIN_A0);
output_low(PIN_B1);
output_low(PIN_B3);
setup_counters(RTCC_8_BIT,RTCC_DIV_128);
enable_interrupts(GLOBAL);
enable_interrupts(INT_RB);
enable_interrupts(INT_EXT);
while(1)
{
if(input(pin_b2))
enable_interrupts(INT_TIMER0);
}
}
float log(float x) *((char *)&y) = 0x7E;
n = *((char *)&x) - 0x7E;
1er PROBLEMA: mal funcionamiento de la interrupción por cambio de estado RB4..RB7
Os paso a detallar lo que me ha pasado. El PROBLEMA está en la interrupción por cambio de estado en portB RB4..RB7, resulta que el compilador al salir de la interrupción baja la bandera RBIF pero no hace una lectura/escritura en el portB y estas dos cosas se deben cumplir (mirar el Datasheet) para que de nuevo no entre en la interrupción hasta que realmente haya otro cambio de estado. Si no se hace una lectura/escritura en el portB el programa se vuelve loco y está contínuamente entrando y saliendo de la interrupción.
SOLUCION:
Leer/escribir el portB antes de abandonar la interrupción mediante un input ó un output de relleno, ó mejor aún para no perder tiempo hacerlo en ensamblador como bien dice el compañero del FORO jfh900 mediante las sentencias: #asm movf port_b,0 #endasm
////////////////////////////////////////////////////////////////// INTERNAL RC
// Constants used in setup_oscillator() are:
// Constants used in setup_oscillator() are:
// First param:
#define OSC_31KHZ 0// este es el arreglo
#define OSC_250KHZ 0x10
#define OSC_500KHZ 0x20
#define OSC_1MHZ 0x30
#define OSC_2MHZ 0x40
#define OSC_4MHZ 0x50
#define OSC_8MHZ 0x60
#define OSC_16MHZ 0x70
#define OSC_32MHZ 0x4060
#define OSC_64MHZ 0x4070
/*#define OSC_31KHZ 0 esto es lo que tiene originalmente
#define OSC_125KHZ 0x10
#define OSC_250KHZ 0x20
#define OSC_500KHZ 0x30
#define OSC_1MHZ 0x40
#define OSC_2MHZ 0x50
#define OSC_4MHZ 0x60
#define OSC_8MHZ 0x70*/
valor = 0;
while(byte_4 !=0) //SE REALIZA ESTO POR QUE LA MULTIPLICACION X100 ES ERRONEA
{
valor += 100;
byte_4--;
}resultado=(float32) resultado_1;
resultado /= cifra_2;
printf("resultado: %f%%\r\n",resultado);int16 valor;
int8 byte_3=48;
valor = (int16) byte_3 * 100;
int16 valor;
int16 byte_3=48;
valor = byte_3 * 100;
El valor '100' es un int8. Si la variable byte3 es declarada como int8, entonces no creo que sea bug de ccs.
El valor '100' es un int8. Si la variable byte3 es declarada como int8, entonces no creo que sea bug de ccs.
Pero realizando multiplicacion por 10 si funciona, como sería en este caso?
Gracias por las respuestas Mig :P
int16 valor;
int8 byte3 = 25;
valor = byte3 * 10;
valor = byte_5 * 10000; //Funciona porque 10000 es un int16 y hace un casting implícito sobre byte_5 a int16
valor += byte_4 * 1000; //Funciona porque 10000 es un int16 y hace un casting implícito sobre byte_4 a int16
valor += byte_3 *100; //No te funciona porque 100 es un int8 y no hace casting implícito, debes hacer uno explícito para pasarlo a int16
valor += byte_2 * 10; //Funciona porque el número va a ser de 0 a 9, el resultado será 0 a 90, que caben en un int8 normalmente
valor += byte_1;
valor = byte_5 * 10000;
valor += byte_4 * 1000;
valor += (int16) byte_3 * 100;
valor += byte_2 * 10; //Lo dejo así porque ya se sabe que byte_2 nunca excederá el 9
valor += byte_1;
#byte DataBus = PORTD // DEFINE BUS DE DATOS
#byte Tris_DataBus = TRISD // DEFINE TRIS DE BUS DE DATOS
#byte ControlBus = PORTE // DEFINE BUS DE CONTROL
#byte Tris_ControlBus = TRISE // DEFINE TRIS DEL BUS DE CONTROL
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LCD.H //
// VERSION 2.1 //
// JULIO 2009 //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#nolist
// DEFINICION DE CONSTANTES PARA USO EN FUNCIONES
#define HOME 0x02 // PARA PONER CURSOR EN LA POSICION 0 DEL DISPLAY. USAR CON WRITE_LCD_COM
#define INCREASE 0x02 // INCREMENTA CURSOR. USAR CON LCD.ID
#define DECREASE 0x00 // DECREMENTA CURSOS. USAR CON LCD.ID
#define SHIFT_ON 0x01 // SHIFT DISPLAY. USAR CON LCD.SHIFT
#define SHIFT_OFF 0x00 // NO SHIFT DISPLAY. USAR CON LCD.SHIFT
#define LCD_ON 0x04 // ACTIVA LCD. USAR CON LCD.MODE
#define LCD_OFF 0x00 // DESACTIVA LCD. USAR CON LCD.MODE
#define CURSOR_ON 0x02 // ACTIVA CURSOR. USAR CON LCD.CURSOR
#define CURSOR_OFF 0x00 // DESACTIVA CURSOR. USAR CON LCD.CURSOR
#define BLINK_ON 0x01 // ACTIVA PARPADEO DEL CURSOR. USAR CON LCD.BLINK
#define BLINK_OFF 0x00 // DESACTIVA PARPADEO DEL CURSOR. USAR CON LCD.BLINK
#define BUS_8 0x10 // DEFINE BUS DE 8 BITS. USAR CON LCD.INTERFASE
#define BUS_4 0x00 // DEFINE BUS DE 4 BITS. USAR CON LCD.INTERFASE
#define CLEAR 0x01 // LIMPIA DISPLAY. USAR CON FUNCION WRITE_LCD_DATA()
#define NOCLEAR 0x00 // NO LIMPIA DISPLAY. USAR CON FUNCION WRITE_LCD_DATA()
#define LINE1 0x00 // PRIMERA DIRECCION DE LINEA 1.
#define LINE2 0x40 // PRIMERA DIRECCION DE LINEA 2.
#define LINE3 0x14 // PRIMERA DIRECCION DE LINEA 3.
#define LINE4 0x54 // PRIMERA DIRECCION DE LINEA 4.
#define LARGO 16 // Editar esta línea para indicar la cantidad de caracteres por línea del display
#define LINEAS 2 // Editar este línea para indicar la cantidad de líneas que dispone el display
#define NULL 0x00
#list
struct
{
char TEXT[LARGO+1]; // define texto para escribir en lcd
int ID; // define si el cursor de incrementará o decrementará
int SHIFT; // define el shift del cursor
int MODE; // define si el display está ON ú OFF
int CURSOR; // define si el cursor estará visible
int BLINK; // define si el cursor parpadeará
int INTERFASE; // define interfase de 4/8 bits
} lcd;
// CONFIGURAR AQUI LOS PUERTO QUE SE USARAN PARA BUS DE DATOS Y DE CONTROL
#byte DataBus = PORTD // DEFINE BUS DE DATOS
#byte Tris_DataBus = TRISD // DEFINE TRIS DE BUS DE DATOS
#byte ControlBus = PORTE // DEFINE BUS DE CONTROL
#byte Tris_ControlBus = TRISE // DEFINE TRIS DEL BUS DE CONTROL
// GENERA PULSOS DE ESCRITURA PARA COMANDOS DEL DISPLAY Y SACA DATO
void WriteLcdComData(int x)
{
Tris_ControlBus = 0xF8 & Tris_ControlBus;
Tris_DatalBus = 0x00;
DataBus = ControlBus = 0x00;
ControlBus = 3;
ControlBus = 0;
ControlBus = 4;
DataBus = x;
ControlBus = 0;
ControlBus = 3;
delay_us(50);
}
// LIMPIA DISPLAY
void ClearLcd(void)
{
WriteLcdComData(CLEAR); // display clear
delay_ms(2);
}
// INICIALIZA EL EL DISPLAY
void IniLcd(void)
{
delay_ms(20);
WriteLcdComData(0x30);
delay_ms(5);
WriteLcdComData(0x30);
delay_us(150);
WriteLcdComData(0x30);
}
// CONFIGURA EL DISPLAY. LOS DATOS PARA LA CONFIGURACION DEBEN SER PUERTOS ANTES DE LLAMAR
// A ESTA FUNCION. LOS DATOS SON PARTE DE LA ESTRUCTURA LCD.
void SetupLcd(void)
{
WriteLcdComData(0x04 | lcd.ID | lcd.SHIFT); //ENTRY MODE SET
WriteLcdComData(0x08 | lcd.MODE | lcd.CURSOR | lcd.BLINK); // DISPLAY ON OFF
WriteLcdComData(0x28 | lcd.INTERFASE); // SET FUNCTION
}
// ESCRIBE DATOS EN EL DISPLAY. X REPRSENTA DESDE QUE DIRECCIÓN DEL DISPLAY SE DESEAN ESCRIBIR LOS DATOS
// E Y INDICA SE SE LIMPIARÁ EL DISPLAY ANTES DE ESCRIBIR
// SI C = CLEAN, EL DISPLAY ES LIMPIADO
// SI C = NOCLEAN, SOLO SE ESCRIBEN LOS DATOS DESDE LA POCISION ESPECIFICADA POR POS
// LOS DATOS A ESCRIBIR DEBE SER COPIADOS PREVIAMENTE EN EL ELEMENTO LCD.TEXT DE LA ESCTRUCTIRA LCD
void WriteLcd(int pos, int c)
{
int *p;
Tris_ControlBus = 0xF8 & Tris_ControlBus;
Tris_DatalBus = 0x00;
DataBus = ControlBus =0x00;
if (c)
{
clear_lcd();
delay_ms(2);
}
pos|= 0x80;
WriteLcdComData(pos);
p = lcd.TEXT;
for (; *p!=NULL; p++)
{
DataBus = 0xff;
ControlBus = 2;
ControlBus = 1;
ControlBus = 5;
DataBus = *p;
ControlBus = 1;
ControlBus = 2;
delay_us(50);
}
}
void PutcLcd(int ini, char data)
{
if (ini != CURRENT)
{
ini|= 0x80;
WriteLcdComData(ini);
}
Tris_ControlBus = 0xF8 & Tris_ControlBus;
Tris_DatalBus = ControlBus = 0x00;
DataBus = 0xff;
ControlBus = 2;
ControlBus = 1;
ControlBus = 5;
DataBus = data;
ControlBus = 1;
ControlBus = 2;
delay_us(50);
}
void ClearLcdLine(int x)
{
int y;
for (y=0; y<=LARGO; y++)
{
lcd.TEXT[y] = ' ';
}
lcd.TEXT[++y] = NULL;
switch (x)
{
case 1 : WriteLcd(LINE1,NOCLEAR);
break;
case 2 : WriteLcd(LINE2,NOCLEAR);
break;
case 3 : WriteLcd(LINE3,NOCLEAR);
break;
case 4 : WriteLcd(LINE4,NOCLEAR);
break;
default : break;
}
}
[ code][ /code]
#use RS232 (Baud=9600, Parity=N, Xmit=PIN_C6, Rcv=PIN_C7, Stream=Master, Bits=8, Enable=PIN_C5)
y uso la interrupción RDA
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
Al principio defino el puerto y el Tris
#byte PORTC = 0x07 // Necesarias
#byte TRISC = 0x87 // Necesarias
Y luego hago estos cambios:
output_bit(PIN_C2,1); lo cambio por bit_set(PORTC,2);
output_bit(PIN_C2,0); lo cambio por bit_clear(PORTC,2);
Calculates X to the Y power.
Note on error handling:
If "errno.h" is included then the domain and range errors are stored in the errno variable. The user can check the errno to see if an error has occurred and print the error using the perror function.
Range error occurs in the following case:
· pow: when the argument X is negative
Bruno, y se supone que el C nos facilita la vida :D
Lo que pasa que la raíz de un numero negativo siempre va a tener resultados imaginarios, por ejemplo -81/3 tiene -2, 1 - 1.73i y 1 + 1.73i. Y si la calculadora no trabaja con números imaginarios no lo va a resolver :mrgreen:
Después miren lo que dice la versión 4.093 de la función Pow:CitarCalculates X to the Y power.
Note on error handling:
If "errno.h" is included then the domain and range errors are stored in the errno variable. The user can check the errno to see if an error has occurred and print the error using the perror function.
Range error occurs in the following case:
· pow: when the argument X is negative
Saludos!
Lo que pasa que la raíz de un numero negativo siempre va a tener resultados imaginarios, por ejemplo -81/3 tiene -2, 1 - 1.73i y 1 + 1.73i. Y si la calculadora no trabaja con números imaginarios no lo va a resolver :mrgreen:
Muchísimas funciones tienen resultados tanto en los reales y en los complejos...
Está bien, pero si vos tenés un resultado dentro del dominio de los Reales, entonces deberías poder encontrarlo si realmente te haces llamar "calculadora". Yo no digo que está mal que la calculadora de Windows no arroje los resultados imaginarios. Digo que está mal que no arroje el -2 como resultado posible siendo que está dentro del dominio que supuestamente maneja. Lo mísmo para el Derive.
Obviamente que el impedimento debe estar en que para poder llegar al -2, las formulas utilizadas deben tener que usar números complejos para ello.
#include "C:\Users\USUARIO22\Desktop\Brujula - Tarjeta nueva\18F4550,solo sin\prueba.h"
#include "C:\Users\USUARIO22\Desktop\Brujula - Tarjeta nueva\18F4550,solo sin\lcd.c"
#include "C:\Users\USUARIO22\Desktop\Brujula - Tarjeta nueva\18F4550,solo sin\math.h"
void main()
{
double res;
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);
// TODO: USER CODE!!
lcd_init();
delay_ms(10);
while(1)
{
delay_ms(5);
res=sin(1);
printf(lcd_putc "\f %4f",res);
}
}
#include "C:\Users\USUARIO22\Desktop\Brujula - Tarjeta nueva\16f877a\16f877a.h"
#include "C:\Users\USUARIO22\Desktop\Brujula - Tarjeta nueva\16f877a\lcd.c"
#include "C:\Users\USUARIO22\Desktop\Brujula - Tarjeta nueva\16f877a\math.h"
void main()
{
double res;
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
// TODO: USER CODE!!
lcd_init();
delay_ms(10);
while(1)
{
delay_ms(5);
res=sin(1);
printf(lcd_putc "\f %4f",res);
}
}
for (char j=0; j<8; j++)
{
if (Hello_World[i][k] & 1<<(7-j)) //Should there be a letter pixel here?
{
LCD_Out(0x00, 0); //yes - draw it in black
LCD_Out(0x00, 0);
}
else
{
LCD_Out(0xFF, 0); //no - draw background in white
LCD_Out(0xFF, 0);
}
} for (k=0; k<5; k++) //Scan Columns
{
m=0x80;
for (j=0; j<8; j++)
{
if (Hello_World[i][k] & (m>>j)) //Should there be a letter pixel here?
{
LCD_Out(0x00, 0); //yes - draw it in black
LCD_Out(0x00, 0);
}
else
{
LCD_Out(0xFF, 0); //no - draw background in white
LCD_Out(0xFF, 0);
}
}
} char j;
char m=128;
for (j=0; j<8; j++)
{
if (Hello_World[i][k] & m) //Should there be a letter pixel here?
{
LCD_Out(0x00, 0); //yes - draw it in black
LCD_Out(0x00, 0);
}
else
{
LCD_Out(0xFF, 0); //no - draw background in white
LCD_Out(0xFF, 0);
}
m/=2;
}Hola Bruno, es cierto que eliminaría el uso de <<, pero la división como tal introduciría más código rom... ¿? :huh:
Este hilo se abre para intentar que otros no pierdan el tiempo que nosotros perdimos por culpa de un mal funcionamiento del compilador de CCS.
Particularmente es el compilador que más uso y es uno de los más usados, por no decir el que más.
1er PROBLEMA: mal funcionamiento de la interrupción por cambio de estado RB4..RB7
en la simulación se me quedaba en la biblioteca flex_lcd.c como si hubiera un lazo infinito... la cuestión que me dijeron que el MPLAB SIM toma al LCD como si estuviera apagado entonces esa biblioteca(flex_lcd.c) tiene un bug ahí??? Alguien sabe como solucionar eso?
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include <lcd.c>
void main() {
lcd_init();
lcd_putc("\fReady...\n");
}
int con_grabar_memo;
int tiempo_menu;
int16 peso_bruto;
short ban_05seg;
short ban_1seg;int con_grabar_memo;
int tiempo_menu;
//int16 peso_bruto;
short ban_05seg;
short ban_1seg;int tiempo_menu;
int16 peso_total;
int16 peso_cero;
int16 peso_inicial;
int16 valor_ad;
int16 valor_temperatura;
int16 peso_total_alar;
int16 peso_bruto;
int16 peso_bruto2;
int16 peso_bruto3;
int16 peso_bruto4;
int16 peso_bruto5;
int16 peso_bruto6;
signed int16 peso_post_cero;
signed int16 peso_diferencia;
signed int16 peso_modi;
signed int16 res_peso_modi;
signed int16 memoria_actual;char dato_recibido;
int dir_ad1100 = 0b10010000;
int pos_flecha;
int max_flecha;
int min_flecha;
int con_menu;
int res_con_menu = 255;
int reg_led;
int con_1seg;
int dec_hora; //Definicion de variables ds1307
int uni_hora;
int dec_minu;
int uni_minu;
int dec_seg;
int uni_seg;
int dia_sem;
int dec_dia;
int uni_dia;
int dec_mes;
int uni_mes;
int dec_anio;
int uni_anio;
int dec_hora_ini;
int uni_hora_ini;
int dec_minu_ini;
int uni_minu_ini; //variable peso inicial
int dec_dia_ini;
int uni_dia_ini;
int dec_mes_ini;
int uni_mes_ini;
int dec_anio_ini;
int uni_anio_ini;
int dec_h_tempo;
int uni_h_tempo;
int dec_m_tempo;
int uni_m_tempo;
int reg_configura;
int reg_peso_mover;
int con_cheq_mover = 4;
int respaldo_global;
int confi_decimal;
int segundos;
int numero_memo;
int con_grabar_memo;
int tiempo_menu;
int16 peso_total;
int16 peso_cero;
int16 peso_inicial;
int16 valor_ad;
int16 valor_temperatura;
int16 peso_total_alar;
int16 peso_bruto;
int16 peso_bruto2;
int16 peso_bruto3;
int16 peso_bruto4;
int16 peso_bruto5;
int16 peso_bruto6;
signed int16 peso_post_cero;
signed int16 peso_diferencia;
signed int16 peso_modi;
signed int16 res_peso_modi;
signed int16 memoria_actual;
short ban_05seg;
short ban_1seg;
short ban_tec_enc;
short ban_tec_menu;
short ban_tec_cero;
short ban_tec_incre;
short ban_tec_decre;
short ban_tec_enter;
short ban_tec_salir;
short ban_tec_p_ini;
short ban_tec_lb;
short ban_tec_m_peso;
short ban_tec_mover;
short ban_tec_tempo;
short ban_tec_egreso;
short ban_temperatura;
short ban_buzzer;
short ban_reloj;
const char los[] = "LOS";
const char pinos[] = "PINOS";
const char tecnologia[] = "TECNOLOGIA PARA UNA VIDA MAS FACIL www.lospinos-sa.com ";
//"TECNOLOGIA-PARA-UNA----VIDA-MAS-FACIL----www.lospinos-sa.com-"
const char peso[] = "PESO";
const char actu[] = "Actu.";
const char inic[] = "Inic.";
const char dife[] = "Dife.";
const char mover[] = " Mover";
const char egreso[] = "Egreso";
const char decimal[] = "Decimal";
const char memoria[] = "Memoria";
const char hora_fecha[] = "Hora fecha";
const char hh_mm[] = "hh:mm";
const char temporizar[] = "Temporizar";
const char configuracion[] = "Configuracion";
const char temporizador[] = "Temporizador";
const char cero[] = "Fijar cero y";
const char restablecer[] = "restablecer los";
const char registros[] = "registros ?";
const char p_inicial[] = "Fijar peso inic. ?";
const char peso_ini[] = "Peso ini.";
const char modi_peso[] = "Modificar peso ?";
char cadena_peso[] = "0000000";
switch(buffer_teclado[++direccion_buffer_teclado])
{
case 'T': ///CONFIGURACION QUE INDICA EL NUMERO DE TEXTO Y REALIZA LA DETECCION DE
{
if(buffer_teclado[direccion_buffer_teclado+2] == '}') ///DETECTA SI EL VALOR ES DE 1 CIFRA
{
if(isdigit(buffer_teclado[++direccion_buffer_teclado])) ///SE ASEGURA QUE EL DATO ES UN NUMERO VALIDO
{
direccion = (buffer_teclado[direccion_buffer_teclado])-48; ///SETEA EL VALOR DE LA DIRECCION EN LA KE SE
direccion *= 100; ///LOS PAKETES DE DIRECCIONES SON MULTIPLOS DE 100
++direccion_buffer_teclado; ///SE COLOCA EL BUFFER PARA QUE LEA LA SIGUIENTE {
itera_max++; ///SE AUMENTA EL CONTROL DE VECES MAXIMO QUE SE ESTA EN ESTA FUNCION
}
}
}
Bueno, me han respondido de CCS, diciendome que estan al tanto de mi reporte de bug, y que me agradecen el detalle del error ofrecido(les detalle todo :) ) y que lo estan investigando. Espero verlo solucionado en la próximas librerias usb :)
Facebook paga por encontrar errores? :shock: Yo ya vi unos cuantos... :)
Basic Types
Range
________________________________________________
Type-Specifier Size Unsigned Signed Digits
int1 1 bit number 0 to 1 N/A 1/2
int8 8 bit number 0 to 255 -128 to 127 2-3
int16 16 bit number 0 to 65535 -32768 to 32767 4-5
int32 32 bit number 0 to 4294967295 -2147483648 to 2147483647 9-10
float32 32 bit float -1.5 x 1045 to 3.4 x 1038 7-8
C Standard Type Default Type
short int1
char unsigned int8
int int8
long int16
long long int32
float float32
Note: All types, except float , by default are unsigned; however, may be preceded by unsigned or
signed . Short and long may have the keyword INT following them with no effect. Also see #TYPE
to change the default size.
y lo que se me hace un poco dificil entender es la conversion del adc
OJO CON EL CÁCULO DE LOS PWMCon que version(es) has probado esto?
(ver ejemplo ex_pwm de ccs)
he descubierto un pequeño error en la documentación del uso del módulo PWM, si os fijais en los elemplos, para el uso de la función set_pwmx_duty(value), que indica el ancho del pulso, nos indica que para variables long la formula es tiempo=value*(1/clock)*t2div, y si usas un int es tiempo=value*4*(1/clock)*t2div, pues bien, yo he usado un int32 y he tenido que usar la segunda, o sea la de int8.
PROBADISIMO
quiero preguntar algo, veran en una simulacion con un pic16f628a en proteus el cual tiene conectado un teclado matricial 3x4 y un display A.C, hago mi programa y cuando lo cargo y simulo, no me simula nada y me aparecen muchos mensajes que dice "el portb es despreciado por el 16628" me pueden decir que significa? o es necesario que suba el codigo de programacion.
aparte me dice algo de que lineas de programacion muy largas para MAIN =/ si alguien me puede ayudar.
Hola Miguel, si, me deja desconcertado esto y créame que me genera una gran desconfianza utilizarla.
Saludos.
Hola amigo, tengo la versión 4.130, he probado con los siguientes PIC y funciona mal 12F675-629-676, con 628-676 funciona bien
Saludos.
Porqué dices que esa versión es la más estable ?, la usas ?
Saludos
hola que tal, tengo una duda a ver si me pueden ayudar, quiero hacer un programa en c, para iluminar una escalera de mi casa con x cantidad de escalones sera un led por cada uno, tendre un interruptor (eso lo manejare externo, aparte con una compuerta) al inicio y al final de la escalera, con un display 7 segmentos uno en cada extremo, con el selector activo la iluminacion de la escalera a traves de un interruptor, en el display cada numero es una manera diferente de iluminar los escalones y asi quedara hasta que se desactive. habran 9 tipos diferentes de que se ilumine la escalera. bueno de antemano le doy las gracias!!! saludos
Voy a advertir sobre algo que ya me ha cansado con CCS, y que me ha fallado, desde la version 4.088(incluso puede ser desde antes, no lo recuerdo) hasta la 4.104 que es la que uso ahora.
Intentar utilizar un puntero de una estructura para recorrer un array de dicha estructura resulta en DESASTRE. El problema es bastante evidente. El CCS muchas veces, no acomoda los elementos del array de la estructura consecutivamente en la RAM. Esto hace que obviamente luego, al querer recorrerlos con un puntero, el puntero se ubique en posiciones de memoria que no corresponden a ningún elemento del array, generando estragos en la ejecución del programa.
Considerense advertidos...
char opc[7][15];
#INT_EXT NOCLEAR
void EXT_isr()
{
char opc[7][15]={"Tipo de onda","Frecuencia","Periodo","","","",""}; //VECTOR GLOBAL
while(!bit_test(PORT_B,0)){delay_us(200);}
disable_interrupts(INT_EXT1 && INT_EXT2);
clear_interrupt(INT_EXT);
menu(opc);
}
void menu(char opc)
{
int i;
disable_interrupts(INT_EXT);
disable_interrupts(INT_EXT1);
disable_interrupts(INT_EXT2);
lcd_clear();
gotoxy(0,0);
printf(print_char,">");
for(i=0;i<=6;i++)
{
gotoxy(10,i);
printf(print_char,opc[i]);
}
}#INT_EXT NOCLEAR
void EXT_isr()
{
while(!bit_test(PORT_B,0)){delay_us(200);}
output_toggle(PIN_C2);
disable_interrupts(INT_EXT1 && INT_EXT2);
clear_interrupt(INT_EXT);
menu();
}
void menu()
{
int i;
char opc[7][15]={"Estado","Tipo de onda","Amplitud","Frecuencia","Periodo","Duty cicle",""};
disable_interrupts(INT_EXT);
disable_interrupts(INT_EXT1);
disable_interrupts(INT_EXT2);
lcd_clear();
gotoxy(0,0);
printf(print_char,">");
for(i=0;i<=6;i++)
{
gotoxy(10,i);
printf(print_char,opc[i]);
}
}Hola matyvico,
tal vez no sea ayuda ni consuelo, pero podrías intentar forzando al CCS a que guarde el array justo alineado al inicio de un banco de RAM, de esa forma por ahi el CCS te lo pone secuencialmente de corrido. Había una sentencia en CCS para indicar la posición RAM pero no la recuerdo. Tal vez es tan evidente como #RAM. Si no la encontrás decime que la busco en algún proyecto pasado.
Un gusto haberte conocido la voz.
Saludos.
char imagen[9][96]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,240,240,240,240,240,240,240,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,240,240,240,
240,240,240,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,240,240,240,240,240,240,240,112,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,3,15,63,255,255,255,255,255,255,252,248,240,224,192,128,0,0,0,0,0,0,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,128,192,224,
240,248,252,255,255,255,255,255,255,63,15,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,7,15,31,
63,127,255,255,255,255,255,254,252,252,248,248,240,240,255,255,255,255,255,255,255,255,240,240,248,248,252,252,254,255,255,255,255,255,127,63,31,15,
7,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,240,240,240,240,240,240,240,240,240,240,240,240,
241,241,243,243,247,247,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,247,247,243,243,241,241,240,240,240,240,240,240,240,
240,240,240,240,240,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,15,15,15,15,15,15,15,15,15,15,15,15,143,
143,207,207,239,239,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,239,239,207,207,143,143,15,15,15,15,15,15,15,15,15,15,15,
15,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,224,240,248,252,254,255,255,255,255,255,127,
63,63,31,31,15,15,255,255,255,255,255,255,255,255,15,15,31,31,63,63,127,255,255,255,255,255,254,252,248,240,224,192,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,240,252,255,255,255,255,255,255,63,31,15,7,3,1,0,0,0,0,0,0,0,0,255,255,255,255,
255,255,255,255,0,0,0,0,0,0,0,0,1,3,7,15,31,63,255,255,255,255,255,255,252,240,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,12,15,15,15,15,15,15,15,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,15,15,15,15,15,15,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,15,15,15,15,15,15,15,
14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
const char imagen[9][96]={...}const Data is read-only. Depending on compiler configuration, this qualifier may just make the data read-only -AND/OR- it may place the data into program memory to save space.
#LOCATE
works like #BYTE however in addition it prevents C from using the area.
A special form of this directive may be used to locate all A functions local variables starting at a fixed location.
Use: #locate Auto = address
This directive will place the indirected C variable at the requested address.
Creo que tenés varios errores en el código, por eso no te funciona.No logré que compile tu código, lo que tiene cierta lógica porque veo un par de cosas que no deberían poder compilar.
Qué es lo que debe hacer la subrutina menú? Imprimir el texto del número de opción seleccionada actualmente?
Hola de nuevo,
estuve leyendo el código. Pensé que era un array de estructuras, como el caso en el que mencionaba que ocurre el bug, pero veo que tu caso es un simple array de dos dimensiones.
Creo que tenés varios errores en el código, por eso no te funciona.No logré que compile tu código, lo que tiene cierta lógica porque veo un par de cosas que no deberían poder compilar.
Qué es lo que debe hacer la subrutina menú? Imprimir el texto del número de opción seleccionada actualmente?
const char opc[7][15]={"Tipo de onda","Frecuencia","Periodo","1","2","3","4"}; //VECTOR GLOBAL
void menu(const char* str)
{
printf("%s\n", str);
}
int main(int argc, char *argv[])
{
int i = 0;
for( ;i < 7; ++i)
{
menu(&opc[i][0]);
}
system("PAUSE");
}Tipo de onda
Frecuencia
Periodo
1
2
3
4
Presione una tecla para continuar . . .Bruno, un gusto leerte por los foros :D
Que tal, no se si este bug este ya colocado igual lo pongo
version CCS 4.130
PIC utilizado PIC16F1933
en la rutina de interrupción para cambio de estado (INT_RB),nunca borra la bandera y por tanto se queda en la rutina en un ciclo infinito.
simulado con MPLAB y comprobado fisicamente.
Solucion:
Borrar manualmente la bandera al finalizar la rutina,similar a hitech o C18.
Eso pasa por confiarse del compilador jeje.
Versión de CCS 4.140
Micro PIC18F2550
Bug: Posible cálculo erróneo del baudrate de la USART
¡Por favor que no me presenten personalmente a nadie de CCS! Porque termino en la cárcel, seguro.
Después de una semana luchando a brazo partido con un hardware que estoy desarrollando, alrededor de un 18F2550, no he sido capaz de comunicar con él por el puerto serie .... parece como si el baudrate estuviese loco y no transmite o recibe a una velocidad estándar ...
Tras revisar hasta el infinito el hardware y viendo que al menos en apariencia todo estaba perfecto se me ocurrió hacer una prueba, gato escaldado del agua fría huye, prueba que ya hice hace tiempo al ocurrirme un error similar ... compilé exactamente el mismo programa, sin tocar un punto y coma, pero con mi versión de referencia del CCS, la 3.242 ...
Y voilá todo funcionando. Sin problema alguno envía y recibe a su baudrate adecuado y sin mayor problema. :5] :5] :5] :5] :5]
Mira las opciones de Use_Delay() .
Prueba ponerle Crystal en vez de Clock (esta opcion ahora es distinta) y despues me dices si hay resultado...
Mira las opciones de Use_Delay() .
Prueba ponerle Crystal en vez de Clock (esta opcion ahora es distinta) y despues me dices si hay resultado...
#include <18f2550.h>
#use delay(clock= 20000000)
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN
#use rs232(baud=115200,xmit= pin_c6,rcv=pin_c7)
void main()
{
printf("Hola Amigos del Foro");
while(true);
}
No creo que Diego lo haya probado en Proteus, mas bien estoy seguro que lo ha hecho en una placa ya armada, y bien sabemos las diferencias entre simular y probarlo en la practica... Mr. Green
Lo curioso es que yo he colocado los dos parámetros y así es como me ha funcionado.Código: CSS
#use delay(clock=20000000,Crystal=20000000)
amigos necesito una ayuda lo que pasas es que creo cualquier programa en picc y compilo y ejecuta bien pero voy a la carpeta donde guarde el archivo y no me crea el punto hex... ayudaCreo que eso no es un bug, pero puedes irte a "Options" luego a "project" y luego en "output files" y verifica que este activa la casilla del .hex, también verifica que no tengas errores, puede que por eso no genere el .hex
no es un bug, creo que es como algo que olvidaron la gente del ccs. me refiero a la opción de intercambiar entre versiones de compiladores en el IDE PCW,
en las versiones 5.x se puede instalar versión sobre versión y clickando en about (dentro del IDE) se puede intercambiar entre compiladores, pero he aquí un detalle que descubrí,
si por ejemplo las librerías de los micros han sufrido cambios entonces puede que una versión diferente del último compilador instalado genere errores, tal como me sucedió con la librería 18f2550.h y con las versiones 4.130 y 5.xxx
la opción de permitir compilar seleccionando compiladores es excelente, pero olvidaron decir que el resto de los archivos se reemplazarán por completo a los antiguos que venían con una versión anterior.
1er PROBLEMA CON INTERRUPCIÓN
Solución:
Al finalizar cualquier interrupción siempre se debe poner
clear_interrupt(INT_XXX);
eso yo lo hago y me funciona perfectamente :-)
#int_rb
void interrup()
{
output_toggle(pin_a1);
c='1';
v=read_adc();
clear_interrupt(int_rb);
}
Otro dato, es que en las interrupciones no deben de tener retardos de ningún tipo.
Deben ejecutar su tarea/función lo mas rápido posible
Hola que tal.
Note que con el pic #include <18F46K22.h> mi ccs versión 5.015
programador PicKit 2 V2.61
el fuse de protección de lectura funciona al revez. con:
#FUSES PROTECT
Después de grabar el micro, al leerlo me muestra todo el código.
mientras que con:
#FUSES NOPROTECT
después de grabar y al leer el pic con el programador me muestra todo ceros.
O sea, PROTECT no proteje, y NOPROTEC si proteje.
solo con este micro me lo hizo, con otros anda bien.