LusoRobótica - Robótica em Português
Sistemas específicos => Arduino / AVR => Tópico iniciado por: vdr em 18 de Janeiro de 2013, 12:09
-
É o seguinte eu estou a tentar ligar dois atmegas 328p através de SPI. Mas acontece que o slave está ciclicamente a fazer reset, já li no avrfreaks que poderia ser por estar a fazer set ao pino SS depois de ter o SPI activo, mas não estou a fazer isso.
Basicamente o código abaixo deveria fazer o seguinte:
- Master envia continuamente a cada 1s um byte
- Slave deveria receber o byte enviado pelo interrupt e imprimi-lo no terminal.
#include <asf.h>
#include "lib.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <stdlib.h>
uint8_t master = 0;
uint8_t val = 10;
uint8_t res=0;
uint8_t debug = 1;
int main (void)
{
board_init();
USART_init();
if(master==1){
USART_putstring("\r\n\t************************************************ ");
USART_putstring("\r\n\t*** MASTER INIT ******************************** ");
SPI_init(1);
while(1){
res = SPI_Write(val);
USART_putstring("\r\n\t*** BYTE SENT : ");
USART_send(val);
USART_putstring("\n\r\n\t************************************************ ");
_delay_ms(1000);
}
}else{
SPI_init(0);
char string[8];
if(debug){
USART_putstring("\r\n\t* DEGUB ********");
USART_putstring("\r\n\t*** PORTB : ");
itoa(PINB, string, 10);
USART_putstring(string);
USART_putstring("\r\n\t*** SPCR : ");
itoa(SPCR, string, 10);
USART_putstring(string);
USART_putstring("\r\n\t****************");
}
USART_putstring("\r\n\t************************************************ ");
USART_putstring("\r\n\t*** SLAVE INIT ********************************* ");
sei();
while(1);
}
}
ISR(SPI_STC_vect)
{
char ch = SPDR;
USART_putstring("\r\n\t************************************************ ");
USART_putstring("\r\n\t***SLAVE RECEIVED: ");
USART_send(ch);
USART_putstring("\n\r\n\t************************************************ ");
}
//FUNÇÕES NA LIB.C
// SPI ------------------------------------------------------------------------------------------------------
#define MOSI PB3
#define MISO PB4
#define SCK PB5
#define SS PB2
//-----------------------------------------------------------------------------------------------------------
uint8_t SPI_Write(uint8_t data){
PORTB &= (~(1<<SS));
SPDR = data; //Start data transfer
while(!(SPSR & (1<<SPIF))); //Wait for the end of the transmission
PORTB |= (1<<SS);
return SPDR; //Return the received data
}
void SPI_init(uint8_t master){
if(master==1){
DDRB |= (1<<MOSI)|(1<<SCK)|(1<<SS); //MOSI, SCK, SS OUTPUTS
DDRB &= ~(1<<MISO); //MISO INPUT
PORTB |= (1<<SS); //SS START HIGH
//Enable SPI, Master mode
//MSB first
//CPOL=0
//CPHA=0
//SPI mode 0
//sck = F_CPU/16 = 1Mhz
//SPSR = (1<<SPI2X); //SPI clock x2
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<SPIE);
}else{
DDRB |= (1<<MISO);
DDRB &= ~(1<<MOSI);
DDRB &= ~(1<<SCK);
DDRB &= ~(1<<SS);
SPCR = (1<<SPE)|(1<<SPIE)|/*(1<<CPHA)|*/(0<<MSTR);
}
}
-
Podes invocar a USART_putstring dentro de uma interrupção? Assm à partida é a única dúvida que tenho.
-
Podes invocar a USART_putstring dentro de uma interrupção? Assm à partida é a única dúvida que tenho.
Li algures na AVRFreaks que não haveria problema, de qualquer modo comentei todas a linhas no interrupt de USART e o problema continua. Outra coisa que me parece muito estranha é quando leio o PORTB vem sempre com valores diferentes, mas também poderá ser devido ao reset.
-
Se faz reset assim que lhe envias um byte pode ser porque não estás a usar a interrupção correcta, já verificaste isso?
Fizeste enable do PRSPI?
-
Se faz reset assim que lhe envias um byte pode ser porque não estás a usar a interrupção correcta, já verificaste isso?
Fizeste enable do PRSPI?
Não tinha mexido nesse pino, pois ele esta por defeito a LOW logo não preciso de lhe mexer, e confirmei que o valor se mantem entre resets.
-
É por omissão e não por defeito. Então se eu fosse a ti corria o slave em simulação para ver o que acontece. É estranho estar a fazer reset nessa situação, isso parece-me problema puramente de sw, corrupção de memória ou coisa do género. Os pinos do SPI são usados para o ISP, vê lá se não estarás a ter algum conflito com isso.
Ah, também deves confirmar que tens os pinos bem ligados. Se houver um curto (2 pinos configurados como saída e ligados entre si) isso pode fazer baixar a tensão de alimentação e causar um reset no chip.
-
Obrigado Njay.
Se eu comentar o sei(), deixa de fazer reset, penso que o problema esteja na interrupção, mas não estou a ver onde.
-
Se fizeres isso deixas de ter interrupções (o sei() habilita as interrupções).
Deve haver aí algum problema com as ints, deve estar a ser chamada alguma int que não está instalada e quqnado isso acontece o sw volta para o endereço zero (reset). Por isso logo no inicio te perguntei se estarias a usar o ISR certo. Corre isso em simulação, vai dar logo para perceber o que se passa (carrega o .ELF no AVRstudio). Tás a indicar o CPU certo ao GCC?
-
Tás a indicar o CPU certo ao GCC?
Era aqui que estava o problema, por descuido meu tinha indicado o 329P em vez de 328..
Obrigado mais uma vez pela ajuda Njay!