Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
STM32F303:具有DMA的ADC仅工作几次_Stm32_Dma_Adc_Nucleo - Fatal编程技术网

STM32F303:具有DMA的ADC仅工作几次

STM32F303:具有DMA的ADC仅工作几次,stm32,dma,adc,nucleo,Stm32,Dma,Adc,Nucleo,我目前正在使用带有STM32F303RE芯片的核仁64板。对于编程,我将Arduino IDE与STM32包一起使用。我现在想避免使用HAL,因为我认为当您必须同时学习寄存器和库函数时,这是相当混乱的 我想能够采样4个输入信号并行在5.1毫秒(最大的F303)。我的计划是让ADC继续运行。然后,当我想要采集样本时,我重置DMA标志并将计数器(CNDTR寄存器)设置为我想要采集的样本数量 下面的部分展示了我实现这一目标的尝试。它基本上可以正常工作,但次数有限。它的工作频率似乎取决于我在程序的某些部

我目前正在使用带有STM32F303RE芯片的核仁64板。对于编程,我将Arduino IDE与STM32包一起使用。我现在想避免使用HAL,因为我认为当您必须同时学习寄存器和库函数时,这是相当混乱的

我想能够采样4个输入信号并行在5.1毫秒(最大的F303)。我的计划是让ADC继续运行。然后,当我想要采集样本时,我重置DMA标志并将计数器(CNDTR寄存器)设置为我想要采集的样本数量

下面的部分展示了我实现这一目标的尝试。它基本上可以正常工作,但次数有限。它的工作频率似乎取决于我在程序的某些部分输入的随机睡眠值。 例如:如果我在takeSamples()函数之后输入10毫秒的延迟,程序将在主循环中工作41个周期,然后它就会卡住

当它卡住时,它会执行以下操作:DMA-CNDTR寄存器只减少一个值,然后它就留在那里。所以程序正在等待寄存器值变为零,但这永远不会发生。ADC一直在采样,我可以很好地读取ADC数据寄存器

有人知道是什么导致DMA在一定时间后停止传输数据吗

以下是该计划的相关部分:

void setup() {
  Serial.begin(57600);

  // Enable clocks
  RCC->AHBENR |= (1 << 17); // GPIOA
  RCC->AHBENR |= (1 << 18); // GPIOB

  // Set ADC pins to analog input
  GPIOA->MODER |= (0b11 << 0); // PA0 for ADC1
  GPIOA->MODER |= (0b11 << 8); // PA4 for ADC2
  GPIOB->MODER |= (0b11 << 2); // PB1 for ADC3
  GPIOB->MODER |= (0b11 << 24); // PB1 for ADC4

  initClock();
  DMA_init();
  ADC_init();

  // Start conversion
  ADC1->CR |= (1 << 2);
  ADC3->CR |= (1 << 2);
}

void initClock()
{
  FLASH->ACR |= (0b10 << 0); // add two wait states

  RCC->CR |= (1 << 18); // Bypass HSE, use external clock signal from STLink instead

  RCC->CR &= ~(1 << 24); // turn off PLL
  delay(100);
  RCC->CFGR |= (0b0000 << 4); // Do not divide system clock
  RCC->CFGR |= (0b0111 << 18);  // PLL multiply = 9
  RCC->CFGR |= (0b10 << 15); // use HSE as PLL source
  RCC->CFGR |= (1 << 10);  // not divided
  delay(100);
  RCC->CR |= (1 << 24); // turn on PLL
  delay(100);
}

