Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ADuC7021: ADC и SPI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
krofork
есть ADuC7021 (ARM7TDMI).

у него работает АЦП
то что он напреобразовывал должно отдаваться по SPI.

На вход подаётся тестовый периодический сигнал (период ~20 мс).
если он то что напреобразовывал отдаёт по UART, то вроде всё нормально

если же включаем SPI (UART продолжает работать - собственно через него я и веду "лог" работы программы), то в оцифрованном сигнале вижу "зарубки" (нулевое значение) через каждые ~2мс. причем периодичность этих "зарубов" не зависит от скорости обмена по SPI (брались скорости и 250кГц и 1 МГц и 4МГц)

канал АЦП - ADC0

интересно также, что в обратном направлении (Ц-А пробразование буфера принятого по SPI, периодическое) - происходит без косяков - то есть работа SPI каким то макаром отражается на АЦП и никак на ЦАП.

может кто нибудь наведет, почему может происходить подобное?
Paramon
Цитата(krofork @ May 10 2007, 14:32) *
есть ADuC7021 (ARM7TDMI).

у него работает АЦП
то что он напреобразовывал должно отдаваться по SPI.

На вход подаётся тестовый периодический сигнал (период ~20 мс).
если он то что напреобразовывал отдаёт по UART, то вроде всё нормально

если же включаем SPI (UART продолжает работать - собственно через него я и веду "лог" работы программы), то в оцифрованном сигнале вижу "зарубки" (нулевое значение) через каждые ~2мс. причем периодичность этих "зарубов" не зависит от скорости обмена по SPI (брались скорости и 250кГц и 1 МГц и 4МГц)

канал АЦП - ADC0

интересно также, что в обратном направлении (Ц-А пробразование буфера принятого по SPI, периодическое) - происходит без косяков - то есть работа SPI каким то макаром отражается на АЦП и никак на ЦАП.

может кто нибудь наведет, почему может происходить подобное?



А у вас АЦП в непрерывном режиме преобразования?
krofork
АЦП запускается по таймеру0 каждые 125 микросекунд
Paramon
Цитата(krofork @ May 11 2007, 08:50) *
АЦП запускается по таймеру0 каждые 125 микросекунд


Табл. 7. Назначение разрядов регистра ADCCON.
Разряд Описание

7 Разрешить преобразование. Устанавливается пользователем с целью разрешить
режим преобразования
Сбрасывается пользователем с целью отменить
режим преобразования
6 Разрешает работу вывода ADCBUSY Устанавливается пользователем с целью разрешить
работу вывода ADCBUSY
Сбрасывается пользователем с целью отменить
работу вывода ADCBUSY
5 Управление питанием АЦП: Устанавливается пользователем с целью перевести
АЦП в нормальный режим работы;
АЦП должен быть включен за время не менее 500 мкс
до момента, когда он будет работать корректно
Сбрасывается пользователем с целью перевести АЦП
в режим малого энергопотребления
4-3 Режим преобразования: 00 Однополярный вход
01 Дифференциальный вход
10 Псевдодифференциальный вход
11 Зарезервировано
2-0 Тип преобразования: 000 Разрешить преобразование по сигналу на
входе CONVSTART
001 Разрешить преобразование по сигналу от
таймера 1
010 Разрешить преобразование по сигналу от
таймера 0
011 Однократное преобразование с управлением
от программы, после
преобразования биты сбрасываются в состояние
000
100 Непрерывное преобразование с управлением
от программы
101 Преобразование по сигналу с выхода PLA
Остальные сочетания зарезервированы

Попробуйте перевести в режим непрерывного преобразования и/или уточните настройку режимов работы АЦП
krofork
сейчас вот так:
10010100010

fADC/2
ADC aquisition time - 2clocks
Enable start conversion
ADCBUSY disabled
ADC power up
Single ended
Conversion on Timer0

...
не могли бы в пояснить как работает АЦП в этом режиме
"100 Непрерывное преобразование с управлением от программы"

т.е. от чего запускается? автоматически после окончания предыдущего преобразования?
Paramon
Цитата(krofork @ May 11 2007, 11:48) *
сейчас вот так:
10010100010

fADC/2
ADC aquisition time - 2clocks
Enable start conversion
ADCBUSY disabled
ADC power up
Single ended
Conversion on Timer0

...
не могли бы в пояснить как работает АЦП в этом режиме
"100 Непрерывное преобразование с управлением от программы"

т.е. от чего запускается? автоматически после окончания предыдущего преобразования?


Да автоматически! Забыл спросить, а с регистром MMR что?
вот его описание:
Табл. 11. Назначение разрядов
MMR-регистра REFCON.
Разряд Описание
7–2 Зарезервированы
1 Отключение внутреннего ИОН
Устанавливается пользователем для
выключения внутреннего ИОН
и использования внешнего источника
опорного напряжения
Сбрасывается пользователем для
перевода внутреннего ИОН в рабочий
режим и использования его для работы
АЦП
0 Разрешить выход внутреннего ИОН
Устанавливается пользователем для
подключения внутреннего 2.5-вольтового
ИОН к выходу VREF. Этот выход может
использоваться внешней схемой в
качестве ИОН, но возможно понадобится
дополнительный буфер.
Сбрасывается пользователем для
отключения внутреннего ИОН от выхода
VREF.


Ваши настройки сейчас посмотрю!
krofork
всмысле MMR регистром?
MMR - memory mapped register их там много smile.gif

регистром REFCON имелось ввиду, тогда опора включена.
да и штука в том, что не вообще АЦП не работает, а в том, что не работает правильно только при постоянном обмене по SPI...
Paramon
Цитата(krofork @ May 11 2007, 12:08) *
всмысле MMR регистром?
MMR - memory mapped register их там много smile.gif

