К1921ВК01Т работа с АЦП

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

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

Ответить
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

К1921ВК01Т работа с АЦП

Сообщение Paul125 »

Добрый день! пытаюсь разобраться с АЦП данного МК. Возникло несколько вопросов.
1) Необходимо получить значения с АЦП, привязал компараторы к каждому каналу АЦП и информацию считываю оттуда при заполнении ФИФО секвенсора (вроде верный способ для получения ADC result)?
2) В однополярном режима вопросов по работе нет, а вот в дифференциальном не понятно. В описании написано, что необходимо использовать только один канал АЦП в дифф режиме (хотя можно и 2 настроить), но диапазон измерения сильно сокращается (относительно однополярного) мерить от 2000 до 4095 дискрет, а отрицательные значения вобще оказываются в насыщении.
Возможно как то не так настроено АЦП или секвенсор? Прошу помощи.
Вложения
Vpp = 1.5V (амплитуда каждой полуволны)
Vpp = 1.5V (амплитуда каждой полуволны)
Screenshot.png (51.04 КБ) 1497 просмотров
dav
Сообщения: 208
Зарегистрирован: 14 дек 2015, 09:21
Предприятие: АО НИИЭТ
Откуда: АО НИИЭТ, Воронеж

Re: К1921ВК01Т работа с АЦП

Сообщение dav »

В одиночном режиме диапазон входных напряжений АЦП: (0 - 1,5) В.
В дифференциальном режиме амплитуда дифференциального сигнала ±0,75В относительно средней точки 0,9В, т.е. (0,15 - 1,65) В.

Формулы пересчета АЦП
Однополярный режим:
(10 разрядный): U = (Dadc/1024)*1.5 В
(12 разрядный): U = (Dadc/4096)*1.5 В

Результат преобразования канала в дифференциальном режиме можно вычислить по следующим формулам:
(10 разрядный): dU = (Dadc/512)*1.5 В - 1.5 В
(12 разрядный): dU = (Dadc/2048)*1.5 В - 1.5 В

Для 12-разрядного режима, в дифф. режиме следующие значения:
U(ADC_A) | U(ADC_B) | Mode | CODE(12 bit)
1.65В | 0.15В | A-B | 0xFFF
1.65В | 0.15В | B-A | 0x0

Пример проекта "Запуск АЦП в дифф режиме по событию ШИМ" можно посмотреть в K1921VKx_SDK по ссылке https://bitbucket.org/niietcm4/k1921vkx ... _diff_pwm/

Также параметры АЦП обсуждались на нашем форуме: viewtopic.php?f=37&t=512&start=20#p3587

На нашем форуме также есть тема, в которой собраны вопрос-ответы, ссылки на полезные посты, обзорная и прочая информация по микроконтроллерам К1921ВК01Т (К1921ВК01Т1): viewtopic.php?f=37&t=931
Paul125
Сообщения: 15
Зарегистрирован: 11 май 2022, 17:02
Предприятие: ООО НПП ЭКРА

Re: К1921ВК01Т работа с АЦП

Сообщение Paul125 »

Спасибо, с данной частью разобрался. Но вот незадача, необходимо измерять 12 каналов с заданной частотой и складывать измерения в массив.
Срез с 12 каналов у меня выходит сделать, но когда складываю в массив 3-4 первых значения всегда измеряются неверно, можете подсказать что не так. Делал и без DMA передачу, разницы нет.

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

#include "niietcm4.h"
#include "system_K1921VK01T.h"

#define SYSTEM_CLK	72000000
// общее количество измерений
#define ADC_MEASURE_PACK	99
#define ADC_CH				12
#define FQ_TIM0				2000 // частота в Гц

#if defined (__CMCPPARM__)
#pragma data_alignment=1024
#endif
DMA_ConfigData_TypeDef DMA_CONFIGDATA __ALIGNED(1024);

uint16_t seq1_arr[16] = { 0 };
uint16_t adc_log[12][ADC_MEASURE_PACK] = { 0 };

