Página 1 de 3

i2c multitarefa + interrupçao

MensagemEnviado: 25 Set 2009 21:50
por cristian
galera estou fazendo um gerador de ticket funciona assim


recebo os pulsos provieniente de uma placa a parte nao posso mudar
estes pulsos tem duraçao de 100ms
estou usando o ccp para capturar a borda de descida deste pulso e dai ligo o timer1 q mede a duraçao se for dentro dos padroes ele salva o pulso

ao salvar os pulsos ele exibe em 2 display de 7segmentos o valor do pulso

e espera ser pressionado o botao para imprimir o ticket

na impressao tenho q ler um memoria 24c256 q contem o numero de tickets
e ler um DS1307 para imprimir a data e hora

depois q imprimir vou salvar uns 20bytes na memoria (24c)

mas durante a impressao posso receber mais pulsos este tem q ser armazenados para assim q imprimir o anterior ele exibir no display o novo valor dos pulsos e esperar a impressao

o que esta ocorrendo é que nesse le e escreve de memoria e relogio ocorrem erros de leitura e escrita ja estou a muito tempo nisso e nao consigo resolver

tenho pra mim q é a interrup do timer 0 q sempre ocorre q esta atrapalhando estes perifericos mas nao posso desativar ela pois o display pode apagar

estava pesando estou usando 2 recusos para medir este pulso se usar a interrupçao extenar é melhor ???

o que sera q esta havendo com esta leitura e escrita errada de memoria e rtc

na interrupçao do timer 0 tem varias coisas pra ele testar e mudar sera que isso demora e acabo perdendo dados do i2c nao tem como o i2c ser automatico por interrupçao assim como é o usart ??

segue o codigo do timer 0

//----------------------------------------------------- ------------------------TIMER 0
#int_TIMER0
void TIMER0_isr(void)
{
static int tm1,TM2,tm3,tm4,tm5,tm6,tm7;
TM1++;

//----------------------------------------------------------------DISPLAY
IF(MEDIR_TEMPO)
{RESET_TIMER++;
if(RESET_TIMER==200)
{
MEDIR_TEMPO=0;
setup_timer_1 ( T1_DISABLED );
setup_ccp1(CCP_CAPTURE_FE);//borda subida
}
}
if(tm1==attdisplay)
{
tm1=0;
switch (PonteiroDisplay) //Alterna Display
{
case 0:
output_low(U);
Display=DEZ;
output_D(mask(display));
output_high(D);
break;
case 1:
output_low(D);
Display=UNI;
output_D(mask(display));
output_high(U);
break;
default:
PonteiroDisplay=0;
break;
}//switch (PonteiroDisplay).
if(++PonteiroDisplay >=2)PonteiroDisplay=0;
//output_D(mask(display));
}//----------------------------------------------------------------PISCA LED 1
if(piscaled1)
{
if(!tm2--)
{
tm2=flash;
led_s=!led_s;
output_bit( led1, led_s);
}
}else
{
output_high(led1);
}
//----------------------------------------------------------------PISCA LED 2
if(piscaled2)
{
if(!tm5--)
{
tm5=flash2;
led2_s=!led2_s;
output_bit( led2, led2_s);
}
}

//---------------------------------------------------------------0,5TIMER
if(timer_pulso)
{
if(pulsos)
{
if(!timer_500ms--)
{
timer_pulso=0;
trat_pulso=1;

}
}
}
//---------------------------------------------------------------1 seg TIMER
if(timer_1seg)
{
if(!tm6--)
{
timer_1seg=0;
tm6==248;
modo=1;//para botao B
}
}
//---------------------------------------------------------------TIMER botao H
if(hab_botaoH)
{
if(!tm7--)
{
if(!tmp_30--)
{
tmp_30=30;
hab_botaoH=0;
flash=125; //indica botaoH bloqueado
}
tm7==0;
}
}
//----------------------------------------------------incrementa contador
if(off_rele)
{
tm4++;
if(tm4==15)// 250MS
{
tm4=0;
off_rele=0;
output_low(rele1);
}
}

if(incr_contador)
{
//rele armar e desarmar
tm3++;


//---------------------------------SINAL SONORO
if(tm3==tempo_att)// 250MS
{
tm3=0;
if(beep)
{
output_high(rele1);
off_rele=1;
}
//-----------------------------------------------INCREMENTA DISPLAY
uni+=1;
if (uni>9)
{dez+=1;
uni=0;
if(dez>9)
{

uni=0;
dez=0;
//falta colocar acima de 99 pisca display
OUTPUT_low(PONTO);
}
}
if(!--NumPulsos)
{
tm3=0;
incr_contador=0;
display_pronto=1;
//output_low(rele1);
//write_EXT_eeprom(10,2);

}
}
}
//-----------------------------------------------------------------------------
}//timer 0

e do i2c memoria 24c

void write_ext_eeprom(long int address, BYTE data)
{
short int status;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>Cool;
i2c_write(address);
i2c_write(data);
i2c_stop();
i2c_start();
delay_ms(50);
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
i2c_stop();
}


BYTE read_ext_eeprom(long int address) {
BYTE data;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>Cool;
i2c_write(address);
i2c_start();
i2c_write(0xa1);
data=i2c_read(0);
i2c_stop();
delay_ms(10);
return(data);
}

rtc

void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x03); // Start at REG 3 - Day of week
i2c_start();
i2c_write(0xD1);
dow = bcd2bin(i2c_read() & 0x7f); // REG 3
day = bcd2bin(i2c_read() & 0x3f); // REG 4
mth = bcd2bin(i2c_read() & 0x1f); // REG 5
year = bcd2bin(i2c_read(0)); // REG 6
i2c_stop();
delay_Ms(10);
}

