При загрузке значения в регистр данных SPI ведущего он сразу же начинает генерить тактовый сигнал на SCK и побитно выдвигать данные на вывод MOSI, который соединен с входами MOSI ведомых устройств. Ведомое устройство получит данные, только если на выводе SS присутствуетнизкий уровень. Т.о. мы можем подключить к шине SPI микроконтроллера несколько SPI устройств и используя дополнительные ножки МК выбирать конкретное устройство с которым мы хотим в данный момент работать. Вывод SS ведущего можно сконфигурировать как выход и использовать его как выходной контакт. Если же он сконфигурирован как вход, его необходимо подключить к шине питания. Если на выводе SS ведущего устройства появится низкий уровень, то онпереключится в режим ведомого.
Вообще, удобен этот интерфейс тем, что с ним очень просто работать. Давайте рассмотрим регистры МК, связанные с шиной SPI
SPDR - регистр данных, содержит посылаемый или принимаемый байт.
SPCR
Бит 7 - SPIE: разрешение прерываний. Прерывание генерится, если этот бит установлен и установлен бит глобального разрешения прерываний регистра SREG (6-й бит).
|
|
Бит 6 - SPE: включение SPI. Перед любыми действиями с SPI этот бит должен быть установлен в "1".
Бит 5 - DORD: порядок передачи данных. Если этот бит установлен в "1" то младший бит данных передается первым. Если этот бит сброшен в "0" - старший бит данных передается первым.
Бит 4 - MSTR: выбор режима работы. Если установлен в "1", то выбран режим ведущего, если в "0" - режим ведомого. Если SS сконфигурирован как вход и на него подан низкий уровень, в то время как бит MSTR установлен в "1", тогда этот бит сбросится в "0" и бит SPIF регистра SPSR (см. ниже) установится в "1".
Бит 3 - CPOL: полярность тактового сигнала. "0" - во время ожидания на SCK присутствует низкий уровень. "1" - во время ожидания на SCK присутствует высокий уровень.
Бит 2 - CPHA: фаза тактового сигнала. Если этот бит установлен в "1", то данные считываются по спадающему фронту SCK, если в "0" - по нарастающему фронту SCK.
SPSR
Бит 7 - SPIF: флаг прерывания. Устанавливается по завершении передачи. Прерывание генерится если установлен бит SPIE регистра SPCR и бит I регистра SREG.
Бит 6 - WCOL: флаг коллизий записи. Устанавливается в "1" при попытке записи в регистр SPDR до окончания передачи.
Бит 0 - SPI2X: бит двойной скорости SPI. Если SPI сконфигурирован как ведущий, тогда мы можем работать с двойной частотой. Но если SPI сконфигурирован как ведомый, то мы не можем расчитывать на двойную скорость работы SPI.
Код программы разработки драйвера MAX5400 в трех частях.
//-------------------------1.c---------------------------
// Target: M16
// Crystal: 10.000Mhz
//---------------------------------------------------------------------
#include <iom16v.h>
#include <macros.h>
#include <delay.h>
#include "def.h"
#include "init.h"
|
|
void main(void)
{
init_devices(); //Ініціалізація мікроконтролера
//--------------------------
while (1) //Головний цикл
{
Data1270=DRVstatusR1W0 (0, AC, 0x1FFABC);
}
}
//---------------------------def.h----------------------
#define DDR_SPI DDRB
#define DD_MOSI 3
#define DD_MISO 4
#define DD_SCK 5
#define SPE 6
#define MSTR 4
#define SPR0 0
#define SPIF 7
//spi pins
#define CS (1<<4)
#define DIN (1<<5)
#define SCK (1<<7)
//---------------------------------------------------------------------------
//-------------------------init.h-------------------------
void port_init(void)
{
PORTA = 0x00;
DDRA = 0xFF;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00; //m103 output only
DDRC = 0xFF;
PORTD = 0x00;
DDRD = 0x00;
}
//---------------------------delay.h-----------------------
void DelayMcs (unsigned int t_mcs)
{ while (t_mcs--)
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
}
//--------------------------------------------------------------------------
//Функция задержки на "t_ms" милисекунд
void DelayMs (unsigned int t_ms)
{ while (t_ms--)
{
DelayMcs(1000);
}
}
//Функция задержки на "t_s" секунд
void DelayS (unsigned int t_s)
{ while (t_s--)
{
DelayMs(1000);
}
}
#define DDR_SPI DDRB
#define DD_MOSI 3
#define DD_MISO 4
#define DD_SCK 5
#define SPE 6
#define MSTR 4
#define SPR0 0
#define SPIF 7
void SPI_MasterInit()
{
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);//настраиваем на выход
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);//вкл SPI, ведущий, частота fck/16
}
//функция передачи байта
void SPI_MasterTransmit(char cData)
{
SPDR = cData;//начинаем передачу
while(!(SPSR & (1<<SPIF)));//ждем пока передача завершится
}