19 Ekim 2019, 17:50:31

Haberler:

Eposta uyarılarını yanıtlamayınız ( ! ) https://bit.ly/2J7yi0d


STM32F303K8x ADC Injected Sequencer problemi

Başlatan Cemre., 05 Ekim 2019, 21:57:32

Cemre.

Merhaba,

STM32F303K8x işlemcisinde ADC2 ile Injected Conversation kullanarak 3 kanal ADC dönüşümü yapmak istiyorum. Bu dönüşümü TIM15 TRGO Yükselen Kenar ile tetikleyecek şekilde ayarlıyorum.

Projeyi CubeMX kullanarak Low Layer kütüphaneler üzerinden üretiyorum.

Yaşadığım sorun şu şekilde.
ADC2->JSQR register'ının JSQx bitleri olması gerektiği gibi ayarlanamıyor.
Normal şartlarda JSQ1 = 0x01, JSQ2 = 0x02, JSQ3 = 0x03, JSQ4 = 0x04 şeklinde olması gerekirken
yalnızca JSQ1 = 0x01 diğerleri 0x00 olarak gözüküyor Debug ekranında. Bu nedenle yalnızca Rank1'e ait Channel1 çevrime giriyor. Diğerleri çevrime girmiyor.

Ancak, ben elle Debug ekranından diğer JSQx bitlerini yukarıdaki değerlerle değiştirirsem her şey sorunsuz çalışıyor.

LL kütüphanede bu ayarları yapan fonksiyon LL_ADC_INJ_SetSequencerRanks
Benim ADC ayarlarımda her kanal için ayrı ayrı bu ayar yapılıyor. Ancak yalnızca JSQ1'e karşılık gelen değer doğru bir şekilde yazılırken diğerlerinin hiçbir etkisi olmuyor.

Bunun sebebi ne olabilir?

LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_1LL_ADC_CHANNEL_1);
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_2LL_ADC_CHANNEL_2);
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_3LL_ADC_CHANNEL_3);
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_4LL_ADC_CHANNEL_4);

Cemre.

CubeMX'in ürettiği ADC Init Fonksiyonu

void MX_ADC2_Init(void)
{
  
LL_ADC_InitTypeDef ADC_InitStruct = {0};
  
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
  
LL_ADC_INJ_InitTypeDef ADC_INJ_InitStruct = {0};

  
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
  
/* Peripheral clock enable */
  
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_ADC12);
  
  
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
  
/**ADC2 GPIO Configuration  
  PA4   ------> ADC2_IN1
  PA5   ------> ADC2_IN2
  PA6   ------> ADC2_IN3
  PA7   ------> ADC2_IN4 
  */
  
GPIO_InitStruct.Pin iCurrent_U_Pin|iCurrent_V_Pin|iCurrent_W_Pin|iVoltage_Bus_Pin;
  
GPIO_InitStruct.Mode LL_GPIO_MODE_ANALOG;
  
GPIO_InitStruct.Pull LL_GPIO_PULL_NO;
  
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  
/* ADC2 interrupt Init */
  
NVIC_SetPriority(ADC1_2_IRQnNVIC_EncodePriority(NVIC_GetPriorityGrouping(),00));
  
NVIC_EnableIRQ(ADC1_2_IRQn);

  
/** Common config 
  */
  
ADC_InitStruct.Resolution LL_ADC_RESOLUTION_12B;
  
ADC_InitStruct.DataAlignment LL_ADC_DATA_ALIGN_RIGHT;
  
ADC_InitStruct.LowPowerMode LL_ADC_LP_MODE_NONE;
  
LL_ADC_Init(ADC2, &ADC_InitStruct);
  
ADC_REG_InitStruct.SequencerLength LL_ADC_REG_SEQ_SCAN_DISABLE;
  
ADC_REG_InitStruct.SequencerDiscont LL_ADC_REG_SEQ_DISCONT_DISABLE;
  
ADC_REG_InitStruct.ContinuousMode LL_ADC_REG_CONV_SINGLE;
  
ADC_REG_InitStruct.DMATransfer LL_ADC_REG_DMA_TRANSFER_LIMITED;
  
ADC_REG_InitStruct.Overrun LL_ADC_REG_OVR_DATA_OVERWRITTEN;
  
LL_ADC_REG_Init(ADC2, &ADC_REG_InitStruct);
  
LL_ADC_DisableIT_EOC(ADC2);
  
LL_ADC_DisableIT_EOS(ADC2);
  
LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(ADC2), LL_ADC_CLOCK_ASYNC_DIV1);
  
/** Configure Injected Channel 
  */
  
ADC_INJ_InitStruct.TriggerSource LL_ADC_INJ_TRIG_EXT_TIM15_TRGO;
  
ADC_INJ_InitStruct.SequencerLength LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS;
  
ADC_INJ_InitStruct.SequencerDiscont LL_ADC_INJ_SEQ_DISCONT_DISABLE;
  
ADC_INJ_InitStruct.TrigAuto LL_ADC_INJ_TRIG_INDEPENDENT;
  
LL_ADC_INJ_Init(ADC2, &ADC_INJ_InitStruct);
  
LL_ADC_INJ_SetQueueMode(ADC2LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE);
  
LL_ADC_DisableIT_JEOC(ADC2);
  
LL_ADC_DisableIT_JEOS(ADC2);
  
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_1LL_ADC_CHANNEL_1);
  
