Autor Tema: Sobre control de puertos  (Leído 3218 veces)

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

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Sobre control de puertos
« en: 15 de Julio de 2015, 15:12:27 »
Holas my programa es muy sencillo. Utiliza 2 displays para contar de 0 a lo que le pida el PORTA (max 99). No entiendo porque los displays parpadean (nunca los corto) este es el programa. Tambien tengo preguntas sobre los puertos.

#include <16f877.h>

#fuses  XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP  // TODAVIA NO QUIERO METERME EN ESTO
 
 
#USE delay(clock=4m)

void main(){
//    Input_x (valor);   Esta directiva nos devuelve el valor en el que se encuentra el "Puerto x".
//    Output_x (valor);  envía lo que valga valor al Puerto correspondiente.
int valor;
 int unit=0, dec=0;
 int unidaz=0;
 int BCD7seg[10]={0b0000,0b0001,0b0010,0b0011,0b0100,
                   0b0101,0b0110,0b0111,0b1000,0b1001}; 
   
   while(TRUE)
   {///wil
   
   valor=input_b();
   
 
if (valor<100){
//output_c(valor);     NO INPORTA Q ANULASE ESTO PORQUE output_c(BCD7seg[unidaz]);  Y  output_c(BCD7seg[dec]); AFECTAN AL PORTC
dec=0;   unidaz=0; valor++;// valor++ LO E PUESTO A CIEGAS (porque si valor era 15 solo contaba hasta 14)
for (unit=0;valor>unit;unit++){///for

   if (unidaz>=10){ dec++;  unidaz=0;}///0b1001  MAS DE 9. DECENAS
   output_high(PIN_d1);   
   output_c(BCD7seg[dec]); delay_ms(50);
   
   
   
  output_high(PIN_d0);   
  output_c(BCD7seg[unidaz]); delay_ms(20);
  // AUNQUE YO NO UTILE output_low(PIN_d0); NI output_low(PIN_d1); NO ENTIENDO PORQUE EL PIN 0 y 1 PASAN A VALER 0
   unidaz++;



}///for*/
}
else{
 output_high(PIN_d0);  output_high(PIN_d1);
output_c(0b0000); delay_ms(5); //¿ SI VALOR>99 COMO AGO PARA MANDAR EL HEXADECIMAL " FF "
}
}///wil

   }
//E TENIDO QUE UTILIZAR PIN 0 y 1 DE PORTD SON NECESARIOS PARA ENVIAR SEÑAL DE ENCENDIDO A LOS DISPLAYS
// SI YO COMO CONTADOR SOLO NECESITO HASTA EL 63 (binario 0011 111) ME GUSTARIA MUCHO TENER LIBRE PIN6 y PIN7 DE PORTD PARA LOS DISPLAYS Y ASI AORRAR PUERTOS QUE
// ME PUEDEN SERVIR PARA OTRA COSA
// PROBLEMA CUANDO APLICO  "  output_c(BCD7seg[unidaz]);  " Esto afecta tambien al pin 6 y 7 (aunque solo cuente hasta 63) me los pone a cero y no puedo utilizar
//a estos 2 para controlar el display ¿como podria hacer que "  output_c(BCD7seg[unidaz]);  " No afectase a los pin 6 y 7 (solo a los demas de 0 a 5)


POS Dejo archivos adjuntos sobre el proyecto si esto sirbe para aclararme algo mas. G

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Sobre control de puertos
« Respuesta #1 en: 15 de Julio de 2015, 19:40:18 »
Bueno veo algunos errores. Y otras cosas que te va a servir.

Errores:

1- La muestra de cada digito se hace MUY MUY MUY rapido, cada numero, es decir 00 -> 01 -> 02 se debe estar realizando cada unos 71ms, solucion simple pero no muy linda es agregarle un for
2- Estas multiplexando mal, no estas apagando los displays
3- Aunque no es un error, si vas a mostrar en el puerto la misma representacion binaria de lo que esta, no es necesario el conversor BCD7Seg que tenes, ya que un 9 en binario es 1001 y es lo que va a salir del puerto, distinto es si tenes que convertir el binario ese en los 7 segmentos, es decir que por ejemplo el 8 ( 0x08 o 0000 1000) sea representado por ( 0111 1111 ) en el que cada bit es un segmento pero vos estas sacando un 1000 asi que no es necesario.
4- Tenes un error en tu logica, si necesitas contar hasta 63 lo mismo ocupas solo 4bits, ya que ese 63 se pasa a "decimal" y queda 6 y 3, es decir solo necesitas representar de 0 a 9 y por lo tanto solo basta 4 bits

Consejos:

1- Utiliza un identado, es decir utiliza el boton TAB (el que esta arriba del bloq mayuscula) para ubicar el codigo, se vuelve mas legible de esa forma. Ya vas a ver el ejemplo abajo