void ADC_init(void) {

  RCC->CFGR2 |= (0b10000 << 4); // Prescaler
  RCC->CFGR2 |= (0b10000 << 9); // Prescaler
  RCC->AHBENR |= (1 << 28); // turn on ADC12 clock
  RCC->AHBENR |= (1 << 29); // turn on ADC34 clock

  // Set ADC clock
  ADC12_COMMON->CCR |= (0b01 << 16); // 0b01
  ADC34_COMMON->CCR |= (0b01 << 16); // 0b01


  // disable the ADC
  ADC1->CR &= ~(1 << 0);
  ADC2->CR &= ~(1 << 0);
  ADC3->CR &= ~(1 << 0);
  ADC4->CR &= ~(1 << 0);

  // enable the ADC voltage regulator
  ADC1->CR &= ~(1 << 29);
  ADC2->CR &= ~(1 << 29);
  ADC3->CR &= ~(1 << 29);
  ADC4->CR &= ~(1 << 29);

  ADC1->CR |= (1 << 28);
  ADC2->CR |= (1 << 28);
  ADC3->CR |= (1 << 28);
  ADC4->CR |= (1 << 28);

  // start ADC calibration cycle
  ADC1->CR |= (1 << 31);
  // wait for calibration to complete
  while (ADC1->CR & (1 << 31));

  // start ADC calibration cycle
  ADC2->CR |= (1 << 31);
  // wait for calibration to complete
  while (ADC2->CR & (1 << 31));

  // start ADC calibration cycle
  ADC3->CR |= (1 << 31);
  // wait for calibration to complete
  while (ADC3->CR & (1 << 31));

  // start ADC calibration cycle
  ADC4->CR |= (1 << 31);
  // wait for calibration to complete
  while (ADC4->CR & (1 << 31));

  // enable the ADC
  ADC1->CR |= (1 << 0);
  ADC2->CR |= (1 << 0);
  ADC3->CR |= (1 << 0);
  ADC4->CR |= (1 << 0);

  while (!(ADC1->ISR & (1 << 0)));
  while (!(ADC2->ISR & (1 << 0)));
  while (!(ADC3->ISR & (1 << 0)));
  while (!(ADC4->ISR & (1 << 0)));

  // Select ADC Channels
  ADC1->SQR1 = (1 << 6);
  ADC2->SQR1 = (1 << 6);
  ADC3->SQR1 = (1 << 6);
  ADC4->SQR1 = (3 << 6);

  // Set sampling time for regular group 1
  ADC1->SMPR1 |= (0b000 << 3); // 0b000 -> 1.5 clock cycles, shortest available sampling time
  ADC2->SMPR1 |= (0b000 << 3);
  ADC3->SMPR1 |= (0b000 << 3);
  ADC4->SMPR1 |= (0b000 << 3);

  // Regular sequence settings
  ADC1->SQR1 |= (0b0000 << 0); // One conversion in the regular sequence
  ADC2->SQR1 |= (0b0000 << 0);
  ADC3->SQR1 |= (0b0000 << 0);
  ADC4->SQR1 |= (0b0000 << 0);

  // Enable continuous conversion mode
  ADC1->CFGR |= (1 << 13); // Master ADC1 + ADC2
  ADC3->CFGR |= (1 << 13); // Master ADC3 + ADC4

  ADC12_COMMON->CCR |= (0b00110 << 0);
  ADC34_COMMON->CCR |= (0b00110 << 0);

  // DMA mode
  ADC12_COMMON->CCR |= (0 << 13); // 0 -> One Shot; 1 -> Circular
  ADC34_COMMON->CCR |= (0 << 13);

  // DMA mode for 12-bit resolution
  ADC12_COMMON->CCR |= (0b10 << 14);
  ADC34_COMMON->CCR |= (0b10 << 14);
}

void DMA_init(void) {

  // Enable clocks
  RCC->AHBENR |= (1 << 0); // DMA1
  RCC->AHBENR |= (1 << 1); // DMA2

  // Transfer complete interrupt enable
  DMA1_Channel1->CCR |= (1 << 1);
  DMA2_Channel5->CCR |= (1 << 1);

  // Memory increment mode
  DMA1_Channel1->CCR |= (1 << 7);
  DMA2_Channel5->CCR |= (1 << 7);

  // Peripheral size
  DMA1_Channel1->CCR |= (0b11 << 8);
  DMA2_Channel5->CCR |= (0b11 << 8);

  // Memory size
  DMA1_Channel1->CCR |= (0b11 << 10);
  DMA2_Channel5->CCR |= (0b11 << 10);

  // Number of data to transfer
  DMA1_Channel1->CNDTR = uint32_t(maxSamples);
  DMA2_Channel5->CNDTR = uint32_t(maxSamples);

  // Peripheral address register
  DMA1_Channel1->CPAR |= (uint32_t)&ADC12_COMMON->CDR;
  DMA2_Channel5->CPAR |= (uint32_t)&ADC34_COMMON->CDR;

  // Memory address register
  DMA1_Channel1->CMAR |= uint32_t(&dataPoints1232);
  DMA2_Channel5->CMAR |= uint32_t(&dataPoints3432);

  // Reset flags
  DMA1->IFCR |= 0xFF;
  DMA2->IFCR |= 0xFF;
}

