fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Problemas al cambia...
 
Avisos
Vaciar todo

Problemas al cambiar el estado de un Pin de un puerto en CCS

19 Respuestas
7 Usuarios
0 Reactions
8,088 Visitas
vcs
Respuestas: 114
 vcs
Topic starter
(@vcs)
Estimable Member
Registrado: hace 18 años

Buenas a todos.

Otra vez tengo un poquito de tiempo (de 6 mese en 6 meses saco un par de dias) y he vuelto a retomar un anteanteproyecto de placa que quiero hacer (la misma de todas las dudas que he ido posteando tiempo atras) tengo problemas con un programa en CCS version 3.222 para un 16F877 y es una tonteria pero no veo el fallo, resulta que lo que quiero es cambiar el estado de dos pines del puerto D de dicho pic, y resulta que he usado varias intrucciones para probar y me pasa algo muy raro y es que en lineas de programa consecutivas cambio el estado del pin 5 del puerdo D (Lo ativo por alta, lo pongo a uno) y en la siguiente linea repito la operacion para el pin 7 del mismo puerto, pero al llegar a esta linea el pin 7 se activa y se desactiva el 5, he probado varias intrucciones y la unica solucion que he encontrado para acceder a nivel de bit a sido haciendolo con una variable intermedia, por ejemplo ponia lo siguiente

bit_set(PORTD,5);
bit_set(PORTD,7);

y al llegar a la segunda linea el pin 5 cambia a valer 0 y el 7 a valer 1, cuando lo que deberia de hacer es mantenerse a 1 los dos bit, todo esto lo he ido programando en CCS y lo he corrido paso a paso bajo simulacion en el Proteus, asi que no se si realmente hago algo mal, es el CCS lo que falla o es el Proteus, no lo he podido probar en Hardware porque no dispongo del Micro en este momento, aqui dejo el codigo donde aparece lo que me ha funcinado (pero no me gusta porque no creo que sea la mejor forma de hacerlo, me ha recordado a horrores al asm cojo una variable a modo acumulador, la modifico y luego la saco por el Puerto) como se puede ver he dejado tambien enmascarados como si fueran comentarios:

// bit_set(PORTD,5);
// bit_set(PORTD,7);

algunos de los otros modos y en todos he obtenido resultados identicos, a ver si algun alma caritativa me puede iluminar un poquito sobre estos misterios que siempre se me escapan.

GRACIAS
#include <16F877A>
#fuses XT,NOWDT
#use delay (clock=1000000)

#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
#BIT D5=0X08.5
#BIT D7=0X08.7

int arranque=0;
int numero_piso=0;
int subida=0;
int bajada=0;
int piso_pulsado=0;
int variable=0;
int lectura_A=1;
int puertod=0;

#int_rb
VOID interrupcion()
{ lectura_A=PORTB;
if(INPUT(PIN_B4))
{
bit_clear(PORTD,5);
bit_clear(PORTD,7);
bit_set(PORTE,2);
// delay_ms(1500);
bit_clear(PORTE,2);
lectura_A=0;
}
if (INPUT(PIN_B5))
{
bit_clear(PORTA,1);
bit_clear(PORTA,2);
}
}

void main(void)
{
disable_interrupts(GLOBAL);

set_tris_a(0b111111);
set_tris_b(0b11111111);
set_tris_c(0b11111111);
set_tris_d(0b00011111);
set_tris_e(0b000);

PORTD=0;
PORTE=0;

enable_interrupts(int_rb);
enable_interrupts(int_ext);
enable_interrupts(GLOBAL);

do
{
if (arranque==0)
{

//bit_set(PORTD,7);
//bit_set(PORTD,5);

//Output_high(PIN_D5);
//Output_high(PIN_D7);

//D5=1;
//D7=1;

bit_set(puertod,7);
bit_set(puertod,5);
PORTD=puertod;

while (lectura_A|=0)
{}
arranque=1;
}

// Delay_ms(5000);
bit_set(PORTE,0);

if (input(pin_c0))
{
variable=porta;
rotate_right(&variable,1);
rotate_right(&variable,1);
rotate_right(&variable,1);
bit_clear(variable,3);
bit_clear(variable,4);
bit_clear(variable,5);
portb=variable;
delay_ms(1000);
}

}WHILE(TRUE);
} // Fin

Responder
18 respuestas
_jm_
Respuestas: 961
 JM
(@_jm_)
Prominent Member
Registrado: hace 19 años

No he leído la priemra página, pero te respondo porque creo que va por aquí el problema (seguro que me equivoco por no leer x_x)

