Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

25/06/2015 #1

Avatar de KuroNek0

Duda pricipiante con el uso de puertos de pics
Mucho gusto. Esta es mi primera pregunta, espero no hacer nada mal.

Soy novato con PICs, pero sé que son muy potentes y versátiles, quiero aprender a usarlos, por eso estoy aprendiendo a usar el PIC C Compiler (en vez de entrar directo con ensamblador), porque tengo algo de experiencia en C, y porque aprender ensamblador es un poco más tardado.
Estoy aprendiendo del libro Compilador C CCS y simulador proteus para microcontroladores PIC, de Eduardo Garcia Breijo, editado por alfaomega.

Concretamente, he intentado hacer muchos programas pero ninguno ha funcionado.
Creo que el problema es la gestión de puertos, por lo que para ensayar hice este sencillo programa (guiado por las indicaciones del texto) para ver si esta era la manera (o al menos se acercaba):
Código PHP:
#include <16f887.h>
#use delay (clock = 4000000)
#BYTE PORTB = 0x06
#BYTE TRISB = 0X86
#BYTE OPTION_REG = 0x81
void main(void)
   {
      
int8 valor 0;
      
TRISB 0x0F;
      
bit_clear(OPTION_REG,7);
      
         
bit_clear(PORTB,4);
         
bit_clear(PORTB,5);
         
bit_clear(PORTB,6);
         
bit_clear(PORTB,7);
      
      do{
      
valor PORTB;    
      switch (
valor)
      {
         case 
0b11111110:
         
bit_set(PORTB,4);
         
bit_set(PORTB,5);
         
delay_ms(500);
         
bit_clear(PORTB,4);
         
bit_clear(PORTB,5);
         break;
         
         case 
0b11111101:
         
bit_set(PORTB,5);
         
delay_ms(500);
         
bit_clear(PORTB,5);
         break;
         
         case 
0b11111100:
         
bit_set(PORTB,PIN_B6);
         
delay_ms(500);
         
bit_clear(PORTB,PIN_B6);
         break;
         
         case 
0b11111011:
         
bit_set(PORTB,6);
         
bit_set(PORTB,7);
         
delay_ms(500);
         
bit_clear(PORTB,6);
         
bit_clear(PORTB,7);
         break;
         
         default:
         
bit_clear(PORTB,4);
         
bit_clear(PORTB,5);
         
bit_clear(PORTB,6);
         
bit_clear(PORTB,7);
         break;
      }
   
   
   }while(
TRUE);
   } 
Adjunto la imagen de la simulacion.

Pero, al ejecutar, no ocurre absolutamente nada, cada que se aprieta un botón se ve como su estado pasa de 0 a 1, pero en la salida, no prende ningún led.

No tengo idea de qué más hacer, pensé en cambiar cada sentencia del switch por if-else, y en vez de usar una variable int8 para conocer el estado del PIC, usar bit_test() como los argumentos de las condicionales, cosa que haría el programa más pesado y difícil de redactar.

He visto cosas geniales hechas con PICs, obras de arte y grandes piezas de ingeniería.
Quisiera llegar a hacer algo bueno, pero debo de aprender por principio a comunicar el micro
con el mundo exterior.
Cualquier ayuda es bienvenida y cualquier consejo será escuchado.

Saludos a todos y gracias por su interés.
25/06/2015 #2
Moderador

Avatar de D@rkbytes

Para empezar deberías estudiar sobre la palabra de configuración de los PIC.
Eso es importante tenerlo en cuenta porque de eso depende el funcionamiento del PIC.
Tipo de oscilador, Power On Reset, Brown-Out Reset, Watch Dog Timer, etc.

En PIC C Compiler puedes olvidarte por ahora de definir los puertos del PIC.
Si bien puede servir en algunos casos, no siempre resulta necesario definirlos.

Para poner en 1 x pin, se hace así: output_high(pin_xx); donde xx es la letra y número de bit.
Por ejemplo, para poner en 1 el pin RA0: output_high(pin_a0);
Y para poner en 0 el pin RA0: output_low(pin_a0);
Tampoco es necesario configurar los registros TRIS porque éstas instrucciones lo hacen automáticamente.
Lo que si es importante, es establecer estados iniciales a los pines que serán salidas.

