TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Diego E. en 26 de Octubre de 2009, 11:52:46
-
Hola grupo, hoy a deferencia de las otras veces no voy a consultar, esta vez quiero hacer un pequeño aporte al foro, que harto me ha ayudado.
Quiero pulbicarles esta aplicación de tipo dedáctico implementada para el PIC-18F4550, pensando en aquellos que al igual que Yo nos estamos iniciando en la programación en C para microcontroladores. Elegí este PIC dada su completa arquitectura y capacidad de memoria.
En esta aplicación utilicé los módulos básicos del PIC:
1- Display LCD a 4 bit
2- Conversión AD a 10 bit
3- Timer1, con interrupción
4- Transmisión serial RS-232 a 4800 bps, con interrupción en recepción RX
5- Cominicación I2C, con RTC DS1307
6- Teclado matricial de 4x4
7- Memoria EEPROM interna
Descripción:
1- El PIC realiza un conversión AD tomando la señal por RA0
2- Se toma el valor entero de 0-1023 y se calcula además en porcentaje, ambos valores son convertidos en cadena y llevados al LCD
3- Esta cadena, resultado AD, es enviada al PC via RS-232
4- El dato recibido del PC, 1 caracter ASCII, es presentado en el LCD y alamacenado en la EEPROM en la dirección 0.
5- Se lee las variables de tiempo real del DS-1307, se convierten en cadena y se presentan en el lcd, ejemplo:"12:00:00 01/01/2000"
5- Por medio del teclado, presionando primero la tecla reloj, se habilita la programación de la hora y fecha, haciendo oscilar el cursor del LCD en la variable correspondiente le llevamos el número deseado desde el teclado, luego el dato es grabado en el DS-1307.
Siempre he programado en assembler y es obvio que tengo muchos vicios de este lenguaje, pero de todos modos trataré de resolver cualquier inquietud que este ejercicio les suscite, además recibo cualquier sugerencia, si se dé el caso, de alguna forma para mejorar un procedimiento.
Lástimosamente el puerto USB, que es mi siguiente paso, no lo domino en absoluto, pero cuando tenga algo se los compartiré.
Un abrazo a todos los miembros del FORO.
saludos.
#include <18F4550.h>
#device adc = 10
#use delay(clock=4000000)
#use i2c(master, sda=PIN_B0, scl=PIN_B1,force_hw)
#use rs232(baud=4800, xmit=PIN_C6,rcv=PIN_C7)
#fuses XT, MCLR, NOWDT
#include <stdlib.h>
//resgistros especiales del PIC
#byte porta = 0xf80
#byte portb = 0xf81
#byte portc = 0xf82
#byte portd = 0xf83
#byte porte = 0xf84
#byte t1con = 0xfcd
#byte latd = 0xf8c
#byte adcon0 = 0xfc2
#byte adcon1 = 0xfc1
#byte adcon2 = 0xfc0
#byte adresl = 0xfc3
#byte adresh = 0xfc4
//etiquetas
#define e porte,0
#define rs porte,1
#define puerto_tec latd
#define tec_c1 portd,4
#define tec_c2 portd,5
#define tec_c3 portd,6
#define tec_c4 portd,7
#define tec_f1 portd,0
#define tec_f2 portd,1
#define tec_f3 portd,2
#define tec_f4 portd,3
//definicion de funciones
void ini_lcd_4b();
void display_4b(short valor , int respaldo);
void msj1();
void teclado();
void msj_analogo();
void msj_ra0();
void conversion_ad();
void msj_analogo1();
void msj_rx();
void msj_datos_rec();
void msj_ds1307();
void leer_ds1307();
void conf_ds1307();
void confi_reloj(int valor);
//variables
char registro_tec;
char datos_rec;
short int ban_tmr1;
short int ban_tec1;
short int ban_tec2;
short int ban_tec3;
short int ban_tec4;
short int ban_tec5;
short int ban_tec6;
short int ban_tec7;
short int ban_tec8;
short int ban_tec9;
short int ban_tec10;
short int ban_tec11;
short int ban_tec12;
short int ban_tec13;
short int ban_tec14;
short int ban_tec15;
short int ban_tec16;
short int ban_reloj;
int dec_hora,uni_hora,dec_minu,uni_minu,dec_seg,uni_seg; //Definicion de variables
int dia_sem, dec_dia, uni_dia, dec_mes, uni_mes, dec_amo, uni_amo;
int cont_prg_reloj;
char analogo[5];
char ds1307[18]; //= "12:00:00 22/09/75";
int16 resultado_ad;
//definicion de constantes
byte const tabla1[] = {"! Bienvenidos !"}; //Tabla que contiene el texto a mostrar
byte const tabla2[] = {"RA0 = "}; //Tabla que contiene el texto a mostrar
byte const tabla_rx[] = {"RX="}; //Tabla que contiene el texto a mostrar
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#INT_timer1 //Vector de interrupcion por desbordamiento del
//timer 1
void interrupcion_tmr1()
{
set_timer1(3042); //62.500 * 8 (prescaler) = 0,5 seg
ban_tmr1 = 1;
}
///////////////////////////////////////////////////////////////////////////////
#int_rda //Vector de interrupcion de la recepcion de datos
void interrupcion_rx() //por el usart
{
datos_rec = getc(); //Se lee el dato recibido
write_eeprom(0,datos_rec);
}
///////////////////////////////////////////////////////////////////////////////
#zero_ram //Borrado de la memoria ram
#rom 0xf00000 = {"Hola"} //Datos precargados en la rom
//Rutina principal
void main()
{
//configuracion de puertos y registros especiales
set_tris_b(0b11111111);
set_tris_d(0x0f);
set_tris_e(0);
t1con=(0b00110101); //Configuracion del tmr1
enable_interrupts(global); //Habilitación de todas las interrupciones
enable_interrupts(INT_timer1); //Habilitación de la interrupción del Tmr1
enable_interrupts(int_rda); //Habilitación, recepcion de datos del PC
adcon0 = (0b00000001);
adcon1 = (0b00001110);
adcon2 = (0b10000000);
//configurar el display
delay_ms(2);
ini_lcd_4b();
msj1();
delay_ms(2000);
display_4b(0 , 1); //Limpia el display
delay_ms(2);
portd = 0;
bit_set(porte,7); //habilita pull-up del puerto d ???
registro_tec = '?';
datos_rec = read_eeprom(0); //se lee los datos de la eeprom
memset(analogo,'0',sizeof(analogo)); //se carga la matriz analogo con valores "0"
msj_ra0();
msj_rx();
///////////////////////////////////////
while(true)
{
delay_ms(10);
teclado();
if(ban_tmr1 == 1)
{
if(ban_reloj == 1) //si esta programando el reloj salta estas rutinas
{goto no_display;}
ban_tmr1 = 0;
conversion_ad();
msj_analogo1();
msj_datos_rec();
leer_ds1307();
msj_ds1307();
no_display:
delay_cycles(1);
}
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//rutina que envia el primer mensaje al lcd
///////////////////////////////////////////////////////////////////////////////
void msj_ds1307()
{
int i;
sprintf(ds1307,"%u%u:%u%u:%u%u %u%u/%u%u/%u%u",dec_hora, uni_hora, dec_minu, uni_minu, dec_seg, uni_seg, dec_dia, uni_dia, dec_mes, uni_mes, dec_amo, uni_amo);
display_4b(0 , 0x94); //Dirección donde se escribirá el mensaje
for(i=0;i<sizeof(ds1307)-1;i++) //Ciclo que envía el texto al LCD
{
display_4b(1 , ds1307[i]);
}
}
///////////////////////////////////////////////////////////////////////////////
void msj_rx()
{
int i;
display_4b(0 , 0x90); //Dirección donde se escribirá el mensaje
for(i=0;i<sizeof(tabla_rx)-1;i++) //Ciclo que envía el texto al LCD
{
display_4b(1 , tabla_rx[i]);
}
}
///////////////////////////////////////////////////////////////////////////////
void msj_datos_rec()
{
display_4b(0 , 0x93); //Dirección donde se escribirá el mensaje
display_4b(1 , datos_rec);
}
///////////////////////////////////////////////////////////////////////////////
void msj1()
{
int i;
display_4b(0 , 0x82); //Dirección donde se escribirá el mensaje
for(i=0;i<sizeof(tabla1)-1;i++) //Ciclo que envía el texto al LCD
{
display_4b(1 , tabla1[i]);
}
}
///////////////////////////////////////////////////////////////////////////////
void msj_ra0()
{
int i;
display_4b(0 , 0x80); //Dirección donde se escribirá el mensaje
for(i=0;i<sizeof(tabla2)-1;i++) //Ciclo que envía el texto al LCD
{
display_4b(1 , tabla2[i]);
}
}
///////////////////////////////////////////////////////////////////////////////
void msj_analogo1() //"RA0 = 0000 000%"
{
int i;
sprintf(analogo,"%04lu",resultado_ad);
printf("RA0 = %s - ",analogo); //datos ap PC, no envia retorno de carro
display_4b(0 , 0x86); //Dirección donde se escribirá el mensaje
for(i=0;i<sizeof(analogo)-1;i++) //Ciclo que envía el texto al LCD
{
display_4b(1 , analogo[i]);
}
///////////////////////////////////
i = ((int32)resultado_ad * 100) / 1024; //se calcula porcentaje
sprintf(analogo,"%03u%%",i);
puts(analogo); //datos al PC, se envia retorno de carro
display_4b(0 , 0x8b); //Dirección donde se escribirá el mensaje
for(i=0;i<sizeof(analogo)-1;i++) //Ciclo que envía el texto al LCD
{
display_4b(1 , analogo[i]);
}
}
///////////////////////////////////////////////////////////////////////////////
//rutina de inicializacion del lcd
void ini_lcd_4b()
{
display_4b(0 , 0b00111000); //Codigo para display a 4 bits
display_4b(0 , 0b00001100); //Codigo que activa el display
display_4b(0 , 0b00000110); //Que se desplace hacia la derecha
//display_4b(0 , 0b00000111)//Codigo que define el cursor para
//que desplace hacia la izquierda
//todo el mensaje
display_4b(0 , 1); //Limpia el display
delay_ms(2);
}
///////////////////////////////////////////////////////////////////////////////
void display_4b(short valor , int respaldo) //Rutina que envia al LCD una palabra de control o dirección
{
int respaldo2;
if(valor == 0)
{bit_clear(rs);}
else
{bit_set(rs);}
portd &= 0x0f;
respaldo2 = respaldo & 0xf0 ;
portd |= respaldo2;
bit_set(e);
delay_cycles(10);
bit_clear(e);
portd &= 0x0f;
respaldo2 = swap(respaldo) & 0xf0 ;
portd |= respaldo2;
bit_set(e);
delay_cycles(10);
bit_clear(e);
delay_ms(1);
}
///////////////////////////////////////////////////////////////////////////////
void conversion_ad() //rutina de conversión AD
{
set_adc_channel(0);
delay_us(10);
resultado_ad = read_adc();
}
///////////////////////////////////////////////////////////////////////////////
void teclado() //Rutina general de teclado
{
puerto_tec=(0xf0);
bit_clear(tec_c1);
delay_us(100);
if((bit_test(tec_f1)==0)&&(ban_tec1==0)) //tecla que programa el reloj
{
int respaldo;
ban_tec1 = 1;
registro_tec = 'A';
cont_prg_reloj++;
respaldo = portd;
switch(cont_prg_reloj)
{
case 1:
ban_reloj = 1;
display_4b(0, 0x94);
display_4b(0 , 0b00001101); //Codigo que hace oscilar el cursor
break;
case 2:
display_4b(0, 0x95);
break;
case 3:
display_4b(0, 0x97);
break;
case 4:
display_4b(0, 0x98);
break;
case 5:
display_4b(0, 0x9a);
break;
case 6:
display_4b(0, 0x9b);
break;
case 7:
display_4b(0, 0x9d);
break;
case 8:
display_4b(0, 0x9e);
break;
case 9:
display_4b(0, 0xa0);
break;
case 10:
display_4b(0, 0xa1);
break;
case 11:
display_4b(0, 0xa3);
break;
case 12:
display_4b(0, 0xa4);
break;
case 13:
ban_reloj = 0;
cont_prg_reloj = 0;
display_4b(0 , 0b00001100); //Codigo para que no oscile el cursor
conf_ds1307();
default:
}
portd = respaldo;
}
if((bit_test(tec_f1)==1)&&(ban_tec1==1)) //tecla soltada
{
ban_tec1 = 0;
}
if((bit_test(tec_f2)==0)&&(ban_tec2==0)) //tecla presionada
{
ban_tec2 = 1;
registro_tec = '3';
confi_reloj(3);
}
if((bit_test(tec_f2)==1)&&(ban_tec2==1)) //tecla soltada
{
ban_tec2 = 0;
}
if((bit_test(tec_f3)==0)&&(ban_tec3==0)) //tecla presionada
{
ban_tec3 = 1;
registro_tec = '2';
confi_reloj(2);
}
if((bit_test(tec_f3)==1)&&(ban_tec3==1)) //tecla soltada
{
ban_tec3 = 0;
}
if((bit_test(tec_f4)==0)&&(ban_tec4==0)) //tecla presionada
{
ban_tec4 = 1;
registro_tec = '1';
confi_reloj(1);
}
if((bit_test(tec_f4)==1)&&(ban_tec4==1)) //tecla soltada
{
ban_tec4 = 0;
}
bit_set(tec_c1);
///////////////////////////////////
bit_clear(tec_c2);
delay_us(100);
if((bit_test(tec_f1)==0)&&(ban_tec5==0)) //tecla presionada
{
ban_tec5 = 1;
registro_tec = 'D';
}
if((bit_test(tec_f1)==1)&&(ban_tec5==1)) //tecla soltada
{
ban_tec5 = 0;
}
if((bit_test(tec_f2)==0)&&(ban_tec6==0)) //tecla presionada
{
ban_tec6 = 1;
registro_tec = '6';
confi_reloj(6);
}
if((bit_test(tec_f2)==1)&&(ban_tec6==1)) //tecla soltada
{
ban_tec6 = 0;
}
if((bit_test(tec_f3)==0)&&(ban_tec7==0)) //tecla presionada
{
ban_tec7 = 1;
registro_tec = '5';
confi_reloj(5);
}
if((bit_test(tec_f3)==1)&&(ban_tec7==1)) //tecla soltada
{
ban_tec7 = 0;
}
if((bit_test(tec_f4)==0)&&(ban_tec8==0)) //tecla presionada
{
ban_tec8 = 1;
registro_tec = '4';
confi_reloj(4);
}
if((bit_test(tec_f4)==1)&&(ban_tec8==1)) //tecla soltada
{
ban_tec8 = 0;
}
bit_set(tec_c2);
///////////////////////////////////
bit_clear(tec_c3);
delay_us(100);
if((bit_test(tec_f1)==0)&&(ban_tec9==0)) //tecla presionada
{
ban_tec9 = 1;
registro_tec = 'I';
}
if((bit_test(tec_f1)==1)&&(ban_tec9==1)) //tecla soltada
{
ban_tec9 = 0;
}
if((bit_test(tec_f2)==0)&&(ban_tec10==0)) //tecla presionada
{
ban_tec10 = 1;
registro_tec = '9';
confi_reloj(9);
}
if((bit_test(tec_f2)==1)&&(ban_tec10==1)) //tecla soltada
{
ban_tec10 = 0;
}
if((bit_test(tec_f3)==0)&&(ban_tec11==0)) //tecla presionada
{
ban_tec11 = 1;
registro_tec = '8';
confi_reloj(8);
}
if((bit_test(tec_f3)==1)&&(ban_tec11==1)) //tecla soltada
{
ban_tec11 = 0;
}
if((bit_test(tec_f4)==0)&&(ban_tec12==0)) //tecla presionada
{
ban_tec12 = 1;
registro_tec = '7';
confi_reloj(7);
}
if((bit_test(tec_f4)==1)&&(ban_tec12==1)) //tecla soltada
{
ban_tec12 = 0;
}
bit_set(tec_c3);
///////////////////////////////////
bit_clear(tec_c4);
delay_us(100);
if((bit_test(tec_f1)==0)&&(ban_tec13==0)) //tecla presionada
{
ban_tec13 = 1;
registro_tec = 'B';
}
if((bit_test(tec_f1)==1)&&(ban_tec13==1)) //tecla soltada
{
ban_tec13 = 0;
}
if((bit_test(tec_f2)==0)&&(ban_tec14==0)) //tecla presionada
{
ban_tec14 = 1;
registro_tec = 'E';
}
if((bit_test(tec_f2)==1)&&(ban_tec14==1)) //tecla soltada
{
ban_tec14 = 0;
}
if((bit_test(tec_f3)==0)&&(ban_tec15==0)) //tecla presionada
{
ban_tec15 = 1;
registro_tec = '0';
confi_reloj(0);
}
if((bit_test(tec_f3)==1)&&(ban_tec15==1)) //tecla soltada
{
ban_tec15 = 0;
}
if((bit_test(tec_f4)==0)&&(ban_tec16==0)) //tecla presionada
{
int respaldo;
respaldo = portd;
ban_tec16 = 1;
registro_tec = 'S';
ban_reloj = 0;
cont_prg_reloj = 0;
display_4b(0 , 0b00001100); //Codigo para que no oscile el cursor
portd = respaldo;
}
if((bit_test(tec_f4)==1)&&(ban_tec16==1)) //tecla soltada
{
ban_tec16 = 0;
}
bit_set(tec_c4);
}
///////////////////////////////////////////////////////////////////////////////
void confi_reloj(int valor) //rutina que carga en las variables de reloj el numero presionado
{
int respaldo;
respaldo = portd;
switch(cont_prg_reloj)
{
case 1:
dec_hora = valor;
display_4b(1, dec_hora + 0x30);
display_4b(0, 0x94);
break;
case 2:
uni_hora = valor;
display_4b(1, uni_hora + 0x30);
display_4b(0, 0x95);
break;
case 3:
dec_minu = valor;
display_4b(1, dec_minu + 0x30);
display_4b(0, 0x97);
break;
case 4:
uni_minu = valor;
display_4b(1, uni_minu + 0x30);
display_4b(0, 0x98);
break;
case 5:
dec_seg = valor;
display_4b(1, dec_seg + 0x30);
display_4b(0, 0x9a);
break;
case 6:
uni_seg = valor;
display_4b(1, uni_seg + 0x30);
display_4b(0, 0x9b);
break;
case 7:
dec_dia = valor;
display_4b(1, dec_dia + 0x30);
display_4b(0, 0x9d);
break;
case 8:
uni_dia = valor;
display_4b(1, uni_dia + 0x30);
display_4b(0, 0x9e);
break;
case 9:
dec_mes = valor;
display_4b(1, dec_mes + 0x30);
display_4b(0, 0xa0);
break;
case 10:
uni_mes = valor;
display_4b(1, uni_mes + 0x30);
display_4b(0, 0xa1);
break;
case 11:
dec_amo = valor;
display_4b(1, dec_amo + 0x30);
display_4b(0, 0xa3);
break;
case 12:
uni_amo = valor;
display_4b(1, uni_amo + 0x30);
display_4b(0, 0xa4);
break;
default:
}
portd = respaldo;
}
///////////////////////////////////////////////////////////////////////////////
void leer_ds1307()
{
int respaldo;
i2c_start(); //Start
i2c_write(0b11010000); //Control
i2c_write(0b00000000); //Direccion
i2c_stop(); //Stop
i2c_start(); //Start
i2c_write(0b11010001); //Control para lectura
respaldo = i2c_read(); //Se lee los segundos
uni_seg = respaldo;
dec_seg = swap(respaldo);
uni_seg &= 0x0f;
dec_seg &= 0x0f;
respaldo = i2c_read(); //Se lee los minutos
uni_minu = respaldo;
dec_minu = swap(respaldo);
uni_minu &= 0x0f;
dec_minu &= 0x0f;
respaldo = i2c_read(); //Se lee las horas
uni_hora = respaldo;
dec_hora = swap(respaldo);
uni_hora &= 0x0f;
dec_hora &= 0x0f;
respaldo = i2c_read(); //Se lee el dia de la semana
dia_sem = respaldo;
respaldo = i2c_read(); //Se lee el dia del mes
uni_dia = respaldo;
dec_dia = swap(respaldo);
uni_dia &= 0x0f;
dec_dia &= 0x0f;
respaldo = i2c_read(); //Se lee el mes
uni_mes = respaldo;
dec_mes = swap(respaldo);
uni_mes &= 0x0f;
dec_mes &= 0x0f;
respaldo = i2c_read(); //Se lee los años
uni_amo = respaldo;
dec_amo = swap(respaldo);
uni_amo &= 0x0f;
dec_amo &= 0x0f;
respaldo = i2c_read();
i2c_stop(); //Stop
}
///////////////////////////////////////////////////////////////////////////////
void conf_ds1307()
{
int respaldo;
i2c_start(); //Start
i2c_write(0b11010000); //Control
i2c_write(0b00000000); //Direccion
respaldo = (uni_seg | (swap(dec_seg))); //Se escriben los segundos
i2c_write(respaldo);
respaldo = (uni_minu | (swap(dec_minu))); //Se escriben los minutos
i2c_write(respaldo);
respaldo = (uni_hora | (swap(dec_hora))); //Se escriben las horas
i2c_write(respaldo);
i2c_write(dia_sem);
respaldo = (uni_dia | (swap(dec_dia))); //Se escriben los dias del mes
i2c_write(respaldo);
respaldo = (uni_mes | (swap(dec_mes))); //Se escribe el mes
i2c_write(respaldo);
respaldo = (uni_amo | (swap(dec_amo))); //Se escribe el año
i2c_write(respaldo);
i2c_write(0); //Control de pulsos
i2c_stop(); //Stop
}
-
Porias Fasilitar un diagrama??
-
Hola arck_khronos, acá te pongo una imagen.
Saludos
-
gracias por la info
-
Hola,
Estoy aprendiendo a programar el pic18F4550 y este ejemplo me esta ayudando a aprender a utilizar cada interfaz, muchas gracias por el aporte.
Si tienes mas ejemplos con este pic te agradeceria que los compartieras.
Saludos
-
Hola Arttak, con este PIC estoy apenas iniciándome, no tengo más ejemplos, esto tratando de encontrar información que me permita poner en funcionamiento su puerto USB, si lo logro con seguridad que lo publicaré.
-
tiempo atras hice algo parecido, sin lectura analoga y con otro RTC , el DS1302.
Te felicito, muy buen ejemplo de manejo de perisfericos. Tambien estoy en busqueda de la comunicacion USB y asi liberarme de la rs232 por un rato jejejejeee :o
saludos pic-maniacos
-
Hola Diego.
Intersante lo q has enviado, t queria pedir de favor si puedes subir el esquematico, alguna foto m seria util.
De antemano gracias socio.
-
Acá les comparto el ejemplo completo:
Lo pueden simular perfectamente en proteus 7.4 (en la versión 7.5 no me funcionó), para verificar el puerto virtual USB pueden utilizar hyperterminal.
En esta aplicación utilicé los módulos básicos del PIC:
1- Display LCD a 4 bit
2- Conversión AD a 10 bit
3- Timer1, con interrupción
4- Transmisión serial RS-232 a 9600 bps, con interrupción en recepción RX
5- Cominicación I2C, con RTC DS1307
6- Teclado matricial de 4x4
7- Memoria EEPROM interna
8- Puerto USB en modo CDC
Descripción:
1- El PIC realiza un conversión AD tomando la señal por RA0
2- Se toma el valor entero de 0-1023 y se calcula además en porcentaje, ambos valores son convertidos en cadena y llevados al LCD
3- Esta cadena, resultado AD, es enviada al PC via RS-232 y por medio del puerto USB, Ejemplo: RA0 = 0000 - 000%
4- El dato recibido del PC, un caracter ASCII tando a través de puerto 232 como del USB, son presentado en el LCD y alamacenados en la EEPROM en la dirección 0.
5- Se lee las variables de tiempo real del DS-1307, se convierten en cadena y se presentan en el lcd, ejemplo:"12:00:00 01/01/2000"
5- Por medio del teclado, presionando primero la tecla reloj, se habilita la programación de la hora y fecha, haciendo oscilar el cursor del LCD en la variable correspondiente le llevamos el número deseado desde el teclado, luego el dato es grabado en el DS-1307.
Nota: El puerto USB crea un COM virtual el cual requiere para su reconocimiento el driver de la Micro-chip mchpcdc.inf
Pasos para verificar el USB:
1- Conecte el circuito al PC a través del USB
2- El PC pide la instalación del driver, está el la carpeta raiz del proyento
3- El dispositivo es reconocido, lo podemos verificar en el administrador de dispositivos, normalmente aparece COM5
4- Inicie una sesión con Hyperterminal, seleccionar COM5 o el puerto asignado al dispositivo, configurar 9600 bps
5- Inmediátamante debe aparecer valores tales como: "RA0 = 0511 - 049%" además al presionar cualquiera tecla, debe aparecer en el lcd ejemplo "USB = A
El ejemplo completo lo pueden obtener en esta dirección
http://rapidshare.com/files/318975801/Ejemplo_18F4550.rar.html
http://www.megaupload.com/?d=4IMYP4FH
Saludos.
-
hola amigo diego gracias por postear este proyecto que hiciste..me ha sido de utilidad...queria sber si me podrias ayudar con un problema fijate yo quiero realizar la transmision de varios valores adc desde un pic a otro por la comunicacion serial...ya lo he hecho entre 2 pic 16f877....pero cuando intente hacerlo entre un 16f877 este como transmisor y un 18f4550 y este como receptor no me funciona...y como vi que sabes mas o menos trabajar con este pic entonces imagine que me podrias ayudar.. aqui te dejo el programa del transmisor y el programa del receptor y adjunto la simulación de proteus en un win rar
programa del transmisor:
#include <16F877.h>
#fuses xt,nolvp,nowdt,noprotect
#use delay(clock=4000000)
#use rs232(baud=9600,bits=9,parity=N,xmit=PIN_C6,rcv=PIN_C7,long_data)
#include <LCD.C>
int valor,valor1,valor2,valor3;
float A0,A1,A2,A3;
void main()
{
setup_adc_ports(AN0_AN1_AN2_AN3_AN4_AN5);//que puertos se van a utilizar para la conversion, en esta caso el pin RA0,RA1,RA2,RA3
setup_adc(adc_clock_internal);//el tiempo de muestreo de la señal analogica, se coloco el clock internal
lcd_init();//inicializar la pantalla. esta instruccion es muy importante
while(1) //bucle: while significa mientras
{
set_adc_channel(0); //definir el canal de entrada 0
delay_us(20); //retardo de 20 microsegundo
valor=read_adc(); //el valor de la conversion se guarda en la constante valor
A0 = valor*((5.0)/255);
lcd_gotoxy(1,1); //esta instruccion es para colocar el cursor en la primera fila primera columna.
printf(lcd_putc,"A0:%1.2f ",A0); //imprimir el valor del adc en la pantalla lcd
putc(1);
putc(valor); //lo envio por la serial
delay_ms(10); //este tiempo es la clave jeje
//*******************************************************************************
set_adc_channel(1); //definir el canal de entrada 1
delay_us(20); //retardo de 20 microsegundo
valor1=read_adc(); //el valor de la conversion se guarda en la constante valor1
A1= valor1*((5.0)/255);
lcd_gotoxy(10,1);//esta instruccion es para colocar el cursor en la primera fila decima columna.
printf(lcd_putc,"A1:%1.2f",A1);//imprimir el valor del adc en la pantalla lcd
putc(2);
putc(valor1); //lo envio por la serial
delay_ms(10); //este tiempo es la clave jeje
//*******************************************************************************
set_adc_channel(2); //definir el canal de entrada 2
delay_us(20); //retardo de 20 microsegundo
valor2=read_adc(); //el valor de la conversion se guarda en la constante valor2
A2 = valor2*((5.0)/255);
lcd_gotoxy(1,2);//esta instruccion es para colocar el cursor en la segunda fila primera columna.
printf(lcd_putc,"A2:%1.2f",A2);//imprimir el valor del adc en la pantalla lcd
putc(3);
putc(valor2); //lo envio por la serial
delay_ms(10); //este tiempo es la clave jeje
//*******************************************************************************
set_adc_channel(3); //definir el canal de entrada 3
delay_us(20); //retardo de 20 microsegundo
valor3=read_adc(); //el valor de la conversion se guarda en la constante valor3
A3 = valor3*((5.0)/255);
lcd_gotoxy(10,2);//esta instruccion es para colocar el cursor en la segunda fila decima columna.
printf(lcd_putc,"A3:%1.2f",A3);//imprimir el valor del adc en la pantalla lcd
putc(4);
putc(valor3); //lo envio por la serial
delay_ms(10); //este tiempo es la clave jeje
}
}
programa del receptor:
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7)
#byte porta = 0xf80
#byte portb = 0xf81
#byte portc = 0xf82
#byte portd = 0xf83
#byte porte = 0xf84
#include <lcd.c>
int dato;
int dato1,dato2,dato3,dato4;
#int_rda
void interrupcion_rx()
{
if (kbhit(1))
{
dato = getc();
if (dato == 1)
{
dato1 = getc();
}
if (dato == 2)
{
dato2 =getc();
}
if (dato == 3)
{
dato3 =getc();
}
if (dato == 4)
{
dato4 =getc();
}
}
}
void main()
{
lcd_init();
enable_interrupts(global);
enable_interrupts(int_rda);
while(true)
{
while(!kbhit());
lcd_gotoxy(1,1);
printf(lcd_putc,"A0=%3u",dato1);
lcd_gotoxy(10,1);
printf(lcd_putc,"A1=%3u",dato2);
lcd_gotoxy(1,2);
printf(lcd_putc,"A2=%3u",dato3);
lcd_gotoxy(10,2);
printf(lcd_putc,"A3=%3u",dato4);
}
}
bueno amigo espero me puedas ayudar y de antemano gracias
-
Hola marturejulio, pues lo que veo a simple vista es un problema con la configuración del transmisor, veo que configuraste el buffer de salida a 9 bits y el receptor está a 8
Saludos
-
a ok si amigo ayer me di cuenta de eso también y se lo acomode pero aun sigue sin funcionar...pero fijate el mismo programa del receptor se lo coloco a un pic16f877 y funciona solo le cambie los fuses y la directiva del pic y la velocidad del pic y funciona a la perfeccion entre los dos 16f877 pero cuando meto el 18f4550 no me funciona no entiendo porque...y sabes otra cosa que me di cuenta y es que si mando a encender un led justo debajo de kbhit () se enciende osea que si recibe datos el buffer de la comunicacion serial pero es como si no los pudiera comparar vez no entiendo porque... gracias por responder amigo...eres muy amable
salu2
-
solo por probar, poné al 18f a correr a 4 o 20Mhz.
Saludos
-
NAGUARA AMIGO GRACIAS SI ERA ESO LE CAMBIE A 4MHZ Y FUNCIONO...NO SABES CUANTO TE AGRADEZCO..ERES MUY AMABLE EN RESPONDER....PERO PORQUE SERIA NO SABES...EL PROBLEMA ES QUE ESE PIC VA A TRABAJAR EN FRECUENCIAS DE 48MHZ PARA PODER CONECTARSE VIA USB
-
BUENO AMIGO YA RESOLVI LE COLOQUE AL 16F877 LA FRECUENCIA MAXIMA DE TRABAJO QUE ES 20MHZ Y AL 18F4550 LO COLOQUE A 48 MHZ Y FUNCIONO FINO PERO NO ME EXPLICO PORQUE...PERO DE NUEVO TE LO AGRADEZCO MUCHO...Y POR LA AMABILIDAD DE RESPONDER
-
si,pero tal parece q a esa frecuencia se tiene problemas con las recepcion serie, habria q probar si tambien con la transmision :?
Saludos
-
a ok pero que me aconsejas que baje la velocidad de la comunicacion serial o que la aumente
-
No pss eso ya es cuestion de tu diseño, si necesitas mas o menos ya es criterio propio pero si funciona asi, no hay q liarse. Si funciona no lo toques :mrgreen:
-
JEJE si tienes razon bueno ahora le cambie y le coloque 2 pics iguales 2 18f4550 y con uno transmito serialmente la informacion de adc...el otro la recibe y la envia por el puerto usb...gracias amigo me sacaste de un apuro
salu2
-
hola diego como estas, mira soy estudiante de ingenieria electronica mi nombre es luis. por lo que veo sabes manejar muy bien el pic 18f455o asi q quisiera hacerte una pregunta ya que soy nuevo en la programacion en c con los pic. estoy construyendo un simulador de señales de electrocardiagrafia con el pic 18f4550, y necesito generar diferentes señales mediante la programacion de este pic, quisiera q me dijeras como puedo generar estas señales, estas señales son 3: q son la señal de bradicardia, la señal de taquicardia y la señal normal del corazon. si buscas en google la forma de cada una de estas señales sabras lo que te estoy preguntando de verdad espero que me ayudes muchas gracias. cualquier cosa mi email es larp87@gmail.com
-
supongo que con el manejo de los Timer's del pic, puedes generar los pulsos con considerable exactitud, si buscas en el foro encontraras lo necesario.
saludos
-
Hola Luis, si lo que pretendes es simular las señales que recibe un electrocardiógrafo lo veo poco complejo dada la calidad dela señal análoga que el corazón entrega, se me ocurre algo así: capturar la señal análoga con un conversor ADC capturando los códigos recibidos durante un período de tiempo y almacenarlos en memoria, luego se lee la memoria y estos códigos son llevados a un puerto donde los recibe un conversor DAC.
Hablo sin conocer el tema, en el papel es muy fácil resolver una aplicación como esta!
saludos.
-
gracias, pues lo que pretendo es simular esas señales como si las estubiece emitiendo el corazon, osea estoy creando un simulador de señales ECG, y a la salida de este simulador deberia obtener las señales analogicas q te dije anteriormente taquicardia, bradicardia, normal depende de la q se selccione con un switch y esta señal analogica de salida se debe ver en el electrocardiagrafo cuando conecte la salida de mi dispositivo a la entrada del electrocardiagrafo, es decir es como si mi dispositivo fuera un corazon. y como capturo las señales? porque necesito es genrarlas para q se vean en el electrocardiagrafo. y pues estas señales no son senoidales puras, osea es una senoidal unida con una triangular, otra senoidal con menor amplitud etc. de verdad agradeceria q me ayudaran. muchisimas gracias
-
HOLA DIEGO PODRIAS ACTUALIZAR DE NUEVO ESTOS LINKS QUE YA NO FUNCIONAN
GRACIAS
El ejemplo completo lo pueden obtener en esta dirección
http://rapidshare.com/files/318975801/Ejemplo_18F4550.rar.html
http://www.megaupload.com/?d=4IMYP4FH
Saludos.
-
Hola Wilson, tienes razón el enlce de rapidshare ya está roto pero el de megaupload funciona correctamente, lo acabo de probar http://www.megaupload.com/?d=4IMYP4FH (http://www.megaupload.com/?d=4IMYP4FH)
si sigues con problemas me dices.
saludos.
-
que tal hombre es q estoy realizando un proyecto para la u y ps estamos utilizando pic c por primera vez y ps utilizando el 18f4550 y ps se nos lleno la memoria rom, y ps vi el programa q coloco y me parece muy interesante, y me comentaron de manejar el i2c y ps vi q en su programa la maneja y no alcance a entender su uso, para ver si me podria dar una explicacion rapida del funcionamiento y q referencia se puede usar o solo se pregunta asi y ya, y ps si se puede manejar por cualquier pin o exclusivamente por esos 2 del puerto b
espero me pueda colaborar. gracias
-
Para utilizar la comunicación i2C solo basta establecer el canal mediante la función #use i2c(....) donde como parámetros se define los pines a utilizar, Maestro o Esclavo, ect. En la ayuda de CCS pueden obtener mucho más detalles.
Con eso declarado, ya pueden utilizar las funciones i2c_start(), i2c_write(), i2c_read().... Si necesitan trabajar con una memoria el compilador tiene librerías como 2464.c, 24512.c ect donde pueden estudiar junto al datasheet de la memoria como trabaja.
Saludos!
PD: que es ps ? :mrgreen:
-
Hola peche, como dice el amigo suky, puedes configurar el bus i2c "#use i2c(master, sda=PIN_B0, scl=PIN_B1,force_hw)" con los pines que necesites, ahora, que dispositivos vas a conectar, son muchos los dispositivos que utilizan este protocolo.
saludos.
-
muchas gracias!!! es decir que es por el mismo lugar donde va conectado el ds1307??? siempre es indispensable manejar esos 2 pine o pueden ser otros?? xq es q la mayoria de programas que visto siempre utilizan nada mas esos 2 pines del 18f4550
-
Que pena con ustedes de nuevo, es x lo q estoy utilizando un teclado por el puerto b y ps segun veo en proteus define el b0 como sda y el b1 como scl. al yo declararlo en i2c como uds me habian dicho en cualquier puerto cambiaria para todo ese programa esas entradas??? o solo en el momento que yo las inicialice y las cierre??
gracias d nuevo.. por cierto... ps es pues q pena por si algo
-
ps puedes configurar para que la comunicación la haga por software seleccionando los pines que quieras colocando por ejemplo:
#use i2c(master, sda=PIN_C0, scl=PIN_C1,force_sw)
Si usas interrupciones lo mejor es des-habilitarlas cuando vas a trabajar con el i2c, ejemplo:
disable_interrupts(global);
i2c_start();
i2c_write(0xA0);
i2c_write(0x00);
i2c_start();
i2c_write(0xA1);
pepe = i2c_read(0);
i2c_stop();
enable_interrupts(global);
Saludos!
-
hola amigo sabes tengo una duda, para comunicacion serie RS232 se necesita un MAA232 para la comunicacion con el PIC y la PC, me podrias proporcionar un diagrama de como conectar el MAX232 con el puerto serial y el PIC porfavor???
-
Hola ROMEITO, utiliza el buscador o el san google, hay cientos de esquemas de conexión..
-
Hola Romeito, revisa este enlace, Max232 (http://www.google.com.co/imgres?imgurl=http://www.maicas.net/goofy/max232.gif&imgrefurl=http://www.maicas.net/goofy/capc.htm&h=309&w=579&sz=7&tbnid=2MK_fcLN5h5CbM:&tbnh=72&tbnw=134&prev=/images%3Fq%3Dmax232&usg=__ll_rTvNTOCxPVYE67NeXnCDWFho=&ei=Kcq_S5ntDoP_8AadwNiICQ&sa=X&oi=image_result&resnum=4&ct=image&ved=0CBIQ9QEwAw) el device puede ser un microcontrolador
saludos
-
Hola amigos, actualizo el link de descarga de este ejemplo.
Ejemplo 18F4550 (http://www.todopic.com.ar/utiles/Ejemplo 18F4550.rar)
Saludos.