К1921ВК01Т электрические параметры АЦП

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

bkolbov
Сообщения: 248
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: К1921ВК01Т электрические параметры АЦП

Сообщение bkolbov »

Насколько я понимаю, вы рассчитываете время исходя из того, что секвенсоры опрашивают каналы последовательно. Однако же, как я писал выше, это не так. Старт всех АЦП происходит параллельно, последовательно лишь измеряются каналы А и Б внутри одного АЦП. Т.е.разбиение на секвенсоры в вашем случае не даст выигрыша по скорости.
Я использую 3 секвенсора. Первому секвенсору назначаю канал 1-4, второму 5-8, третьему 9-12. Каждому секвенсору назначаю одинаковое событие запуска (например прерывание ШИМ) и каждый секвенсор работает с 4 каналами. Усреднение отключено.
Я ожидаю, что секвенсоры запустятся параллельно и каждый из них потратит на преобразование 250ns*4 = 1ms. Поскольку секвенсоры запустились параллельно в один момент времени, то и завершить работу они должны одновременно и спустя 1ms с момента запуска я должен забрать из памяти результаты преобразований. (время одинаковое у всех секвенсоров т.к. настройки идентичны)
Что происходит когда приходит событие запуска: все секвенсоры разом выставляют запросы на измерение каналов 1-12, которые относятся первым 6 АЦП. Все 6 АЦП стартуют параллельно разом делать свои измерения. Т.к. каждому АЦП необходимо измерить как канал А так и Б, то время преобразования 2 каналов одного АЦП это 250нс*2 (сначала А, потом Б). Помним, что все АЦП были запущены одновременно, а значит все секвенсоры получат результаты измерений в свои фифо спустя 250нс*2 от старта.

Что произойдет если 1 секвенсору назначить 12 каналов? Тоже самое. Он по событию выставит запрос на измерение 12 каналов, все 6 АЦП параллельно запустятся, и через 250нс*2 в фифо секвенсора будет лежать 12 результатов измерений, соответствующих каждому из каналов.
Аватара пользователя
MR.Smith
Сообщения: 78
Зарегистрирован: 25 апр 2016, 10:56

Re: К1921ВК01Т электрические параметры АЦП

Сообщение MR.Smith »

bkolbov писал(а):Насколько я понимаю, вы рассчитываете время исходя из того, что секвенсоры опрашивают каналы последовательно. Однако же, как я писал выше, это не так. Старт всех АЦП происходит параллельно, последовательно лишь измеряются каналы А и Б внутри одного АЦП. Т.е.разбиение на секвенсоры в вашем случае не даст выигрыша по скорости.
Я использую 3 секвенсора. Первому секвенсору назначаю канал 1-4, второму 5-8, третьему 9-12. Каждому секвенсору назначаю одинаковое событие запуска (например прерывание ШИМ) и каждый секвенсор работает с 4 каналами. Усреднение отключено.
Я ожидаю, что секвенсоры запустятся параллельно и каждый из них потратит на преобразование 250ns*4 = 1ms. Поскольку секвенсоры запустились параллельно в один момент времени, то и завершить работу они должны одновременно и спустя 1ms с момента запуска я должен забрать из памяти результаты преобразований. (время одинаковое у всех секвенсоров т.к. настройки идентичны)
Что происходит когда приходит событие запуска: все секвенсоры разом выставляют запросы на измерение каналов 1-12, которые относятся первым 6 АЦП. Все 6 АЦП стартуют параллельно разом делать свои измерения. Т.к. каждому АЦП необходимо измерить как канал А так и Б, то время преобразования 2 каналов одного АЦП это 250нс*2 (сначала А, потом Б). Помним, что все АЦП были запущены одновременно, а значит все секвенсоры получат результаты измерений в свои фифо спустя 250нс*2 от старта.

Что произойдет если 1 секвенсору назначить 12 каналов? Тоже самое. Он по событию выставит запрос на измерение 12 каналов, все 6 АЦП параллельно запустятся, и через 250нс*2 в фифо секвенсора будет лежать 12 результатов измерений, соответствующих каждому из каналов.
Большое спасибо, теперь все понятно!
Аватара пользователя
MR.Smith
Сообщения: 78
Зарегистрирован: 25 апр 2016, 10:56

Re: К1921ВК01Т электрические параметры АЦП

Сообщение MR.Smith »

Столкнулся я с интересным явлением.
Настроил я насколько АЦП на работу с одним секвенсором. Однократное событие запуска застроена на максимум счетчика ШИМ.
Все вроде хорошо, но иногда не очень))
В моем случае в FIFO я ожидаю 9 выборок. Читаю так:

Код: Выделить всё

