collapse

* Links de Robótica

* Posts Recentes

Ajuda Projecto IR / RF por Njay
[Hoje às 00:03]


Recomendação de um opamp para um DAC r2r por jm_araujo
[Ontem às 23:05]


Ideias para construir um quadrúpede simples por dropes
[Ontem às 22:43]


Ajuda com TRIAC por senso
[17 de Novembro de 2017, 18:00]


TV LG White Screen por almamater
[15 de Novembro de 2017, 08:37]


Pergunta sobre prototipagem ( Pesquisa ) por luisjustin
[14 de Novembro de 2017, 23:22]


Medir Agua que está no Poço por Njay
[14 de Novembro de 2017, 13:28]


Amplificador audio por beirao
[12 de Novembro de 2017, 23:43]


Power_OK Enermax por edeweld
[12 de Novembro de 2017, 17:15]


Driver motor por beirao
[11 de Novembro de 2017, 17:40]

Autor Tópico: Atmega 328p reinicia-se sozinho  (Lida 3302 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Atmega 328p reinicia-se sozinho
« em: 05 de Maio de 2013, 19:37 »
Boas

O que tenho estado a a fazer é interagir com lcd (HD44780) atravez do comando da tv que usa o protocolo rc5. Para tal estou a usar innterrupçoes para descodificar o comando mas quando carrego num botão neste o atmega reinicia-se sozinho e o valor micros() começa do zero.

O codigo é este

main.c
Código: [Seleccione]
#include "other.h" //all includes and defenition are here
#include "TWI.h"
#include "ds1307.h"
#include "lcd.h"
uint8_t temp,temp2;


char buf[30];

volatile uint32_t time=0;
volatile uint32_t RC5_Code=0;
bool enab;

int main(void){
Timer_Init();
USART_Init();
Interruption_Init();
sei();
while(1){
if( (micros() -time > 4000) && (enab == true)){
ultoa(micros(),buf,10);
comDrv_puts(&buf[0]);
comDrv_putc('\t');
utoa(RC5_Code,buf,2);
comDrv_puts(&buf[0]);
comDrv_putc('\n');
comDrv_putc('\0');
enab = false;
}
}return -1;
}

#define RC5_max 1111
#define RC5_min 667

ISR(PCINT0_vect){ // RC5
uint32_t aux = micros() -time;
time = micros();
if(aux >= 4000){
comDrv_putc('\n');
comDrv_putc('\n');
RC5_Code = 0;
}else{
enab = true;
if(aux >= RC5_min & aux <= RC5_max){
RC5_Code = (RC5_Code << 1) | (PINB & (1<<PINB0));
}
if(aux >= (RC5_min<<1) & aux <= (RC5_max<<1)){
RC5_Code = (RC5_Code << 2) | ((PINB & (1<<PINB0))<<1) | (PINB & (1<<PINB0));
}
}
}


uart.c
Código: [Seleccione]
#include "usart.h"

#if (BAUDRATE != 115200) & (BAUDRATE != 57600) & (BAUDRATE != 19200) & (BAUDRATE != 9600)
#error incorrect BAUDRATE
#endif

void USART_Init(void){
uint16_t UBRR = F_CPU/8/BAUDRATE-1;
/*Set baud rate */
UBRR0H = (uint8_t)(UBRR>>8);
UBRR0L = (uint8_t)UBRR;
//Set double speed
UCSR0A = (1<<U2X0);
/*Enable receiver and transmitter and their interruptions*/
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<TXCIE0)|(1<<UDRIE0); //UDRIEn: USART Data Register Empty Interrupt Enable n ????
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
comDrv_flux(&rxb);
comDrv_flux(&txb);
}

void comDrv_flux(circularBuffer *aux){
//Initialize variables of buffer
aux->count = 0;
aux->data[0] = '\0';
aux->head = 0;
aux->tail = 0;
}

void comDrv_putc(char ch){
while(txb.count == BUF_SIZE);
txb.data[txb.tail] = ch;
txb.tail = (txb.tail +1 ) & INDEX_MASK;
UCSR0B &= ~(1<<UDRIE0); //DisableUartTxInterrup
txb.count++;
UCSR0B |= (1<<UDRIE0); //EnableUartTxInterrup
}

