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

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

Desconectado nordestenica

  • PIC16
  • ***
  • Mensajes: 215
RE: Microcursillo en C
« Respuesta #30 en: 10 de Agosto de 2004, 03:23:00 »
me estoy volviendo loco con el c e intentado acer varias experiencias cojiendo trocos de codigo de otras personas e juntando algo de mi cabeca ay vezes que consigo acer algo que funcione pero la verdade es que nunca e conseguido entender lo que significan muchos comandos

les pondre un exenplo esto lo e cojido por ay

#include <lcd.c> // con esto incluimos en nuestro codigo una driver para controlar una lcd


set_adc_channel( 0 );// aqui le decimos al micro que usaremos como entrada adc el pin A0 del micro (si fura el pin A1 pondriamos set_adc_channel( 1 );


lcd_init();// esto lo usamos para iniciar el driver lcd e se coloca despues del inicio del programa por exemplo

void main()
{
   int16 i;

   //float const resoluc=5.0/256.0;
   float const resoluc=5.0/1024.0;
   float valor;

   // Inicializacion del micro
   setup_port_a( ALL_ANALOG );
   setup_adc( ADC_CLOCK_INTERNAL );
   set_adc_channel( 0 );
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);

   lcd_init();       //Inicializacion del display LCD

aver esto creo que es correcto no

bueno e yo creo que antes de enpecar a programar micros devemos aprender lo que significan todas estas cosas porque sino me passa como a mi que escrivo un pequenho codigo e no se lo que significan todos estes comandos

aver qual va a ser el prof que nos ensenhe que significan todas estas cosas




Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #31 en: 10 de Agosto de 2004, 10:27:00 »
Hombre,es que te estás lanzando ya a por el manejo de periféricos y cuestiones más avanzadas.Para entender la misión de cada función lo mejor es echarle un ojo al manual de CCS,que está en castellano y es magnífico.
Para ayudarte un poco con tu duda,voy a poner un programa completo e iré explicando un poco la estructura y lo que y para qué es cada cosa:
Codigo:

///////////////////////////// DIRECTIVAS DE PREPROCESADO /////////////////////////////

#include <16F876.h>   // Dispositivo a utilizar
#device adc=8         // Resolución de 8 bits para el conversor ADC
#fuses HS,NOWDT,NOPROTECT,NOLVP,NOBROWNOUT  // Fusibles
#use delay(clock=10000000)  // Velocidad del cristal
#include "lcd.c"  // Librería para el manejo del lcd.En mi caso está configurada para
                  // manejar el lcd desde el puerto B
// Con la siguiente directiva,se optimiza código,ya que el compilador asume que en cada momento que accedemos al puerto B,
// este está configurado adecuadamente(como entrada ó como salida) para la acción que vamos a ejercer sobre él
// Si no añadimos esta directiva,cada vez que accedamos al puerto,el compilador generará código para
// asegurar que el puerto esté configurado como salida si lo que vamos a hacer es escribir en él y viceversa
#use fast_io(B)

////////////////////////////////////// GLOBALES //////////////////////////////////////

// Estos parámetros son visibles desde todo el código,por eso se les llama globales.
// Al ser constantes,lo más práctico es declararlas aquí.
const int escala = 255;       // Escala del conversor ADC (8 bits)
const float v_max = 25.2;     // Voltaje máximo que entrega mi fuente

////////////////////////////////////// RUTINAS ////////////////////////////////////////

void borra_lcd()
   {
   lcd_putc("f");  // Con esta instrucción borramos el lcd
   }

// Como se observa en la cabecera,los nombres de los parámetros no tienen por qué ser iguales
// que los de la llamada ( calcula_voltaje(valor,voltaje) ),pero sí deben estar en el mismo
// orden.
// "voltaje",al ser de entrada-salida,debe llevar el símbolo "&" delante
void calcula_voltaje(int val,float &voltaje)
   {
   // "escala" y "v_max" son parámetros globales,por eso son visibles dentro
   // de esta rutina(y en todo el código).Si no lo fueran,al no estar declarados dentro de ella ni
   // ser parámetros de entrada ó entrada-salida como los de la cabecera,se produciría
   // error al compilar
   voltaje = (val*v_max)/escala;
   }

