Autor Tema: Microcursillo en C  (Leído 178986 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado gfp

  • PIC18
  • ****
  • Mensajes: 274
RE: Microcursillo en C
« Respuesta #165 en: 04 de Diciembre de 2004, 13:38:00 »
La verdad lo veo un poco complicado en C, aunque no es el mejor código pero se intentó. Cristal de 40 Mhz

#include <16f876.h>
#fuses XT, NOPROTECT, PUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay (clock=40000000)
#use fast_io(A)
#use fast_io(B)


#int_TIMER0
void TIMER0_isr()
{
      output_bit(pin_b2,1);
}
void main()
{
   set_tris_b(0x00);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_1 | RTCC_8_BIT);   


   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   set_timer0(212);
   for(;Giño {}   
}  

Intenté realizarlo en asm y los resultados sdon mejores. Al parecer para el control de tiempos específico es mejor utilizar asembler.

   LIST P=PIC16F876
#INCLUDE <P16F876.INC>
      ORG   00
      GOTO   INICIO
      ORG   04
      BTFSS INTCON, T0IF      ; Timer has overflowed
      RETFIE               ;NO
      NOP                  ;YES
      NOP
      RETFIE
INICIO   BCF   STATUS,RP1
      BSF   STATUS,RP0
      CLRF   TRISA
      CLRF   TRISB
      CLRF   TRISC
      MOVLW   0XC4
      MOVWF   OPTION_REG
      MOVLW   0X07
      MOVWF   ADCON1      ;RA, PINES DIGITALES
      BCF   STATUS,6
      BCF   STATUS,5
      CLRF   PORTA
      CLRF   PORTB
      CLRF   TMR0
      CLRF   INTCON
      BSF      STATUS,RP0   ; Bank1
      MOVLW 0xC0
      MOVWF OPTION_REG      ; Timer0 increment from internal clock with a prescaler of 1:16.
      BCF STATUS, RP0 ; Bank0
      BSF INTCON, T0IE ; Enable TMR0 interrupt
      BSF INTCON, GIE ; Enable all interrupts
      MOVLW   .233
      MOVWF   TMR0
      GOTO   $
      END



gfp Sonrisa

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Microcursillo en C
« Respuesta #166 en: 07 de Diciembre de 2004, 09:48:00 »
Hola a todos

Pues ya le di uso a la función rand() que me recomendó Pocher.

Hice el programa del dado electrónico que está en el foro de AVRs pero ahora con PIC y en C. :]

Hay que hacer un cambio a la librería stdlib.h. Al valor RANDOM_MAX hay que ponerle el número máximo (más uno) que uno espera entregue la función rand();.

Les agrego el programa. Luego le mando el DSN de proteus a Modulay. Ah y en el programa pueden ahorrarse líneas de programación.

Ah y la idea de hacer un dado electrónico se la copié a Carlete. :c)




//Programa que genera la salida de un dado electrónico con PIC
//migsantiago@tutopia.com
//dado electrónico
//B0   B1   B2   B3   B4   B5   B6   B7
//1   2   3   4   5   6   7   NC

//  _______
//   1|O 4 O|5
//   2|O O O|6
//   3|O   O|7
//    -------

#include <16F84.h>

/*Para random de 6 modifique stdlib.h*/
//RANDOM_MAX=6
#include <D:santiagoPICsprogramasc_dadoSTDLIB-dado.H>

#use delay(clock=4000000)
#fuses XT,NOWDT,NOPROTECT

#use fast_io(B)
#byte portb = 0x06
#byte porta =0x05


void main()
{
int x_numero;
set_tris_b(0b00000000); /*PtoB salida*/
set_tris_a(0xff); /*PtoA entrada*/

output_b(0x00); /*Limpio puerto*/

while(1){
   if (input(PIN_A0)==1)
   {
   x_numero=rand(); /*Saca un random 0 a 5 en x*/
   if(x_numero==0) /*Cayó 1*/
      {
      portb=0x08; /*Prende 4*/
      delay_ms(1000);
      }
   if(x_numero==1) /*Cayó 2*/
      {
      portb=0x41; /*Prende 1 7*/
      delay_ms(1000);
      }
   if(x_numero==2) /*Cayó 3*/
      {
      portb=0x49; /*Prende 1 4 7*/
      delay_ms(1000);
      }
   if(x_numero==3) /*Cayó 4*/
      {
      portb=0x55; /*Prende 1 3 5 7*/
      delay_ms(1000);
      }
   if(x_numero==4) /*Cayó 5*/
      {
      portb=0x5d; /*Prende 1 3 4 5 7*/
      delay_ms(1000);
      }
   if(x_numero==5) /*Cayó 6*/
      {
      portb=0x77; /*Prenden todos menos el 4*/
      delay_ms(1000);
      }
   }
}
}



Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #167 en: 07 de Diciembre de 2004, 10:39:00 »
migsantiago,no es necesario modificar el fichero stdlib.h.
Basta con definir el valor de RAND_MAX antes del include correspondiente:

