Добрый день! пытаюсь разобраться с АЦП данного МК. Возникло несколько вопросов.
1) Необходимо получить значения с АЦП, привязал компараторы к каждому каналу АЦП и информацию считываю оттуда при заполнении ФИФО секвенсора (вроде верный способ для получения ADC result)?
2) В однополярном режима вопросов по работе нет, а вот в дифференциальном не понятно. В описании написано, что необходимо использовать только один канал АЦП в дифф режиме (хотя можно и 2 настроить), но диапазон измерения сильно сокращается (относительно однополярного) мерить от 2000 до 4095 дискрет, а отрицательные значения вобще оказываются в насыщении.
Возможно как то не так настроено АЦП или секвенсор? Прошу помощи.
К1921ВК01Т работа с АЦП
Модераторы: ea, dav, bkolbov, Alis, pip, _sva_
К1921ВК01Т работа с АЦП
- Вложения
-
- Vpp = 1.5V (амплитуда каждой полуволны)
- Screenshot.png (51.04 КБ) 1393 просмотра
-
- Сообщения: 179
- Зарегистрирован: 14 дек 2015, 09:21
- Предприятие: АО НИИЭТ
- Откуда: АО НИИЭТ, Воронеж
Re: К1921ВК01Т работа с АЦП
В одиночном режиме диапазон входных напряжений АЦП: (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
В дифференциальном режиме амплитуда дифференциального сигнала ±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
Re: К1921ВК01Т работа с АЦП
Спасибо, с данной частью разобрался. Но вот незадача, необходимо измерять 12 каналов с заданной частотой и складывать измерения в массив.
Срез с 12 каналов у меня выходит сделать, но когда складываю в массив 3-4 первых значения всегда измеряются неверно, можете подсказать что не так. Делал и без DMA передачу, разницы нет.
Срез с 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 (35.48 КБ) 697 просмотров