/////////////////////////////////////// PRINCIPAL //////////////////////////////////////

void main()
   {
   int valor,;    // La declaración de variables SIEMPRE debe ir lo primero
   float voltaje; //
   set_tris_B(0b00000000); // Puerto B configurado como salida
   port_b_pullups(FALSE);  // Desactivamos pull-ups del puerto B
   setup_adc_ports(RA0_RA1_RA3_ANALOG); //Configura A0,A1 y A3 como entradas analógicas y Vdd como voltaje de referencia
   setup_adc(ADC_CLOCK_INTERNAL); // Reloj para el conversor
   set_adc_channel(0); // Seleccionamos el canal 0 (RA0)
   lcd_init();  // Antes de usar el lcd,hay que inicializarlo
   for(;;)  // Bucle infinito,que se ejecuta de forma indefinida
     {
     valor = read_adc(); // Capturamos señal analógica que entra por el canal previamente seleccionado (RA0)
     // Esta rutina tiene a "valor" como parámetro de entrada y a "voltaje" como parámetro de entrada-salida.
     // "valor",al ser de entrada,podrá ser utilizado por la rutina pero NO podrá ser modificado.
     // "voltaje",al ser de entrada-salida,si puede ser modificado dentro de la rutina
     calcula_voltaje(valor,voltaje); // Le mandamos el parámetro "valor" y nos devuelve "voltaje"
     borra_lcd();  // Llamada a rutina que borra el lcd
     printf(lcd_putc,"%f",voltaje)   // Mostramos en el lcd el contenido de la variable "voltaje"
     delay_ms(10);  // Retardo de un 10 ms
     }
   }



Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Microcursillo en C
« Respuesta #32 en: 10 de Agosto de 2004, 11:06:00 »
Ha quedado muy ilustrativo, Modulay.

¿Lo has escrito tú o lo has sacado de algún sitio donde haya más ejemplos como este?. Si la respuesta correcta es la segunda, dinos dónde está por favor. He aprendido muchísimo con este ejemplo.

Gracias

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #33 en: 10 de Agosto de 2004, 11:38:00 »
Es de cosecha propia,Nocturno.
He adaptado un poco el código del voltímetro de mi fuente de alimentación destacando las cosillas que me parecían interesantes.
Un saludo

Desconectado Duende_Azul

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 902
RE: Microcursillo en C
« Respuesta #34 en: 10 de Agosto de 2004, 13:40:00 »
Que diferencia hay entre:

valor==(valor && 0x80)     y
valor &= 0x80

la primera no me funciona, la segunda si.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #35 en: 10 de Agosto de 2004, 14:47:00 »
La segunda lo que hace es asignar a valor la operación AND,a nivel de bits,de su contenido con el literal 0x80.
La primera no vale para asignar al ser un doble igual (==).
Al ser una comparación,supongo que lo tendrás como condición de control en una estructura de control (while,for,if...).Tal y como está escrita,no puede desempeñar ninguna otra función.
Saludos

Desconectado Duende_Azul

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 902
RE: Microcursillo en C
« Respuesta #36 en: 10 de Agosto de 2004, 14:53:00 »
Gracias Modulay por responder, lo que quiero hacer es una mascara para saber el estado del bit mas significativo de un puerto...  leo el puerto y lo guardo en valor, luego con un "and logico" pongo todo a cero menos el ultimo bit para saber si esta a 1 o a cero.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #37 en: 10 de Agosto de 2004, 15:00:00 »
Pues el segundo método es el que te va al pelo.
El operador && trabaja a nivel lógico,pero no a nivel de bits.Un uso correcto seria...
BOOLEAN condicion;
int numero;
if (condicion1 && numero == 15)
  {
   bla bla bla...
  }

