Программирование DSP Blackfin: чтение АЦП AD7691 через SPORT с использованием 2D DMA Thu, November 21 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


Blackfin: чтение АЦП AD7691 через SPORT с использованием 2D DMA Печать
Добавил(а) microsin   

Описывается пример чтения 18-битного АЦП с последовательным интерфейсом AD7691 через порт SPORT3 процессора Blackfin ADSP-BF538. В данном примере отдельные выборки вычитываются из АЦП абсолютно автоматически, с помощью аппаратуры DMA, разгружая процессор для выполнения эффективных фоновых вычислений.

AD7691 3 Wire CS Mode without Busy Indicator BF538 connection

Рис. 1. Схема подключения AD7691 к SPORT3 ADSP-BF538.

АЦП AD7691 подключен следующими сигналами:

VIO: эта ножка (вход) имеет многофункциональное назначение в проприетарном последовательном интерфейсе АЦП. В данном случае на неё жестко подан + питания, чем выбран 3-проводный режим интерфейса, без генерации сигнала занятости [1].

CNV: эта ножка (вход) выполняет сразу 2 функции - во-первых, положительный перепад на ней задает момент начала преобразования conv. Во-вторых, на эту же ножку по окончании преобразования должен быть подан сигнал выборки для чтения последовательных данных через выход SDO, интервал лог. 0 между моментами времени select и deselect (см. рис. 3).

SDO: выход данных, которые выдвигаются из АЦП по отрицательным перепадам сигнала SCK.

SCK: тактовый вход, импульсами на котором мастер шины (в нашем примере это процессор Blackfin ADSP-BF538) управляет чтением данных через сигнал SDO. По фронтам SCK (переход 0->1) данные вычитываются, а по спадам (1->0) переключаются на следующий бит (см. рис. 2 и 3).

Как уже упоминалось, АЦП подключен по 3-проводной схеме без использования сигнала занятости (подробное описание различных режимов подключения см. в [1]). Для работы этого режима на вход запуска преобразования CNV требуется подать сигнал особой формы, который будет запускать оцифровку сигнала, и также будет служить сигналом выборки последовательного интерфейса, по которому АЦП будет выдвигать данные на провод SDO по тактовому сигналу SCK.

Сигнал данных SDO от АЦП приходит на вход данных DR3PRI порта SPORT3, и сигнал тактов для АЦП формируется выходными тактами RSCLK3 от SPORT3. При этом данные вычитываются из SDO аппаратно с помощью двойного буферизирования, организованного на основе 2D DMA [3]. Обработка со стороны процессора вызывается только в момент заполнения одного из двух буферов по прерыванию. Канал приема SPORT настроен для 18 бит на фрейм, с длительностью фрейма 32 бита. Из этих 32 бит приходится 18 на вычитывание данных, а остальная часть из 12 бит - на интервал запуска оцифровки и ожидание завершения преобразования АЦП.

Сигнал CNV, поскольку от него требуется специальная форма, синтезируется с помощью сигнала данных передачи DT3PRI того же SPORT3, синхронно с работой канала приема. Синхронная работа каналов приема и передачи возможна по той причине, что оба этих канала тактируются от одного и того же источника - сигнал SCLK системной шины процессора ADSP-BF538.

Для канала передачи также используется DMA, но в другом режиме - простой одномерный автобуфер на 4 слова. Частота бит на передачу выбрана в 4 раза выше с той целью, чтобы можно было точнее подобрать форму сигнала CNV. Это может быть важным для работы последовательного интерфейса на высоких частотах, когда между АЦП и процессором стоят гальванические изоляторы для передачи сигналов (они вносят дополнительные задержки, которые желательно компенсировать).

AD7691 reading AKIP 9103 diag

Рис. 2. Диаграмма опроса АЦП с помощью сигналов SPORT3.

[Пример кода настройки 2D DMA для чтения АЦП]

Код настройки SPORT:

////////////////////////////////////////////////////////////////////////////
// sport.h
#ifndef __SPORT__
#define __SPORT__
 
#include "system.h"
 
/*   Для корректной работы чтения АЦП нужно выбрать правильное соотношение между
   частотой прерываний таймера, который генерит сигнал конверсии (короткие импульсы
   лог. 0 формируют сигналы конверсии CNV для АЦП, сейчас их частота 32768 Гц).
   Пусть частота CNV называется Fcnv.
 
   Частота тактирования АЦП RSCLK_frequency выбирается так, чтобы соотношение
   RSCLK_frequency / Fcnv было с запасом больше количества бит (18). Здесь выбрано
   RSCLK_frequency / Fcnv = 1024 / 32 = 32, т. е. 32 такта SCK для АЦП влезают
   в период между опросами АЦП.
 
   Отсюда выбирается RFSDIV, которое равно (RSCLK_frequency / Fcnv)-1 = 31.*/
 
