问题与微控制器STM32L031G6UxS有关。 我使用计时器来触发ADC,然后使用DMA将数据(整个序列)传输到RAM。 使用ADC,我扫描通道1、8和9。实际上,由于SCANDIR = 0(从CH0扫描到CHx),因此读出阵列中的数据应遵循该方向:
ADCReadOut [0] = ValueCH1
ADCReadOut [1] = ValueCH8
ADCReadOut [2] = ValueCH9
我目前有以下奇怪行为:
ADCReadOut [0] = ValueCH9
ADCReadOut [1] = ValueCH1
ADCReadOut [2] = ValueCH8
正如您所看到的,这些值被替换为一个条目。
下面的代码显示了适当的实现。
#define GPIO_ADC_VP_PORT (ps_GPIO_PORT_A)
#define GPIO_ADC_VP_BIT (u32_GPIO_PIN_1)
#define GPIO_ADC_PREAMP_POS_PORT (ps_GPIO_PORT_B)
#define GPIO_ADC_PREAMP_POS_BIT (u32_GPIO_PIN_0)
#define GPIO_ADC_PREAMP_NEG_PORT (ps_GPIO_PORT_B)
#define GPIO_ADC_PREAMP_NEG_BIT (u32_GPIO_PIN_1)
#define ADC1_TRIGGER ( ADC_CFGR1_EXTSEL_2 ) /* TIM22 (TRGO) connected to TRG4 of ADC1 */
#define ADC1_SMPT ( ADC_SMPR_SMP_1 | ADC_SMPR_SMP_0 ) /* Sampling time: 12.5 ADC clock cylce */
#define ADC1_CHANNELS ( ADC_CHANNEL_1 | ADC_CHANNEL_8 | ADC_CHANNEL_9 ) /* VP, Preamp pos, Preamp neg */
#define ADC1_DMA ( DMA1_Channel1 )
#define DMA_DATA_COUNT ( 3 )
...
/*--- TIM22 / ADC1 / DMA1 ---*/
v_Timer22_Init( pb_UseEdsk_Flag );
v_Adc1_Init( &au16_ReadoutBufferAdc1[0] );
v_Adc1_Calibrate();
/*--- Enable second level hardware ---*/
/* Enable DMA1 */
ADC1_DMA->CCR |= DMA_CCR_EN;
/* Enable ADC1 */
ADC1->CR |= ADC_CR_ADEN;
/* Start ADC1 and corresponding timer */
ADC1->CR |= ADC_CR_ADSTART;
v_StartTimer22();
...
static void v_Timer22_Init( bool_t* pb_UseEdsk_Flag )
{
/* OC1REF signal is used as trigger output: TRGO triggers ADC1 */
ADC1_TIMER->CR2 |= TIM_CR2_MMS_2;
/* Prescaler */
if( *pb_UseEdsk_Flag )
{
ADC1_TIMER->PSC = ADC1_TIMER_PRESCALER_EDSK;
}
else
{
ADC1_TIMER->PSC = ADC1_TIMER_PRESCALER_ANALOG;
}
/* Auto reload register */
ADC1_TIMER->ARR = ADC1_TIMER_RELOAD_VALUE;
/* Delay until ADC1 is triggerd: duty cycle off time */
ADC1_TIMER->CCR1 = ACD1_TIMER_CYCLE_OFF_VALUE;
/* Configure channel 1 as output */
ADC1_TIMER->CCMR1 &= ~TIM_CCMR1_CC1S;
/* Configure channel 1 to PWM Mode 2 (OC1M = 0b111),
channel 1 is inactive as long as TIM22_CNT < TIM22_CCR1 */
ADC1_TIMER->CCMR1 |= ( TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0 );
}
static void v_StartTimer22( void )
{
/* Reset timer count register */
ADC1_TIMER->CNT = 0;
/* Start timer */
ADC1_TIMER->CR1 |= TIM_CR1_CEN;
}
static void v_Adc1_Init( uint16_t* pu16_MemAdr )
{
/*--- ADC1 part ----*/
/* Select PCLK divided by 1 as ADC clock */
ADC1->CFGR2 |= ADC_CLOCKPRESCALER_PCLK_DIV1;
/* Enable voltage regulator */
ADC1->CR |= ADC_CR_ADVREGEN;
/* Every time a trigger is received, 1 sequence is sampled */
ADC1->CFGR1 &= ~ADC_CFGR1_DISCEN;
/* Insert a delay after each conversion until the DR register is read */
ADC1->CFGR1 |= ADC_CFGR1_WAIT;
/* Enable hardware trigger on rising edge */
ADC1->CFGR1 |= ADC_CFGR1_EXTEN_0;
/* Set ADC1_TIMER as trigger source */
ADC1->CFGR1 |= ADC1_TRIGGER;
/* DMA circular mode selected */
ADC1->CFGR1 |= ADC_CFGR1_DMACFG;
/* Enable DMA */
ADC1->CFGR1 |= ADC_CFGR1_DMAEN;
/* Sampling time in ADC clock cycles */
ADC1->SMPR |= ADC1_SMPT;
/* ADC1 Channels */
ADC1->CHSELR |= ADC1_CHANNELS;
/*--- DMA part ---*/
/* Peripheral address */
ADC1_DMA->CPAR = ( uint32_t )&ADC1->DR;
/* Memory address */
ADC1_DMA->CMAR = ( uint32_t )pu16_MemAdr;
/* Number of data to transfer */
ADC1_DMA->CNDTR = DMA_DATA_COUNT;
/* Priority: Very high */
ADC1_DMA->CCR |= DMA_CCR_PL;
/* Disable Memory-To-Memory mode */
ADC1_DMA->CCR &= ~DMA_CCR_MEM2MEM;
/* Memory size: 16-Bit */
ADC1_DMA->CCR |= DMA_CCR_MSIZE_0;
/* Peripheral size: 16-Bit */
ADC1_DMA->CCR |= DMA_CCR_PSIZE_0;
/* Enable memory increment mode */
ADC1_DMA->CCR |= DMA_CCR_MINC;
/* Disable peripheral increment mode */
ADC1_DMA->CCR &= ~DMA_CCR_PINC;
/* Enable circular mode */
ADC1_DMA->CCR |= DMA_CCR_CIRC;
/* Data direction: Read from peripheral and write to memory */
ADC1_DMA->CCR &= ~DMA_CCR_DIR;
/* Disable transfer complete interrupt */
ADC1_DMA->CCR &= ~DMA_CCR_TCIE;
}
static void v_Adc1_Calibrate( void )
{
/* Make sure that ADC1 is stabilized before the calib process starts */
v_SysClk_BusyWaitUs( 10 );
/* Stops ADC1 */
ADC1->CR |= ADC_CR_ADSTP;
/* Check if ADC1 is disabled */
if( ADC1->CR & ADC_CR_ADEN )
{
/* Disable ADC1 */
ADC1->CR |= ADC_CR_ADDIS;
}
/* Wait until ADC1 is disabled */
while( ADC1->CR & ADC_CR_ADEN ) {}
/* Start calibration */
ADC1->CR |= ADC_CR_ADCAL;
/* Wait until ADC1 is calibrate */
while( ADC1->CR & ADC_CR_ADCAL ) {}
}
有人有什么想法吗? 我猜想,当定时器,ADC和DMA开始工作时,RAM上显示的DMA指针已经增加了一个。这通常可以想象吗?