реклама на сайте
подробности

 
 
> Не работает SPI., на at91sam7x256
Dars
сообщение Oct 23 2008, 15:51
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 238
Регистрация: 11-08-05
Пользователь №: 7 557



Ситуация такова. К AT91SAM7X256 подключены два датчика. Акселерометр ADIS16201 и гироскоп ADIS16255. Акселерометр 3-х вольтовый(5 вольт выдерживает, раньше к авр 5вольтовому был подключен), гироскоп 5-вольтовый(но 3.3В понимает) ну и SAM7X 3-х вольтовый. Подтяжки аппаратные есть только на чип селектах датчиков. чип селект акселерометра подтянут к 3.3В, чип селект гироскопа к 5В. SPCK,MOSI,MISO никаких подтяжек не имеют. при работе на всех ножках (CS,SPCK,MOSI,MISO) напряжение 3.3В. кабель длинной ~40см ну и плюс какое-то(~10см) расстояние на тоненькие(0.15мм) дорожки на самой плате. Это, что касается железной части SPI. Датчики подключены к SPI0. Чип селекты NPCS0..3 не используются! В качестве CS используются две ножки PB0 и PB1. Дергаются программно. Сам интерфейс вроде запускается, клок идет. какие то данные на MISO и MOSI есть. но читается фигня!
Привожу код работы с SPI0. Посмотри пожалуйста, не могу понять где ошибка. Датчики общаются по 16бит SPI. Чтобы с них что-то прочитать нужно сначала отправить адрес регистра который нужно прочитать, датчик вернет результат предыдущего запроса. потом еще раз отправить что-нибудь и датчик тока датчик вернет то, что мы просили у него в первый раз. сама логика работы с акселерометром прописана на стр15 http://www.analog.com/static/imported-file...s/ADIS16201.pdf

Выкладываю свой код. Здесь я пытаюсь прочитать по адресу 0x02 напряжение питания акселерометра. он мне возвращает 16 бит, из них 12 само напряжение в binary format.далее оно умножается на 1.22мВ и получается напр питания. у меня по этому коду, читается через раз. иногда 0, иногда ерунда какая-то. показания зависят от положения датчика! если его крутить то данные меняются, если пытаться читать из других регистров то результат примерно такой же. В общем help.gif
я думаю ошибка где то в самом коде работы с 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;
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aaarrr
сообщение Oct 24 2008, 14:08
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Хорошо, а что говорит осциллограф? И Вы не пробовали писать в регистры?
Go to the top of the page
 
+Quote Post
Dars
сообщение Oct 24 2008, 15:22
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 238
Регистрация: 11-08-05
Пользователь №: 7 557



Цитата(aaarrr @ Oct 24 2008, 18:08) *
Хорошо, а что говорит осциллограф? И Вы не пробовали писать в регистры?


Осциллограф в наличии только старый GOS-310. Поэтому я не могу проверить, что конкретно передается и принимается. но клок идет. чип селект дергается. на линиях MOSI и MISO какие то данные есть.
но принимается ерунда. самое интересное что если посмотреть буфер POWER_SUPPLY то там будут 0. нажать ресет, перезапустить программу и посмотреть еще раз - какие то цифры. потом опять нажать на ресет и посмотреть, что пришло - нули будут.и так постоянно. один раз нули.другой данные.

что значит писать в регистры?
я даже не могу предположить где может быть ошибка...сейчас посмотрел по осциллу на линии MISO был уровень в ~два раза меньше чем 3.3В. хотя pull up включен. допаял резистор - результат то же самый.

Хм. сейчас посмотрел на буфер POWER_SUPPLY там всегда поле PCS = 0!!!. такое может быть только если проц работает как слэйв. иначе там должен быть номер текущего чип селекта. то есть там должно быть записано E.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Oct 24 2008, 15:31
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Dars @ Oct 24 2008, 19:22) *
что значит писать в регистры?

Насколько я понимаю, у ADIS16201 есть регистры для записи, можно записать-прочитать-сравнить.

Цитата(Dars @ Oct 24 2008, 19:22) *
Хм. сейчас посмотрел на буфер POWER_SUPPLY там всегда поле PCS = 0!!!. такое может быть только если проц работает как слэйв. иначе там должен быть номер текущего чип селекта. то есть там должно быть записано E.

POWER_SUPPLY у Вас float.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th August 2025 - 06:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01419 секунд с 7
ELECTRONIX ©2004-2016