while (NT_ADC->RIS_bit.INR0 == 0); 	// Ожидаем окончания измерений
if(NT_ADC->SEQ[0].FSTAT_bit.FLOAD == 9)
{
	// Здесь читаем FIFO
	val0 = (NT_ADC->SEQ[0].FIFO & 0x0FFF);
	...
	val8 = (NT_ADC->SEQ[0].FIFO & 0x0FFF);
}
Однако примерно один раз на 400 запусков секвенсоров я получаю: NT_ADC->SEQ[0].FSTAT_bit.FLOAD > 9
т.е. в FIFO результатов измерений больше, чем я ожидаю. Похоже, что кол-во результатов либо кратно 9, либо равно 32 (максимальная глубина FIFO).

FIFO я вычитываю в каждом прерывании и даже если мне не нравится кол-во элементов в FIFO я его все равно очищаю:

Код: Выделить всё

void adcClearFifo(void)
{
	volatile uint16_t tmp = 0;
	while(NT_ADC->SEQ[0].FSTAT_bit.FLOAD > 0)
	{
		tmp = NT_ADC->SEQ[0].FIFO;
	}
}
В чем может быть причина такой работы?
bkolbov
Сообщения: 248
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: К1921ВК01Т электрические параметры АЦП

Сообщение bkolbov »

Добрый день!

Ничего подобного ранее не всплывало, сходу причину назвать не могу.
Дайте пожалуйста больше информации. Какие каналы используете? Как настроили прерывания? Не совсем понятно как соотносятся между собой оба куска кода. Первый вообще похож на работу без прерываний (поллинг флага). Когда adcClearFifo() вызывается? Какая частота ядра? Какие предделители ШИМ (какая частота счета ШИМ)? Какое значение периода?
Аватара пользователя
MR.Smith
Сообщения: 78
Зарегистрирован: 25 апр 2016, 10:56

Re: К1921ВК01Т электрические параметры АЦП

Сообщение MR.Smith »

bkolbov, добрый день!
bkolbov писал(а): 25 июл 2017, 13:00Какие каналы используете?
Используются следующие каналы: ADC6A, ADC6B, ADC7A, ADC7B, ADC8A, ADC9A, ADC10A, ADC10B и ADC11B.
bkolbov писал(а): 25 июл 2017, 13:00Как настроили прерывания?
Прерывания настроены только для ШИМ при событиях PRD=CTR и PRD=ZERO.
Запуск секвенсора осуществляется при событии PRD=CTR автоматически. Далее в обработчике прерывания (PRD=CTR) я вычитываю результаты из FIFO.
Вот полная функция вычитки из FIFO:

Код: Выделить всё

uint8_t getAdcData(struct AdcData *adcData)
{
	/* Результаты измерений модулей АЦП записываются в буферы секвенсоров в
	 * порядке возрастания номеров каналов. Сохраненные в буфере данные доступны
	 * для чтения посредством регистра FIFO */
	 
	while (NT_ADC->RIS_bit.INR0 == 0); 	// Ожидаем окончания измерений

	/*
	 * Если буфер не содержит искомое количество выборок, то его содержимое
	 * следует считать НЕ действительным и такие данные не интерпретировать.
	 */
	if(NT_ADC->SEQ[0].FSTAT_bit.FLOAD != 9)
	{
		adcClearFifo();
		NT_ADC->ISC = 0x01;
		return 0;
	}
	adcData->val0= (NT_ADC->SEQ[0].FIFO);
	adcData->val1= (NT_ADC->SEQ[0].FIFO);
	adcData->val2= (NT_ADC->SEQ[0].FIFO);
	adcData->val3= (NT_ADC->SEQ[0].FIFO);
	adcData->val4= (NT_ADC->SEQ[0].FIFO);
	adcData->val5= (NT_ADC->SEQ[0].FIFO);
	adcData->val6= (NT_ADC->SEQ[0].FIFO);
	adcData->val7= (NT_ADC->SEQ[0].FIFO);
	adcData->val8= (NT_ADC->SEQ[0].FIFO);
	
	NT_ADC->ISC = 0x01;
	return 1;
}
До того, как эта функция будет запущена я считаю некоторую математику. Все равно секвенсор еще работает и надо немного подождать.
Затем я проверяю готовность через флаг INR0 и вычитываю FIFO если меня устраивает количество элементов в нем.
bkolbov писал(а): 25 июл 2017, 13:00Какая частота ядра?
96 МГц
bkolbov писал(а): 25 июл 2017, 13:00Какие предделители ШИМ (какая частота счета ШИМ)? Какое значение периода?
ШИМ 24 КГц.
Счетчик UpDown. Предделителей на ШИМ нет. Период 2000.
Частота работы ШИМ проверенна на осциллографе. Корректность вызова обработчиков прерываний тоже.

Полный код настройки ШИМ:

Код: Выделить всё

