Оптимизация работы АЦП

This commit is contained in:
Dmitry Shpak 2021-08-09 16:22:08 +03:00
parent c7fb6db1d2
commit 7b592829d8
5 changed files with 66 additions and 83 deletions

View File

@ -5,7 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1428732868423050069" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1548003095956541040" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@ -16,7 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1413074244047209090" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="1588485529958774947" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@ -195,6 +195,7 @@ void SM_Sys_Init(TSM_Sys *p) {
//! \memberof TSM_Sys
void SM_Sys_Fast_Calc(TSM_Sys *p) {
sm_net.fast_calc(&sm_net);//ðàñ÷åò êîììóíèêàöèîííûõ äðàéâåðîâ
adc.fast_calc(&adc);//расчет АЦП
if (drv_params.sens_type == POS_SENSOR_TYPE_ENCODER) // òèïå äàò÷èêà âûáðàí ýíêîäåð
posspeedEqep.calc(&posspeedEqep); //ÄÏÐ ýíêîäåð
if (drv_params.sens_type == POS_SENSOR_TYPE_HALL){ // òèïå äàò÷èêà âûáðàí ÄÏÐ Õîëëà
@ -226,6 +227,8 @@ void SM_Sys_Fast_Calc(TSM_Sys *p) {
cur_par.calc(&cur_par); //Ðàñ÷åò òåêóùèõ ïîêàçàòåëåé ïðèâîäà
drv_params.sens_type = drv_params.sens_type & 7; //Îòñåêàåì âåðõíþþ ÷àñòü ïåðåìåííîé, òàì ìóñîð
ADC->SEQSYNC_bit.GSYNC = 1; // Запуск АЦП
#ifdef WATCHDOG_ON
WatchDog.calc();//åñëè ñòîðîæåâîé òàéìåð èñïîëüçóåòñÿ, ñáðàñûâàåì åãî çäåñü
#endif //WATCHDOG_ON

View File

@ -35,67 +35,60 @@
#include "main.h"
//!Инициализация.
//! Настраиваются секвенсоры и тип оцифровки данных. каналы для оцифровки, частота.
//! В данном случае оцифровка происходит по событию таймера,частота которого
//! равна частоте ШИМ, чтобы измерять ровно посередине периода ШИМ (требуется для шунтовых
//! датчиков тока)
//Запуск оцифровки производится по таймеру NT_PWM3, который синхронизирован с другими таймерами ШИМ.
//Оцифрованные измерения складываются в ФИФО. Каждый канал АЦП настроен на отдельный секвенсор с ФИФО длиной до 16 измерений.
//В прерывании с частотой 10 кГц данные забираются из ФИФО и складываются в кольцевые массивы (старые затираются новыми).
//В том же прерывании из кольцевого массива берется N последних точек и из них вычисляется среднее арифметическое.
//Число выборок для усреднения N зависит от частоты ШИМ и равна Fшим/10кГц. Если частоты ШИМ меньше 10 кГц, то берется одна выборка, если больше 40 кГц - 4 выборки.
//К вычисленному среднему значению добавляется калибровочный сдвиг, и оно умножается на коэффициент измерения, в результате получается окончательный результат измерения.
//! \memberof TAdcDrv
//!
void AdcDrv_init(TAdcDrv *p) {
PWM0->ETSEL_bit.SOCAEN = 1;
PWM0->ETSEL_bit.SOCASEL = ET_CTR_ZERO;
PWM0->ETPS_bit.SOCAPRD = 0;
Uint32 AdcClock, AdcDiv, trash;
//! Èíèöèàëèçàöèÿ ÀÖÏ ïðè ïðîãðàììíîì çàïóñêå áåç èñïîëüçîâàíèè ïðåðûâàíèé è ôèôî
// Сколько SYSCLKOUT тактов занимает период ШИМ
Uint32 pwmPrd = PWM0->TBPRD * (SystemCoreClock / APB0BusClock);
if (PWM0->TBCTL_bit.CTRMODE == TB_COUNT_UPDOWN)
pwmPrd = pwmPrd << 1;
Uint32 trash;
// Çàïðåò âñåõ ñåêâåíñîðîâ
ADC->SEQSYNC = 0;
// Сколько SYSCLKOUT тактов занимает один такт АЦП (AdcDiv)
AdcDiv = 2 * (RCU->ADCCFG_bit.DIVN + 1); // Итого деление частоты
AdcClock = SystemCoreClock / AdcDiv; // Снимаем сброс
// Ñáðîñ Ñ÷åò÷èêîâ ïðåðûâíèé è èçìåðåíèé
ADC->SEQ[0].SCVAL = 0;
ADC->SEQ[1].SCVAL = 0;
ADC->SEQ[2].SCVAL = 0;
ADC->SEQ[3].SCVAL = 0;
ADC->SEQ[4].SCVAL = 0;
ADC->SEQ[5].SCVAL = 0;
ADC->SEQ[6].SCVAL = 0;
ADC->SEQ[7].SCVAL = 0;
//Инициализация ADC
ADC->ACTL[0].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
//Âêëþ÷àåì ñåêâåíñîð
ADC->SEQSYNC_bit.SYNC0 = 1;
//Ñòàâèì ìàñêó ïðåðûâàíèÿ
ADC->IM_bit.SEQIM0 = 1;
//Íàñòðàèâàåì èñòî÷íèê çàïóñêà ïðîãðàììíûé
ADC->EMUX_bit.EM0 = ADC_EMUX_EM0_SwReq;
// Ðàçðåøèòü ñåêâåíñîðîâ
ADC->SEQEN_bit.SEQEN0 = 1;
//Íàñòðàèâàåì êîëè÷åñòâî ïåðåçàïóñêîâ ñåêâåíñîðà RCNT + 1
ADC->SEQ[0].SCCTL_bit.RCNT = 3;
ADC->SEQ[0].SCCTL_bit.RAVGEN = 1; // Ðàçðåøåíî óñðåäíåíèå
// Íåò ïðåðûâàíèÿ
ADC->SEQ[0].SCCTL_bit.ICNT = 0;
ADC->SEQ[0].SRQCTL_bit.RQMAX = 0x6;
ADC->ACTL[0].ACTL_bit.ADCEN = 0x1; // Ðàçðåøàåì ðàáîòó ÀÖÏ
ADC->ACTL[0].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[1].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[1].ACTL_bit.ADCEN = 0x1; // Ðàçðåøàåì ðàáîòó ÀÖÏ
ADC->ACTL[1].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[2].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[2].ACTL_bit.ADCEN = 0x1; // Ðàçðåøàåì ðàáîòó ÀÖÏ
ADC->ACTL[2].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
ADC->ACTL[3].ACTL_bit.ADCEN = 0x1; // Разрешаем работу АЦП
ADC->ACTL[3].ACTL_bit.ADCEN = 0x1; // Ðàçðåøàåì ðàáîòó ÀÖÏ
ADC->ACTL[3].ACTL_bit.SELRES = ADC_ACTL_ACTL_SELRES_12bit;
//Настройка секвенсора 0
// CH0, CH1, CH2, CH3.
ADC->EMUX_bit.EM0 = ADC_EMUX_EM0_PWM012A; // Запуск от таймера
ADC->SEQSYNC = ADC_SEQSYNC_SYNC0_Msk; // Разрешить секвенсор SEQ0
ADC->SEQ[0].SRQCTL_bit.RQMAX = 0x6; // Опрашивать 4 канала за раз = RQMAX + 1
ADC->SEQ[0].SRQSEL0_bit.RQ0 = 13; // Какой вход АЦП когда опрашивается
ADC->SEQ[0].SRQSEL0_bit.RQ1 = 19; // --//--
ADC->SEQ[0].SRQSEL0_bit.RQ2 = 1; // --//--
ADC->SEQ[0].SRQSEL0_bit.RQ3 = 31; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ4 = 18; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ5 = 27; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ6 = 29; // --//--
ADC->SEQ[0].SCCTL_bit.RCNT = 3; // Делать ещё три перезапуска после первого запуска
ADC->SEQ[0].SRTMR_bit.VAL = pwmPrd / (ADC->SEQ[0].SCCTL_bit.RCNT + 1) / AdcDiv; // Пауза между пусками АЦП на период ШИМ в тактах ACLK
ADC->SEQ[0].SCCTL_bit.RAVGEN = 1; // Разрешить усреднять по 4 точкам
ADC->SEQEN_bit.SEQEN0 = 1; // Разрешить секвенсор 0
ADC->SEQ[0].SCCTL_bit.ICNT = 6; // Вызов прерывания через каждые (ICNT + 1) записи в fifo
// Очистка FIFO
while (ADC->SEQ[0].SFLOAD)
trash = ADC->SEQ[0].SFIFO;
ADC->SEQ[0].SRQSEL0_bit.RQ0 = 13; // Êàêîé âõîä ÀÖÏ êîãäà îïðàøèâàåòñÿ
ADC->SEQ[0].SRQSEL0_bit.RQ1 = 19; // --//--
ADC->SEQ[0].SRQSEL0_bit.RQ2 = 1; // --//--
ADC->SEQ[0].SRQSEL0_bit.RQ3 = 20; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ4 = 15; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ5 = 27; // --//--
ADC->SEQ[0].SRQSEL1_bit.RQ6 = 29; // --//--
// Æä¸ì, ïîêà ÀÖÏ âûñòàâèò ôëàã "ÃÎÒÎÂ" (ìîæíî âñòàâèòü ýòîò öèêë ïîñëå "ADCEN = 1")
while (!ADC->ACTL[0].ACTL_bit.ADCRDY) {};
@ -103,10 +96,6 @@ void AdcDrv_init(TAdcDrv *p) {
while (!ADC->ACTL[2].ACTL_bit.ADCRDY) {};
while (!ADC->ACTL[3].ACTL_bit.ADCRDY) {};
// Разрешить прерывание от первого секвенсера
ADC->IM_bit.SEQIM0 = 1;
NVIC_EnableIRQ(ADC_SEQ0_IRQn);
NVIC_SetPriority(ADC_SEQ0_IRQn, IRQ_PRIORITY_ADC);
}
@ -121,24 +110,28 @@ void AdcDrv_fast_calc(TAdcDrv *p) {
Uint32 trash;
Uint16 pot, ain1, ain2, temper;
// Если всё пошло хорошо, то в ФИФЕ будут уже усреднённые результаты - 4 штуки.
p->IA_temp = ADC->SEQ[0].SFIFO;
p->IC_temp = ADC->SEQ[0].SFIFO;
p->Udc_temp = ADC->SEQ[0].SFIFO;
pot = ADC->SEQ[0].SFIFO;
ain1 = ADC->SEQ[0].SFIFO;
ain2 = ADC->SEQ[0].SFIFO;
temper = ADC->SEQ[0].SFIFO;
p->IA_temp = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
p->IC_temp = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
// Очистка FIFO на случай, если почему-то там оказалось больше чем надо значений (бывает после остановки житагом)
while (ADC->SEQ[0].SFLOAD)
trash = ADC->SEQ[0].SFIFO;
p->Udc_temp = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
pot = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
ain1 = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
ain2 = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
p->T_temp = (int16) ADC->SEQ[0].SFIFO_bit.DATA;
// Ïðåîáðàçîâàíèå
p->Imeas_a = p->IaGainNom * (((p->IA_temp<< 4) + p->Imeas_a_offset));
p->Imeas_c = p->IcGainNom * (((p->IC_temp<< 4) + p->Imeas_c_offset));
p->Udc_meas = p->UdcGainNom * (p->Udc_temp + p->Udc_meas_offset);
p->Imeas_b = -p->Imeas_a - p->Imeas_c;
p->T_meas = p->TGainNom*(p->T_temp);
// Î÷èñòêà ÔÈÔÎ
while (ADC->SEQ[0].SFLOAD)
trash = ADC->SEQ[0].SFIFO;
}
//!Ìåäëåííûé ðàñ÷åò.
@ -180,25 +173,12 @@ void AdcDrv_fast_calc(TAdcDrv *p) {
//! \memberof TAdcDrv
void AdcDrv_slow_calc(TAdcDrv *p) {
// Пересчёт пауз между перезапусками
volatile Uint16 pwmPrd = PWM0->TBPRD * (SystemCoreClock / APB0BusClock);
// Если считает вверх-вниз, то период на деле в два раза больше
if (PWM0->TBCTL_bit.CTRMODE == TB_COUNT_UPDOWN)
pwmPrd = pwmPrd << 1;
// Делитель частоты АЦП
Uint16 AdcDiv = 2 * (RCU->ADCCFG_bit.DIVN + 1);
if (pwmPrd < 1000) pwmPrd = 1000;
// Пауза между перезапускмами
// VAL = (Период ШИМ в тактах SysClkOut) / (Кол-во перезапусков) / (Делитель частоты АЦП)
ADC->SEQ[0].SRTMR_bit.VAL = pwmPrd / (ADC->SEQ[0].SCCTL_bit.RCNT + 1) / AdcDiv;
p->IaGainNom = _IQ16mpy(p->Imeas_a_gain, drv_params._1_I_nom) << 1;
p->IbGainNom = _IQ16mpy(p->Imeas_b_gain, drv_params._1_I_nom) << 1;
p->IcGainNom = _IQ16mpy(p->Imeas_c_gain, drv_params._1_I_nom) << 1;
p->UdcGainNom = _IQ16mpy(p->Udc_meas_gain, drv_params._1_Udc_nom) << 4;
p->TGainNom = _IQ16mpy(p->T_meas_gain, _IQ(0.05)) << 4; //0.05 = 1/20
}
//! Ìèëëèñåêóíäíûé ðàñ÷åò

View File

@ -322,6 +322,6 @@ void QEP1_IRQHandler(void)
//Прерывание вызывается один раз на периоде ШИМ и забирает 4 результата за период
void ADC_SEQ0_IRQHandler (void) {
adc.fast_calc(&adc);
ADC->IC_bit.SEQIC0 = 1;
// adc.fast_calc(&adc);
// ADC->IC_bit.SEQIC0 = 1;
}

View File

@ -3776,7 +3776,7 @@
<description description=""/>
</obj_5114h.01h>
<obj_5114h.02h DataType="Editable" name="Ðåæèì ðàáîòû" addr="sm_ctrl.run_mode" group="14" groupName="Íàñòðîéêè ÑÓ" fullgroup="28" callback="">
<format Type="StandartNum" Size="16" Signed="false"/>
<format Type="Bit" Visualization="Text" Length="5" StartBit="0"/>
<text text="ÐåæÐàá" textID="411"/>
<defaults default="4" min="" max=""/>
<description description="Æåëàåìîå ñîñòîÿíèå ðàáîòû ïðèâîäà. 5 - äàò÷èêîâîå, 4 - èñòî÷íèê òîêà, 3 - ñêàëÿðíîå óïðàâëåíèå U(f), 2 - ðåæèì óæåðæàíèÿ ïîä òîêîì."/>