void takeSamples(void) {

  // Reset flags
  DMA1->IFCR |= (0b1111111111111111111111111111111 << 0);
  DMA2->IFCR |= (0b1111111111111111111111111111111 << 0);

  // Number of data to transfer
  DMA1_Channel1->CNDTR = uint32_t(maxSamples);
  DMA2_Channel5->CNDTR = uint32_t(maxSamples);

  delay(10); // does not work without this random delay

  elapsedTime = micros();
  // Enable DMA
  DMA1_Channel1->CCR |= (1 << 0);
  DMA2_Channel5->CCR |= (1 << 0);

  while ((DMA1_Channel1->CNDTR > 0) || (DMA2_Channel5->CNDTR > 0))
  }

  elapsedTime = micros() - elapsedTime;

  // Reset flags
  DMA1->IFCR |= (0b1111111111111111111111111111111 << 0);
  DMA2->IFCR |= (0b1111111111111111111111111111111 << 0);;

  DMA1_Channel1->CCR &= ~(1 << 0);
  DMA2_Channel5->CCR &= ~(1 << 0);

  // ADC stop conversion
  ADC1->CR |= (1 << 4);
  ADC3->CR |= (1 << 4);

  while ((ADC1->CR & (1 << 2)) || (ADC3->CR & (1 << 2)));

  ADC12_COMMON->CCR &= ~(0b10 << 14);
  ADC34_COMMON->CCR &= ~(0b10 << 14);

  ADC12_COMMON->CCR |= (0b10 << 14);
  ADC34_COMMON->CCR |= (0b10 << 14);

  // ADC start conversion
  ADC1->CR |= (1 << 2);
  ADC3->CR |= (1 << 2);
}