void adcSetup(void)
{
  /* Частота тактирования
   * Для 12-разрядного режима работы АЦП необходимо обеспечить частоту
   * тактирования 24 МГц. Применим для этого делитель DIV_ADCn (6 бит).
   * Fadc = Fsysclk/(2*(DIV_ADCn + 1)) = 96/(2*(1+1)) = 24 МГц
   * После установки частоты включаем тактирование для каждого канала
   * с помощью регистра настроек модуля АЦП PPm, где:
   *    PPm[ENA] = PPm[31] - бит разрешения работы модуля (1 - разрешено / 0 - запрещено)
   *    PPm[OM] = PPm[19] - разрядность (0 - 12 бит / 1 - 10 бит)
   *    PPm[OM] = PPm[18-16] - режим (000 - выключен / 001 - StandBy / 011 - включен)
   */
  
  NT_COMMON_REG->ADC_CTRL1_bit.DIV_ADC6   = 1;	// DIV_ADC0
  NT_COMMON_REG->ADC_CTRL1_bit.DIVEN_ADC6 = 1;	// Выбираем тактовый сигнал после делителя
  NT_COMMON_REG->ADC_CTRL1_bit.CLKEN_ADC6 = 1;	// Включаем тактовый сигнал
  
  NT_COMMON_REG->ADC_CTRL1_bit.DIV_ADC7   = 1;	// DIV_ADC1
  NT_COMMON_REG->ADC_CTRL1_bit.DIVEN_ADC7 = 1;	// Выбираем тактовый сигнал после делителя
  NT_COMMON_REG->ADC_CTRL1_bit.CLKEN_ADC7 = 1;	// Включаем тактовый сигнал
  
  NT_COMMON_REG->ADC_CTRL2_bit.DIV_ADC8   = 1;	// DIV_ADC2
  NT_COMMON_REG->ADC_CTRL2_bit.DIVEN_ADC8 = 1;	// Выбираем тактовый сигнал после делителя
  NT_COMMON_REG->ADC_CTRL2_bit.CLKEN_ADC8 = 1;	// Включаем тактовый сигнал
  
  NT_COMMON_REG->ADC_CTRL2_bit.DIV_ADC9   = 1;	// DIV_ADC3
  NT_COMMON_REG->ADC_CTRL2_bit.DIVEN_ADC9 = 1;	// Выбираем тактовый сигнал после делителя
  NT_COMMON_REG->ADC_CTRL2_bit.CLKEN_ADC9 = 1;	// Включаем тактовый сигнал
  
  NT_COMMON_REG->ADC_CTRL2_bit.DIV_ADC10   = 1;	// DIV_ADC6
  NT_COMMON_REG->ADC_CTRL2_bit.DIVEN_ADC10 = 1;	// Выбираем тактовый сигнал после делителя
  NT_COMMON_REG->ADC_CTRL2_bit.CLKEN_ADC10 = 1;	// Включаем тактовый сигнал
  
  NT_COMMON_REG->ADC_CTRL2_bit.DIV_ADC11   = 1;	// DIV_ADC7
  NT_COMMON_REG->ADC_CTRL2_bit.DIVEN_ADC11 = 1;	// Выбираем тактовый сигнал после делителя
  NT_COMMON_REG->ADC_CTRL2_bit.CLKEN_ADC11 = 1;	// Включаем тактовый сигнал
  
  /* Деинициализация
   * Отключаем все компараторы (регистр DCCTLn)
   * Для этого в поле CHNL регистра DCCTLn может быть записан номер канала,
   * который выбран в регистре MUX или любое значение из диапазона
   * от 18h до 1Fh. Запишем везде 18h.
   */
  for(i=0;i<24;i++)
  {
      NT_ADC->DCCTL[i] = (0x18 << 16);
  }
  
  // Запрет всех секвенсоров
  NT_ADC->ACTSS = 0;
  
  // Сброс счётчиков прерываний и измерений
  NT_ADC->SEQ[0].OP = 0;
  NT_ADC->SEQ[1].OP = 0;
  NT_ADC->SEQ[2].OP = 0;
  NT_ADC->SEQ[3].OP = 0;
  NT_ADC->SEQ[4].OP = 0;
  NT_ADC->SEQ[5].OP = 0;
  NT_ADC->SEQ[6].OP = 0;
  NT_ADC->SEQ[7].OP = 0;
  
  // Включаем секвенсор
  NT_ADC->ACTSS_bit.ASEN0 = 1;
  
  // Событие запуска
  NT_ADC->EMUX_bit.EM0 = 6;		// Сигнал от ШИМ0
  
  // Разрешение работы секвенсора
  NT_ADC->PSSI_bit.SS0 = 1;
  
  //Перезапуск секвенсора не требуется
  NT_ADC->SEQ[0].CTL_bit.RCNT = 0;
  
  // Режим функционирования - однополярный.
  NT_ADC->PP_bit[6].OM  = 0x3;
  NT_ADC->PP_bit[7].OM  = 0x3;
  NT_ADC->PP_bit[8].OM  = 0x3;
  NT_ADC->PP_bit[9].OM  = 0x3;
  NT_ADC->PP_bit[10].OM = 0x3;
  NT_ADC->PP_bit[11].OM = 0x3;
  
  // Включение модулей АЦП
  NT_ADC->PP_bit[6].ENA  = 1;
  NT_ADC->PP_bit[7].ENA  = 1;
  NT_ADC->PP_bit[8].ENA  = 1;
  NT_ADC->PP_bit[9].ENA  = 1;
  NT_ADC->PP_bit[10].ENA = 1;
  NT_ADC->PP_bit[11].ENA = 1;
  
  // Выберем каналы для секвенсора
  NT_ADC->SEQ[0].MUX_bit.CH12 = 1; /* ADC6A  */
  NT_ADC->SEQ[0].MUX_bit.CH13 = 1; /* ADC6B  */
  NT_ADC->SEQ[0].MUX_bit.CH14 = 1; /* ADC7A  */
  NT_ADC->SEQ[0].MUX_bit.CH15 = 1; /* ADC7B  */
  NT_ADC->SEQ[0].MUX_bit.CH16 = 1; /* ADC8A  */
  NT_ADC->SEQ[0].MUX_bit.CH18 = 1; /* ADC9A  */
  NT_ADC->SEQ[0].MUX_bit.CH20 = 1; /* ADC10A */
  NT_ADC->SEQ[0].MUX_bit.CH21 = 1; /* ADC10B */
  NT_ADC->SEQ[0].MUX_bit.CH23 = 1; /* ADC11B */
  
  // Отключаем усреднители на секвенсоре
  NT_ADC->SAC_bit.AVG0 = 0;		// Секвенсор 0
}
Аватара пользователя
MR.Smith
Сообщения: 78
Зарегистрирован: 25 апр 2016, 10:56