Aunque si quieres saber el estado de un bit de cualquiera de los puertos basta con hacer :
if ( input(PIN_B7) )
  {
  // Esto se ejecuta si RB7 está a 1
  }

Espero que te ayude
Saludos

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #38 en: 10 de Agosto de 2004, 15:17:00 »
Bueno,lo importante es dar ideas y que cada uno aporte dentro de sus posibilidades.Qué mas da quien esté al frente mientras sigamos aprendiendo unos de otros.
Aún así...gracias!!!!
Un saludote

Desconectado YF-21

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 185
RE: Microcursillo en C
« Respuesta #39 en: 10 de Agosto de 2004, 18:11:00 »
Compañeros muchas gracias por abrir el cursillo de "C", ya que es mas sencillo ke el asm ... No cabe duda que se van a ir al cielo

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Microcursillo en C
« Respuesta #40 en: 12 de Agosto de 2004, 00:58:00 »
Estoy probando las comunicaciones serie en C y hay algo que me tiene comido el coco pero no consigo.

Se trata de que cuando ejecuto el programa que aparece a continuación no me aparece nada en Hyperterminal, a veces me aparece un carácter extraño si reseteo el PIC y otras veces nada, pero ni mucho menos lo que tendría que salir.

La conexión es correcta porque, de hecho, grabo el PIC con el PICDownloader a través del COM1 a 19200.

He revisado la configuración de Hyperterminal y parece que está bien, puesto que también está seleccionado Com1 y 19200.

No entiendo lo que pasa.

Codigo:
#include <16F877A.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 1

