Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не работает SPI.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Dars
Ситуация такова. К 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;
}
aaarrr
Цитата(Dars @ Oct 23 2008, 19:51) *
Код
  //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);

NCPHA нужно сбросить - у него обратная полярность по сравнению с AVR'ом.

Цитата(Dars @ Oct 23 2008, 19:51) *
Код
AT91C_BASE_PMC->PMC_PCER |= 1 << AT91C_ID_PIOB;

Не нужно читать write-only регистры.

Цитата(Dars @ Oct 23 2008, 19:51) *
Код
void SPI0_Send_data(unsigned short data)
unsigned short SPI0_Get_data(void)

Обе эти процедуры можно заменить на одну такую:
Код
unsigned int spi0_trans(unsigned int data)
{
    AT91C_BASE_SPI0->SPI_TDR = data;
    while(!(AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_RDRF));
    return (AT91C_BASE_SPI0->SPI_RDR);
}

А в случае повышенных требований скорости еще и заинлайнить.

Цитата(Dars @ Oct 23 2008, 19:51) *
Код
AT91C_BASE_PIOB->PIO_ODSR = (AT91C_PIO_PB1 & ~AT91C_PIO_PB0);

Зачем так сложно? Не проще ли написать:
Код
AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB1;


P.S. Спасибо, что не пользуетесь атмеловской библиотекой.
Сергей Борщ
Цитата(aaarrr @ Oct 23 2008, 20:57) *
Зачем так сложно? Не проще ли написать:
Код
AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB1;
А если есть желание отметить, что значение PB0 не забыто, а в него намеренно записан ноль, то можно так:
Код
AT91C_BASE_PIOB->PIO_ODSR = (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0);
Цитата(aaarrr @ Oct 23 2008, 20:57) *
P.S. Спасибо, что не пользуетесь атмеловской библиотекой.
Присоединяюсь.
Dars
Подправил немного код и железо. все равно не работает зараза! пятый день уже сижу smile3046.gif
Сделал следующее. выпаял подтягивающий к 5В резистор на линии CS гироскопа. включил внутренние подтягивающие резисторы на SPCK,MISO,MOSI, CS гироскопа. Исправил все места где читались регистры только для записи. исправил процедуру передачи данных по SPI.сбросил NCPHA. Все. больше не знаю, что делать. ставлю брэйкпоинт на while(1), смотрю, что лежит в POWER_SUPPLY. при первом запуске там все 0. жму ресет, запускаю еще раз, там в основном число 90мв, иногда 246мв,иногда 0. help.gif
Код
#include <global.h>

#define SPI_PCS(npcs)       ((~(1 << npcs) & 0xF) << 16)
#define SCBR(_scbr)         (_scbr<<8)

//функция иннициализация SPI
void SPI0_Init(void);
//Фунцкия передачи данных по SPI
unsigned int SPI0_trans(unsigned int data);
//Включение чип селекта акселлерометра 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 на 1.22mV и получаем
  //напряжение питания акселлерометра
  const float k = 1.22;
  unsigned int addr = 0x0200;
  unsigned int dummy = 0;
  unsigned int result;
  unsigned int i=0;
  float POWER_SUPPLY[100]=0;
  //Инициализируем SPI
  SPI0_Init();
  //Будем читать с акселлерометра регистр POWER SUPPLY по адресу 0x02.
  for(i=0;i<100;i++)
  {
    //Включаем акселлерометр    
    ACCE_ON();
    //Отправляем в акселлерометр адрес регистра который надо прочитать
    dummy = SPI0_trans(addr);
    //После того как отправили адрес по которому хотим прочитать данные. нужно
    //совершить вторую итерацию чтения, по любому адресу. и акселлерометр выдаст нам
    //данные запрошенные в первой итерации(т.е по адресу addr)
  
    //Вторая итерация чтения
    //Передергиваем чип селект для начала второй итерации чтения
    //Выключаем датчик
    SENSORS_OFF();    
    //Включаем чип селект акселлерометра
    ACCE_ON();    
    //Отправляем в акселлерометр любое число. не имеет значения какое
    //В ответ получаем то что лежит по адресу который отправили в первой итерации
    //чтения
    result = SPI0_trans(addr);
    //Выключаем акселлерометр
    SENSORS_OFF();
    //Значащие данные в result - 12бит. затиравем остальное нулями
    result &= 0xFFF;
    POWER_SUPPLY[i] = result *k;
    }
  
  while(1);
    
  return 0;
}