Re: К1921ВК01Т электрические параметры АЦП

Сообщение MR.Smith »

bkolbov, не удалось ли Вам воспроизвести описанную ситуацию?
bkolbov
Сообщения: 248
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: К1921ВК01Т электрические параметры АЦП

Сообщение bkolbov »

MR.Smith писал(а): 28 июл 2017, 12:16 bkolbov, не удалось ли Вам воспроизвести описанную ситуацию?
Пока еще не удалось.
Аватара пользователя
MR.Smith
Сообщения: 78
Зарегистрирован: 25 апр 2016, 10:56

Re: К1921ВК01Т электрические параметры АЦП

Сообщение MR.Smith »

bkolbov, разобрался я с АЦП.
При вычитке FIFO для обнаруждения неверного количества элементов я использовал следующую конструкцию:

Код: Выделить всё

if(NT_ADC->SEQ[0].FSTAT_bit.FLOAD != 9)
{
	adcClearFifo();
	NT_ADC->ISC = 0x01;
	return 0;
}
Для того, чтобы проверить срабатывает ли она я разместил внутри breakpoint. Именно эта точка останова и вызывала данный эффект. Наличие точки останова похоже замедляла работу кода, а поскольку запуск секвенсора осуществлялся железно из модуля ШИМ, то реально в буфере скапливалось несколько наборов (2 или 3 раза по 9 измерений).
При выполнении из ОЗУ без каких либо точек останова проблем не наблюдается.
Загадка раскрыта.
Аватара пользователя
MR.Smith
Сообщения: 78
Зарегистрирован: 25 апр 2016, 10:56

Re: К1921ВК01Т электрические параметры АЦП

Сообщение MR.Smith »

Здравствуйте!
Еще один момент встретил непонятный, прошу помощи.
Настроил АЦП по примерам, все работает, но вот результаты преобразований не устраивают.
Код настройки прикрепляю к сообщению.
adc_setup.c
(3.16 КБ) 207 скачиваний
Подаю на вход АЦП (в частности на ADC11A) следующие потенциалы (в скобках результаты преобразований)
0,2135 В (538) - должно быть около: (0,2135/1,5)*4096 = 583
0,3413 В (880) - должно быть около: (0,3413/1,5)*4096 = 932
и т.д.
дельта в около 50 отсчетов АЦП всегда присутствует для любого напряжения.
На других каналах дельта также присутствует, но межет быть меньше (около 20 в лучшем случае).
В чем здесь может быть дело? Замечания у меня только к точности оцифровки, все остальное работает.
Пытался снизить частоту тактирования АЦП - становится только хуже.
Ответить

Вернуться в «32-разрядные микроконтроллеры»