void main() {

   printf("Press any key to begin
";
   getc();
   printf("1 khz signal activated
";

   while (TRUE) {
     output_high(PIN_B0);
     delay_us(500);
     output_low(PIN_B0);
     delay_us(500);
   }
}

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #41 en: 12 de Agosto de 2004, 04:46:00 »
Lo he probado,pero con un cristal de 20 MHz y me va perfectamente.
Aunque a mí me funciona bien tu programa,en la directiva #use rs232 vendría bien que especificaras si la comunicación es a 8 bits o no,más que nada,para ahorrarte posibles complicaciones o despistes:

// 19200 baudios,8 bits sin paridad
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7,bits=8)

A lo mejor es por la velocidad del cristal,ponle otro mas potente

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
RE: Microcursillo en C
« Respuesta #42 en: 12 de Agosto de 2004, 04:50:00 »
Probaré con el cristal de 20MHz, y añadiendo lo de los 8 bits.
Es extraño, porque la comunicación aguanta perfectamente a 19200 bps cuando grabo el PIC desde el PicDownloader.

Desconectado T0ni0

  • PIC16
  • ***
  • Mensajes: 196
RE: Microcursillo en C
« Respuesta #43 en: 12 de Agosto de 2004, 09:26:00 »
Yo toy empezando con el C PIC, pero creo que se tendría que parar cuenta con poner XT si se utiliza un cristal de 20MHz

Voy a probar cosillas, que tal el CCS para empezar?

De momento no lo he podido provar bien, me pide un registro y luego me me da un error al compilar, supongo que no funciona si no estas registrado, seguiré buscando para hacerme con el
- T0ni0 -
30RCF112

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Microcursillo en C
« Respuesta #44 en: 12 de Agosto de 2004, 15:50:00 »
Un pequeño inciso para comentar una serie de cosas que pueden resultar útiles para familiarizarnos un poco más con el uso de variables y procedimientos(rutinas).
AMBITO DE LAS VARIABLES:
Dependiendo del lugar donde sea declarada,una variable podrá ser visible o no desde una parte concreta de nuestro código.
Si la declaramos como variable global,su ámbito(alcance) será todo el programa,por lo que podremos consultar o modificar su valor desde el main o desde cualquiera de los procedimientos de nuestro código.La pega es que hacer uso de variables globales no es lo más recomendado,no por una cuestión formal,sino porque estarán ocupando memoria durante toda la ejecución aunque no las usemos,y eso no interesa.
Así,si lo que queremos es optimizar los recursos del micro,lo bueno es reducir al máximo el ámbito de las variables y que éstas estén localizadas en segmentos concretos del código.
Un ejemplo:
Codigo:

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include "lcd.c"

int numero1;  // Esta variable es global,por lo que ocupará 1 byte durante
              // toda la ejecución

void suma()
   {
   // numero2 está localizada en este procedimiento,por lo que su ámbito es
   // exclusivamente este procedimiento y no será visible desde ningún otro sitio.
   // ¿Qué ganamos con ello? Pues es sencillo,cuando suma() es llamado desde el main,
   // lo primero que ocurre es que se crea la variable numero2,que ocupará 1 byte
   // en algún lugar de la memoria.Cuando suma() termina de ejecutarse,ese byte
   // quedará liberado para que otro dato pueda usarlo si fuera necesario.
   // Conclusión: se optimiza memoria
   int numero2;
   numero2 = 15;
   numero1 = numero1 + numero2;  // Modificamos el valor de nuestra variable global
   }

void main()
   {
   lcd_init();
   numero1 = 10;  // La vemos porque es global
   suma();       // Llamada al procedimiento suma()
   printf(lcd_putc,"%u",numero1); // La mostramos en el lcd
   for(;;) {}
   }




Ya no es sólo cuestión de optimizar memoria,así se consigue también un código más estructurado y modularizado.
A otra cosa,mariposa.
PARAMETROS POR VALOR O POR REFERENCIA:
Como se ve en un ejemplo que hay un poco más arriba,también se puede conseguir que una variable sea visible,para que podamos usarla,dentro de una rutina en la que no está declarada.La forma de hacerlo es enviar dicha variable como parámetro cuando se efectúa la llamada al procedimiento...¡¡Ponme un ejemplo!!:-/
Codigo:

#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#include "lcd.c"


void suma(int num1,int num2,long int &res)
   {
   // "num1" y "num2" son parámetros de entrada.
   // "res" es de entrada-salida.
   // "num1" es un parámetro de entrada por valor.Al ser un parámetro de entrada,cuando se produce
   // la llamada al procedimiento,se crea una copia de dicho valor y el procedimiento
   // trabaja con dicha copia,y no con el original como cabe pensar.
   // "num2" es otro parámetro pasado por valor.Al ser sólo de entrada,también se crea una copia en
   // memoria con la que trabajaremos y que será destruída,al igual que "num1",cuando
   // acabe la ejecución de la rutina.
   // Por último nuestro parámetro de entrada-salida.Ni que decir tiene que un parámetro
   // de entrada-salida JAMAS DE LOS JAMASES es pasado por valor,siempre lo es por referencia y
   // deberá tener SIEMPRE como origen una variable.
   // Esta vez,al ser un parámetro de entrada-salida,susceptible de ser modificado,el
   // el procedimiento no hace copia ninguna y trabaja con el original de forma dinámica
   // ¿qué quiere decir eso? Pues que se crea un puntero que apuntará al dato de origen y la
   // rutina trabajará con ese puntero en vez de hacerlo directamente con el dato.
   res = num1 + num2;  // Asiganmos a "res" la suma de los otros 2 parámetros
   }


void main()
   {
   // Declarar variables en el programa principal es casi como declararlas globales,
   // por lo que tampoco es lo más óptimo.
   int numero;
   long int resultado;
   lcd_init();
   resultado = 0;  // Esta acción es superflua ya que vamos a modificar su valor en breve.
   // suma() lleva 3 parámetros: uno por valor y dos por referencia.
   suma(numero,23,resultado);    // Llamada al procedimiento suma()
   // "resultado" ha sido modificado y devuelto por el procedimiento suma()
   printf(lcd_putc,"%lu",resultado);   // La mostramos en el lcd
   for(;;) {}
   }




Para ver más claro esto de las copias de los parámetros y tal,una vez compilado el programa,se puede ver la distribución de los datos en la memoria del pic en el menú de CCS:
View -> Symbol map

Saludos


 

anything