void loop() {
  takeSamples();
  Serial.print("Elapsed time: ");
  Serial.println(elapsedTime);
}
void setup(){
序列号。开始(57600);
//启用时钟
(0 B11现代124??=(0 B11现代124??)10 B11现代124;(0 B11 1现代124??=(0 B11现代124??=(0 B11现代124难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难难1 AHBENR |=(1 CCR |=(0b01 CCR |=(0b01 CR&=)1 CR&=(1 CR&=)1 CR&=(1 CR&=)1 CR&=~1.CR 124;=(1 CR 124??)1.1 CR \124??=,(1 CR 124??=(1 CR 124?\124??=(1 CR 124??=,(1 CR和1 CR 124?=)1 CR和1 CR ,(1 CR和1 CR和1 CR (()1 CR和1 CR ,=,(1 CR)1 CR 124?=,(1 CR 124??===,(1 1 CR 124?)1)1 CR ,(1 CR \124?????===,(1)1 CR \\124??????==,(1)1)1.1 CR 124 \124 \124 124 124 \124 \\124 124 \124可用采样时间
ADC2->SMPR1 |=(0b000 SMPR1 |=(0b000 SMPR1 |=(0b0000 SQR1 |=(0b0000 SQR1 |=(0b0000 SQR1 |=(0b0000 CFGR |=(1 CFGR |=(1 CCR |=(0b00110 CCR |=(0b00110 CCR |=)(0单次;1->圆形
ADC34|u COMMON->CCR |=(0 CCR |=(0 B10 CCR |=(1 AHBENR |=(1 CCR |=(1 CCR |=(1 CCR |=(1 CCR |=(0 B11 CCR |=)(0 B11 CCR |=(0 B11 CCR |=(0 B11 CCR |=(0 B11 CNDTR=2个样本)最大值);
DMA2_通道5->CNDTR=uint32_t(最大样本);
//外围地址寄存器
DMA1_通道1->CPAR |=(uint32_t)和ADC12_公共->CDR;
DMA2_通道5->CPAR |=(uint32_t)和ADC34_公共->CDR;
//存储器地址寄存器
DMA1_通道1->CMAR |=uint32_t(&dataPoints1232);
DMA2_通道5->CMAR |=uint32_t(和数据点3432);
//重置标志
DMA1->IFCR |=0xFF;
DMA2->IFCR |=0xFF;
}
作废样品(作废){
//重置标志
DMA1->IFCR |=(0B1111111111111 IFCR |=(0B1111111111111111111 CNDTR=uint32_t(最大样本);
DMA2_通道5->CNDTR=uint32_t(最大样本);
延迟(10);//没有这个随机延迟就不能工作
elapsedTime=micros();
//启用DMA
DMA1|U通道1->CCR |=(1 CCR |=(1 CNDTR>0)| |(DMA2|U通道5->CNDTR>0))
}
elapsedTime=micros()-elapsedTime;
//重置标志

DMA1->IFCR |=(0B1111111111111111111111 IFCR |=(0b1111111111111111111111111111111 CCR&=(1CR&=(1CR&=(1CR&)(1CR&(1CR&)(1CCR&=(0B10CCR&=)0B10CCR&=(0B10CCR&=(0B10CR&=)作为一个简单的触发定时器转换示例

void ReadChannels(int channel, size_t nsamples, uint8_t *obuff) 
 {
     TIM1 -> CR1 = 0;
     TIM1 -> CR2 = 0;
     TIM1 -> PSC = PSC;
     TIM1 -> ARR = ARR;
     TIM1 -> EGR |= TIM_EGR_UG;

     DMA1_Channel1 -> CPAR = (uint32_t)&(ADC1 -> DR);
     DMA1_Channel1 -> CMAR = (uint32_t)obuff;
     DMA1_Channel1 -> CNDTR = nsamples;
     DMA1_Channel1 -> CCR = DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_EN;

     ADC1 -> CFGR = ADC_CFGR_DMAEN | (0b10 << ADC_CFGR_RES_Pos) | (9 << ADC_CFGR_EXTSEL_Pos) | (0b01 << ADC_CFGR_EXTEN_Pos);
     ADC1 -> SMPR1 = 0;
     ADC1 -> SMPR2 = 0;

     ADC1 -> SQR1 &= ~(ADC_SQR1_L_Msk);
     ADC1 -> SQR1 &= ~(ADC_SQR1_SQ1_Msk);

     ADC1 -> SQR1 |= channel << ADC_SQR1_SQ1_Pos);
     ADC1 -> CR |= ADC_CR_ADSTART;

     TIM1 -> CR2 |= TIM_CR2_MMS_1;
     TIM1 -> CR1 |= TIM_CR1_CEN;

     DMA1_Channel1 -> CCR = 0;
     TIM1 -> CR1 = 0;
 }
void ReadChannels(整数通道、大小样本、uint8*obuff)
{
TIM1->CR1=0;
TIM1->CR2=0;
TIM1->PSC=PSC;
TIM1->ARR=ARR;
TIM1->EGR |=TIM_EGR_UG;
DMA1\U通道1->CPAR=(uint32\U t)和(ADC1->DR);
DMA1_通道1->CMAR=(uint32_t)obuff;
DMA1\U通道1->CNDTR=nsamples;
DMA1_Channel1->CCR=DMA_CCR_MINC | DMA_CCR|TCIE | DMA_CCR|EN;
ADC1->CFGR=ADC_CFGR_DMAEN |(0b10 SQR1&=~(ADC_SQR1_L_Msk);
ADC1->SQR1&=~(ADC_SQR1_SQ1_Msk);
ADC1->SQR1 |=通道CR |=ADC | U CR | U ADSTART;
TIM1->CR2 |=TIM_CR2_MMS_1;
TIM1->CR1 |=TIM_CR1_CEN;
DMA1_通道1->CCR=0;
TIM1->CR1=0;
}

1.首先开始使用人类可读的值。2.放弃arduino IDE,开始使用一些像样的东西-例如安装了openSTM32的eclipse。3.使用CMSIS定义4.忘记artuino
设置
循环
方法谢谢你的回答!使用这些定义会使程序更具可读性。Mayb问题可以从代码本身分离为另一个问题:什么可以使ADC+DMA工作一段时间,但在一定数量的完整DMA周期后,DMA停止传输数据?数量多少取决于我在程序不同部分插入的睡眠间隔。可能与不同的nt时钟?这个问题很复杂,一般无法回答。出现问题时,您需要调试程序,并检查DMA、ADC和TIM寄存器的值以查看实际状态和错误。