collapse

* Links de Robótica

* Posts Recentes

Palavras Cruzadas por Hugu
[Hoje às 18:07]


[Projecto] Bomba Airsoft por jm_araujo
[23 de Setembro de 2017, 16:54]


Apresentação por Tech_JA
[23 de Setembro de 2017, 09:19]


Medir Agua que está no Poço por filjoa
[21 de Setembro de 2017, 20:58]


URGENTE - display de 7 segmentos com backpack por helderjsd
[20 de Setembro de 2017, 12:30]


Preços e fabricantes de pcb por Sérgio_Sena
[19 de Setembro de 2017, 10:20]


Isaac Asimov - I, Robot por senso
[18 de Setembro de 2017, 03:41]


ic SL440 da Plessey? por senso
[16 de Setembro de 2017, 13:11]


Compra Colectiva RS-Amidata por brunus
[15 de Setembro de 2017, 22:31]


Ideias para construir um quadrúpede simples por zordlyon
[15 de Setembro de 2017, 10:18]

Autor Tópico: [Problema] Atmega 328P - SPI  (Lida 2217 vezes)

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

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.726
[Problema] Atmega 328P - SPI
« em: 10 de Abril de 2011, 20:57 »
Estou a tentar colocar o SPI do atmega328p a funcionar no entanto não está facil, tenho este código, as funções foram retiradas da datasheet.

Código: [Seleccione]
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 16000000UL
#include <util/delay.h>

#include "bit_tools.h"

#define DDR_SPI     DDRB

#define DD_SS       DDB2
#define DD_MOSI     DDB3
#define DD_MISO     DDB4
#define DD_SCK      DDB5

void SPI_MasterInit(void){
  /* Set MOSI and SCK output, all others input */
  DDR_SPI = (1<<DD_SS)|(1<<DD_MOSI)|(1<<DD_SCK);
  /* Enable SPI, Master, set clock rate fck/16 */
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(char cData){
  /* Start transmission */
  SPDR = cData;
  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)))
    ;
}

int main(void) {
 
  SPI_MasterInit();
  sei();
 
  DDRB |= (1<<PB1);
  bit_clear(PORTB,PB1);
  bit_set(PORTB,PB2);
  while(1){
    bit_clear(PORTB,PB1);
    bit_set(PORTB,PB1);
    bit_clear(PORTB,PB1);
    bit_set(PORTB,PB1);
    bit_clear(PORTB,PB1);
    bit_set(PORTB,PB1);
    bit_clear(PORTB,PB1);
    SPI_MasterTransmit(0x0F);
    _delay_ms(1);
  }

  return 0;
}

O que parece estar a acontecer é que ele fica parado dentro da função de SPI_MasterTransmit, eu neste momento não tenho nenhum slave, será por isso?! Só queria mesmo configurar e ver os sinais.

Estou a ver os sinais num logic analyser.

EDIT1:
Ás vezes a comunicação é feita mas não o SS não muda.
« Última modificação: 10 de Abril de 2011, 21:48 por metRo_ »

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: [Problema] Atmega 328P - SPI
« Responder #1 em: 10 de Abril de 2011, 22:05 »
Já estou meio enferrujado, mas não tens de fazer isso manualmente?

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.726
Re: [Problema] Atmega 328P - SPI
« Responder #2 em: 10 de Abril de 2011, 22:09 »
Será?! :s

Offline Tyran

  • Mini Robot
  • *
  • Mensagens: 293
Re: [Problema] Atmega 328P - SPI
« Responder #3 em: 10 de Abril de 2011, 22:13 »
Axo que sim, senão imagina como era se tivesses vários slaves... já para não dizer que podias ter algum tempo de espera após activar o chip select do slave... embora também pudesse dar para usar os dois modos por isso vê melhor no datasheet que ele é que manda :)

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.390
  • Helpdesk do sitio
Re: [Problema] Atmega 328P - SPI
« Responder #4 em: 11 de Abril de 2011, 02:34 »
Não estive a comparar os códigos com atenção mas eu uso isto:

Código: [Seleccione]
#define MOSI PB3

#define MISO PB4

#define SCK PB5

#define SS PB2

#define ADDR 0x06 //Address/configuration byte for the spi ADC

#define DUMMY 0x00 //Dummy byte, because in each SPI comm we must send data

#define DATA_MASK 0x0F //Mask used to extract the first 4 bits that arrive in the second byte received

void SPI_init(void){



DDRB |= ((1<<MOSI)|(1<<SCK)|(1<<SS)); //Mosi, sck and ss are outputs

DDRB &= (~(1<<MISO)); //Miso is input

PORTB |= (1<<SS); //Start with SS at 1 (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));



}



uint8_t SPI_Write(uint8_t data){



SPDR = data; //Start data transfer

while(!(SPSR & (1<<SPIF))); //Wait for the end of the transmission



return SPDR; //Return the received data



}

Isto é para falar com um ADC 12 bits da Microchip de 8 canais, um MCPxx08 qualquer, o SPI_Write escreve e lê, pois o SPI envia e recebe os dados de uma só vez.
Avr fanboy

StarRider

  • Visitante
Re: [Problema] Atmega 328P - SPI
« Responder #5 em: 11 de Abril de 2011, 19:24 »
Boas,