Any instruction which performs a write operation actually does a read followed by a write operation.
The BCF and BSF instructions, for example, read the register into the CPU, execute the bit
operation, and write the result back to the register. Caution must be used when these instructions
are applied to a port with both inputs and outputs defined. For example, a BSF operation on bit5
of PORTB will cause all eight bits of PORTB to be read into the CPU. Then the BSF operation
takes place on bit5 and PORTB is written to the output latches. If another bit of PORTB is used
as a bi-directional I/O pin (e.g., bit0) and it is defined as an input at this time, the input signal
present on the pin itself would be read into the CPU and rewritten to the data latch of this particular
pin, overwriting the previous content. As long as the pin stays in the input mode, no problem
occurs. However, if bit0 is switched to an output, the content of the data latch may now be
unknown.
Reading the port register, reads the values of the port pins. Writing to the port register writes the
value to the port latch. When using read-modify-write instructions (ex. BCF, BSF, etc.) on a port,
the value of the port pins is read, the desired operation is performed on this value, and the value
is then written to the port latch.
Example 9-9 shows the effect of two sequential read-modify-write instructions on an I/O port.

Aquí lo tienes: http://ww1.microchip.com/downloads/en/D ... 33023a.pdf

9.10.1

Creo que va por aquí lo que te pasa. Supongo que tu simulador tomará esto último como general, hay que mirarlo más a nivel de hard que de firm.

Prueba a escribir directamente el puerto de una vez, o crea una registro en ram que representa el puerto y haz las operaciones de bits sobre éste, y una vez que hayas hecho todas muevelo al portb.

Hace una lectura del puerto cada vez que escribes, si tu bit 5 estaba a 0 y lo has puesto a 1, y en la siguiente instrucción cambias el 7. Esa instrucción tarda en ejecutarse 250 ns (20 Mhz de cristal), en esos 250 ns el bit 5 puede que no haya alcanzado aún su 1 (cualquier capacitancia) y al volverlo a leer con la siguiente instrucción lo machacas con el 0 y sobrescribe el latch. De ahí que al poner una instrucción entre medias tarde más y le da tiempo a alcanzar el 1 y no machacass el latch con 0 al hacer la lectura de nuevo cuando metes la istrucción de cambio de bit en el 7. Lee el manual que te he indicado que es muy completo.

Resumiendo, que me éxplico mu mal:

a BSF operation on bit5 of PORTB will cause all eight bits of PORTB to be read into the CPU.

Reading the port register, reads the values of the port pins. Writing to the port register writes the value to the port latch.

Si no das tiempo machacas el latch.

Responder
ucfort
Respuestas: 760
(@ucfort)
Ardero
Registrado: hace 19 años

output_low(PIN_B0;
output_high(PIN_B0);

Responder
vcs
Respuestas: 114
 vcs
Topic starter
(@vcs)
Estimable Member
Registrado: hace 18 años

Hola a los dos.

Gracias por las respuestas, después de este mensaje seguía sin poder creer que siendo el CCS tan usado pudiera tener un fallo como este así que efectivamente como comenta JM decidí probarlo a nivel Hard, probé a usar bit_clear en un puerto en el que todo está a 1 y lo simule, efectivamente seguía pasando lo mismo, al poner solo un bit a cero TODO el puerto pasaba a cero, el mismo HEX lo copié en un PIC, y para mi "sorpresa" todo funcionaba como debía, el bit que pedí que se apagara se apago y el resto seguía a High, ya probé con el resto de instrucciones como output_high(PIN_B0);...

Lo que sucede es que siempre uso el Proteus para simular y hasta que no funciona en proteus no copio al Hard, recordaba haber probado set_bit(PortX,1) en hard pero al parecer no lo hice, por tanto empecé a trabajar como dicen en el post de JM cojo la variable puerto,

puerto=PORTA;
bit_clear(puerto,2);
PORTA=puerto;

Claro de esa forma el simulador no se equivoca, y además para el PIC a nivel Hard también es correcto, En fins el problema esta en el PROTEUS, ¿alguien usa proteus? ¿Esto le va bien?

GRACIAS POR LAS AYUDAS

Responder
_jm_
Respuestas: 961
 JM
(@_jm_)
Prominent Member
Registrado: hace 19 años

Las instrucciones a nivel de bit con el 16f877a suelen funcionar perfectamente o casi siempre, pero si ese mismo programa lo grabas en un 16f690 por ejemplo, ocurre lo que se te sucede en el proteus, si cambias dos bits consecutivos con una instruccion de bit te machaca el primero.

Supongo que esto de tiempos depende de los tiempos de propagación internos y de las capacitancias que puedas tener en el pin, aunque funcione con el 16f877a lo mejor es tenerlo en cuenta siempre que se pueda ya que es lo que te dice en ese manual que te puede ocurrir.

La mejor forma es crearte un registro por cada puerto en ram, y realizar todas las operaciones sobre estos, y mover el resultado final al puerto.

Yo suelo usar BCF y BSF con el 16f877a y otros directmante y no da problemas, pero con otros pic si los da. Supongo que para el proteus lo correcto es tomar que da problemas para todos.

Responder
Página 4 / 4
Compartir: