Autor Tema: Ejemplo con PIC18F4550  (Leído 42924 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Ejemplo con PIC18F4550
« 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.
Código: [Seleccionar]
#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
}


Desconectado darck_khronos

  • PIC18
  • ****
  • Mensajes: 493
Re: Ejemplo con PIC18F4550
« Respuesta #1 en: 26 de Octubre de 2009, 22:39:28 »
Porias Fasilitar un diagrama??

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: Ejemplo con PIC18F4550
« Respuesta #2 en: 27 de Octubre de 2009, 09:28:52 »
Hola arck_khronos, acá te pongo una imagen.

Saludos

Desconectado darck_khronos

  • PIC18
  • ****
  • Mensajes: 493
Re: Ejemplo con PIC18F4550
« Respuesta #3 en: 28 de Octubre de 2009, 00:05:25 »
gracias por la info

Desconectado Arttak

  • PIC10
  • *
  • Mensajes: 4
Re: Ejemplo con PIC18F4550
« Respuesta #4 en: 03 de Noviembre de 2009, 00:06:56 »
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

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: Ejemplo con PIC18F4550
« Respuesta #5 en: 03 de Noviembre de 2009, 09:17:09 »
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é.

Desconectado jt_decepticon

  • PIC10
  • *
  • Mensajes: 5
Re: Ejemplo con PIC18F4550
« Respuesta #6 en: 06 de Noviembre de 2009, 09:40:57 »
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

Desconectado eleazar83

  • PIC10
  • *
  • Mensajes: 3
Re: Ejemplo con PIC18F4550
« Respuesta #7 en: 10 de Diciembre de 2009, 00:51:33 »
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.

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: Ejemplo con PIC18F4550
« Respuesta #8 en: 10 de Diciembre de 2009, 12:48:35 »
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.


Desconectado marturetjulio

  • PIC10
  • *
  • Mensajes: 44
Re: Ejemplo con PIC18F4550
« Respuesta #9 en: 30 de Diciembre de 2009, 22:01:45 »
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
Expeciencia es simplemente el nombre que le damos a nuestros errores!!!

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: Ejemplo con PIC18F4550
« Respuesta #10 en: 31 de Diciembre de 2009, 20:14:19 »
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

Desconectado marturetjulio

  • PIC10
  • *
  • Mensajes: 44
Re: Ejemplo con PIC18F4550
« Respuesta #11 en: 01 de Enero de 2010, 15:05:13 »
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
Expeciencia es simplemente el nombre que le damos a nuestros errores!!!

Desconectado jhozate

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1698
Re: Ejemplo con PIC18F4550
« Respuesta #12 en: 01 de Enero de 2010, 17:10:01 »
solo por probar, poné al 18f a correr a 4 o 20Mhz.
Saludos
Ser Colombiano es un Premio, Saludos desde CALI-COLOMBIA

Desconectado marturetjulio

  • PIC10
  • *
  • Mensajes: 44
Re: Ejemplo con PIC18F4550
« Respuesta #13 en: 01 de Enero de 2010, 17:18:16 »
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
Expeciencia es simplemente el nombre que le damos a nuestros errores!!!

Desconectado marturetjulio

  • PIC10
  • *
  • Mensajes: 44
Re: Ejemplo con PIC18F4550
« Respuesta #14 en: 01 de Enero de 2010, 17:23:30 »
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
Expeciencia es simplemente el nombre que le damos a nuestros errores!!!