//Peripheral Interrupt ID:
#define DMA10_SPORT3_RX_Peripheral  35
 
//Определения приоритетов:
#define ADC_double_buffer_DMA_IVG   ik_ivg11    //прерывание заполнения буфера АЦП
 
//////////////////////////////////////////////////////////////////////////
// Параметры настройки канала приема SPORT3, канал приема используется
//  для автоматического (через 2D DMA) чтения АЦП AD7691.
#define SCLK 32768    //частота системной шины, кГц
#define RSCLK_frequency (128*32) // 4096 кГц, для частоты оцифровки 128 кГц
#define SPORT_RCLKDIV (SCLK/RSCLK_frequency/2-1)
#define DTYPE_SIGN 0x0004
#define RCR1 (LARFS | LRFS | RFSR | IRFS | DTYPE_SIGN | IRCLK)
#define RCR2 17     //18 бит на фрейм, потому что АЦП выдает 18 бит
#define RFSDIV 31 //период RFS составит 32 бита.
#define SPORT3RX_U32_WORDS 256
 
//////////////////////////////////////////////////////////////////////////
// Параметры настройки канала передачи SPORT3, канал передачи используется
//  для автоматического (через 1D DMA) формирования сигнала конверсии
//  и выборки для чтения АЦП AD7691.
#define TSCLK_frequency (RSCLK_frequency*4)  // 16384 кГц
#define SPORT_TCLKDIV   (SCLK/TSCLK_frequency/2-1)
#define TCR1 (TCKFE | LATFS | LTFS | TFSR | ITFS | ITCLK)
#define TCR2 31   //32 бита на фрейм
#define SPORT3TX_U32_WORDS 4
 
extern int adcdatarx[2][SPORT3RX_U32_WORDS];

void SportInit(void);
void  SportInitDMA(void);
void  SportRun(void);
void  SportStop(void);
 
#endif //__SPORT__

Обратите внимание на маску для флажка DTYPE_SIGN, которая используется для создания константы настройки RCR1. Установкой поля RDTYPE в значение 01 Она включает функцию расширения знаком (Sign-Extended, см. описание регистра SPORTx_RCR1 в [2]) для принимаемых данных через SPORT3. Таким образом, если функция расширения знаком включена, то принятое 18-битное значение со знаком в старшем разряде D17 распространится на все остальные старшие разряды D31..D17, и в буфере автоматически получатся 32-битные числа со знаком.

////////////////////////////////////////////////////////////////////////////
// sport.c
#include "settings.h"
#include "SPORT.h"
 
//Массив для формирования сигнала SDI (выборка) АЦП AD7691 (автобуфер 1D):
static int adcdatatx[SPORT3TX_U32_WORDS];
//Массив для получения данных с АЦП AD7691 через сигнал SDO (автобуфер 2D):
int adcdatarx[2][SPORT3RX_U32_WORDS];
 
void SportInit (void)
{
   //Настройка канала приема, в него будут поступать данные АЦП:
   *pSPORT3_RCLKDIV=SPORT_RCLKDIV;
   *pSPORT3_RCR1 = RCR1;
   *pSPORT3_RCR2 = RCR2;
   *pSPORT3_RFSDIV = RFSDIV;
   ssync();
   //Настройка канала передачи, он должен формировать выборки SDI для АЦП:
   *pSPORT3_TCLKDIV=SPORT_TCLKDIV;
   *pSPORT3_TCR1 = TCR1;
   *pSPORT3_TCR2 = TCR2;
   *pSPORT3_TFSDIV = RFSDIV;
   ssync();
}
 
