I am currently using ADC for continuous conversion. Below is my program.
#include "adc.h"
void adc_init(ADC_TypeDef* adc){
// ADC3 PC0 PC1 (IN10 IN11)
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
RCC->APB2ENR |= RCC_APB2ENR_ADC3EN;
// analog mode
GPIOC->MODER |= (3 << GPIO_MODER_MODE0_Pos);
GPIOC->MODER |= (3 << GPIO_MODER_MODE1_Pos);
// enable scan mode
adc->CR1 = (0x1 << ADC_CR1_SCAN_Pos);
// 12bit resolution
adc->CR1 |= (0x0 << ADC_CR1_RES_Pos);
//Continuous Conversion
adc->CR2 = (0x1 << ADC_CR2_CONT_Pos);
//EOC after each conversion
adc->CR2 |= (0x1 << ADC_CR2_EOCS_Pos);
// Data Alignment RIGHT
adc->CR2 &= ~(0x1 << ADC_CR2_ALIGN_Pos);
// Enable DMA for ADC
adc->CR2 |= (0x1 << ADC_CR2_DMA_Pos);
// Enable Continuous Request
adc->CR2 |= (0x1 << ADC_CR2_DDS_Pos);
// sampling time
adc->SMPR1 |= ((0x3 << ADC_SMPR1_SMP10_Pos) | (0x3 << ADC_SMPR1_SMP11_Pos));
adc->SMPR1 |= (0x3 << ADC_SMPR1_SMP10_Pos);
//Set the Regular channel sequence length in ADC_SQR1
adc->SQR1 |= (0x0 << ADC_SQR1_L_Pos);
// Channel Sequence
adc->SQR3 |= (10 << ADC_SQR3_SQ1_Pos);
adc->SQR3 |= (11 << ADC_SQR3_SQ2_Pos);
// enable adc
adc->CR2 |= (1 << ADC_CR2_ADON_Pos);
delay_ms(2000);
}
void adc_psc(ADC_Common_TypeDef* adc){
// ADC prescaler divide two
adc->CCR |= (0x0 << ADC_CCR_ADCPRE_Pos);
}
void start_adc(ADC_TypeDef* adc){
adc->SR = 0;
adc->CR2 |= (1 << ADC_CR2_SWSTART_Pos);
}
#include "dma.h"
void init_dma(DMA_TypeDef* dma){
//enable dma2
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
// ADC3 -> DMA2 stream 0 channel 2
// Data direction
DMA2_Stream0->CR &= ~(3 << DMA_SxCR_DIR_Pos);
// Select Circular mode
DMA2_Stream0->CR |= (1 << DMA_SxCR_CIRC_Pos);
// Enable Memory Address Increment
DMA2_Stream0->CR |= (1 << DMA_SxCR_MINC_Pos);
// Set the size for data 16 bit
DMA2_Stream0->CR |= ((1 << DMA_SxCR_MSIZE_Pos) | (1 << DMA_SxCR_PSIZE_Pos));
// channel 2
DMA2_Stream0->CR |= (0x2 << DMA_SxCR_CHSEL_Pos);
}
void start_dma(uint32_t scrAddress,uint32_t destAddress){
// Set the size of the transfer
DMA2_Stream0->NDTR = 0x2;
// Source address is peripheral address
DMA2_Stream0->PAR = scrAddress;
// memory address
DMA2_Stream0->M0AR = destAddress;
//start
DMA2_Stream0->CR |= (1 << DMA_SxCR_EN);
}
#include "adc.h"
#include "uart.h"
#include "delay.h"
#include "dma.h"
#include <stdio.h>
#define pc_mcu_uart USART2
uint16_t Rxdata[2] = {0};
int fputc(int ch, FILE* stream){
USART_sendByte(USART2,ch);
return ch;
}
int main(void){
init_dma(adc_dma);
adc_psc(ADC123_COMMON);
adc_init(hw504_adc);
init_uart(pc_mcu_uart);
start_adc(hw504_adc);
start_dma((uint32_t)&ADC3->DR,(uint32_t)Rxdata);
delay_ms(100);
while(1){
printf("%d",ADC3->DR);
printf("x = %d\n",Rxdata[0]);
printf("y = %d\n",Rxdata[1]);
delay_ms(200);
}
return 0;
}
My ADC conversion is only successful after the first reset, and the Rxdata values are all zero.Does any expert know where the problem is in my program?