void comDrv_puts(char *s){
while(*s != '\0'){
comDrv_putc(*s);
s++;
}
}

bool comDrv_getc(char * pchar){
if(rxb.count == 0)
return false;
UCSR0B &= ~(1<<RXCIE0); //DisableUartRxInterrup
pchar = rxb.data[rxb.head];
rxb.count--;
rxb.head = (rxb.head + 1) & INDEX_MASK;
UCSR0B |= (1<<RXCIE0); //EnableUartRxInterrup
return true;
}

ISR(USART_UDRE_vect){
if(txb.count > 0){
UDR0 = txb.data[txb.head];
txb.head = (txb.head + 1) & INDEX_MASK;
txb.count--;
}
if(txb.count == 0){
UCSR0B &= ~(1<<UDRIE0); //DisableUartTxInterrup
}
}

ISR(USART_RX_vect){
rxb.data[rxb.tail] = UDR0;
rxb.tail = (rxb.tail + 1) & BUF_SIZE;
if(rxb.count < BUF_SIZE)
rxb.count++;
else
rxb.head++;
}

other.c
Código: [Seleccione]
void Timer_Init(void){
TCCR2A = (1<<COM2B1) | (1<<COM2A1) | (1<<WGM21) | (1<<WGM20); // fast pwm non inverting mode
TCCR2B = (1<<CS22); // 64 prescaller

TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM10);
TCCR1B = (1<WGM12) | (1<<CS11) | (1<<CS10);

DDRD |= (1<<DDD3); // OC2B
DDRB |= (1<<DDB3) | (1<<DDB2) | (1<<DDB1); // 0C2A , 0C1A, OC1B

TIMSK2 = (1<<TOIE2); // TOIE2: Timer/Counter2 Overflow Interrupt Enable
micro = 0;

OCR2B = 50; //lcd
OCR2A = 255;
OCR1A = 255;
OCR1B = 255;
}

void Interruption_Init(void){
PCICR |= (1<<PCIE1) | (1<<PCIE0); // Interruption pcint0 & pcint1 enable
PCMSK1 = (1<<PCINT11); // interruption pin 11 enable
PCMSK0 = (1<<PCINT0); // interruption pin 11 enable
DDRC &= ~(1<<DDC3); // pin adc3 as input;
DDRB &= ~(1<<DDB0); // pin pb0 as input;
PORTC |= (1<<PORTC3); // pull up;
}


uint32_t micros(void){
cli(); // deactivate interruption
uint32_t aux = micro + (TCNT2<<2);
sei(); // activate interruption
return aux;
}