void SportInitDMA(void)
{
///////////////////////////////////////////////////
// Канал приема будет получать данные от АЦП:
   *pDMA10_PERIPHERAL_MAP = 0x2000;    // Канал DMA для приема через SPORT3
   //FLOW_AUTO: автозаполнение буфера по кругу |
   //DI_EN: резрешение прерывания по завершению буфера |
   //DI_SEL: прерывание по каждому буферу
   //DMA2D: двухмерный (двойной) буфер |
   //WDSIZE_32: передачи 32-битные |
   //WNR: запись в память со стороны DMA
   *pDMA10_CONFIG = FLOW_AUTO | DI_EN | DI_SEL | DMA2D | WDSIZE_32 | WNR;
   *pDMA10_START_ADDR = (void *)&adcdatarx;
   *pDMA10_X_COUNT = SPORT3RX_U32_WORDS;
   *pDMA10_X_MODIFY = 4;      //sizeof(int)
   *pDMA10_Y_COUNT = 2;       // 2 буфера
   *pDMA10_Y_MODIFY = 4;      //sizeof(int)
   ssync();
///////////////////////////////////////////////////
// Канал передачи будет формировать сигнал выборки SDI для АЦП:
   //Вариант для TCLK==RCLK*4:
   adcdatatx[0] = 0x00000000;   // 0000 0000 0000 0000 0000 0000 0000 0000
   adcdatatx[0] = 0x007FFE1F;   // 0000 0000 0111 1111 1111 1110 0001 1111
   adcdatatx[0] = 0xFFFFFFFF;   // 1111 1111 1111 1111 1111 1111 1111 1111
   adcdatatx[0] = 0x80000000;   // 1000 0000 0000 0000 0000 0000 0000 0000
   *pDMA11_PERIPHERAL_MAP = 0x3000;    // Канал DMA для передачи через SPORT3
   //Канал передачи | 32-битные передачи | автопередача буфера по кругу.
   *pDMA11_CONFIG = WDSIZE_32 | FLOW_AUTO;
   *pDMA11_START_ADDR = (void *)&adcdatatx;
   *pDMA11_X_COUNT  = 4;
   *pDMA11_X_MODIFY = 4;      //sizeof(int)
   ssync();
}
 
void SportRun(void)
{
   *pDMA10_CONFIG |= DMAEN;
   *pSPORT3_RCR1 |= RSPEN;
   ssync();
   *pDMA11_CONFIG |= DMAEN;
   *pSPORT3_TCR1 |= TSPEN;
   ssync();
}
 
void SportStop (void)
{
   *pSPORT3_RCR1 &= ~RSPEN;
   *pDMA10_CONFIG &= ~DMAEN;
}

AD7691 Blackfin SPORT reading principle

Рис. 3. Пояснение синтеза сигнала CNV для управления запуском конверсии и чтения АЦП AD7691.

С помощью сигнала передачи DT3PRI порта SPORT3 формируется сигнал CNV для опроса АЦП. Момент conv соответствует запуску преобразования (конверсия, когда заряжаются внутренние конденсаторы схемы выборки/хранения АЦП). Момент select соответствует началу сигнала выборки, когда начинается чтение линии SDO по тактам SCK. Между моментом conv и select должно пройти не меньше 2.2 мкс, это максимально возможное паспортное время преобразования АЦП (см. параметр tCONV из таблицы 4 параметров интервалов времени из [1]). Момент deselect соответствует окончанию чтения АЦП, когда выдвинуты все 18 разрядов данных.

Код обработчика прерывания заполнения половинки буфера (ADC_data_ISR) и подпрограмма настройки запуска обработки прерывания (ADC_Init):

////////////////////////////////////////////////////////////////////////////
// AD7691.h
#ifndef __AD7691__
#define __AD7691__
 
#include "SPORT.h"
 
#define REF198_VOLTAGE  4.096
#define ONE_BIT_VOLTAGE (REF198_VOLTAGE/131071)
 
void ADC_Init (void);
 
#endif   //__AD7691__

////////////////////////////////////////////////////////////////////////////
// AD7691.c
#include "pins.h"
#include "AD7691.h"
 
EX_REENTRANT_HANDLER(ADC_data_ISR)
{
   *pDMA10_IRQ_STATUS |= 0x0001;
   TOGGLEVD10();
}
 
void ADC_Init (void)
{
   //Инициализация прерывания заполнения половинки буфера 2D DMA
   // для чтения данных из АЦП.
   //                  (ID периферии,               приоритет                )
   *pSIC_IAR4 |= PX_IVG(DMA10_SPORT3_RX_Peripheral, ADC_double_buffer_DMA_IVG);
   //              (приоритет,                 ISR         )
   register_handler(ADC_double_buffer_DMA_IVG, ADC_data_ISR);
   *pSIC_IMASK1 |= DMA10_IRQ;      // установка маски прерывания
}

[Ссылки]

1. АЦП AD7691.
2. ADSP-BF538: интерфейс SPORT.
3. ADSP-BF538: DMA.
4. Blackfin: настройка обработчика прерывания.

 

Добавить комментарий


Защитный код
Обновить

Top of Page