LL_ADC_SetChannelSamplingTime(ADC2LL_ADC_CHANNEL_1LL_ADC_SAMPLINGTIME_1CYCLE_5);
  
LL_ADC_SetChannelSingleDiff(ADC2LL_ADC_CHANNEL_1LL_ADC_SINGLE_ENDED);
  
LL_ADC_INJ_SetTriggerEdge(ADC2LL_ADC_INJ_TRIG_EXT_RISING);
  
/** Configure Injected Channel 
  */
  
LL_ADC_INJ_Init(ADC2, &ADC_INJ_InitStruct);
  
LL_ADC_INJ_SetQueueMode(ADC2LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE);
  
LL_ADC_DisableIT_JEOC(ADC2);
  
LL_ADC_DisableIT_JEOS(ADC2);
  
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_2LL_ADC_CHANNEL_2);
  
LL_ADC_SetChannelSamplingTime(ADC2LL_ADC_CHANNEL_2LL_ADC_SAMPLINGTIME_1CYCLE_5);
  
LL_ADC_SetChannelSingleDiff(ADC2LL_ADC_CHANNEL_2LL_ADC_SINGLE_ENDED);
  
LL_ADC_INJ_SetTriggerEdge(ADC2LL_ADC_INJ_TRIG_EXT_RISING);
  
/** Configure Injected Channel 
  */
  
LL_ADC_INJ_Init(ADC2, &ADC_INJ_InitStruct);
  
LL_ADC_INJ_SetQueueMode(ADC2LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE);
  
LL_ADC_DisableIT_JEOC(ADC2);
  
LL_ADC_DisableIT_JEOS(ADC2);
  
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_3LL_ADC_CHANNEL_3);
  
LL_ADC_SetChannelSamplingTime(ADC2LL_ADC_CHANNEL_3LL_ADC_SAMPLINGTIME_1CYCLE_5);
  
LL_ADC_SetChannelSingleDiff(ADC2LL_ADC_CHANNEL_3LL_ADC_SINGLE_ENDED);
  
LL_ADC_INJ_SetTriggerEdge(ADC2LL_ADC_INJ_TRIG_EXT_RISING);
  
/** Configure Injected Channel 
  */
  
LL_ADC_INJ_Init(ADC2, &ADC_INJ_InitStruct);
  
LL_ADC_INJ_SetQueueMode(ADC2LL_ADC_INJ_QUEUE_2CONTEXTS_LAST_ACTIVE);
  
LL_ADC_DisableIT_JEOC(ADC2);
  
LL_ADC_DisableIT_JEOS(ADC2);
  
LL_ADC_INJ_SetSequencerRanks(ADC2LL_ADC_INJ_RANK_4LL_ADC_CHANNEL_4);
  
LL_ADC_SetChannelSamplingTime(ADC2LL_ADC_CHANNEL_4LL_ADC_SAMPLINGTIME_1CYCLE_5);
  
LL_ADC_SetChannelSingleDiff(ADC2LL_ADC_CHANNEL_4LL_ADC_SINGLE_ENDED);
  
LL_ADC_INJ_SetTriggerEdge(ADC2LL_ADC_INJ_TRIG_EXT_RISING);

}

Cemre.

Sorunun kaynağını buldum. Yalnız CubeMX'in bu tuzağa düşmesi, dolayısıyla beni de düşürmesi ilginç.

Sorun Injected Conversion'un Context yapısından kaynaklanıyor. JSQR register'ına her bir Write erişimi bir Context sayılıyor ve bu Context'ler Queue'ya alınıyor. Ancak ADC Init fonksiyonu her bir değişiklik için ayrı ayrı JSQR register'ına eriştiğinden sıradaki ilk değişiklik olan JSQ1 işlevsel olabiliyor. Çünkü en fazla 2 Context olabiliyor (sanırım).

LL_ADC_INJ_SetSequencerRanks fonksiyonu yerine JSQR register'ı üzerinde yapılacak değişiklikleri tek seferde yapmaya yarayan LL_ADC_INJ_ConfigQueueContext fonksiyonu kullanılarak Init işlemi gerçekleştirildiğinde sorun kalmıyor. Ancak bu Context yapısını kullanmıyor olmamdan ötürü bu özelliğin Disable olması gerektiğini düşünmüştüm, bu nedenle üzerine düşmemiştim. CubeMX'in ise bu şekilde bir Init'e izin vermesi ilginç geldi.

Değerli yorumlarınızı bekliyorum.

mufitsozen

Alıntı yapılan: Cemre. - 05 Ekim 2019, 23:03:36Değerli yorumlarınızı bekliyorum.

Benim 2 kurusluk yorumum asagida:

UM1786 icinde JSQR arayarak baslardim ise, ornegin "uint32_t ADC_InjectionConfigTypeDef::ChannelCount
Number of channels in the injected sequence" nasil kullaniliyor onu arastirirdim mesela.


Dünyanın en büyük sorunu, cahiller özgüven içindeyken akıllı insanların kuşkuyla dolu olmasıdır.

Cemre.

Ben de bu dokümanı referans alarak çözüme ulaştım.


Ref Manual de bahsediyor, ben ilk bakışta algılayamamıştım.


apsis

06 Ekim 2019, 02:11:34 #5 Son düzenlenme: 06 Ekim 2019, 02:13:04 apsis
.
"Makineye Beyin" MEKATRONİK