AVR ATMega128 SPI-konstigheter
Postat: 23 mars 2008, 12:02:43
Jag har stött på ett underligt fenomen när jag försöker använda SPI-bussen i mega128 (ATMEGA128-16AI 0314). Problemet uppstår när jag försöker initiera AVRen som master med SPI-klockan delad med 128 gentemot systemklockan. Då hamnar AVRen i interruptvektorn direkt och överföringen fungerar ej!? Delar jag klockan med 64 eller 16 så funkar det klockrent som förväntat. Nån som har stött på något liknande? Jag har letat igenom hela internet från början till slut, tittat i errata från Atmel osv. Jag inser ju att detta inte kan vara en hårdvarubugg efter alla år mega128 har funnits. Vad gör jag för fel???
Här är min lilla testapplikation:
Här är min lilla testapplikation:
Kod: Markera allt
#define uint16 uint16_t
#define uint8 uint8_t
#define SET_LED() PORTE|=(1<<PE6)
#define CLR_LED() PORTE&=~(1<<PE6)
#define TGL_LED() PORTE^=(1<<PE6)
#define CS_ENABLE() PORTE|=(1<<PE0)
#define CS_DISABLE() PORTE&=~(1<<PE0)
#define DDR_SPI (DDRB)
#define DD_MOSI (PB2)
#define DD_SCK (PB1)
#define DD_CS (PE0)
#define AVR_SS (PB0)
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdbool.h>
ISR(SPI_STC_vect)
{
TGL_LED();
}
void delay_ms(uint16 delay);
void SPI_MasterInit(void);
void SPI_MasterTransmit(uint8 cData);
bool MAX5482_Send(uint16 WiperValue);
int main(void)
{
DDRE = 0xFF;
SREG |= (1<<SREG_I);
SPI_MasterInit();
while(1)
{
MAX5482_Send(0);
delay_ms(3000);
MAX5482_Send(125);
delay_ms(3000);
MAX5482_Send(250);
delay_ms(3000);
MAX5482_Send(512);
delay_ms(3000);
MAX5482_Send(1023);
while(1)
;
}
return 0;
}
void delay_ms(uint16 delay)
{
while(delay--)
_delay_ms(1);
}
void SPI_MasterInit(void)
{
// Set MOSI, SCK and SS output, all others input
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK) | (1<<AVR_SS);
PORTB |= (1<<AVR_SS);
// Enable SPI, Master, set clock rate fck/128 --- Detta fungerar inte!!!
SPCR = (1<<MSTR) | (1<<SPE) | (1<<SPIE) | (1<<SPR1) | (1<<SPR0) | (1<<CPOL);
// Enable SPI, Master, set clock rate fck/64 --- Detta fungerar
//SPCR = (1<<MSTR) | (1<<SPE) | (1<<SPIE) | (1<<SPR1) | (1<<CPOL);
}
void SPI_MasterTransmit(uint8 cData)
{
cData = ~cData;
// Start transmission
SPDR = cData;
// Wait for transmission complete
while(!(SPSR & (1<<SPIF)))
;
}
bool MAX5482_Send(uint16 WiperValue)
{
bool RetVal;
RetVal = true;
if(WiperValue>1023)
RetVal = false;
CS_ENABLE();
_delay_us(5);
SPI_MasterTransmit(0x00);
SPI_MasterTransmit((WiperValue>>2));
SPI_MasterTransmit((WiperValue<<8));
_delay_us(5);
CS_DISABLE();
_delay_ms(12);
return RetVal;
}