Y con respecto a que te cambia los bits eso es por que estas cambiando TODO el port.
Para cambiar solo un pedacito del port deberias leerlo y luego cambiar lo que quieras, ejemplo

valorport = input_c();
valorport &= 0b11110000);      // aca hago valorport AND 0xF0 , lo que me deja los bits 7,6,5,4 sin modificarse, por que no se usan, luego le tengo que agregar lo del BCD7seg
output_c(valorport | BCD7seg[dec]);


Otra cosa que por ahi molesta del CCS es que por ejemplo vos queres que el bit 6 y 7 sean entradas y no salidas. Si vos haces
output_c(0x0F);

CCS las va a poner a TODAS como salida.
Esto es un tema que no me gusta de CCS pero que se puede arreglar. Si se usa la directiva:

#use fast_io(c)

Y luego en el main hacemos:

set_tris_c(0xF0); // 1111 0000 , es decir de 0 a 3 como salidas y de 4 a 7 como entradas.
La proxima ves que hagas:
output_c(0xFF);

Vas a modificar UNICAMENTE las salidas (es decir bits 0 a 3), esto es por que CCS comienza con todos los puerto donde lo define como standard_io , eso hace que CADA ves que vos pongas algo en el puerto (lectura o escritura), ya sea que le digas a un bit o a todo el puerto, se agregue codigo para cambiar la direccion del pin

input_pin(PIN_A0);   // Aca lo pone como entrada
output_pin(PIN_A0); // Aca lo pone como salida , a pesar que antes lo use como entrada antes. Y podria hacer un hermoso cortocircuito al pasar de una alta impedancia a GND cuando tal ves en la entrada tengo VCC, Y requiere atencion.

Como dije esto NO ocurre si usas fast_io, ya que ahi no modifica mas los TRISx , tris que definiste al comienzo de tu programa. Ademas el fast_io al no agregar codigo y solo modificar el registro que necesita se termina ejecutando mas rapido.


Aca tenes un ejemplo y tal ves el codigo que necesitas, no se que tan bien ande, y a esto me refiero con "identado"
Código: C
  1. #include <16f877.h>
  2.  
  3. #fuses  XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
  4. #use fast_io(c)
  5.  
  6.  
  7. #USE delay(clock=4m)
  8.  
  9. void main(){
  10.         set_tris_C(0b11000000);                                 //Ejemplo de como es el TRIS de un puerto, deje unicamente como entrada bit 6 y 7
  11.         int8 j;                                                 // Por lo tanto no va a cambiar cuando uses output_c , aunque solo usas los bits de 0 a 3, por lo que podria haber puesto 0xF0 en el TRIS
  12.         int unit=0, dec=0, unidaz=0, valor;
  13.    
  14.         while(TRUE)
  15.         {
  16.    
  17.                 valor=input_b();
  18.                 if (valor<100)
  19.                 {
  20.                         valor++;
  21.                         for (unit=0;valor>unit;unit++)
  22.                         {
  23.                                 dec=valor/10;                   //Como dec es un entero, se va a guardar unicamente el entero
  24.                                 unidaz= valor%10;               //El resto de la division de 10
  25.                                 for(j=0;j<10;j++)               // For para que tarde un poco mas de tiempo
  26.                                 {
  27.                                         output_low(PIN_d0);     // Apago ANTES del cambio del puerto, asi se cambia cuando esta apagado
  28.                                         output_low(PIN_d1);
  29.                                         output_c(dec);          // Como valor esta limitado a 99 , si divido por 10 solo me queda un maximo de 9, es decir va de 0 a 9 (0x00 a 0x09)
  30.                                         output_high(PIN_d1);
  31.                                         delay_ms(50);
  32.                                         output_low(PIN_d1);     // Apago ANTES del cambio del puerto
  33.                                         output_c(unidaz);       // El modulo de 10, me deja con el resto de la division, es decir las unidades, por lo tanto va de 0 a 9
  34.                                         output_high(PIN_d0);
  35.                                         delay_ms(49);
  36.                                 }
  37.                         }
  38.                 }
  39.                 else
  40.                 {
  41.                         output_high(PIN_d0);                    // Mayor a 100, por lo tanto pones 00 en ambos, como ambos son iguales no es necesario la multiplexacion
  42.                         output_high(PIN_d1);
  43.                         output_c(0b0000);
  44.                         delay_ms(5);
  45.                 }
  46.         }
  47.  
  48. }
« Última modificación: 15 de Julio de 2015, 19:48:09 por KILLERJC »

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re: Sobre control de puertos
« Respuesta #2 en: 22 de Julio de 2015, 11:57:19 »
Hola Killer. Gracias sobretodo por esto:

            dec=valor/10;         //Como dec es un entero, se va a guardar unicamente el entero
            unidaz= valor%10;      //El resto de la division de 10