void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec)
{
i2c_start();
i2c_write(0xD0);
i2c_write(0x00); // Start at REG 0 - Seconds
i2c_start();
i2c_write(0xD1);
sec = bcd2bin(i2c_read() & 0x7f);
min = bcd2bin(i2c_read() & 0x7f);
hr = bcd2bin(i2c_read() & 0x3f);

i2c_stop();
delay_Ms(10);

}


estou usando CCS 4.093

MensagemEnviado: 26 Set 2009 11:32
por Alesandro F Zagui
Qual pic voce ta usando? Ele nao tem I2C por hw?

MensagemEnviado: 26 Set 2009 11:33
por cristian
PIC 16F877A TEM SIM

MensagemEnviado: 26 Set 2009 11:48
por Alesandro F Zagui
Tenta usar o I2C por HW entao.

Por que voce usa CCP pra capturar a borda de descida, porque nao usa a Interrupcao Externa (PortB0)?

MensagemEnviado: 26 Set 2009 11:57
por cristian
JA ESTOU USANDO POR HARDWARE SERA Q NAO

e do i2c memoria 24c

#use i2c(Master,SLOW,sda=PIN_C4,scl=PIN_C3)

void write_ext_eeprom(long int address, BYTE data)
{
short int status;
i2c_start();
i2c_write(0xa0);
i2c_write(address>>Cool;
i2c_write(address);
i2c_write(data);
i2c_stop();
i2c_start();
delay_ms(50);
status=i2c_write(0xa0);
while(status==1)
{
i2c_start();
status=i2c_write(0xa0);
}
i2c_stop();
}
o CCP é pra medir a duração do sinal q tem 100Ms

TEM COMO FAZER ISSO PELA INT EXTERNA so que tem momentos onde recebo so um pulso
ou seja sai do alto vai a nivel baixo por 100ms e volta pro alto

MensagemEnviado: 26 Set 2009 13:18
por Alesandro F Zagui
Talvez eu esteja enganado, mas me parece que essa configuração de I2C é por SW.

Tente configurar os registradores da I2C manualmente.

MensagemEnviado: 26 Set 2009 14:30
por Sergio38br
Por que vc esta usando um delay na saida das rotinas de leitura?? Geralmente usa-se isto apenas na gravação..

[ ]`
Sergio

MensagemEnviado: 26 Set 2009 16:31
por cristian
estou apelando pra tudo achando q pode ser na leitura o erro

as vezes grava na memoria o valor correto e ler errado

Re: i2c multitarefa + interrupçao

MensagemEnviado: 26 Set 2009 20:21
por Djalma Toledo Rodrigues
. _

MensagemEnviado: 27 Set 2009 16:43
por elzirobotelho
Olá Cristian
Eu tive um problema parecido com ao seu, só consegui solucionar desativando as interrupções enquanto lia ou escrevia no RTC. Pois quando ocorria uma interrupção no meio de uma comunicação I2C, a leitura do RTC não era concluída. e não aparecia nada no display e o programa se "perdia". Após a leitura eu habilitava as interrupções novamente vindo a solucionar o problema.

Sds
Elziro Botelho

MensagemEnviado: 27 Set 2009 22:18
por cristian
eu fiz isso mas o cliente ta reclamando q o display de 7 segementos esta piscando

estou pensando em mudar o clock pra 8mhz

nunca usei interrupçao de I2C sera que ajudaria

Re: i2c multitarefa + interrupçao

MensagemEnviado: 27 Set 2009 23:34
por Djalma Toledo Rodrigues
cristian escreveu:galera .... na impressao tenho q ler um memoria 24c256 q contem o numero de tickets

É o número de Série do Ticket ?

Se sim: Lê ao ligar e vai incrementando no uC

Há possibilidade de Criar Buffer na Ram 3 x 20 Bytes e Salvar na EEprom por Página ?

PIC16F877
Clock ----> 20 MHz
Ram ------> 368 Bytes
.

Re: i2c multitarefa + interrupçao

MensagemEnviado: 29 Set 2009 08:16
por andre_luis
Cristian,

Algumas observações importantes, mas que sempre as pessoas apanham nisso :

1 ) Voce está usando o mesmo barramento I2C - ou seja, mesma pinagem - para 2 dispositivos com bus interno de 8 e 16 bits. No datasheet, fica claro que não podemos pendurar dispositivos diferentes. Até o 24C16 isso poderia ser feito.

2 ) Pelo fato do protocolo I2C ser síncrono, voce não precisa se preocupar com a temporização. Essa característica permite usar esses componentes em ambientes multitarefas.

3 ) Por acaso, também usei uma topologia parecida com a sua ( 16F877 + DS1307 + 24C16 ) e por algum motivo, o compilador não aceitava acessar o I2C por HW. Tive que forçar na diretiva do CCS - versão 3.242 - para acessar por SW.

+++

MensagemEnviado: 29 Set 2009 11:45
por cristian
Djalma Toledo Rodrigues
ja faço isso leio varios dados e vou incrementando depois da impressao é q vou salvar todos os dados para evitar q uma falta de energia coloque tudo a perder

mas a hora tenho q ler na hora da impressao

uma das soluçoes seria aumentar o clock


andre_teprom

qual seria uma soluçao viavel ???
fazer i2c por software para separar os dispositivos

MensagemEnviado: 29 Set 2009 12:34
por vtrx
Voce sabe programar em ASM?provavelmente controlaria eficazmente os tempos e eventos.