Así que el código que muestras puede quedar más simple haciendo uso de esas instrucciones.
bit_set y bit_clear, sirven más que nada para el manejo de variables, por eso es que cuando se usan para controlar puertos, éstos se tienen que definir.
26/06/2015 #3

Avatar de TRILO-BYTE

es verdad CCS es muy facil de usar yo en lo personal lo sigo usando apesar de que conosco mikro C , C18 ,etc.

como dice el colega output_high(pin_b0); pone en 1 el pin b0 etc.

algo que te puedo dar como consejo es hacer uso del INDEX del CCS , esa ayuda se encuentra en un simbolo de interrogacion en la parte superior derecha .

y ahi vienen muchos usos de las directivas del CCS y su respectivo ejemplo.

CCS no es del todo estandar pero si se puede programar en estandar con uso de otras directivas.

ejemplo de funciones no estandar: output, xfer(), #users232, etc.

pero eso no es para espantarse para hacer proyectos es bastante comodo
26/06/2015 #4

Avatar de KuroNek0

Muchas gracias, conr especto a los consejos de D@rkbytesx, esperaba primero aprender a trabajar con los puertos a travez de la ram, pero creo que trabajar con directivas es mas sencillo; ademas supongo que no debi de obviar la linea de los fuses, tengo una vaga nocion de lo que son y buscando en el datasheet encontre cuales son los validos, pero al investigar cada uno la cosa se complica (son muchos y no hay mucha informacion al respecto), alguien puede recomendar algun libro al respecto???, solo una duda, es necesario siempre establecer el valor inicial de los pines que seran salidas incluso en el caso de que un mismo pin alterne como entrada y salida al transcurrir el programa???

con respecto a los comentarios de TRILO-BYTE, es cierto, todos los que conosco (y que saben) me dicen que CCS es una de las herramientas mas simples y hasta "amigables" para programar pics, la verdad siempre habia obviado la ayuda, pero index tiene bastante informacion, me sera bastante util.

vuelvo a escribir el programa y comparto los resultados; saludos y gracias.
26/06/2015 #5
Moderador

Avatar de D@rkbytes

KuroNek0 dijo: Ver Mensaje
¿Alguien puede recomendar algún libro al respecto?
Algo así como un libro dedicado a ese tema, lo dudo.
El problema es que cada familia y tipo de PIC, tienen fuses diferentes.
Pero mira este documento que te va a servir para comprender los más básicos. Significado de los Fuses
KuroNek0 dijo: Ver Mensaje
Sólo una duda. ¿Es necesario siempre establecer el valor inicial de los pines que serán salidas, incluso en el caso de que un mismo pin alterne como entrada y salida al transcurrir el programa?
Es necesario establecer estados iniciales cuando se configuran los pines como salida usando el registro TRISX, porque cada puerto adquiere valores por defecto en el POR (Power On Reset)

Como un ejemplo:
set_tris_b(0x00); // Esta instrucción establece todos los pines del puerto B como salidas.

Aquí no se está estableciendo ningún valor inicial, sólo se están configurando como salidas.
Pero en el POR, el puerto B adquirirá un valor por defecto que se puede encontrar en la hoja de datos.
Eso hará que algunos pines se inicien en 0 y otros en 1.
Caso no deseado cuando cierto pin debe iniciar en 0 o en 1.

Una forma de inicialización del puerto, sería esta:
output_b(0b11100011);
Aquí todos los pines del puerto B serán salidas, pero ya se están estableciendo estados iniciales.
27/06/2015 #6

Avatar de KuroNek0

Bueno, siguiendo los consejos que me dieron, ya reescribí el programa.
El código quedó mucho más compacto, aunque me parece un poco más críptico (pero igual se entiende):
Código PHP:
#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4000000)
#use standard_io(B)