void delay(uint32_t us){
uint32_t start = micros();
while ((micros() - start) < us);


As vezes o avr reinicia outras bloqueia e tenho de disconnectar  a energia
Alguem pode me ajudar com isto?
« Última modificação: 05 de Maio de 2013, 19:41 por pmj_pedro »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.139
    • Tróniquices
Re: Atmega 328p reinicia-se sozinho
« Responder #1 em: 05 de Maio de 2013, 19:59 »
Dás pouca informação e o código está incompleto, e/ou faltam-te handlers de interrupção pelo que me parece (não fui ver os detalhes do chip). Se ocorrer uma interrupção que não tem handler, o micro "faz reset". Também pareces ter código (#include) a mais (não usado).

Já experimentaste fazer printfs a ver até onde ele executa? Já experimentaste simular o código no AVRStudio?

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #2 em: 05 de Maio de 2013, 20:10 »
Dás pouca informação e o código está incompleto, e/ou faltam-te handlers de interrupção pelo que me parece (não fui ver os detalhes do chip). Se ocorrer uma interrupção que não tem handler, o micro "faz reset". Também pareces ter código (#include) a mais (não usado).

Já experimentaste fazer printfs a ver até onde ele executa? Já experimentaste simular o código no AVRStudio?

Nao sei fazer simulação de codigo, e estou a ler dados que vêm de fora (rc5)

de facto tem includes a mais, mas nao os estou a utilizar agr, acho que nao faz grande diferença

e as unicas interrupçoes que tou a usar sao
ISR(PCINT0_vect);
ISR(TIMER2_OVF_vect);
ISR(USART_UDRE_vect);

posso fazer zip do projecto e por aqui se achares necessario para me ajudares

obgd

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.139
    • Tróniquices
Re: Atmega 328p reinicia-se sozinho
« Responder #3 em: 05 de Maio de 2013, 21:21 »
Nao sei fazer simulação de codigo, e estou a ler dados que vêm de fora (rc5)

Nada disso é desculpa :D. Sacas o AVRStudio do site da ATMEL. Lá abres o .ELF, respondes às perguntas e ele depois mostra-te o main.c. Metes breakpoints em sítios interessantes do teu código, e depois é só fazer "Run" e o gajo há-de lá parar (ou não :) ), e podes inspeccionar variáveis, etc.
Quanto ao RC5 é tudo uma questão de ser "criativo". A qualquer momento páras a execução (simulação), activas manualmente a flag de interrupção no registo apropriado, continuas a execução et voilá, tens uma interrupção. Há sempre forma de dar a volta à coisa, nem que às vezes seja preciso fazer algum pedacito de código para ajudar.

Citação de: pmj_pedro
de facto tem includes a mais, mas nao os estou a utilizar agr, acho que nao faz grande diferença
É só para teres a certeza de que esses includes não estão a instalar handlers por cima dos teus ou a fazer algo de que não estás à espera. Como alguns recursos são partilhados...

Citação de: pmj_pedro
e as unicas interrupçoes que tou a usar sao
ISR(PCINT0_vect);
ISR(TIMER2_OVF_vect);
ISR(USART_UDRE_vect);

E isto?

   PCMSK1 = (1<<PCINT11);                  // interruption pin 11 enable
   PCMSK0 = (1<<PCINT0);                  // interruption pin 11 0 enable


Não vi nenhum ISR(PCINT11_vect) no teu código...

Citação de: pmj_pedro
posso fazer zip do projecto e por aqui se achares necessario para me ajudares
Não é preciso que já tenho coisas para me ocupar o tempo, mas de qualquer forma obrigado :)

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #4 em: 05 de Maio de 2013, 22:32 »
Nao sei fazer simulação de codigo, e estou a ler dados que vêm de fora (rc5)

Nada disso é desculpa :D. Sacas o AVRStudio do site da ATMEL. Lá abres o .ELF, respondes às perguntas e ele depois mostra-te o main.c. Metes breakpoints em sítios interessantes do teu código, e depois é só fazer "Run" e o gajo há-de lá parar (ou não :) ), e podes inspeccionar variáveis, etc.
Quanto ao RC5 é tudo uma questão de ser "criativo". A qualquer momento páras a execução (simulação), activas manualmente a flag de interrupção no registo apropriado, continuas a execução et voilá, tens uma interrupção. Há sempre forma de dar a volta à coisa, nem que às vezes seja preciso fazer algum pedacito de código para ajudar.

Estou a programar no avrstudio, hei de experimentar


Citação de: pmj_pedro
e as unicas interrupçoes que tou a usar sao
ISR(PCINT0_vect);
ISR(TIMER2_OVF_vect);
ISR(USART_UDRE_vect);

E isto?

   PCMSK1 = (1<<PCINT11);                  // interruption pin 11 enable
   PCMSK0 = (1<<PCINT0);                  // interruption pin 11 0 enable


Não vi nenhum ISR(PCINT11_vect) no teu código...

o portB so tem uma interrupçao para todos os seus pinos B, por isso é que se escreve ISR(PCINT0_vect) e nao ISR(PCINT11_vect);
acho que estou correcto(essa é a interrupçao do rc5)?!?

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.401
  • Helpdesk do sitio
Re: Atmega 328p reinicia-se sozinho
« Responder #5 em: 05 de Maio de 2013, 23:14 »
Vai ler a datasheet com atenção, interrupções sem handlers vão criar algo que parece um reset, porque a tabela de interrupções fica logo no inicio da memória, se não existir um handler o que acontece é que o programa salta para o inicio.
Avr fanboy

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.139
    • Tróniquices