регистром REFCON имелось ввиду, тогда опора включена.
да и штука в том, что не вообще АЦП не работает, а в том, что не работает правильно только при постоянном обмене по SPI...


Будьте добры поделитесь кусочком кода по работе с АЦП.
(Он в прерывании? - пользуетесь ли регистром ADCRST?)
Плохо представляю как это у вас работает. У меня всё нормально, правда с 7024.
Waso
День добрый!
Подниму тему ибо уже неделю бьюсь и не могу победить. Тоже ADuc7021, тоже проблема с SPI. Причем уже передавать пытаюсь банальный алфавит, но на приемной стороне его нет, а только нули, нули... Это проверено осциллографом. Вот код:
Код
  // SPISTA (p.70)
#define SPIRX_OVF   (SPISTA & (1<<5))
#define SPIRX_IRQ   (SPISTA & (1<<4))
#define SPIRX_FULL  (SPISTA & (1<<3))
#define SPITX_UDF   (SPISTA & (1<<2))
#define SPITX_IRQ   (SPISTA & (1<<1))
#define SPITX_EMPTY (!(SPISTA & (1)))

// SPICON  (p.70)
#define SPI_CONTINUOUS_TX   (1UL << 12)
#define SPI_LOOPBACK        (1UL << 11)
#define SPI_SO_EN           (1UL << 10)
#define SPI_SLAVE_SELECT_EN (1UL << 9)
#define SPI_RXOVF_OVERWRITE (1UL << 8)
#define SPI_TXUDF_SENDZERO  (1UL << 7)
#define SPI_TXWRITE_TRANS   (1UL << 6)
#define SPI_LSB_FIRST       (1UL << 5)
#define SPI_CLK_IDLEHIGH    (1UL << 3)
#define SPI_PHASE           (1UL << 2)
#define SPI_MASTER_MODE     (1UL << 1)
#define SPI_ENABLE          (1UL << 0)

#define SPI_BITRATE     1000000LL
#define SPI_MODE  (SPI_TXWRITE_TRANS | SPI_SO_EN | SPI_ENABLE \
                   | SPI_TXUDF_SENDZERO | SPI_CONTINUOUS_TX)

#ifndef SPI_BITRATE
#define SPI_BITRATE  100000LL
#endif

#define SPI_DIVISOR (((41779200LL/2)/SPI_BITRATE)-1)

#if (SPI_DIVISOR >= 0xFE)
#error "Bad SPI_BITRATE value! Look p.69 datasheet."
#endif

#ifndef SPI_MODE
#error "SPI_MODE not defined!"
#endif

uint8_t spidata[SPI_N];     // буфер выходных данных SPI

void SPI_Init(void)
{
  SPICON = SPI_MODE;
  SPIDIV = SPI_DIVISOR;
#if (SPI_MODE&SPI_MASTER_MODE)
  dir_out(SPI_SCK);
  dir_out(SPI_MOSI);
  dir_in(SPI_MISO);
  GP1CON &= ~(0x0FFF0000); GP1CON |= 0x02220000; // выбрали функцию GPIO как SPI
#else // (SPI_MODE&SPI_MASTER_MODE)
  dir_in(SPI_SCK);
  dir_in(SPI_MOSI);
  dir_out(SPI_MISO);
  dir_in(SPI_CS);  
  GP1CON &= ~(0xFFFF0000); GP1CON |= 0x22220000; // выбрали функцию GPIO как SPI
#endif //(SPI_MODE&SPI_MASTER_MODE)
}

__inline void SPI_StartIRQTX(void)
{
  spitxcount = 0;
  SPITX = spidata[spitxcount++];
  IRQEN = SPI_SLAVE_BIT;
  on(Req);      // сигнал что данные готовы - когда мастер его видит - он выставляет SlaveSelect и читает данные.
}

void SPI_Ready_ISR(void)
{
  SPITX = spidata[spitxcount++];
  if(spitxcount>=SPI_N)
  {
    IRQCLR = SPI_SLAVE_BIT;
    off(Req);
    if(AdcBufRdy_flag) ADC_Start();
  }
}

void main(void){
...
SPI_Init();
...
while(1)    // вечный цикл
  {
      while(spitxcount < SPI_N);  // Ждем окончания передачи предыдущих байт..

spidata[0] = 'A'; spidata[1] = 'B'; spidata[2] = 'C'; spidata[3] = 'D';
spidata[4] = 'E'; spidata[5] = 'F'; spidata[6] = 'G'; spidata[7] = 'H';

      SPI_StartIRQTX();   // запускаем передачу данных на фоне
  }
}

Если убрать из режима SPI_TXUDF_SENDZERO (передача нуля если передающий регистр не готов), то шлет не нули а всякую чушь. Тоесть на лицо Underflow (передающий регистр не готов). А почему оно так - непойму.
Waso
Разобрался. Проблема была в мастере. Я щелкал SlaveSelect после каждого байта, а когда стоит флаг SPI_CONTINUOUS_TX, этого делать не надо. Кроме того, не было предусмотрено механизма синхронизации между мастером и слейвом, и если терялся хоть один байт, то вся посылка сдвигалась. А терялись они именно в режиме отладки, когда я JTAG-ом просматривал регистры после приема каждого байта. При непрерывной работе таких потерь небыло, но я все-же ввел синхронизацию - если слейв не передал еще все данные, но видит что мастер убрал чипселект, то он сбрасывает свой буфер и готовится к новой передаче. И еще были проблемы в основной программе (в рассчетах), из-за которых также проскакивали левые числа.

Вот так вот. Бьешься неделю головой о стену, а потом напишешь на форум и тут-же тебе самому решение в голову придет. =) Так и телепатом стать не долго.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.