void SPI0_Init(void)
{
  //аппаратные чип селекты не используются для управления гироскопом и
  //акселлерометром. для активация/деактивации датчиков используются линии
  //PIO. PB0-чип селект акселлерометра. PB1-чип селект гироскопа.
  
  //Включение тактирования PIOB и SPI0
  AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOB) | (1 << AT91C_ID_SPI0);
  //Инициализация PB0 и PB1
  //включение PB0,PB1 как линии ввода,вывода
  AT91C_BASE_PIOB->PIO_PER = AT91C_PIO_PB0 |  AT91C_PIO_PB1;
  //отключение подтягивающих к плюсу питания резисторов на PB0,SPCK
  //MOSI,MISO. на PB0-есть аппартная подтяжка 4.7K к 3.3В. на PB1 оставляем
  //включенной встроенную в МК подтяжку к 3.3В. SPCK,MOSI,MISO - без подтяжек
  //AT91C_BASE_PIOB->PIO_PPUDR = AT91C_PIO_PB0 | AT91C_PA16_SPI0_MISO |
    //                   AT91C_PA17_SPI0_MOSI  | AT91C_PA18_SPI0_SPCK;
  
  //настраиваем 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();
  //Отключаем 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;
  //конфигурируем 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;
  //отключение 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,16 битный режим, SPCKHMhz/255 = 188,2Khz
  AT91C_BASE_SPI0->SPI_CSR[0]  =  AT91C_SPI_CPOL |
                                  AT91C_SPI_BITS_16 | SCBR(0xFF);
  //SPI enable
  AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIEN;
  
  //--------------------------------------------------------------------------//
}

unsigned int SPI0_trans(unsigned int data)
{
    AT91C_BASE_SPI0->SPI_TDR = data;
    while(!(AT91C_BASE_SPI0->SPI_SR & AT91C_SPI_RDRF));
    return (AT91C_BASE_SPI0->SPI_RDR);
}

//Включаем акселлерометр PB0=0, PB1=1
void ACCE_ON(void)
{
  AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB1;
}

//Включаем гироскоп PB0=1, PB1=0
void GYRO_ON(void)
{
  AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB0;
}
//PB0=1,PB1=0
void SENSORS_OFF(void)
{
  AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB0 | AT91C_PIO_PB1;
}
aaarrr
Хорошо, а что говорит осциллограф? И Вы не пробовали писать в регистры?
Dars
Цитата(aaarrr @ Oct 24 2008, 18:08) *
Хорошо, а что говорит осциллограф? И Вы не пробовали писать в регистры?


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

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

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

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

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

POWER_SUPPLY у Вас float.
Dars
Цитата(aaarrr @ Oct 24 2008, 19:31) *
Насколько я понимаю, у ADIS16201 есть регистры для записи, можно записать-прочитать-сравнить.
POWER_SUPPLY у Вас float.

Писать не пробовал. там технология записи такая же, что и чтения(разница в 16бите). но чтение то не работает. пробовал по разным другим регистрам читать. с гироскопа пробовал читать. не работает и все..
на авр все работало..
aaarrr
Попробуйте немного модифицировать инициализацию:
Код
  //SPI enable
  AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SPIEN;
  //SPI в режиме Master, фиксированная перефирия,тактирование от MCK
  AT91C_BASE_SPI0->SPI_MR = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;
  //CPOL=1,16 битный режим, SPCKHMhz/255 = 188,2Khz
  AT91C_BASE_SPI0->SPI_CSR[0]  =  AT91C_SPI_CPOL |
                                  AT91C_SPI_BITS_16 | SCBR(0xFF);


И сделайте хотя бы аппаратный loopback на удаленном конце.
Dars
Заработало! yeah.gif Проблема была в том, что пауза между двумя передергиваниями чип селекта отсутствовала. Надо было доку на датчики читать, а я на проц грешил. такой код работает.
Код
  
for(i=0;i<100;i++)
  {
    //ждем  
    j=0;
    for(j=0;j<800;j++);
    ACCE_ON();
    dummy = SPI0_trans(addr);
    SENSORS_OFF();    
    //ждем опять
    j=0;
    for(j=0;j<800;j++);
    ACCE_ON();  
    result = SPI0_trans(addr);
    SENSORS_OFF();
    result &= 0xFFF;
    POWER_SUPPLY[i] = result *k;
    }
  
  while(1);