void timerInit() {

	uint32_t time = 1000000 / FQ_TIM0;

	// инициализация таймера
	RCC_PeriphRstCmd(RCC_PeriphRst_Timer0, ENABLE);
	TIMER_PeriodConfig(NT_TIMER0, SYSTEM_CLK, time);
	TIMER_ITCmd(NT_TIMER0, ENABLE);
	TIMER_Cmd(NT_TIMER0, ENABLE);
	Энвик_EnableIRQ(TIM0_IRQn);
}

void PeriphInit() {
	// переходим на системную частоту 72МГц
	RCC_PLLAutoConfig(RCC_PLLRef_XI_OSC, SYSTEM_CLK);

	// хак, чтобы избежать зависших секвенсоров от выставленных запросов по 0 каналу
	// цифровыми компараторами. Хотя в данном случае это необязательно, т.к. 0-ой канал используется.
	for (uint32_t i = 0; i < 24; i++) {
		ADC_DC_DeInit((ADC_DC_Module_TypeDef) i);
	}

	// делим системную частоту на 6, и получаем тактирование АЦП 12МГц.
	RCC_ADCClkDivConfig(RCC_ADCClk_0, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_1, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_2, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_3, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_4, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_5, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_6, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_7, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_8, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_9, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_10, 2, ENABLE);
	RCC_ADCClkDivConfig(RCC_ADCClk_11, 2, ENABLE);

	RCC_PeriphClkCmd(RCC_PeriphClk_ADC, ENABLE);

	RCC_ADCClkCmd(RCC_ADCClk_0, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_1, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_2, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_3, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_4, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_5, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_6, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_7, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_8, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_9, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_10, ENABLE);
	RCC_ADCClkCmd(RCC_ADCClk_11, ENABLE);

	// настройка модуля АЦП
	ADC_Init_TypeDef ADC_InitStruct;
	ADC_StructInit(&ADC_InitStruct);
	ADC_InitStruct.ADC_Resolution = ADC_Resolution_12bit;
	ADC_InitStruct.ADC_Average = ADC_Average_8;
	ADC_InitStruct.ADC_Measure_A = ADC_Measure_Diff;
	ADC_InitStruct.ADC_Mode = ADC_Mode_Active;
	ADC_Init(ADC_Module_0, &ADC_InitStruct);

	ADC_StructInit(&ADC_InitStruct);
	ADC_InitStruct.ADC_Resolution = ADC_Resolution_12bit;
	ADC_InitStruct.ADC_Average = ADC_Average_8;
	ADC_InitStruct.ADC_Measure_A = ADC_Measure_Diff;
	ADC_InitStruct.ADC_Mode = ADC_Mode_Active;
	ADC_Init(ADC_Module_1, &ADC_InitStruct);

	ADC_StructInit(&ADC_InitStruct);
	ADC_InitStruct.ADC_Resolution = ADC_Resolution_12bit;
	ADC_InitStruct.ADC_Average = ADC_Average_8;
	ADC_InitStruct.ADC_Measure_A = ADC_Measure_Diff;
	ADC_InitStruct.ADC_Mode = ADC_Mode_Active;
	ADC_Init(ADC_Module_2, &ADC_InitStruct);
	ADC_Init(ADC_Module_3, &ADC_InitStruct);
	ADC_Init(ADC_Module_4, &ADC_InitStruct);
	ADC_Init(ADC_Module_5, &ADC_InitStruct);
	ADC_Init(ADC_Module_6, &ADC_InitStruct);
	ADC_Init(ADC_Module_7, &ADC_InitStruct);
	ADC_Init(ADC_Module_8, &ADC_InitStruct);
	ADC_Init(ADC_Module_9, &ADC_InitStruct);
	ADC_Init(ADC_Module_10, &ADC_InitStruct);
	ADC_Init(ADC_Module_11, &ADC_InitStruct);

	// включение модуля АЦП
	ADC_Cmd(ADC_Module_0, ENABLE);
	ADC_Cmd(ADC_Module_1, ENABLE);
	ADC_Cmd(ADC_Module_2, ENABLE);
	ADC_Cmd(ADC_Module_3, ENABLE);
	ADC_Cmd(ADC_Module_4, ENABLE);
	ADC_Cmd(ADC_Module_5, ENABLE);
	ADC_Cmd(ADC_Module_6, ENABLE);
	ADC_Cmd(ADC_Module_7, ENABLE);
	ADC_Cmd(ADC_Module_8, ENABLE);
	ADC_Cmd(ADC_Module_9, ENABLE);
	ADC_Cmd(ADC_Module_10, ENABLE);
	ADC_Cmd(ADC_Module_11, ENABLE);

	// секвенсор 1 работает по таймеру 0
	ADC_SEQ_Init_TypeDef ADC_SEQ_InitStruct;
	ADC_SEQ_DeInit(ADC_SEQ_Module_1);
	ADC_SEQ_InitStruct.ADC_SEQ_StartEvent = ADC_SEQ_StartEvent_TIM; //ADC_SEQ_StartEvent_TIM / ADC_SEQ_StartEvent_SWReq
	ADC_SEQ_InitStruct.ADC_SEQ_SWReqEn = DISABLE;
	ADC_SEQ_InitStruct.ADC_Channels = ADC_Channel_0 | ADC_Channel_2 | ADC_Channel_4 | ADC_Channel_6 | ADC_Channel_8 | ADC_Channel_10 | ADC_Channel_12 | ADC_Channel_14 | ADC_Channel_16 | ADC_Channel_18 | ADC_Channel_20 | ADC_Channel_22;
	ADC_SEQ_InitStruct.ADC_SEQ_ConversionCount = 16;
	ADC_SEQ_InitStruct.ADC_SEQ_ConversionDelay = 2;
	ADC_SEQ_InitStruct.ADC_SEQ_DC = ADC_DC_None;
	ADC_SEQ_Init(ADC_SEQ_Module_1, &ADC_SEQ_InitStruct);
	ADC_SEQ_DMAConfig(ADC_SEQ_Module_1, ADC_SEQ_FIFOLevel_16);

	// включаем секвенсор
	ADC_SEQ_Cmd(ADC_SEQ_Module_1, ENABLE);
}