Quando a SPI está a funcionar em modo Master o pin SS pode estar em duas situações:
- Se SS é configurado como output então este pin pode ser usado como um pin IO normal e o seu estado não altera a funcionalidade da interface SPI MASTER.
- Se SS for configurado como input então deve ser mentido com um nível high, e for levado a low a interface SPI interpreta isso como um pedido de um outro Master e muda para o modo Slave.

Resumindo, em modo Master SS deve ser configurado como output e pode (ou não) ser usado para seleccionar um Slave devendo para ir ser levado a high programaticamente

Abraços,
PA
« Última modificação: 12 de Abril de 2011, 02:28 por StarRider »

Offline Capeleiro

  • Mini Robot
  • *
  • Mensagens: 127
Re: [Problema] Atmega 328P - SPI
« Responder #6 em: 11 de Abril de 2011, 20:52 »
Estou a usar o SPI num projecto e dessa mesma forma, talvez o problema seja mesmo por não haver um slave...

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.726
Re: [Problema] Atmega 328P - SPI
« Responder #7 em: 12 de Abril de 2011, 22:50 »
@senso Tu no main não mexes mais no SS!?

Quando a SPI está a funcionar em modo Master o pin SS pode estar em duas situações:
- Se SS é configurado como output então este pin pode ser usado como um pin IO normal e o seu estado não altera a funcionalidade da interface SPI MASTER.
- Se SS for configurado como input então deve ser mentido com um nível high, e for levado a low a interface SPI interpreta isso como um pedido de um outro Master e muda para o modo Slave.

Resumindo, em modo Master SS deve ser configurado como output e pode (ou não) ser usado para seleccionar um Slave devendo para ir ser levado a high programaticamente

Abraços,
PA
Só para ter a certeza se o meu atmega está a funcionar como master tenho que ser eu a comandar o SS!?

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.390
  • Helpdesk do sitio
Re: [Problema] Atmega 328P - SPI
« Responder #8 em: 12 de Abril de 2011, 22:59 »
No main não, na função que lê o ADC sim, esqueci-me de meter essa aqui:

Código: [Seleccione]
uint16_t Read_ADC(uint8_t channel){

uint8_t upper_addr, lower_addr, upper_data, lower_data;



if(channel > 3){

upper_addr = ADDR | 0x01; }

else{

upper_addr = ADDR; }

lower_addr = channel<<6;



PORTB &= (~(1<<SS)); //Put SS at 0 (LOW), to start the data transfer



SPI_Write(upper_addr);

upper_data = SPI_Write(lower_addr);

lower_data = SPI_Write(DUMMY);

upper_data &= DATA_MASK;



PORTB |= (1<<SS); //Puts SS at 1 (HIGH), because we already stoped all the data transfer



return ((upper_data<<8)|lower_data);





}

Avr fanboy

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.726
Re: [Problema] Atmega 328P - SPI
« Responder #9 em: 13 de Abril de 2011, 00:11 »
Parece que faltava mexer no ss para isto funcionar :)
Agora o meu problema é converter os sinais de 5v para 3.3v mas acho que ja há aqui um tópico sobre isso, vou procurar, para ja o que noto é que com divisor de tensão, a onda de clock não é tão boa!

EDIT1:
Independentemente do valor que colocar em SPR a velocidade do clock é a mesma :s
Código: [Seleccione]
#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 16000000UL
#include <util/delay.h>
#include "bit_tools.h"

#define MOSI PB3
#define MISO PB4
#define SCK PB5
#define SS PB2

void SPI_init(void){

DDRB |= ((1<<MOSI)|(1<<SCK)|(1<<SS)); //Mosi, sck and ss are outputs
DDRB &= (~(1<<MISO)); //Miso is input
PORTB |= (1<<SS); //Start with SS at 1 (HIGH)

//MSTR: Enable SPI, Master mode
//SPIE: SPI Interrupt Enabl
//(1<SPR1)|(1<SPR0) : FOSC/128
SPCR = ((1<<SPE)|(1<<MSTR)|(1<SPR1)|(1<SPR0));
}

uint8_t SPI_Write(uint8_t data){
SPDR = data; //Start data transfer
while(!(SPSR & (1<<SPIF))); //Wait for the end of the transmission
return SPDR; //Return the received data
}

int main(void) {
 
  SPI_init();
  sei();
 
  while(1){
    PORTB &= (~(1<<SS)); //Put SS at 0 (LOW), to start the data transfer
    SPI_Write(0x01);
    SPI_Write(0x41);
    SPI_Write(0x05);
    SPI_Write(0xff);
    PORTB |= (1<<SS); //Puts SS at 1 (HIGH), because we already stoped all the data transfer
    _delay_ms(100);
   
  }

  return 0;
}

EDIT2
Tem aqui as imagens:
Sem divisor:


Com divisor:
« Última modificação: 13 de Abril de 2011, 00:26 por metRo_ »

StarRider

  • Visitante
Re: [Problema] Atmega 328P - SPI
« Responder #10 em: 25 de Abril de 2011, 09:15 »
Boas,

metRo_, que LigicSniffer é esse que estás a usar ?

Abraços,
PA

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.726
Re: [Problema] Atmega 328P - SPI
« Responder #11 em: 25 de Abril de 2011, 10:08 »
Boas,
metRo_, que LigicSniffer é esse que estás a usar ?
Abraços,
PA

Olá, é o Open Logic Sniffer: http://dangerousprototypes.com/open-logic-sniffer/