всем спасибо за помощь. aaarrr a14.gif
Пока писал этот код возникли четыре вопроса.
1) Есть регистры только для записи. Из них читать нельзя. Допустим я хочу в одном месте включить тактирование PIOB. я пишу
Код
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOB)


потом, в другом месте программы, я хочу включить тактирование SPI
я пишу
Код
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI0);

тем самым затирая бит (1 << AT91C_ID_PIOB) и выключая тактирование PIOB.
писать так
Код
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_SPI0);

чтобы не трогать ранее записанное в PCER значение я не могу.
Вопрос: Как правильно писать в такие регистры(только для записи), чтобы не затирать ранее записанные в них значения?

2)
Код
AT91C_BASE_PIOB->PIO_ODSR = (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0);

каков тайный смысл данного кода?я так понял что 1UL и 0UL- это unsigned long единица и ноль.
а (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0) = AT91C_PIO_PB1. в чем смысл этой записи?

3)Кто каким образом делаем задержки в программах? в авр была функция __delay_cycles(). и с помощью нее можно было делать паузы. кто как в арм делает?

4)Если мне надо работать с данными от байта до двух. какой тип данных под них лучше резервировать? я так думаю, что если памяти не жалко и нужно быстродействие то лучше все переменные хранить в int. процессор то 32 бита(режим АРМ). а если памяти жалко и скорость не важна то лучше распихивать все по char или short в зависимости от велечины переменной. правильно я думаю?
Alexandro
Цитата(Dars @ Oct 25 2008, 10:24) *
Вопрос: Как правильно писать в такие регистры(только для записи), чтобы не затирать ранее записанные в них значения?


При записи в такие регистры устанавливаются только единичные биты. Там где бит равен нулю, значение не изменяется.
Сергей Борщ
Цитата(Dars @ Oct 25 2008, 10:24) *
2)
Код
AT91C_BASE_PIOB->PIO_ODSR = (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0);

каков тайный смысл данного кода?я так понял что 1UL и 0UL- это unsigned long единица и ноль.
а (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0) = AT91C_PIO_PB1. в чем смысл этой записи?
Очень простой. Через месяц-полгода глядя в свои же исходники, в которых написано AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB1; вы будете думать "А ведь микросхема висит на PB1 и PB0, я тут забыл PB0! Потом посмотрите в схему и поймете, что в PB0 здесь надо записать ноль и ошибки нет. А глядя в запись (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0) сразу видно: в PB1 записана 1, в PB0 записан 0. Еще один плюс такой записи: надо внести изменение - меняем одну цифру. В вашем же случае пришлось бы стирать или вписывать "AT91C_PIO_PBx".
Цитата(Dars @ Oct 25 2008, 10:24) *
3)Кто каким образом делаем задержки в программах? в авр была функция __delay_cycles(). и с помощью нее можно было делать паузы. кто как в арм делает?
В ARM время исполнения инструкции зависит от того, откуда выполняется код (ОЗУ, флеш, кэш), от настроек контроллера флеш и других факторов. Поэтому невозможно реализовать __delay_cycles(). Если нужна точная задержка - используйте таймер. Если точность не важна - for(volatile int i = 0; i < TIME; ++i);
Цитата(Dars @ Oct 25 2008, 10:24) *
4)Если мне надо работать с данными от байта до двух. какой тип данных под них лучше резервировать? я так думаю, что если памяти не жалко и нужно быстродействие то лучше все переменные хранить в int. процессор то 32 бита(режим АРМ). а если памяти жалко и скорость не важна то лучше распихивать все по char или short в зависимости от велечины переменной. правильно я думаю?
В принципе, да. А еще лучше использовать типы из stdint.h, которые добавляют портируемости.
aaarrr
Цитата(Сергей Борщ @ Oct 25 2008, 14:36) *
Очень простой. Через месяц-полгода глядя в свои же исходники, в которых написано AT91C_BASE_PIOB->PIO_ODSR = AT91C_PIO_PB1; вы будете думать "А ведь микросхема висит на PB1 и PB0, я тут забыл PB0! Потом посмотрите в схему и поймете, что в PB0 здесь надо записать ноль и ошибки нет. А глядя в запись (1UL * AT91C_PIO_PB1) | (0UL * AT91C_PIO_PB0) сразу видно: в PB1 записана 1, в PB0 записан 0. Еще один плюс такой записи: надо внести изменение - меняем одну цифру. В вашем же случае пришлось бы стирать или вписывать "AT91C_PIO_PBx".

Я грешным делом думал, что гораздо логичнее было бы написать соответствующий комментарий smile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.