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

 
 
> Не работает 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



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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 07:44
Рейтинг@Mail.ru


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