#define RAND_MAX 6
#include "stdlib.h"

Pos eso,un curioso ejemplo de generación de números completamente aleatorios.
Gracias migsantiago Sonrisa

http://personal.auna.com/asencio5/Ejemplos%20C/RUTINAS/

SALUDOS

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Microcursillo en C
« Respuesta #168 en: 07 de Diciembre de 2004, 11:30:00 »
Ohhhh, ahora entiendo. Lo que hice fue definirlo después del include, me regañaba que porque ya lo había declarado dos veces.

Gracias Muchas risas

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Microcursillo en C
« Respuesta #169 en: 08 de Diciembre de 2004, 08:29:00 »
Estoy con un problemita... no logro echar a andar este programa:



#include "16f877.h"
#use delay(clock=4000000)
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect

#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)

#byte porta = 0x05
#byte portb = 0x06
#byte portc = 0x07
#byte portd = 0x08
#byte porte = 0x09

//Este programa sólo checa si las terminales del
//PIC16F877A están funcionando correctamente

void main(void)
{
int unos,ceros;
unos=0xff;
ceros=0x00;

while(true){
output_a(unos);
output_b(unos);
output_c(unos);
output_d(unos);
output_e(unos);
delay_ms(1000);

output_a(ceros);
output_b(ceros);
output_c(ceros);
output_d(ceros);
output_e(ceros);
delay_ms(1000);
}
}




Se supone que enciende y apaga todos los puertos del 877a, pero ya que lo conecto, no prende ninguno. No tiene ningún fusible activado (WDT, LVP no se qué... etc.)

Sé que hay que ponerle unas instrucciones que indiquen que los puertos son digitales, por ejemplo el A, que no sea análogo... pero no me las sé... Sonrisa Gigante

Podría alguien explicarme que le falta a mi programa... tal vez sólo sea un error mínimo. Vacilando

Bueno, y hablando de otra cosa, hace tiempo programé mi 877a con un programa en ensamblador que prendía y apagaba el puertoB, pero extrañamente el Puerto B PB3 no hacía nada. Yo pensaba que estaba quemado, pero ya que lo programé ayer, ya funcionó... ¿a qué se debe? Recuerdo que activaba el fusible LVP y ayer no lo activé.

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Microcursillo en C
« Respuesta #170 en: 08 de Diciembre de 2004, 11:49:00 »
Si usas las directivas fast_io(), tienes que definir como quieres que sean los puertos (con la sentencia set_tris_X), si de entrada o salida, si no usas las directivas, el compilador realiza esta operacion automaticamente (con lo cual el programa también funcionará).

Prueba a realizarlo de ambas formas ya  verás como va.

En cuanto a la pregunta sobre lo del LVP, no sabria responderte, ese fuse se activa para la programacion en bajo voltaje, ahora bien no se en que puede haber influido ese fuse para el funcionamiento de ese pin.


Un saludo.

Desconectado CharlyM

  • PIC10
  • *
  • Mensajes: 2
RE: Microcursillo en C
« Respuesta #171 en: 08 de Diciembre de 2004, 22:13:00 »
Hola, mi problema es q nesecito conectar 2 pics 16f84, y hacer una especia de chat conectandoles tambien un teclado y un lcd, pero no se ni configurar y sacar los datos por el lcd, ademas todo es simulado en el proteus y uso un lcd de 16x2, si alguien puede ayudarme

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Microcursillo en C
« Respuesta #172 en: 09 de Diciembre de 2004, 13:27:00 »
Gracias por la respuesta. Checaré sus sugerencias. Luego subo el programa funcionando.


Por otro lado, CharlyM, te dejo este programa en C para el control de la LCD. Sólo define como el puerto de salida de la LCD el puerto B del 16f84a:

#define use_portb_lcd TRUE

En el que yo escribí está el puerto D como salida predeterminada.

Al escribir tu programa checa el archivo lcd.c que trae tu compilador para que hagas los cambios necesarios.




#include "16f877.h"
#use delay(clock=4000000)
#fuses nowdt,noput,nobrownout,nolvp,noprotect
#include "lcd.c"

#use standard_io (D)