Re: Atmega 328p reinicia-se sozinho
« Responder #6 em: 05 de Maio de 2013, 23:50 »
o portB so tem uma interrupçao para todos os seus pinos B (...)
Em alguns AVR da geração anterior sim (como o ATtiny26), mas no 328P quase de certeza que não...

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #7 em: 06 de Maio de 2013, 00:13 »
Vai ler a datasheet com atenção, interrupções sem handlers vão criar algo que parece um reset, porque a tabela de interrupções fica logo no inicio da memória, se não existir um handler o que acontece é que o programa salta para o inicio.

datasheet:
Citar
The pin change interrupt PCI2 will trigger if any enabled PCINT[23:16] pin toggles.
The pin change interrupt PCI1will trigger if any enabled PCINT[14:8] pin toggles.
Thepin change interrupt PCI0 will trigger if any enabled PCINT[7:0] pin toggles.

Pelo que tiro daqui, concluo que existem 3 interrupçoes a tratar de todos pins, obvimente sem contar com as INT0 e INT1

Citar
Bit 1 – PCIF1: Pin Change Interrupt Flag 1
When a logic change on any PCINT[14:8] pin triggers an interrupt request, PCIF1 becomes set (one). If the I-bit in SREG and the PCIE1 bit in PCICR are set (one), the MCU will jump to the corresponding interrupt Vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing a logical one to

Citar
Address Labels Code Comments
0x0000 jmp RESET ; Reset Handler
0x0002 jmp EXT_INT0 ; IRQ0 Handler
0x0004 jmp EXT_INT1 ; IRQ1 Handler
0x0006 jmp PCINT0 ; PCINT0 Handler
0x0008 jmp PCINT1 ; PCINT1 Handler
0x000A jmp PCINT2 ; PCINT2 Handler
0x000C jmp WDT ; Watchdog Timer Handler
0x000E jmp TIM2_COMPA ; Timer2 Compare A Handler
0x0010 jmp TIM2_COMPB ; Timer2 Compare B Handler
0x0012 jmp TIM2_OVF ; Timer2 Overflow Handler
0x0014 jmp TIM1_CAPT ; Timer1 Capture Handler
0x0016 jmp TIM1_COMPA ; Timer1 Compare A Handler
0x0018 jmp TIM1_COMPB ; Timer1 Compare B Handler
0x001A jmp TIM1_OVF ; Timer1 Overflow Handler
0x001C jmp TIM0_COMPA ; Timer0 Compare A Handler
0x001E jmp TIM0_COMPB ; Timer0 Compare B Handler
0x0020 jmp TIM0_OVF ; Timer0 Overflow Handler
0x0022 jmp SPI_STC ; SPI Transfer Complete Handler
0x0024 jmp USART_RXC ; USART, RX Complete Handler
0x0026 jmp USART_UDRE ; USART, UDR Empty Handler
0x0028 jmp USART_TXC ; USART, TX Complete Handler
0x002A jmp ADC ; ADC Conversion Complete Handler
0x002C jmp EE_RDY ; EEPROM Ready Handler
0x002E jmp ANA_COMP ; Analog Comparator Handler
0x0030 jmp TWI ; 2-wire Serial Interface Handler
0x0032 jmp SPM_RDY ; Store Program Memory Ready Handler
;

e o avrstudio nao conhece ISR(PCINT11_vector);
« Última modificação: 06 de Maio de 2013, 00:16 por pmj_pedro »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.139
    • Tróniquices
Re: Atmega 328p reinicia-se sozinho
« Responder #8 em: 06 de Maio de 2013, 00:52 »
Não fui ver mas ok, faz sentido. Se calhar o que acontece em AVRs como o tiny26 é que não podes definir uma máscara para os pinos que queres ver gerar a interrupção, e nos mais recentes já podes.

Então dá uma olhada nas rotinas de envio pela UART. Se receberes muitas interrupções do RC5 e os teus "uart.send" encherem o buffer, o próximo char não vai encalhar tudo em "while(txb.count == BUF_SIZE);" no send? É que as intrs estão OFF porque já tás dentro de uma (do RC5) e o buffer só é vazado na intr da UART. Comenta os putc que tens na intr do PCINT0.
« Última modificação: 06 de Maio de 2013, 00:54 por Njay »

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #9 em: 06 de Maio de 2013, 00:56 »
Não fui ver mas ok, faz sentido. Se calhar o que acontece em AVRs como o tiny26 é que não podes definir uma máscara para os pinos que queres ver gerar a interrupção, e nos mais recentes já podes.

