// --- Hardware ---
#define digito_minutos1 RA3_bit
#define digito_minutos2 RA2_bit
#define digito_horas1 RA1_bit
#define digito_horas2 RA0_bit
int display(int num); //Exibe o valor correspondente no display de catodo comum
// --- Variávei Globais ---
int tempo = 0x00; //Inicializa contador
int control = 1; //Variável de controle (para saber qual display está ativo)
int segundos, minutos1,horas1,minutos2,horas2 = 0;
// --- Rotina de Interrupção ---
void interrupt()
{
if(T0IF_bit) //Houve o estouro do TMR0?
{
T0IF_bit = 0x00; //Sim, limpa a flag
TMR0= 6;
tempo++;
if(/*digito_horas2 &&*/ control==1){
control = 2;
digito_minutos2 = 1 ;
digito_horas1 = 1 ;
digito_minutos1 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_horas2 = 0;
PORTB = display(horas2);
}else if(/*digito_horas1 &&*/ control==2){
control = 3;
digito_minutos2 = 1;
digito_minutos1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_horas1 = 0;
PORTB = display(horas1);
}else if(/*digito_minutos2 &&*/ control==3){
control = 4;
digito_minutos1 = 1 ;
digito_horas1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_minutos2 = 0;
PORTB = display(minutos2);
}else if(/*digito_minutos1 &&*/ control == 4){
control = 1;
digito_minutos2 = 1 ;
digito_horas1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_minutos1 = 0;
PORTB = display(minutos1);
}
} //end if (teste de estouro)
} //end interrupt
// --- Função Principal ---
void main()
{
//Desabilita os resistores de pull-up internos
OPTION_REG = 0x81; // e configura o prescaler para 1:16 ou 1:4 se 11 ou 01 associado ao TMR0
GIE_bit = 0x01; //Habilita a interrupção global
PEIE_bit = 0x01; //Habilita a interrupção por periféricos
T0IE_bit = 0x01; //Habilita a interrupção por estoiro do TMR0
TMR0 = 0x06; //Inicia neste valor para dar contagem precisa (250*4*1 us cada estoiro ou seja 1 ms cada estoiro do Timer0)*/
CMCON = 0x07; // desabilita os comparadores
TRISA=0b00000000; //PORTA é configurado como saidas
TRISB=0b00000000; //PORTB configurado como saídas
digito_minutos2 = 1 ; // gate signal to pnp transistors to control the displays
digito_horas1 = 1 ;
digito_minutos1 = 1 ;
digito_horas2 = 1 ;
// -- Loop infinito --
while(1)
{
if(tempo == 1000) // ( 1us(=ciclo maquina) * 4(=PRESCALER) * 250(=256-6)) * 1000 = 1s
{
segundos++; // increments 1 second
tempo = 0x00;
}
if(segundos == 60)
{
minutos1++; // increments minute 1st digit
segundos = 0;
}
if(minutos1 == 10)
{
minutos2++; // increments minutes 2nd digit
minutos1 = 0;
}
if(minutos2 == 6)
{
horas1++; // increments hours 1st digit
minutos2 = 0;
}
if(horas1 == 10)
{
horas2++; // increments hours 2nd digit
horas1 = 0;
}
} //end while
} //end main
int display(int num)
{
int anode; //armazena código BCD
// -- Vetor para o código BCD --
int SEGMENTO[10] = {0b01000000,0b01111001,0b00100100,0b00110000,0b00011001,0b00010010,0b00000010,0b01111000,0b00000000,0b00011000} ;
anode = SEGMENTO[num];
return(anode);
} //end display
I could not see any explicit delay between consecutive accesses to PORTB, so that considering that your circuit is assembled on a breadboard with so aerial wires, you are certainly facing to signal integrity issues. Try adding a delay before each port assignement of let's say 10ms, gradually decreasing it.
void interrupt()
{
if(T0IF_bit) //Houve o estouro do TMR0?
{
T0IF_bit = 0x00; //Sim, limpa a flag
TMR0= 6;
tempo++;
if(digito_horas2 && control==1){
control = 2;
digito_minutos2 = 1 ;
digito_horas1 = 1 ;
digito_minutos1 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_horas2 = 0;
[COLOR="#FF0000"]delay_us(500);[/COLOR]
PORTB = display(horas2);
}else if(digito_horas1 && control==2){
control = 3;
digito_minutos2 = 1;
digito_minutos1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_horas1 = 0;
[COLOR="#FF0000"]delay_us(500);[/COLOR]
PORTB = display(horas1);
}else if(digito_minutos2 && control==3){
control = 4;
digito_minutos1 = 1 ;
digito_horas1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_minutos2 = 0;
[COLOR="#FF0000"]delay_us(500);[/COLOR]
PORTB = display(minutos2);
}else if(digito_minutos1 && control == 4){
control = 1;
digito_minutos2 = 1 ;
digito_horas1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
digito_minutos1 = 0;
[COLOR="#FF0000"]delay_us(500);[/COLOR]
PORTB = display(minutos1);
}
} //end if (teste de estouro)
} //end interrupt
void interrupt()
{
if(T0IF_bit) //Houve o estouro do TMR0?
{
T0IF_bit = 0x00; //Sim, limpa a flag
TMR0= 6;
tempo++;
if(digito_horas2 && control==1){
control = 2;
digito_minutos2 = 1 ;
digito_horas1 = 1 ;
digito_minutos1 = 1;
PORTB = 0b11111111; //LIMPA PORTB
[COLOR="#FF0000"]delay_us(atraso1);[/COLOR]
digito_horas2 = 0;
[COLOR="#FF0000"]delay_us(atraso2);[/COLOR]
PORTB = display(horas2);
[COLOR="#FF0000"]delay_us(atraso3);[/COLOR]
}else if(digito_horas1 && control==2){
control = 3;
digito_minutos2 = 1;
digito_minutos1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
[COLOR="#FF0000"]delay_us(atraso1);[/COLOR]
digito_horas1 = 0;
[COLOR="#FF0000"]delay_us(atraso2);[/COLOR]
PORTB = display(horas1);
[COLOR="#FF0000"]delay_us(atraso3);[/COLOR]
}else if(digito_minutos2 && control==3){
control = 4;
digito_minutos1 = 1 ;
digito_horas1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
[COLOR="#FF0000"]delay_us(atraso1);[/COLOR]
digito_minutos2 = 0;
[COLOR="#FF0000"]delay_us(atraso2);[/COLOR]
PORTB = display(minutos2);
[COLOR="#FF0000"]delay_us(atraso3);[/COLOR]
}else if(digito_minutos1 && control == 4){
control = 1;
digito_minutos2 = 1 ;
digito_horas1 = 1 ;
digito_horas2 = 1;
PORTB = 0b11111111; //LIMPA PORTB
[COLOR="#FF0000"]delay_us(atraso1);[/COLOR]
digito_minutos1 = 0;
[COLOR="#FF0000"]delay_us(atraso2);[/COLOR]
PORTB = display(minutos1);
[COLOR="#FF0000"]delay_us(atraso3);
[/COLOR]
}
} //end if (teste de estouro)
} //end interrupt
I have made a two digits 7segment display with PIC16F628A and two transistors in the past and it worked well.
Are you sure that you have correct segments connected to correct pins?
Maybe try to comment out your code and start with testing if the correct segments are lit?
And then start testing without multiplexing, just display the same digit on all digit displays.
And then add multiplexing.
I suspect that your problem is what is known as the "read-modify-write" problem and is caused by making changes to the individual PORT pins too rapidly.
Unfortunately the chip you are using does not have LAT registers that Microchip added to newer devices to get around exactly this problem.
Look at the internet for a technical description of the RMW problem but the solution in your case is to change all of the bits on PORTA at the same time. Looking at your code, you seem to always be setting the various PORTA bits in consecutive instructions. Use a 'shadow' register if you need to set individual bits at different times or work out the correct settings for all of the PORTA pins and write them all at once with one instruction.
Susan
if(digito_horas2 && control==1){
control = 2;
digito_minutos1, digito_horas1,digito_minutos2 = 1 ;
PORTB = 0b11111111; //LIMPA PORTB
digito_horas2 = 0; // [COLOR="#FF0000"]????[/COLOR]
PORTB = display(horas2);
}else if (...)
Try:
#define digito_minutos1 PORTA=0x08
#define digito_minutos2 PORTA=0x04
#define digito_horas1 PORTA=0x02
#define digito_horas2 PORTA=0x01
then use the defined name to select the digit. It should write all the bits to PORTA at once and avoid RMW problems. It looks like MikroC code which I can't check at the moment and I do not have ISIS at all.
Brian.
#define digito_minutos1 RA3_bit
#define digito_minutos2 RA2_bit
#define digito_horas1 RA1_bit
#define digito_horas2 RA0_bit
if(digito_horas2 && control==1){
control = 2;
digito_minutos1 = 1;
digito_horas1 = 1 ;
digito_minutos2 = 1 ;
while(digito_horas1 != 1 || digito_minutos2 != 1 || digito_minutos1 != 1){
}
PORTB = 0b11111111; //CLEAN PORTB
digito_horas2 = 0;
while(digito_horas2!=0){
}
PORTB = display(horas2);
}else if (........)
Sry Brian but I didnt understand, my define is basically the same right?
#define digito_minutos1 PORTA = 0b00000111
#define digito_minutos2 PORTA = 0b00001011
#define digito_horas1 PORTA = 0b00001101
#define digito_horas2 PORTA = 0b00001110
[B][COLOR="#FF0000"]int segundos, minutos1,horas1,minutos2,horas2 = 0;[/COLOR][/B]
// The 'if' statement above this ensures that digit0_horas2 (RA0) is 1
digito_minutos1 = 1; // Port RA3
digito_horas1 = 1; // Port RA1
digito_minutos2 = 1; // Port RA2
...
digit0_horas2 = 0; // Port RA0
PORTA = 0b1110; // RA3, RA2 and RA1 = 1, RA0 = 0
PORTA = digito_minutos1 | digito_minutos2 | digito_horas1;
An additional gain on that approach is that the code becomes more portable to other cores which do not supports bit mapping the ports.This will set all of the PORTA bits at the same time.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?