Se entiende mejor como se puede pasar de 15 con solo 4bits. Lo demas hay cosas que tengo que leer mas detenidamente. Me an enseñado a ahorrar el PORTD solo tengo que hacer una suma u or 16=pin 4 32=pin 5.
Hay algo que falla tengo que resetear el micro para obtener un nuevo valor (No son los { } valor=input_b(); esta dentro de WHILE).
Otra cosa porque los displays parpadean primero se enciende  uno y luego otro, me gustaria que mostrasen el valor al unisono.

POS
No recibi la notificacion de este correo, supongo que no pinche en notificar nuevas respuestas.
My perfil esta bien es berto3soydd@hotmail.com si os di otro modificarlo por favor.


Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re: Sobre control de puertos
« Respuesta #3 en: 22 de Julio de 2015, 12:04:12 »
Bueno veo algunos errores. Y otras cosas que te va a servir.

Errores:

1- La muestra de cada digito se hace MUY MUY MUY rapido, cada numero, es decir 00 -> 01 -> 02 se debe estar realizando cada unos 71ms, solucion simple pero no muy linda es agregarle un for
2- Estas multiplexando mal, no estas apagando los displays
3- Aunque no es un error, si vas a mostrar en el puerto la misma representacion binaria de lo que esta, no es necesario el conversor BCD7Seg que tenes, ya que un 9 en binario es 1001 y es lo que va a salir del puerto, distinto es si tenes que convertir el binario ese en los 7 segmentos, es decir que por ejemplo el 8 ( 0x08 o 0000 1000) sea representado por ( 0111 1111 ) en el que cada bit es un segmento pero vos estas sacando un 1000 asi que no es necesario.
4- Tenes un error en tu logica, si necesitas contar hasta 63 lo mismo ocupas solo 4bits, ya que ese 63 se pasa a "decimal" y queda 6 y 3, es decir solo necesitas representar de 0 a 9 y por lo tanto solo basta 4 bits

Consejos:

1- Utiliza un identado, es decir utiliza el boton TAB (el que esta arriba del bloq mayuscula) para ubicar el codigo, se vuelve mas legible de esa forma. Ya vas a ver el ejemplo abajo


Y con respecto a que te cambia los bits eso es por que estas cambiando TODO el port.
Para cambiar solo un pedacito del port deberias leerlo y luego cambiar lo que quieras, ejemplo

valorport = input_c();
valorport &= 0b11110000);      // aca hago valorport AND 0xF0 , lo que me deja los bits 7,6,5,4 sin modificarse, por que no se usan, luego le tengo que agregar lo del BCD7seg
output_c(valorport | BCD7seg[dec]);


Otra cosa que por ahi molesta del CCS es que por ejemplo vos queres que el bit 6 y 7 sean entradas y no salidas. Si vos haces
output_c(0x0F);

CCS las va a poner a TODAS como salida.
Esto es un tema que no me gusta de CCS pero que se puede arreglar. Si se usa la directiva:

#use fast_io(c)

Y luego en el main hacemos:

set_tris_c(0xF0); // 1111 0000 , es decir de 0 a 3 como salidas y de 4 a 7 como entradas.
La proxima ves que hagas:
output_c(0xFF);

Vas a modificar UNICAMENTE las salidas (es decir bits 0 a 3), esto es por que CCS comienza con todos los puerto donde lo define como standard_io , eso hace que CADA ves que vos pongas algo en el puerto (lectura o escritura), ya sea que le digas a un bit o a todo el puerto, se agregue codigo para cambiar la direccion del pin

input_pin(PIN_A0);   // Aca lo pone como entrada
output_pin(PIN_A0); // Aca lo pone como salida , a pesar que antes lo use como entrada antes. Y podria hacer un hermoso cortocircuito al pasar de una alta impedancia a GND cuando tal ves en la entrada tengo VCC, Y requiere atencion.

Como dije esto NO ocurre si usas fast_io, ya que ahi no modifica mas los TRISx , tris que definiste al comienzo de tu programa. Ademas el fast_io al no agregar codigo y solo modificar el registro que necesita se termina ejecutando mas rapido.


Aca tenes un ejemplo y tal ves el codigo que necesitas, no se que tan bien ande, y a esto me refiero con "identado"
Código: C
  1. #include <16f877.h>
  2.  
  3. #fuses  XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP
  4. #use fast_io(c)
  5.  
  6.  
  7. #USE delay(clock=4m)
  8.  
  9. void main(){
  10.         set_tris_C(0b11000000);                                 //Ejemplo de como es el TRIS de un puerto, deje unicamente como entrada bit 6 y 7
  11.         int8 j;                                                 // Por lo tanto no va a cambiar cuando uses output_c , aunque solo usas los bits de 0 a 3, por lo que podria haber puesto 0xF0 en el TRIS
  12.         int unit=0, dec=0, unidaz=0, valor;
  13.    
  14.         while(TRUE)
  15.         {
  16.    
  17.                 valor=input_b();
  18.                 if (valor<100)
  19.                 {
  20.                         valor++;
  21.                         for (unit=0;valor>unit;unit++)
  22.                         {
  23.                                 dec=valor/10;                   //Como dec es un entero, se va a guardar unicamente el entero
  24.                                 unidaz= valor%10;               //El resto de la division de 10
  25.                                 for(j=0;j<10;j++)               // For para que tarde un poco mas de tiempo
  26.                                 {
  27.                                         output_low(PIN_d0);     // Apago ANTES del cambio del puerto, asi se cambia cuando esta apagado
  28.                                         output_low(PIN_d1);
  29.                                         output_c(dec);          // Como valor esta limitado a 99 , si divido por 10 solo me queda un maximo de 9, es decir va de 0 a 9 (0x00 a 0x09)
  30.                                         output_high(PIN_d1);
  31.                                         delay_ms(50);
  32.                                         output_low(PIN_d1);     // Apago ANTES del cambio del puerto
  33.                                         output_c(unidaz);       // El modulo de 10, me deja con el resto de la division, es decir las unidades, por lo tanto va de 0 a 9
  34.                                         output_high(PIN_d0);
  35.                                         delay_ms(49);
  36.                                 }
  37.                         }
  38.                 }
  39.                 else
  40.                 {
  41.                         output_high(PIN_d0);                    // Mayor a 100, por lo tanto pones 00 en ambos, como ambos son iguales no es necesario la multiplexacion
  42.                         output_high(PIN_d1);
  43.                         output_c(0b0000);
  44.                         delay_ms(5);
  45.                 }
  46.         }
  47.  
  48. }

Gracias por la ayuda killer. sorry .Creo que me e respondido a mi mismo en este tema en vec de citarte si tienes un momento te agradeceria que pasases por aqui


Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Sobre control de puertos
« Respuesta #4 en: 22 de Julio de 2015, 12:40:24 »
Vamos por parte

Citar
Otra cosa porque los displays parpadean primero se enciende  uno y luego otro, me gustaria que mostrasen el valor al unisono.

Esto es por que se esta multiplexando y es la idea, si es MUY notable entonces tenes que disminuir el tiempo que esta prendido, para mantener masomenos el mismo tiempo, supone que le aumentamos velocidad entre que un display enciende y el otro apaga a unos 50 veces por segundo, ya que teniamos 20, asi que modificamos esta parte:

Código: C
  1. for(j=0;j<25;j++)               // For para que tarde un poco mas de tiempo
  2.                                 {
  3.                                         output_low(PIN_d0);     // Apago ANTES del cambio del puerto, asi se cambia cuando esta apagado
  4.                                         output_low(PIN_d1);
  5.                                         output_c(dec);          // Como valor esta limitado a 99 , si divido por 10 solo me queda un maximo de 9, es decir va de 0 a 9 (0x00 a 0x09)
  6.                                         output_high(PIN_d1);
  7.                                         delay_ms(20);
  8.                                         output_low(PIN_d1);     // Apago ANTES del cambio del puerto
  9.                                         output_c(unidaz);       // El modulo de 10, me deja con el resto de la division, es decir las unidades, por lo tanto va de 0 a 9
  10.                                         output_high(PIN_d0);
  11.                                         delay_ms(20);
  12.                                 }

Ahora el for es de 25, pero el delay es de 20ms, entonces en ves de estar 50ms uno y luego 50ms el otro, lo hacemos 20ms uno y 20ms el otro. El tiempo total entre digito y digito es de 40ms * 25 = 1000ms = 1s, es decir cada 1 segundo va a aumentar
De esa forma al ser mas rapido, se quita esa sensacion de que estan parpadeando. Si aun asi se nota que parpadea se puede disminuir mas el tiempo

Citar
Hay algo que falla tengo que resetear el micro para obtener un nuevo valor (No son los { } valor=input_b(); esta dentro de WHILE).

No creo, ahora que aumentamos mucho mas el tiempo en que se muestran los numeros hace que hasta que vaya desde 0 a 50 por ejemplo, le tome 50 segundos, y recien ahi va a leer el puerto. Si quieres hacerlo mas rapido como para probar entonces cambia el valor del for de arriba por otro menor. elegimos 25, si usaramos 10 por ejemplo el numero cambiaria cada 10 * 40ms = 400ms.  Si lo haces por 5, cada 200ms se sumaria 1. Entonces la maxima pasada (es decir 99, tomo 100 para ahorrar calculos) puede tardar

Para dos delays de 20ms, con for:

1(sin for) -> 4s
2 -> 8s
5 -> 20s
10 -> 40s
25 -> 100s

Recordar que esto es lo que va a tardar aproximadamente a contar hasta el numero 99, si tenes un numero mas chico obviamente va a contar va a completarse mas rapido. Cuando se termine de mostrar todos los numeros recien ahi va a tomar de nuevo el valor del puerto. Si no es asi como deseas que funcione entonces explicalo con el mayor detalle y vemos como hacerlo.

Citar
Se entiende mejor como se puede pasar de 15 con solo 4bits. Lo demas hay cosas que tengo que leer mas detenidamente. Me an enseñado a ahorrar el PORTD solo tengo que hacer una suma u or 16=pin 4 32=pin 5.

Ojo que no es lo mismo una suma que una OR, si antes tenias un 0 ahi el resultado de ambas operaciones va a ser igual

0000 1001 + 0001 0000   =  0001 1001
0000 1001  | 0001 0000   =  0001 1001

Pero si es era un 1, se vuelve distinto.

0001 1001 + 0001 0000   =  0010 1001
0001 1001  | 0001 0000   =  0001 1001
« Última modificación: 22 de Julio de 2015, 12:57:06 por KILLERJC »

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re: Sobre control de puertos
« Respuesta #5 en: 22 de Julio de 2015, 13:51:29 »
Vamos por parte

Citar
Otra cosa porque los displays parpadean primero se enciende  uno y luego otro, me gustaria que mostrasen el valor al unisono.

Esto es por que se esta multiplexando y es la idea, si es MUY notable entonces tenes que disminuir el tiempo que esta prendido, para mantener masomenos el mismo tiempo, supone que le aumentamos velocidad entre que un display enciende y el otro apaga a unos 50 veces por segundo, ya que teniamos 20, asi que modificamos esta parte:

Código: C
  1. for(j=0;j<25;j++)               // For para que tarde un poco mas de tiempo
  2.                                 {
  3.                                         output_low(PIN_d0);     // Apago ANTES del cambio del puerto, asi se cambia cuando esta apagado
  4.                                         output_low(PIN_d1);
  5.                                         output_c(dec);          // Como valor esta limitado a 99 , si divido por 10 solo me queda un maximo de 9, es decir va de 0 a 9 (0x00 a 0x09)
  6.                                         output_high(PIN_d1);
  7.                                         delay_ms(20);
  8.                                         output_low(PIN_d1);     // Apago ANTES del cambio del puerto
  9.                                         output_c(unidaz);       // El modulo de 10, me deja con el resto de la division, es decir las unidades, por lo tanto va de 0 a 9
  10.                                         output_high(PIN_d0);
  11.                                         delay_ms(20);
  12.                                 }

Ahora el for es de 25, pero el delay es de 20ms, entonces en ves de estar 50ms uno y luego 50ms el otro, lo hacemos 20ms uno y 20ms el otro. El tiempo total entre digito y digito es de 40ms * 25 = 1000ms = 1s, es decir cada 1 segundo va a aumentar
De esa forma al ser mas rapido, se quita esa sensacion de que estan parpadeando. Si aun asi se nota que parpadea se puede disminuir mas el tiempo

Citar
Hay algo que falla tengo que resetear el micro para obtener un nuevo valor (No son los { } valor=input_b(); esta dentro de WHILE).

No creo, ahora que aumentamos mucho mas el tiempo en que se muestran los numeros hace que hasta que vaya desde 0 a 50 por ejemplo, le tome 50 segundos, y recien ahi va a leer el puerto. Si quieres hacerlo mas rapido como para probar entonces cambia el valor del for de arriba por otro menor. elegimos 25, si usaramos 10 por ejemplo el numero cambiaria cada 10 * 40ms = 400ms.  Si lo haces por 5, cada 200ms se sumaria 1. Entonces la maxima pasada (es decir 99, tomo 100 para ahorrar calculos) puede tardar

Para dos delays de 20ms, con for:

1(sin for) -> 4s
2 -> 8s
5 -> 20s
10 -> 40s
25 -> 100s

Recordar que esto es lo que va a tardar aproximadamente a contar hasta el numero 99, si tenes un numero mas chico obviamente va a contar va a completarse mas rapido. Cuando se termine de mostrar todos los numeros recien ahi va a tomar de nuevo el valor del puerto. Si no es asi como deseas que funcione entonces explicalo con el mayor detalle y vemos como hacerlo.

Citar
Se entiende mejor como se puede pasar de 15 con solo 4bits. Lo demas hay cosas que tengo que leer mas detenidamente. Me an enseñado a ahorrar el PORTD solo tengo que hacer una suma u or 16=pin 4 32=pin 5.

Ojo que no es lo mismo una suma que una OR, si antes tenias un 0 ahi el resultado de ambas operaciones va a ser igual

0000 1001 + 0001 0000   =  0001 1001
0000 1001  | 0001 0000   =  0001 1001

Pero si es era un 1, se vuelve distinto.

0001 1001 + 0001 0000   =  0010 1001
0001 1001  | 0001 0000   =  0001 1001