void DMAInit() {

	// Базовый указатель
	DMA_BasePtrConfig((uint32_t) (&DMA_CONFIGDATA));

	DMA_Init_TypeDef DMA_InitStruct;
	DMA_StructInit(&DMA_InitStruct);

	//-- Ch9
	DMA_StructInit(&DMA_InitStruct);
	DMA_InitStruct.DMA_Channel = DMA_Channel_ADCSEQ1;
	DMA_InitStruct.DMA_ChannelEnable = ENABLE;
	DMA_Init(&DMA_InitStruct);

	//-- Ch10
	DMA_StructInit(&DMA_InitStruct);
	DMA_InitStruct.DMA_Channel = DMA_Channel_10;
	DMA_InitStruct.DMA_ChannelEnable = ENABLE;
	DMA_Init(&DMA_InitStruct);
}

void DMA_ADC_start16(uint16_t *resiver, uint32_t val_copy) {

	ADC_SEQ_DMACmd(ADC_SEQ_Module_1, DISABLE);
	// Инициализация каналов
	DMA_ChannelInit_TypeDef DMA_ChannelInitStruct;
	DMA_ChannelStructInit(&DMA_ChannelInitStruct);
	DMA_ChannelInitStruct.DMA_SrcDataSize = DMA_DataSize_16;
	DMA_ChannelInitStruct.DMA_DstDataSize = DMA_DataSize_16;
	DMA_ChannelInitStruct.DMA_ArbitrationRate = DMA_ArbitrationRate_16;
	DMA_ChannelInitStruct.DMA_Mode = DMA_Mode_Basic;
	DMA_ChannelInitStruct.DMA_SrcDataInc = DMA_DataInc_Disable;
	DMA_ChannelInitStruct.DMA_DstDataInc = DMA_DataInc_16;
	// DMA9 - SEQ1
	DMA_ChannelInitStruct.DMA_TransfersTotal = val_copy;
	DMA_ChannelInitStruct.DMA_SrcDataEndPtr = (uint16_t*) (&NT_ADC->SEQ[1].FIFO);
	DMA_ChannelInitStruct.DMA_DstDataEndPtr = &(resiver[val_copy - 1]);

	DMA_ChannelInitStruct.DMA_SrcProtect.BUFFERABLE = DISABLE;
	DMA_ChannelInitStruct.DMA_SrcProtect.PRIVELGED = ENABLE;
	DMA_ChannelInitStruct.DMA_SrcProtect.CACHEABLE = DISABLE;

	DMA_ChannelInitStruct.DMA_DstProtect.BUFFERABLE = DISABLE;
	DMA_ChannelInitStruct.DMA_DstProtect.PRIVELGED = ENABLE;
	DMA_ChannelInitStruct.DMA_DstProtect.CACHEABLE = DISABLE;

	DMA_ChannelInitStruct.DMA_NextUseburst = ENABLE;

	DMA_ChannelInit(&DMA_CONFIGDATA.PRM_DATA.CH[9], &DMA_ChannelInitStruct);

	DMA_ChannelEnableCmd(DMA_Channel_ADCSEQ1, ENABLE);
	DMA_MasterEnableCmd(DISABLE);
	DMA_MasterEnableCmd(ENABLE);
	ADC_SEQ_DMACmd(ADC_SEQ_Module_1, ENABLE);
}