Então dá uma olhada nas rotinas de envio pela UART. Se receberes muitas interrupções do RC5 e os teus "uart.send" encherem o buffer, o próximo char não vai encalhar tudo em "while(txb.count == BUF_SIZE);" no send? É que as intrs estão OFF porque já tás dentro de uma (do RC5) e o buffer só é vazado na intr da UART. Comenta os putc que tens na intr do PCINT0.

Mt bem visto, vou ver isso com cuidado e depois logo digo alguma coisa

edit: removi os putc(); da interrupção, e continua igual, eles ja nao estavam la a fazer nd
Mas algumas o atmega parecia que encrava, pode ter haver com esse while tenho de ver isso bem

obgd
« Última modificação: 06 de Maio de 2013, 00:59 por pmj_pedro »

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.139
    • Tróniquices
Re: Atmega 328p reinicia-se sozinho
« Responder #10 em: 06 de Maio de 2013, 01:17 »
Não devias fazer cli/sei na micros(). Quando a chamas a partir da int do RC5, que é logo à cabeça, deixas as interrupções ligadas. Faz antes assim:

uint8_t  prevSREG = SREG;
cli();
...
SREG = prevSREG;

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #11 em: 06 de Maio de 2013, 23:43 »
Não devias fazer cli/sei na micros(). Quando a chamas a partir da int do RC5, que é logo à cabeça, deixas as interrupções ligadas. Faz antes assim:

uint8_t  prevSREG = SREG;
cli();
...
SREG = prevSREG;

poderias explicar pk se nao te importares, eu tinha assim como dizes, mas apos testar algumas vezes nao vi qualquer diferença

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #12 em: 06 de Maio de 2013, 23:48 »
Descobri o erro

o ficheiro uart.c
tinha a seguinte linha:
Código: [Seleccione]
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<TXCIE0)|(1<<UDRIE0);Estava a activar a interrupção TX, que nao estou a utilizar em lado nenhum
assim é que está correcto
Código: [Seleccione]
UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0)|(1<<UDRIE0);

Offline Njay

  • Mini Robot
  • *
  • Mensagens: 3.139
    • Tróniquices
Re: Atmega 328p reinicia-se sozinho
« Responder #13 em: 07 de Maio de 2013, 00:05 »
Não devias fazer cli/sei na micros(). Quando a chamas a partir da int do RC5, que é logo à cabeça, deixas as interrupções ligadas. Faz antes assim:

uint8_t  prevSREG = SREG;
cli();
...
SREG = prevSREG;

poderias explicar pk se nao te importares, eu tinha assim como dizes, mas apos testar algumas vezes nao vi qualquer diferença

Regra geral a razão é deixar as interruções como estavam à entrada, porque pode ser importante para quem chama a função.

No teu caso, a 1ª vez que a chamas dentro da intr do RC5 as intrs ficam ON. Tu chamas esta função várias vezes, e pode acontecer que entre 2 chamadas ocorram outras interrupções, que vão introduzir um atraso de tamanho desconhecido no teu código, por exemplo fazendo que algum check de tempo falhe.

Offline pmj_pedro

  • Mini Robot
  • *
  • Mensagens: 327
Re: Atmega 328p reinicia-se sozinho
« Responder #14 em: 07 de Maio de 2013, 20:00 »
Não devias fazer cli/sei na micros(). Quando a chamas a partir da int do RC5, que é logo à cabeça, deixas as interrupções ligadas. Faz antes assim:

uint8_t  prevSREG = SREG;
cli();
...
SREG = prevSREG;

poderias explicar pk se nao te importares, eu tinha assim como dizes, mas apos testar algumas vezes nao vi qualquer diferença

Regra geral a razão é deixar as interruções como estavam à entrada, porque pode ser importante para quem chama a função.

No teu caso, a 1ª vez que a chamas dentro da intr do RC5 as intrs ficam ON. Tu chamas esta função várias vezes, e pode acontecer que entre 2 chamadas ocorram outras interrupções, que vão introduzir um atraso de tamanho desconhecido no teu código, por exemplo fazendo que algum check de tempo falhe.

entendido

obrigado