CITA1
Esto ya me lo an dicho antes.
Utilizo el simulador Proteus pero aunque vaje el delay(5) unicamente ocurre que el parpadeo es mas rapido.
Yo llevo directamente del pin del micro al terminal del display (cosa que se. No se debe hacer en la practica) ¿podria ser por esto?(un simulador permite saltarte estas cosas)
CITA 2
Eso es. Eso era paciencia o bajar los delay(no hay pregunta)
CITA 3
el OR yo lo vi similar pero en el programa que me ofrecieron tambien funciona la SUMA (valor no parece afectar pin de 4 a 7)

#include <16f877.h>
#use     delay(crystal = 4MHz)


void main (void)
{
   int8 unidades,decenas,puerto;
   
   while (true)
   {

      puerto = input_b();
     
      if(puerto > 99){puerto = 99;}   
     
      decenas = (puerto / 10);       
      puerto -= (decenas * 10);  // AUNQUE FUNCIONA NO LO ENTEIENDO  unidades = valor%10;  TIENE MAS SENTIDO
      unidades = puerto;               
     
      // Multiplexar los displays.
      output_c(unidades + 32);         
      delay_ms(2);                     
      output_c(decenas + 16);         
      delay_ms(2);                     
   }


Otra cosa en estos 3 programs e visto que no son necesarias las #FUSES

Saludos.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Sobre control de puertos
« Respuesta #6 en: 22 de Julio de 2015, 20:17:49 »
Citar
Esto ya me lo an dicho antes.
Utilizo el simulador Proteus pero aunque vaje el delay(5) unicamente ocurre que el parpadeo es mas rapido.
Yo llevo directamente del pin del micro al terminal del display (cosa que se. No se debe hacer en la practica) ¿podria ser por esto?(un simulador permite saltarte estas cosas)

El proteus es una simulacion, si esta corriendo lentamente entonces vas a ver que ocurre eso, para que funcione bien en el proteus bajale lo mas posible el delay o tal ves quitaselo. Asi como esta formulado el programa vas a tener problemas con eso ya que de quitar el delay se terminaria rapido la cuenta a no ser que agrandes muchisimo el for. En fisico no deberia notarse a 50 fps
Si, no deberias llevarlo directo al display, pero el simulador no creo que le importe mucho.

Citar
el OR yo lo vi similar pero en el programa que me ofrecieron tambien funciona la SUMA (valor no parece afectar pin de 4 a 7)

Por que esta aplicado distinto, ahi antes de sumarle se le asigna el valor a unidades/decenas, dejando unicamente un valor que queda 0000 xxxx , donde xxxx es el numero en binario de las unidades o decenas ( solo 4 bits para representar de 0 a 9). y luego terminas sumando 16 o 32, pero siempre los demas eran 0. Asi que no te va a cambiar. Pero vuelvo a repetirte: no es lo mismo. Al micro le "cuesta" lo mismo hacer esa suma que hacer una OR por el mismo valor, asi que no hay excusas. En este caso funciona por lo que dije.

Código: C
  1. decenas = (puerto / 10);        
  2.       puerto -= (decenas * 10);  // AUNQUE FUNCIONA NO LO ENTEIENDO  unidades = valor%10;  TIENE MAS SENTIDO
  3.       unidades = puerto;

Tiene sentido, lo que no tiene sentido es hacer el pasaje de una variable a la otra.

Código: C
  1. puerto -= (decenas*10);

es lo mismo que

Código: C
  1. puerto = puerto - (decenas*10);

Es decir a lo que hay en la variable puerto de 0 a 99 le restas las decenas es decir 0,10,20,30,40,50,60,70,80 y 90 segun las decenas que tenias. un eejemplo simple si toams el valor 54 , decenas te qeuda en 5, entonces al restar queda 54 - 50 => 4 y eso se guarda en unidades.
Son 2 formas de hacerlo. Hay que ver que ocupa menos espacio y tiempo del micro.

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re: Sobre control de puertos
« Respuesta #7 en: 23 de Julio de 2015, 15:07:01 »
puerto = valor (distinto programa)

puerto =67

puerto = puerto - (decenas*10); /// puerto = 67 - (6 x 10 ) --> Resultado 7 -ENTIENDO-

Y dices que a pesar de escribir mas codigo "puerto -= (decenas * 10);"
Es mas rapido que                                    "puerto = valor%10;"
Que le pasa al operando "%" ¿hace mas operaciones internas, ocupa mas ciclos de reloj?

Un saludo y gracias Killer

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Sobre control de puertos
« Respuesta #8 en: 23 de Julio de 2015, 19:46:45 »
Citar
Que le pasa al operando "%" ¿hace mas operaciones internas, ocupa mas ciclos de reloj?

Todo depende del compilador. Por ejemplo para multiplicar por 10 ( 1010b)
Tendrias que rotar 1 ves y guardar, rotar 2 veces mas y sumarlo a lo guardado. Y asi multilpicas por 10 con operaciones binarias.
La resta es directa. tiene una sola instruccion en ASM y listo.

En cambio la division ya no es TAN facil. El compilador la puede hacer de 2 formas, 1 es restando uno por uno los valores, y la otra es "multiplicando" por 0.00011001100110011
Eso requiere muchas mas rotaciones que una operacion de *10

Entonces si me baso en el principio que "%" es el modulo, yo no se exactamente como va a hacer el compilador para sacarlo, pero presupongo que lo va a dividir y luego restar, y eso requiere muchos mas ciclos que multiplicar y restar.
OJO! todo esto asumiendo que el compilador decide dividirla y no hacer una resta y mltiplicacion, para sacarlo, para ver exactamente que hace deberias simularlo. Y ver la cantidad de ciclos que requiere.
Todo esto por que no es multiplo de 2. Pero bueno esos son "problemas" de ASM, la idea de C es que vos te olvides completamente de eso, ademas por 1ms nadie se va a querer quemar la cabeza, a no ser que tengas que respetar unos tiempos muy estrictos.

EDIT:

Luego de tu observacion fui e hice un par de pruebas en XC8, no en CCS. Y simule paso a paso para saber cuantos ciclos tardaban.
Inclui la division por 10 para que sea "equivalente" en ambos casos, ya que el caso de la multiplicacion y resta necesita SI o SI de esa division

Codigo, use varios valores para ver si cambiaba los ciclos segun el valor de las decenas.
Código: C
  1. Conta1=99;
  2.         Conta2=Conta1/10;
  3.         Conta2=Conta1%10;
  4.         Conta1=92;
  5.         Conta2=Conta1/10;
  6.         Conta2=Conta1%10;
  7.         Conta1=79;
  8.         Conta2=Conta1/10;
  9.         Conta2=Conta1%10;
  10.         Conta1=59;
  11.         Conta2=Conta1/10;
  12.         Conta2=Conta1%10;
  13.         Conta1=39;
  14.         Conta2=Conta1/10;
  15.         Conta2=Conta1%10;
  16.         Conta1=19;
  17.         Conta2=Conta1/10;
  18.         Conta2=Conta1%10;
  19.         Conta1=9;
  20.         Conta2=Conta1/10;
  21.         Conta2=Conta1%10;

Resultados:

Citar
Target halted. Stopwatch cycle count = 625 (125 µs)
Target halted. Stopwatch cycle count = 625 (125 µs)
Target halted. Stopwatch cycle count = 632 (126,4 µs)
Target halted. Stopwatch cycle count = 625 (125 µs)
Target halted. Stopwatch cycle count = 625 (125 µs)
Target halted. Stopwatch cycle count = 618 (123,6 µs)
Target halted. Stopwatch cycle count = 611 (122,2 µs)

A pesar que hay ligeros cambios se podria redondear a 625 ciclos de reloj, De los cuales:

Primero la division y luego el modulo. Ocupan:
Citar
Target halted. Stopwatch cycle count = 325 (65 µs)
Target halted. Stopwatch cycle count = 280 (56 µs)


Ahora a probar con el tema no del modulo sino de la multiplicacion y la resta, usando los mismos valores:

Código: C
  1. Conta1=99;
  2.         Conta2=Conta1/10;
  3.         Conta2=Conta1 - (Conta2*10);
  4.         Conta1=92;
  5.         Conta2=Conta1/10;
  6.         Conta2=Conta1 - (Conta2*10);
  7.         Conta1=79;
  8.         Conta2=Conta1/10;
  9.         Conta2=Conta1 - (Conta2*10);
  10.         Conta1=59;
  11.         Conta2=Conta1/10;
  12.         Conta2=Conta1 - (Conta2*10);
  13.         Conta1=39;
  14.         Conta2=Conta1/10;
  15.         Conta2=Conta1 - (Conta2*10);
  16.         Conta1=19;
  17.         Conta2=Conta1/10;
  18.         Conta2=Conta1 - (Conta2*10);
  19.         Conta1=9;
  20.         Conta2=Conta1/10;
  21.         Conta2=Conta1 - (Conta2*10);

Resultados:

Citar
Target halted. Stopwatch cycle count = 377 (75,4 µs)
Target halted. Stopwatch cycle count = 377 (75,4 µs)
Target halted. Stopwatch cycle count = 381 (76,2 µs)
Target halted. Stopwatch cycle count = 377 (75,4 µs)
Target halted. Stopwatch cycle count = 377 (75,4 µs)
Target halted. Stopwatch cycle count = 373 (74,6 µs)
Target halted. Stopwatch cycle count = 371 (74,2 µs)

De los cuales la division y la proxima operacion ocupan:

Citar
Target halted. Stopwatch cycle count = 325 (65 µs)
Target halted. Stopwatch cycle count = 32 (6,4 µs)

La division ocupa lo mismo, PERO para sacar las unidades es mucho menor.

Esto lleva a 2 conclusiones:

- Si necesitas sacar UNICAMENTE las unidades y no las decenas, usa el modulo % ( 285 ciclos )
- Si necesitas sacar AMBOS , decenas y unidades, entonces usa la resta ( 357 ciclos )

Y espero que esto solucione tu pregunta.
( Tener en cuenta que se hizo con un divisor de 10, y variables de 16 bits)
Con variables de 8bits XC8 necesita mas ciclos para trabajarlo.
« Última modificación: 23 de Julio de 2015, 23:53:12 por KILLERJC »

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re: Sobre control de puertos
« Respuesta #9 en: 24 de Julio de 2015, 16:34:49 »
Si es posible que el " % " sea mas pesado que " * ". Si pides el "resto" supongo que el micro siempre va a tener que hacer la division esta requiere multiplicaciones y restas continuas al menos es lo que yo hacia mentalmente.

Acabo de ver varios compiladores XC, tambien e leido algo sobre Hi-Tech este ultimo dicen (en ingles) que es mas avanzado aunque CCS es mas sencillo y empiezo a estar agusto con el. Cuando instale CCS me pidio si queria MPLAB (solo ahora e visto lo que es) por defecto estaba anulado y no la instale ¿hice mal?.

Hacia muchisimo que no programaba. Aunque muchas cosas no os entiendo. me gusta y es interesante oir hablar a los de tu talla, no lo necesito todo pero me gusta entender.

Mi primer proyecto ya esta finiquitado incluso redecorado. Gracias por la ayuda Killer.

// ESTE PROGRAMA CUENTA DEL PORTC de 0 a 99 (segun el numero binario aplicado al PORTA)

#include <16f877.h>

//#fuses  XT,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP  // TODAVIA NO QUIERO METERME EN ESTO
 
 
#USE delay(clock=4m)

    void main(){
       set_tris_C(0b11000000);
       
int valor;
 int unit=0;
 int unidaz=0;
 int decez;
 int origen;
   
   while(TRUE)
   {///wil
   
   valor=input_b();
   origen=valor;
 
if (valor<100){
              valor++;// valor++ LO E PUESTO A CIEGAS (porque si valor era 15 solo contaba hasta 14)
//dec=valor/10;         //Como dec es un entero, se va a guardar unicamente el entero***
//unidaz= valor%10;     //El resto de la division de 10*********************************INTERESA
output_c(48); delay_ms(200);
unidaz=0; decez=0;
for (unit=0;valor>unit;unit++){///contador "for"
output_low(PIN_C4);  output_low(PIN_C5);
   if (unidaz>=10){ unidaz=0; decez++; }///0b1001  MAS DE 9. DECENAS
   //output_high(PIN_c5);   
   output_c(decez + 32); delay_ms(20);
   
   
   output_c(unidaz + 16); delay_ms(20);
   unidaz++;

if (origen != input_b()) //Si cambia la lectura de entrada en PORTB se fuerza a slir del contador "for"
{
unit=100;
decez=15;
for (unidaz=0;decez>unidaz;unidaz++){
output_c(17); delay_ms(10);
output_c(33); delay_ms(10);
}
}///fuerza a slir del contador "for"


}///contador "for"
}
else{////valor > 99
output_c(48); delay_ms(50);
output_low(PIN_C4);  output_low(PIN_C5);
output_c(57); delay_ms(100);// output_c(48 + 9);
}
}///wil
}
 

Ahora me gustaria hacer un proyecto propio con un KEY-PAD solo e modificado el codigo de otros.

Un Saludo.   

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Sobre control de puertos
« Respuesta #10 en: 24 de Julio de 2015, 20:51:50 »
Citar
Acabo de ver varios compiladores XC, tambien e leido algo sobre Hi-Tech este ultimo dicen (en ingles) que es mas avanzado aunque CCS es mas sencillo y empiezo a estar agusto con el. Cuando instale CCS me pidio si queria MPLAB (solo ahora e visto lo que es) por defecto estaba anulado y no la instale ¿hice mal?.

Hi-Tech creo que fue la primera version de compiladores en C para PIC, luego aparecieron C18, C32, y por ultimo y que tiene soporte ahora es XC8 y XC16.

El IDE es el MPLAB X, ahi programo en ASM, y solo tenes que instalar XC8, o XC16 para usar C en el mismo programa.
Las desventajas entre CCS y XC8 es que CCS tiene muchas funciones ya prearmadas como #use rs232, lo que hace muy facil crear incluso una UART por software, mientras que XC8 se asemeja un poco mas al ASM, donde modificas registro por registro o podes usar una libreria que trae microchip que funciona masomenos de la misma forma que en CCS, es decir una funcion y te condigura sola la UART ( para seguir el ejemplo ).

En fin el IDE del gusto de cada uno.

Desconectado Berto

  • PIC16
  • ***
  • Mensajes: 191
Re: Sobre control de puertos
« Respuesta #11 en: 25 de Julio de 2015, 10:59:09 »
RE
En fin el IDE del gusto de cada uno.

Lo ultimo si lo e entendido me que con CCS. Gracias.


 

anything