void DMA_mem_copy16(uint16_t *source, uint16_t *resiver) {

	DMA_MasterEnableCmd(DISABLE);
	DMA_ChannelInit_TypeDef DMA_ChannelInitStruct;
	/* источник */
	DMA_ChannelInitStruct.DMA_SrcDataEndPtr = source;
	DMA_ChannelInitStruct.DMA_SrcDataSize = DMA_DataSize_16;
	DMA_ChannelInitStruct.DMA_SrcDataInc = DMA_DataInc_Disable;
	DMA_ChannelInitStruct.DMA_SrcProtect.BUFFERABLE = DISABLE;
	DMA_ChannelInitStruct.DMA_SrcProtect.PRIVELGED = DISABLE;
	DMA_ChannelInitStruct.DMA_SrcProtect.CACHEABLE = DISABLE;
	/* приемник */
	DMA_ChannelInitStruct.DMA_DstDataEndPtr = resiver;
	DMA_ChannelInitStruct.DMA_DstDataSize = DMA_DataSize_16;
	DMA_ChannelInitStruct.DMA_DstDataInc = DMA_DataInc_Disable;
	DMA_ChannelInitStruct.DMA_DstProtect.BUFFERABLE = DISABLE;
	DMA_ChannelInitStruct.DMA_DstProtect.PRIVELGED = DISABLE;
	DMA_ChannelInitStruct.DMA_DstProtect.CACHEABLE = DISABLE;
	/* общее */
	DMA_ChannelInitStruct.DMA_NextUseburst = DISABLE;
	DMA_ChannelInitStruct.DMA_ArbitrationRate = DMA_ArbitrationRate_1;
	DMA_ChannelInitStruct.DMA_TransfersTotal = 1;
	DMA_ChannelInitStruct.DMA_Mode = DMA_Mode_Basic;

	DMA_ChannelInit(&DMA_CONFIGDATA.PRM_DATA.CH[10], &DMA_ChannelInitStruct);

	DMA_ChannelEnableCmd(DMA_Channel_10, ENABLE);
	DMA_MasterEnableCmd(ENABLE);
	DMA_SWRequestCmd(DMA_Channel_10);
}

static uint16_t arr_address = 0;
uint8_t dma_irq_flag = 0;

int main() {
	timerInit();
	PeriphInit();
	DMAInit();

	while (1) {

		if (dma_irq_flag) {

			dma_irq_flag = 0;

			if (arr_address > (ADC_MEASURE_PACK - 1)) {
					arr_address = 0;
				}

				for (uint8_t i = 0; i < ADC_CH; i++) {
				DMA_mem_copy16(&seq1_arr[i], &adc_log[i][arr_address]);
				}

				arr_address++;

		}
	}
}

void TIM0_IRQHandler() {

	DMA_ADC_start16(seq1_arr, 16);

	dma_irq_flag = 1;

	TIMER_ITStatusClear(NT_TIMER0);

}


Вложения
Screenshot_1.png
Screenshot_1.png (35.48 КБ) 801 просмотр
Ответить

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