void main(void)
{
  
   
output_low(PIN_B6);
   
output_low(PIN_B7);
   
   while(
1)
   {
    
         
         if((
input(PIN_B0)==1)&&(input(PIN_B1)==1))//cuando ambos botones se pulsan, se encienden los 2 leds
         
{
          
output_high(PIN_B6);
          
output_high(PIN_B7); 
         }
         
         else if((
input(PIN_B0)==0)&&(input(PIN_B1)==0))//cuando se dejan de pulsar ambos botones, se apagan los leds
         
{
           
           
output_low(PIN_B6);
           
output_low(PIN_B7);
           
         }         
         
        
   }


Me costó bastante trabajo hacer que corriera, pero creo que ahora tengo una mejor idea de como usar los pines (en modo digital)
Fue algo complicado, un mismo programa que no hacia nada, al ser cargado por segunda o tercera vez en el simulador (proteus), mostraba los resultados que debía mostrar.

Un par de dudas mas. ¿Cómo puedo hacer para qué en vez de leer cada pin por separado se lea el valor de todo el puerto?

¿Es válido usar en este ejemplo:

int8 valor1=0;
valor1=input_B();

Y aplicar valor1 en el switch del primer programa?

Y en caso de querer enviar, por ejemplo, el valor de los pines por USB a alguna aplicación en PC. ¿Es conveniente el uso de variables? Algo como:

int8 valor1=0;
variable1=input(PIN_B0);

Muchas gracias por la atención, espero no estar abusando.

Sigo experimentando y probando. Saludos.
27/06/2015 #7

Avatar de TRILO-BYTE

Yo lo dejaría así:
Código PHP:
#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4M)

void main(void)
{


while(
true)
{


if((
input(PIN_B0)==1)&&(input(PIN_B1)==1))//cuando ambos botones se pulsan, se encienden los 2 leds
{
output_high(PIN_B6);
output_high(PIN_B7); 
}

else 
//cuando se dejan de pulsar ambos botones, se apagan los leds
{

output_low(PIN_B6);
output_low(PIN_B7);


---------- Actualizado después de 4 minutos ----------

Muy fácil. Para las dudas, tan fácil que da risa.
char = 8 bits con signo -127 a 127
unsigned char = 8 bits 0 a 255

Con esto decimos:

Código PHP:
unsigned char puerto;

puerto=input_b();

y para el switch


unsigned char puerto;

while(
true)
{
puerto=input_b();

switch(
puerto)
{
case 
0:
// tarea 1
break;

case 
1:
// tarea 2
break;
.
.
.
.
case 
255:
// tarea 256
break;
}

28/06/2015 #8
Moderador

Avatar de D@rkbytes

KuroNek0 dijo: Ver Mensaje
Un par de dudas más. ¿Cómo puedo hacer para qué en vez de leer cada pin por separado se lea el valor de todo el puerto?

¿Es válido usar en este ejemplo:

int8 valor1=0;
valor1=input_B();

Y aplicar valor1 en el switch del primer programa?
Si, así está bien, pero si piensas leer y actuar sobre el mismo puerto, necesitas usar una máscara.
¿Por qué? Porque la lectura con input_x(); incuirá todo el puerto.
Este es un ejemplo sencillo haciendo uso de la directiva fast_io_(port); y una máscara:
Código PHP:
#include <16f887.h>
#fuses   NOFCMEN
#use     delay(internal = 8MHz)
#use     fast_io(b)  // Indicar al compilador que genere código para el uso de set_tris_x().


void main (void)
{
   
set_tris_b(0b00111111);       // Sólo RB7 y RB6 como salidas.
   
   
while (true)
   {
      switch(
input_b() & 0x03)   // Establecer una máscara para RA1 y RA0. 0x03=(0b00000011)
      
{
         case 
0:                 // Caso valor 0 (Cuando RA1 y RA0 estén en 0)
            /* Al usar fast_io(b) conjuntamente con set_tris_b(),
            sólo se pondrán en 0 los bits configurados como salidas. */
            
output_b(0x00);      // Se ponen en 0 RB7 y RB6 (Porque son salidas)
            
break;
         case 
3:                 // Caso valor 3 (Cuando RA1 y RA0 estén en 1)
            
output_b(0xC0);      // Se ponen en 1 RB7 y RB6
            
break;
         default:                
// Caso por defecto. (Cualquier otro valor no incluido)
            
output_b(0x00);      // Se ponen en 0 RB7 y RB6 (Porque son salidas)
      
}
   }

KuroNek0 dijo: Ver Mensaje
Y en caso de querer enviar, por ejemplo, el valor de los pines por USB a alguna aplicación en PC. ¿Es conveniente el uso de variables? Algo como:

int8 valor1=0;
variable1=input(PIN_B0);
Claro, aunque no siempre es requerido el uso de variables, porque también se pueden enviar datos directamente.
Por ejemplo:
printf("%u",input_state(PIN_B0));
TRILO-BYTE dijo: Ver Mensaje
Muy fácil. Para las dudas, tan fácil que da risa.
char = 8 bits con signo -127 a 127
unsigned char = 8 bits 0 a 255
Algo a tomar en cuenta sobre este compilador, es que las declaraciones de variables siempre son sin signo.
char variable; siempre será sin signo a menos que se indique lo contrario con signed
La ayuda de PIC C Compiler dijo:
Remember that with unsigned ints (the default for this compiler) the values are never negative.
Traducción:
Recuerde que con enteros sin signo (por defecto para este compilador) los valores nunca son negativos.

28/06/2015 #9


KuroNek0 dijo: Ver Mensaje
Bueno, siguiendo los consejos que me dieron, ya reescribí el programa.
El código quedó mucho más compacto, aunque me parece un poco más críptico (pero igual se entiende):
Código PHP:
#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4000000)
#use standard_io(B)

void main(void)
{
  
   
output_low(PIN_B6);
   
output_low(PIN_B7);
   
   while(
1)
   {
    
         
         if((
input(PIN_B0)==1)&&(input(PIN_B1)==1))//cuando ambos botones se pulsan, se encienden los 2 leds
         
{
          
output_high(PIN_B6);
          
output_high(PIN_B7); 
         }
         
         else if((
input(PIN_B0)==0)&&(input(PIN_B1)==0))//cuando se dejan de pulsar ambos botones, se apagan los leds
         
{
           
           
output_low(PIN_B6);
           
output_low(PIN_B7);
           
         }         
         
        
   }


Mira por lo que yo llevo aprendido tambien puedes hacer lo siguiente, con lo que ahorras codigo.

En vez de poner:
Código PHP:
        if((input(PIN_B0)==1)&&(input(PIN_B1)==1))//cuando ambos botones se pulsan, se encienden los 2 leds
         
{
          
output_high(PIN_B6);
          
output_high(PIN_B7); 
         }
         
         else if((
input(PIN_B0)==0)&&(input(PIN_B1)==0))//cuando se dejan de pulsar ambos botones, se apagan los leds
         
{
           
           
output_low(PIN_B6);
           
output_low(PIN_B7);
           
         } 
Pones:
Código PHP:
        if((input(PIN_B0))&&(input(PIN_B1)))//cuando ambos botones se pulsan, se encienden los 2 leds
         
{
          
output_high(PIN_B6);
          
output_high(PIN_B7); 
         }
         
         else if((!
input(PIN_B0)) && (!input(PIN_B1)))//cuando se dejan de pulsar ambos botones, se apagan los leds
         
{
           
           
output_low(PIN_B6);
           
output_low(PIN_B7);
           
         } 
Es lo mismo pero con menos codigo.

---------- Actualizado después de 6 minutos ----------

TRILO-BYTE dijo: Ver Mensaje
Yo lo dejaría así:
Código PHP:
#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4M)

void main(void)
{


while(
true)
{


if((
input(PIN_B0)==1)&&(input(PIN_B1)==1))//cuando ambos botones se pulsan, se encienden los 2 leds
{
output_high(PIN_B6);
output_high(PIN_B7); 
}

else 
//cuando se dejan de pulsar ambos botones, se apagan los leds
{

output_low(PIN_B6);
output_low(PIN_B7);


TRYLO-BYTE, yo creo que es mejor que ponga else if por que esta hablando de 2 botones, podria querer que uno estubiese en 1 y el otro en 0, si fuese un solo boton entenderia que fuese con else, ya que o esta en 1 o esta en 0, pero con 2 o mas creo que es mejor con else if.
28/06/2015 #10

Avatar de TRILO-BYTE

pues si pero el else if quedaria bien cuando hay una interrupcion del pormedio por ejemplo algo muy muy rapido como una comunicacion uart , usb , un timer no se algo rapido.

pero como es el dedo pues el dedo por mas rapido que sea puede ser 400ms un dedo muy acrobatico

el micro corre una instruccion a 1/4 de la frecuencia de reloj que pues nuestro dedo deberia ser mas rapido que flash

ademas es poleo no es una interrupcion de RB0 o un CCP asi que pues puede nadamas quedar en ELSE
01/07/2015 #11

Avatar de KuroNek0

Muchas gracias por sus comentarios.
He estado practicando un poco y podría decir que ya he comprendido el tema.
Supongo que sólo necesitaba desatascarme de las dudas y practicar un poco

Aquí un par de programas que ya corren como deberían:
Código PHP:
//Programa que genera tres secuencias diferentes de salida, dependiendo del botón pulsado;
// si dos botones son pulsados se apagan todos los leds


#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4M)
#use standard_io(B)

//funcion que incluye las secuencias, se controlan con una variable entera
void secuencia(int8 a)
{
     switch (
a)
     {
         case 
1:
         
output_low(PIN_B5);
         
output_low(PIN_B6);
         
output_low(PIN_B7);
        
         
output_high(PIN_B5);
         
delay_ms(500);
         
output_low(PIN_B5);
         
         
output_high(PIN_B6);
         
delay_ms(500);
         
output_low(PIN_B6);
         
         
output_high(PIN_B7);
         
delay_ms(500);
         
output_low(PIN_B7);
         break;
           
         case 
2:
         
output_high(PIN_B5);
         
delay_ms(1000);
         
         
delay_ms(500);
         
output_high(PIN_B6);
         
delay_ms(500);
         
         
delay_ms(700);
         
output_high(PIN_B7);
         
delay_ms(300);
         
         
output_low(PIN_B5);
         
output_low(PIN_B6);
         
output_low(PIN_B7);
         break;
 
         case 
3:
         
         
output_low(PIN_B5);
         
output_low(PIN_B6);
         
output_low(PIN_B7);
         
delay_ms(500);
         
         
output_high(PIN_B5);
         
output_high(PIN_B6);
         
output_high(PIN_B7);
         
delay_ms(500);
              
         
output_low(PIN_B5);
         
output_low(PIN_B6);
         
output_low(PIN_B7);
         
delay_ms(500);
         
         
output_high(PIN_B5);
         
output_high(PIN_B6);
         
output_high(PIN_B7);
         
delay_ms(500);
         break;
     }
}



void main()
{
   
//definiciones e inicializaciones básicas
   
int8 var=0;
   
output_low(PIN_B5);
   
output_low(PIN_B6);
   
output_low(PIN_B7);
   
   while(
1)
   {
      
      
//selección de la secuencia
      
      
if((input(PIN_B0)==1)&&(input(PIN_B1)==0)&&(input(PIN_B2)==0)) 
      {      
           var=
1;
      }
      
      else if((
input(PIN_B0)==0)&&(input(PIN_B1)==1)&&(input(PIN_B2)==0))
      {        
           var=
2;
      }
   
      else if((
input(PIN_B0)==0)&&(input(PIN_B1)==0)&&(input(PIN_B2)==1))
      {
         var=
3;
      }
      else
      {
         
output_low(PIN_B5);
         
output_low(PIN_B6);
         
output_low(PIN_B7);
      }
      
//decir a la función que secuencia va a correr
      
secuencia(var);
   }

El programa anterior se tarda mucho en cambiar de una secuencia a otra, supongo que el programa es algo ineficiente.
Código PHP:
//Uso  de puertos mediante la RAM, le el valor de poerto B, y dependiendo de su valor, genera una //secuencia en el puerto a


#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4M)
#BYTE PORTA = 0x05              //Definición de los puertos
#BYTE PORTB = 0x06
#BYTE TRISA = 0x85
#BYTE TRISB = 0x86


void main()
{
   
int8 valor=0;
   
TRISA=0x00;
   
TRISB=0xFF;
   
PORTA=0x00;
   while (
1)
   {
      
valor=input_B();     //obtener el valor del puerto
      
      
switch (valor)       //selección de la secuencia
      
{
         case 
0b00000001:
         
output_A(0b01010101);
         
delay_ms(500);
         
output_A(0b10101010);
         
delay_ms(500);
         break;
         
         case 
0b00000010:
         
output_A(0b00001111);
         
delay_ms(500);
         
output_A(0b11110000);
         
delay_ms(500);
         break;
         
         case 
0b00000100:
         
output_A(0b00110011);
         
delay_ms(500);
         
output_A(0b11001100);
         
delay_ms(500);
         break;
         
         default:
         
output_A(0b00000000);
      
      }
   
   
   }



Este programa hace lo que debería, pero en la salida, los pines RA6 y RA7 no alternan como en la demás secuencia.
Supongo que habrá que revisar el diseño.


Creo que ya casi estoy listo para comenzar a hacer mis propias implementaciones.
Estaba pensando en un teclado numérico que usara 4 bits de algún puerto, pero antes una última duda:
Código PHP:
//Programa para leer y extraer datos por el mismo puerto, 4 bits (de menor peso) como salidas, y 
//4 bits (de mayor peso) como entradas

#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4M)
#BYTE PORTB = 0x06            //definiendo los puertos desde la ram
#BYTE TRISB = 0x86


void main()
{
   
int8 valor=0;        //variable que almacenara el estado del puerto
   
   
TRISB=0b11111111;          //inicializacion del registro tris B
   
PORTB=0b00000000;         //inicializacion del puerto B
   
   
while(1)
   {
         
TRISB=0b11111111;               //puerto B comoentradas
         
valor=input_B();                    //lee el estado del puerto B
         
valor=(valor&(0b11110000));   //enmascaramiento (espero que sea asi)
         
         
          //definicion de las secuencias
          
         //si RB7 y RB6 estan presionados, o si RB6 y RB5 lo estan, se encienden RB2 y RB3
         
if((valor == 0b11000000)||(valor==0b00110000)) 
         {
            
TRISB=0b00000000;
            
PORTB=0b00001100;
         }
         
         
//si RB7 y RB5 estan presionados, o si RB6 y RB4 lo estan, se encienden RB0 y RB1
         
else if((valor == 0b10100000)||(valor==0b01010000))
         {
            
            
TRISB=0b00000000;
            
PORTB=0b00000011;
         }
         
         else
         {
            
TRISB=0b00000000;
            
PORTB=0b00000000;
         }
   
   
   }



Aunque el compilador no arrojó ningún error, al simularlo no produjo los resultados esperados (no produjo ningún resultado), y en verdad me quedé sin ideas.

Muchas gracias por la ayuda.
He avanzado más una semana aquí que en un mes practicando yo solo.
Cualquier sugerencia es bienvenida.

Saludos.
01/07/2015 #12

Avatar de TRILO-BYTE

Antes que nada, usar TRIS en los puertos A o B, etc.
Debes tener conocimiento previo de como funciona el hardware del micro o al menos algo de experiencia usando el compilador.

Yo te recomendaría, que mientras, uses primero las directivas propias del CCS y después brinques a hacer uso del los TRIS bits.

Código PHP:
//Programa para leer y extraer datos por el mismo puerto, 4 bits (de menor peso) como salidas, y 
//4 bits (de mayor peso) como entradas

#include <16f887.h>
#fuses XT,NOWDT
#use delay (clock = 4M)

void main()
{
   
int8 valor=0;        //variable que almacenara el estado del puerto
   
   
   
while(1)
   {
         
         
valor=input_B();                    //lee el estado del puerto B
         
         
          //definicion de las secuencias
          
         //si RB7 y RB6 estan presionados, o si RB6 y RB5 lo estan, se encienden RB2 y RB3

         
if((valor == 0b11000000)||(valor==0b00110000)) 
         {
        
            
output_b=(0b00001100);
         }
         
         
//si RB7 y RB5 estan presionados, o si RB6 y RB4 lo estan, se encienden RB0 y RB1
         
else if((valor == 0b10100000)||(valor==0b01010000))
         {
            
output_b=(0b00000011);
         }
         
         else
         {
            
output_b=(0b00000000);
         }
   
   
   }



Pero me doy apenas cuenta de tu error, porque no genera nada.
Lo que pasa, es que todo el tiempo estás escribiendo 0 en el puerto B, es decir, no le das tiempo al puerto de leer.

Sólo usa ahorita un puerto para leer y el otro para escribir.

Ejemplo:

Puerto B para leer y el puerto A o el D para escribir.
01/07/2015 #13
Moderador

Avatar de D@rkbytes

Otras cosas aparte de lo que menciona TRILO-BYTE...
El primer programa se tarda en cambiar entre secuencias porque existen retardos y se tiene que cumplir la tarea para que pase a la siguiente.
Eso normal porque el PIC no es multitarea.
Eso se puede solucionar con el uso de la interrupción por cambio de estado en el puerto B.
Ahí detectas los cambios de estado de los pines RB4 a RB7 y según el valor de esos 4 bits, puedes seleccionar tareas inmediatamente aún existiendo retardos en ejecución. (Requiere polling)

En el segundo programa mencionas que no funcionan RA6 y RA7.
Eso es porque esos pines pertenecen al oscilador y estás usando el externo a cristal.
Si quieres usar esos pines como entradas o salidas, debes usar el oscilador interno.
Ese PIC puede funcionar hasta 8 MHz con el oscilador interno y ya tendrás libres RA6 y RA7.

Otra cosa. Si ya tienes declarados los puertos y los registros, ya los puedes usar directamente en el programa.
No tiene caso que los declares para usarlos nada más en la inicialización.
Eso se puede hacer con las instrucciones propias del compilador sin necesidad de declararlos.

Al declarar puertos ya puedes usarlos también en cualquier parte del programa.
Por ejemplo:
PORTA = 0b11011010; en vez de output_a(0b11011010);

También puedes usar output_b(0b11011010) y no escribir tantas veces output_high(pin); y output_low(pin);

En fin, aún te falta comprender bastantes cosas.
Siempre debes leer la hoja de datos del PIC y también estudiar sobre las instrucciones del compilador.
Este compilador como casi todos, tiene un archivo de ayuda muy completo, aunque en inglés.

Suerte.
02/07/2015 #14


D@rkbytes dijo: Ver Mensaje


Al declarar puertos ya puedes usarlos también en cualquier parte del programa.
Por ejemplo:
PORTA = 0b11011010; en vez de output_a(0b11011010);

También puedes usar output_b(0b11011010) y no escribir tantas veces output_high(pin); y output_low(pin);
Buenas D@rkbytes, un par de preguntas:

1º Que ahorra mas codigo, declarar puertos y luego usarlos o no declararlos y usar, por ejemplo, como pones tu, output_a(0b11011010);?.

2º Dices usar, por ejemplo, para activar el pin_b0 "output_b(0x01);" y no "output_high(pin_b0);" , por no escribirlo tantas veces, pero si quieres activarlo y transcurrido un tiempo desactivarlo luego tendras que poner "output_b(0x00);", no estas haciendo tambien de esta manera la misma cantidad de codigo?.
02/07/2015 #15
Moderador

Avatar de D@rkbytes

miglo dijo: Ver Mensaje
¿Qué ahorra más código, declarar puertos y luego usarlos o no declararlos y usar, por ejemplo, como pones tu, output_a(0b11011010);?
Código no se ahorra, tiempo sí.
La instrucción output_x(valor); tiene que hacer uso de los registros TRISX y PORTX, establecer valores y colocarlos en cada registro cada vez que se usa.
Lo mismo sucede con cualquier otra instrucción nativa del compilador que acceda a los puertos.

En cambio, ya una vez declarados registros y puertos, sólo se accede al registro que se vaya a usar.
Por lo tanto, eso requiere menor tiempo de proceso.
miglo dijo: Ver Mensaje
Dices usar, por ejemplo, para activar el pin_b0 "output_b(0x01);" y no "output_high(pin_b0);", por no escribirlo tantas veces, ¿pero si quieres activarlo y transcurrido un tiempo desactivarlo luego tendrás que poner "output_b(0x00);", no estás haciendo también de esta manera la misma cantidad de código?
Todo depende del tipo de proceso que ejecute el programa.
Si quieres modificar el estado de un sólo pin, conviene hacer uso de output_high(pin); y output_low(pin);
Pero si se requiere establecer varios estados de una sola vez, entonces el uso de output_x(valor); es más conveniente.
03/07/2015 #16


D@rkbytes dijo: Ver Mensaje
Código no se ahorra, tiempo sí.
La instrucción output_x(valor); tiene que hacer uso de los registros TRISX y PORTX, establecer valores y colocarlos en cada registro cada vez que se usa.
Lo mismo sucede con cualquier otra instrucción nativa del compilador que acceda a los puertos.

En cambio, ya una vez declarados registros y puertos, sólo se accede al registro que se vaya a usar.
Por lo tanto, eso requiere menor tiempo de proceso.

Todo depende del tipo de proceso que ejecute el programa.
Si quieres modificar el estado de un sólo pin, conviene hacer uso de output_high(pin); y output_low(pin);
Pero si se requiere establecer varios estados de una sola vez, entonces el uso de output_x(valor); es más conveniente.

Lo de TRISX y PORTX, entendido ahora lo tengo mas claro y con lo de output_x no lo habia visto de esa manera, tienes razon ya que yo me hincho de poner, en mis modestos programas, output_high y low asta artarme, gracias por la explicacion.

Ya me gustaria encontrar alguna informacion que explique mas o menos las cosas con esos matizes que son importantes conocerlos, todo lo que leo sobre C es lo mismo pero sin estas matizaciones y sin ejemplos que ayuden a comprender.
03/07/2015 #17

Avatar de TRILO-BYTE

no se que es matizacion

pero lo que si hay que aclarar

output_b(XX); no es una instruccion propia del lenguaje C

tampoco input_X(); ni nada de eso

lo que pasa es que son funciones propias del Pic C compiler "CCS"

son instrucciones inventadas por asi decirlo , otra cosa que hiso CCS fue la barbaridad de podre usar el printf y la LCD

ejemplo

printf(lcd_putc,"xx"); esto no es valido en cualquier compilador pero CCS hiso esa patraña
lo correcto seria algo asi;

char *cadena;
char i;
sprintf(cadena,"xx");

while( cadena[i]!= "\0")
{
lcd_putc(cadena[i]);
i++
}

CCS no es un mal compilador si se puede usar el ANSI C pero es tan facil usarlo por las directivas inventadas que trae y tambien genera algunos bugs pero no son tantos.

es como la gente que usa Arduino no es del todo un lenguaje estandar es tambien uno facil por las directivas inventadas que trae.

otra cosa que CCS hiso que no es del todo estandar

int1 int8 ,int16 int 32

eso no es estandar pues el int por default es de 32 bits para que fuese de 16 bits es conosido como short

y el int8 es un char.

pero CCS es malevolo y confunde a los novatos con sus artimañas
05/07/2015 #18


Matización viene a ser más o menos, resaltar algo enconcreto, o si hablas de una cosa especifica, pues explicarlo de la mejor manera comprensible, extendiendo al máximo la información de esa cosa.

Si te fijas en tu explicación de que, int por defecto es de 32 bits, ahí estás dando una información sobre ese punto en concreto, no de todo en general.

Por lo demás, gracias por tu explicación.
05/07/2015 #19

Avatar de TRILO-BYTE

int es estándar en todos los compiladores de 32 bits, pero CCS no lo respetó y lo deja a 8 bits, eso lo hizo para ahorrar memoria ram en la compilación.

Pero si hay que tener mucho en cuenta esos detalles en las compilaciones.
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.