Привожу код работы с SPI0. Посмотри пожалуйста, не могу понять где ошибка. Датчики общаются по 16бит SPI. Чтобы с них что-то прочитать нужно сначала отправить адрес регистра который нужно прочитать, датчик вернет результат предыдущего запроса. потом еще раз отправить что-нибудь и датчик тока датчик вернет то, что мы просили у него в первый раз. сама логика работы с акселерометром прописана на стр15 http://www.analog.com/static/imported-file...s/ADIS16201.pdf
Выкладываю свой код. Здесь я пытаюсь прочитать по адресу 0x02 напряжение питания акселерометра. он мне возвращает 16 бит, из них 12 само напряжение в binary format.далее оно умножается на 1.22мВ и получается напр питания. у меня по этому коду, читается через раз. иногда 0, иногда ерунда какая-то. показания зависят от положения датчика! если его крутить то данные меняются, если пытаться читать из других регистров то результат примерно такой же. В общем

я думаю ошибка где то в самом коде работы с SPI.раньше это пара датчиков отлично работала с 5В авр.
Код
#define SPI_PCS(npcs) ((~(1 << npcs) & 0xF) << 16)
#define SCBR(_scbr) (_scbr<<8)
//функция инициализации SPI
void SPI0_Init(void);
//отправка 16 бит данных по SPI
void SPI0_Send_data(unsigned short data);
//функция принимает 16 бит данных по SPI
unsigned short SPI0_Get_data(void);
//Включение чип селекта акселлерометра PB0=0,
//выключение чип селекта гироскопа PB1=1
void ACCE_ON(void);
//Включение чип селекта гироскопа PB1=0,
//выключение чип селекта акселлерометра PB0=0
void GYRO_ON(void);
//Выключение и гироскопа и акселлерометра PB0=1,PB1=1;
void SENSORS_OFF(void);
int main()
{
//Умножаем 12бит данных из регистра POWER SUPPLY на k = 1.22mV и получаем
//напряжение питания акселлерометра
const float k = 1.22;
//адрес по которому читаем данные
unsigned short addr = 0x02;
unsigned short dummy = 0;
unsigned short result;
float POWER_SUPPLY[100]=0;
//Инициализируем SPI
SPI0_Init();
//Будем читать с акселлерометра регистр POWER SUPPLY по адресу 0x02.
while(1)
{
//Включаем акселлерометр
ACCE_ON();
//Отправляем в акселлерометр адрес регистра который надо прочитать
SPI0_Send_data(addr);
//Читаем результат основанный на предыдущей команде и игнорируем его
dummy = SPI0_Get_data();
//После того как отправили адрес по которому хотим прочитать данные. нужно
//совершить вторую итерацию чтения, по любому адресу. и акселлерометр выдаст нам
//данные запрошенные в первой итерации(т.е по адресу addr)
//Вторая итерация чтения
//Передергиваем чип селект для начала второй итерации чтения
//Выключаем датчик
SENSORS_OFF();
//Включаем чип селект акселлерометра
ACCE_ON();
//Отправляем в акселлерометр любое число. не имеет значения какое
SPI0_Send_data(addr);
//В ответ получаем то что лежит по адресу который отправили в первой итерации
//чтения
result= SPI0_Get_data();
//Выключаем акселлерометр
SENSORS_OFF();
//Значащие данные в result - 12бит. затиравем остальное нулями
result &= 0x0FFF;
//тут получаем ответ
POWER_SUPPLY = result *k;
}
return 0;
}
void SPI0_Init(void)
{
//--------Настройка чип селектов акселлерометра и гироскопа-----------------//
//аппаратные чип селекты не используются для управления гироскопом и
//акселлерометром. для активация/деактивации датчиков используются линии
//PIO. PB0-чип селект акселлерометра. PB1-чип селект гироскопа.
//Включение тактирования PIOB
AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_PIOB;
//Инициализация PB0 и PB1
//включение PB0,PB1 как линии ввода,вывода
AT91C_BASE_PIOB->PIO_PER |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//отключение подтягивающих к плюсу питания резисторов
AT91C_BASE_PIOB->PIO_PPUDR |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//настраиваем PB0 и PB1 на выход
AT91C_BASE_PIOB->PIO_OER |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//разрешаем синхронный вывод данных на PB0 и PB1
AT91C_BASE_PIOB->PIO_OWER |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//выключаем оба датчика. PB0=1 и PB1=1
SENSORS_OFF();
//--------------------------------------------------------------------------//
//----------------------Настройка SPI0--------------------------------------//
//Отключаем PIO от управления MOSI,SCK,MISO,NPCS0.NPCS0-не используется!
AT91C_BASE_PIOA->PIO_PDR |= AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO |
AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK;
//Отключаем подтяжки на линиях MISO,MOSI,SPCK
AT91C_BASE_PIOA->PIO_PPUDR |= AT91C_PA16_SPI0_MISO |
AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK;
//конфигурируем MOSI,MISO,SPCK,NPCS0 как перифирию A
AT91C_BASE_PIOA->PIO_ASR |= AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO |
AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK;
//Включаем тактирование SPI0
AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_SPI0;
//отключение SPI и сброс SPI
AT91C_BASE_SPI0->SPI_CR |= AT91C_SPI_SPIDIS | AT91C_SPI_SWRST;
//SPI в режиме Master, фиксированная перефирия,тактирование от MCK
AT91C_BASE_SPI0->SPI_MR |= AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | SPI_PCS(0);
//CPOL=1,PHASE=1,16 битный режим, SPCKHMhz/255 = 188,2Khz
AT91C_BASE_SPI0->SPI_CSR[0] |= AT91C_SPI_CPOL | AT91C_SPI_NCPHA |
AT91C_SPI_BITS_16 | SCBR(0xFF);
//SPI enable
AT91C_BASE_SPI0->SPI_CR |= AT91C_SPI_SPIEN;
//--------------------------------------------------------------------------//
}
void SPI0_Send_data(unsigned short data)
{
//Ждем когда TDRE и внутреннее сдвигающие устройство станут пустыми
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
//копируем данные в регистр передачи TDR
AT91C_BASE_SPI0->SPI_TDR = data | SPI_PCS(0) | AT91C_SPI_LASTXFER;
//Ждем пока данные скопируются в сдвигающий реситр
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0);
}
unsigned short SPI0_Get_data(void)
{
//читаем данные
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_RDRF) == 0);
return AT91C_BASE_SPI0->SPI_RDR & 0xFFFF;
}
//Включаем акселлерометр PB0=0, PB1=1
void ACCE_ON(void)
{
AT91C_BASE_PIOB->PIO_ODSR = (AT91C_PIO_PB1 & ~AT91C_PIO_PB0);
}
//Включаем гироскоп PB0=1, PB1=0
void GYRO_ON(void)
{
AT91C_BASE_PIOB->PIO_ODSR = (AT91C_PIO_PB0 & ~AT91C_PIO_PB1);
}
void SENSORS_OFF(void)
{
AT91C_BASE_PIOB->PIO_ODSR |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
}
#define SCBR(_scbr) (_scbr<<8)
//функция инициализации SPI
void SPI0_Init(void);
//отправка 16 бит данных по SPI
void SPI0_Send_data(unsigned short data);
//функция принимает 16 бит данных по SPI
unsigned short SPI0_Get_data(void);
//Включение чип селекта акселлерометра PB0=0,
//выключение чип селекта гироскопа PB1=1
void ACCE_ON(void);
//Включение чип селекта гироскопа PB1=0,
//выключение чип селекта акселлерометра PB0=0
void GYRO_ON(void);
//Выключение и гироскопа и акселлерометра PB0=1,PB1=1;
void SENSORS_OFF(void);
int main()
{
//Умножаем 12бит данных из регистра POWER SUPPLY на k = 1.22mV и получаем
//напряжение питания акселлерометра
const float k = 1.22;
//адрес по которому читаем данные
unsigned short addr = 0x02;
unsigned short dummy = 0;
unsigned short result;
float POWER_SUPPLY[100]=0;
//Инициализируем SPI
SPI0_Init();
//Будем читать с акселлерометра регистр POWER SUPPLY по адресу 0x02.
while(1)
{
//Включаем акселлерометр
ACCE_ON();
//Отправляем в акселлерометр адрес регистра который надо прочитать
SPI0_Send_data(addr);
//Читаем результат основанный на предыдущей команде и игнорируем его
dummy = SPI0_Get_data();
//После того как отправили адрес по которому хотим прочитать данные. нужно
//совершить вторую итерацию чтения, по любому адресу. и акселлерометр выдаст нам
//данные запрошенные в первой итерации(т.е по адресу addr)
//Вторая итерация чтения
//Передергиваем чип селект для начала второй итерации чтения
//Выключаем датчик
SENSORS_OFF();
//Включаем чип селект акселлерометра
ACCE_ON();
//Отправляем в акселлерометр любое число. не имеет значения какое
SPI0_Send_data(addr);
//В ответ получаем то что лежит по адресу который отправили в первой итерации
//чтения
result= SPI0_Get_data();
//Выключаем акселлерометр
SENSORS_OFF();
//Значащие данные в result - 12бит. затиравем остальное нулями
result &= 0x0FFF;
//тут получаем ответ
POWER_SUPPLY = result *k;
}
return 0;
}
void SPI0_Init(void)
{
//--------Настройка чип селектов акселлерометра и гироскопа-----------------//
//аппаратные чип селекты не используются для управления гироскопом и
//акселлерометром. для активация/деактивации датчиков используются линии
//PIO. PB0-чип селект акселлерометра. PB1-чип селект гироскопа.
//Включение тактирования PIOB
AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_PIOB;
//Инициализация PB0 и PB1
//включение PB0,PB1 как линии ввода,вывода
AT91C_BASE_PIOB->PIO_PER |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//отключение подтягивающих к плюсу питания резисторов
AT91C_BASE_PIOB->PIO_PPUDR |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//настраиваем PB0 и PB1 на выход
AT91C_BASE_PIOB->PIO_OER |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//разрешаем синхронный вывод данных на PB0 и PB1
AT91C_BASE_PIOB->PIO_OWER |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
//выключаем оба датчика. PB0=1 и PB1=1
SENSORS_OFF();
//--------------------------------------------------------------------------//
//----------------------Настройка SPI0--------------------------------------//
//Отключаем PIO от управления MOSI,SCK,MISO,NPCS0.NPCS0-не используется!
AT91C_BASE_PIOA->PIO_PDR |= AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO |
AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK;
//Отключаем подтяжки на линиях MISO,MOSI,SPCK
AT91C_BASE_PIOA->PIO_PPUDR |= AT91C_PA16_SPI0_MISO |
AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK;
//конфигурируем MOSI,MISO,SPCK,NPCS0 как перифирию A
AT91C_BASE_PIOA->PIO_ASR |= AT91C_PA12_SPI0_NPCS0 | AT91C_PA16_SPI0_MISO |
AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK;
//Включаем тактирование SPI0
AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_SPI0;
//отключение SPI и сброс SPI
AT91C_BASE_SPI0->SPI_CR |= AT91C_SPI_SPIDIS | AT91C_SPI_SWRST;
//SPI в режиме Master, фиксированная перефирия,тактирование от MCK
AT91C_BASE_SPI0->SPI_MR |= AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | SPI_PCS(0);
//CPOL=1,PHASE=1,16 битный режим, SPCKHMhz/255 = 188,2Khz
AT91C_BASE_SPI0->SPI_CSR[0] |= AT91C_SPI_CPOL | AT91C_SPI_NCPHA |
AT91C_SPI_BITS_16 | SCBR(0xFF);
//SPI enable
AT91C_BASE_SPI0->SPI_CR |= AT91C_SPI_SPIEN;
//--------------------------------------------------------------------------//
}
void SPI0_Send_data(unsigned short data)
{
//Ждем когда TDRE и внутреннее сдвигающие устройство станут пустыми
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
//копируем данные в регистр передачи TDR
AT91C_BASE_SPI0->SPI_TDR = data | SPI_PCS(0) | AT91C_SPI_LASTXFER;
//Ждем пока данные скопируются в сдвигающий реситр
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_TDRE) == 0);
}
unsigned short SPI0_Get_data(void)
{
//читаем данные
while ((AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_RDRF) == 0);
return AT91C_BASE_SPI0->SPI_RDR & 0xFFFF;
}
//Включаем акселлерометр PB0=0, PB1=1
void ACCE_ON(void)
{
AT91C_BASE_PIOB->PIO_ODSR = (AT91C_PIO_PB1 & ~AT91C_PIO_PB0);
}
//Включаем гироскоп PB0=1, PB1=0
void GYRO_ON(void)
{
AT91C_BASE_PIOB->PIO_ODSR = (AT91C_PIO_PB0 & ~AT91C_PIO_PB1);
}
void SENSORS_OFF(void)
{
AT91C_BASE_PIOB->PIO_ODSR |= AT91C_PIO_PB0 | AT91C_PIO_PB1;
}