//migsantiago
// As defined in the following structure the pin connection is as follows:
//     D0  enable
//     D1  rs
//     D2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.
void main(void)
{
lcd_init(); //Inicia LCD
while(1){

lcd_putc("    Santiago
"); //Saca texto
delay_ms(1000);

lcd_putc("   PIC16F877A");
delay_ms(1000);

lcd_putc("f"); //Limpia pantalla
delay_ms(1000);

lcd_putc("     :) :(
");
delay_ms(1000);

lcd_putc("     XD :-P");
delay_ms(1000);

lcd_putc("f");
delay_ms(1000);

}
}



Desconectado CharlyM

  • PIC10
  • *
  • Mensajes: 2
RE: Microcursillo en C
« Respuesta #173 en: 10 de Diciembre de 2004, 00:07:00 »
Hola, de nuevo
Gracias por la repuesta pero ya intente implementarlo y me salen los siguientes errores

Error[000] C:Documents and SettingsCarlosEscritorioPICS2.c 2 : Illegal # command "use"
Error[000] C:Documents and SettingsCarlosEscritorioPICS2.c 3 : Illegal # command "fuses"
Error[000] C:HT-PICINCLUDElcd.c 17 : Cannot open include file "ztimer/include/debug.h"

estoy usando el picc de Ht con mplab, ademas de q no tenia el lcd.c aun q bueno ya lo baje pero no se si sea una buena version, bueno por fa si me pueden volver a ayudar, la verdad es q estoy verde en esto de pics y lcds loco

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: Microcursillo en C
« Respuesta #174 en: 10 de Diciembre de 2004, 03:02:00 »
Eso es porque el programa de migsantiago está hecho para el compilador de CCS no para el de Ht (que dicho sea de paso desconozco).

Un saludo

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Microcursillo en C
« Respuesta #175 en: 10 de Diciembre de 2004, 08:30:00 »
Pues sólo te puedo recomendar que leas el manual de usuario que tu compilador trae incluido, es decir, la ayuda. Checa los comandos que puedes usar.

También puedes checar el archivo lcd.c que usaste y modificarlo para que corra tu programa.

Por ahora subo el programa del dado, pero ahora sale en la LCD el número que cae.



#include "16f877.h"
#use delay(clock=4000000)
#fuses nowdt,noput,nobrownout,nolvp,noprotect
#include "lcd.c"

#define RAND_MAX 6 //Número aleatorio máximo
#include "stdlib.h" //rand();

#use standard_io (D)

#use fast_io(B)
#byte portb = 0x06

//migsantiago
// As defined in the following structure the pin connection is as follows:
//     D0  enable
//     D1  rs
//     D2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.

void main(void)
{
int x_numero; //random

lcd_init(); //Inicia LCD

set_tris_b(0xff); /*PtoB entrada*/

lcd_putc("   Bienvenido
"); //Saca texto
lcd_putc("  Dado Virtual"); //Saca texto
delay_ms(3000);

lcd_putc("f"); //Limpia pantalla
lcd_putc("Aprieta Switch
"); //Saca texto
delay_ms(1000);

while(1){

if(input(PIN_B0)==1)
   {
   delay_ms(500);
   x_numero=rand(); /*Saca un random 0 a 5 en x*/
   x_numero++; /*anula cero*/
   printf(lcd_putc,"El dado cae en %u",x_numero);
   lcd_gotoxy(1,2); /*Regresa a segunda línea*/
   }
}
}



Ya me di cuenta que no conviene usar el rand(), porque genera números random, pero en la misma secuencia... siempre prende en 3 la primera caída del dado, luego 1, luego 4, etc. Lo mejor será usar el contador timer para generar los randoms.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #176 en: 10 de Diciembre de 2004, 13:36:00 »
Tienes razón,migsantiago.La forma de solucionarlo es tener al timer siempre corriendo y capturar su valor en el momento de la pulsación,para coger ese valor y mandárselo a la rutina srand(unsigned int32 seed) como parámetro.De esta forma se consigue cambiar el valor de la semilla de la que la función rand() parte para generar el número aleatorio.He puesto el nuevo ejemplo del dado en la carpeta de ejemplos LCD:

http://personal.auna.com/asencio5/Ejemplos%20C/LCD/

Saludos

Desconectado migsantiago

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8257
    • Sitio de MigSantiago
RE: Microcursillo en C
« Respuesta #177 en: 11 de Diciembre de 2004, 09:57:00 »
Gracias Modulay

Pues como veo tu servidor muy vacío todavía, te mando en un ratito un convertidor AD de temperatura con el LM35 y saca el dato al LCD.

En Proteus simulé el LM35 con un potenciómetro lineal, porque cuando conectaba el LM35 me regañaba y decía que algo estaba mal declarado o algo así. En la vida real el circuito sí funciona.



//Convierte señal analógica en RA0
//Usa LM35 para medir temperatura en °C
//La saca por un LCD

//LM35
//Vout=(°C)/100

//Vref=+2.5V en 16f877a (RA3)

// migsantiago
// Conexiones de la LCD:
//     D0  enable
//     D1  rs
//     D2  rw
//     D4  D4
//     D5  D5
//     D6  D6
//     D7  D7
//
//   LCD pins D0-D3 are not used and PIC D3 is not used.


#include "16f877.h"

#device adc=8 //Usa resolución de 8 bits
#use delay(clock=4000000)
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect

#include "lcd.c"
#use standard_io (D)
//#use fast_io (B)

//Puerto B sólo indica lectura digital

void main (void)
{
   int medicion;
   float temper;
//   set_tris_b (0x00);

   lcd_init(); //Inicia LCD
   lcd_putc("    Digital
"); //Saca texto
   lcd_putc("   Termometer"); //Saca texto
   delay_ms(3000);
   lcd_putc("f"); //Limpia pantalla
   lcd_putc("Temperatura
"); //Saca texto
   lcd_putc("actual"); //Saca texto
   delay_ms(1000);
   lcd_gotoxy(14,2); //Acomoda cursor LCD
   lcd_putc("oC");

   while (1)
      {

      lcd_gotoxy(8,2); //Acomoda cursor LCD
      lcd_putc("      "); //Limpia ese sector de pantalla
      lcd_gotoxy(8,2); //Acomoda cursor LCD
     
     
      setup_adc (adc_clock_div_32); //Enciende ADC

      //Elige terminales análogicas
      //RA0 y RA1 miden, RA3 es Vref (2.5V)
      setup_adc_ports (RA0_RA1_ANALOG_RA3_REF);

      set_adc_channel (0); //Elige canal a medir RA0
      delay_us (20);
      medicion=read_adc (); //Hace conversión AD
      setup_adc (adc_off); //Apaga ADC
     
//      output_b(medicion); //Saca valor a portB
//      delay_ms(1000);

      temper=medicion*(0.9803); //Pasa binario a °C

      printf(lcd_putc,"%03.1f",temper); //xxx.x °C
      delay_ms (1000);
   }
}



Hay que mejorar la resolución de este programa, ya que sólo usa un quinto de los 8bits en total.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #178 en: 11 de Diciembre de 2004, 11:07:00 »
Gracias migsantiago por tu dedicación.A ver si se anima más gente.
Ya tenemos un ejemplo de uso del conversor AD:

http://personal.auna.com/asencio5/Ejemplos%20C/ADC/

Saludos desde Málaga,España

Desconectado YF-21

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 185
RE: Microcursillo en C
« Respuesta #179 en: 14 de Diciembre de 2004, 20:50:00 »
Me uno a la coperacha

Pues asi es ... este es el codigo que usé es para presionar una tecla de un teclado 4x4 en el micro master y esta aparece en el esclavo en un lcd...

Para el master ...

#include "16f877.h"
#fuses noprotect,nobrownout,noput,nowdt,nolvp
#use delay(clock=4000000)
#use standard_io(A)
#use standard_io(b)
#use standard_io(d)

#use i2c(MASTER, SDA=PIN_C4, SCL=PIN_C3,FAST,FORCE_HW)

int tecla=0,conta=0,x,corrim=8;

int getkey (conta)
{
   i2c_start ();

   i2c_write (254);

   i2c_write (conta);

   i2c_stop ();

   output_a (conta);
   delay_ms (1000);
}


void main ()
{
conta=0;
while (1){
for (x=0;x<=3;x++)
{
   output_b(corrim);
   output_d (conta);

   if (input(PIN_B4))
      {
         getkey(conta);
      }
      conta++;
      output_d(conta);

      if (input(PIN_B5))
      {
         getkey(conta);
      }

      conta++;
      output_d(conta);

         if (input(PIN_B6))
      {
         getkey(conta);
      }

      conta++;
      output_d(conta);

         if (input(PIN_B7))
      {
         getkey(conta);
      }
      conta++;
      rotate_right(&corrim,1);
      output_d(conta);

}
conta=0;
corrim=8;
}
}--------------------------------------------------------------------------------



y slave ...


Codigo:--------------------------------------------------------------------------------#include "16f877.h"
#use     i2c (slave, ADDRESS=254, scl=pin_c3, sda=pin_c4, fast, force_hw)
#use delay(clock=4000000)
#fuses noprotect,nobrownout,noput,nowdt,nolvp
#include "lcd.c"
#use fast_io (C)
#use standard_io (A)


int data;

void main ()
{
   set_tris_c (0xff);
   lcd_init ();
   lcd_putc ("Esperando"Giño;

   while (1)
   {
   if(~input(PIN_c4))
    {
      data=i2c_read ();
      if (data==254)
      {
            data=i2c_read ();
            lcd_putc ("f"Giño;
            printf (lcd_putc, "El dato es el %i", data);
      }
    }
   }
}

Si funciona pero no uso el i2c_poll, te envio por privado los archivos compilados y en proteus, OK Modulay ??