Something wrong in program using STM32F103 ADC.
Dear reader
I hope someone can help me with my question. I have programmed an ADC1 on a STM32F103 with the following functions activated:
- Continues conversion mode
- Scan mode with two channels A0 And A1
- DMA to an array in memory ADC_data[2]
- ( ADC Interrupt enabled which is the problem)
It all works and generates output based on the code below. The output generated in the loop looks like this
ADC1 = 2890
ADC2 = 0
ADCcnt = 0
ADC_data[0] = 2906
ADC_data[1] = 0 But when I add and activate the interrupt function using NVIC_EnableIRQ which basically only counts the nr of conversions I have a problem.
When I comment in line 89 NVIC_EnableIRQ(ADC1_2_IRQn); everything work till the end of the setup functions but as soon line 89 is executed the loop stops and everything hangs.
I checked the code against what others do but I can't find what is wrong.
What am i missing that i do wrong.
uint16_t value;
uint32_t val32, ADCcnt=0;
uint16_t ADC_data[2] = { 0xAAAA, 0x5555 };
/*
HEX_MEM : Function to output a given section of memory starting from ptr till ptr+(rowa x cols)
a integers mutiple of cols is always output.
cols : nr of colums to out put
rows : nr of rows to be displayed
ptr : pointer/address to the data area to be examend.
Note : replace the prinf() funccvtion
*/
void HEX_MEM(void* ptr, uint8_t width, uint8_t c, uint8_t r) {
uint8_t cols = c, rows = r;
uint8_t rcnt, ccnt;
uint8_t* ptr8;
ptr8 = (uint8_t*)ptr;
switch (width) {
case 8: {
Serial.printf("HEX-MEM ");
for (ccnt = 0; ccnt < cols; ccnt++) Serial.printf(" %X", ccnt);
Serial.printf("\r\n");
for (rcnt = 1; rcnt <= rows; rcnt++) {
Serial.printf("%p: ", ptr8);
for (ccnt = 1; ccnt <= cols; ccnt++) {
Serial.printf("%02X ", (*ptr8));
ptr8++;
}
ptr8 -= ccnt - 1;
for (ccnt = 1; ccnt <= cols; ccnt++) {
if (*ptr8 >= 0x20 && *ptr8 <= 0x7E) Serial.printf("%c.", *ptr8);
else Serial.printf("-.");
ptr8++;
}
Serial.printf("\r\n");
}
} break;
default: Serial.println("Error");
}
}
void ADC1_IRQHandler(void) { // ADC Interupt ISR
ADC1->SR &= ~(0x00000002); // clear EOC status bit
val32 = ADC1->DR;
ADCcnt++;
}
void setup() // The setup() function runs once each time the micro-controller starts
{
Serial.begin(115200);
delay(2000);
Serial.println("program start");
Serial.println("RCC1 ==========================");
HEX_MEM((uint8_t*)RCC, 8, 4, 9);
RCC->APB2ENR = 0x00004615; // Enable: UART1 ADC1, ADC2, IOPCEN IOPAEN, AFIOEN
RCC->AHBENR = 0x00000015; // enable: SRAM, Flash, DMA
GPIOC->CRH = 0x44144444; // Enable: port C PC13 as digital output
GPIOA->CRL = 0x44444400; // Enable: port A PA0 PA1 as analog input
ADC1->SMPR2 = 0x0000003F; // Set Sample time chanel A0 A1 to 239.5 cycles
ADC1->SQR3 = 0x00000020; // Set scan sequence[1.2] to cahnnel A0 en A1
ADC1->SQR1 = 0x00100000; // Set scan sequence cnt=2 cycles
ADC1->CR1 = 0x00000120; // Enable: Scan Mode, IRQ enabled
ADC1->CR2 = 0x00000107; // Enable: DMA, Calibrate, Continues sample Mode, Wakup the ADC
DMA1_Channel1->CNDTR = 0x00000002; // DMA cycle cnt=2
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR; // DMA periferal register adress = ADC.DR
DMA1_Channel1->CMAR = (uint32_t)ADC_data; // DMA Memeory adress = ADC_data[0]
DMA1_Channel1->CCR = 0x000005A0; // Set: MEM=16b, PER=16b, MINC=1, CIR=1, EN=1
DMA1_Channel1->CCR |= 0x00000001; // Enable DMA channel1
delay(1); // Stabelise ADCmachine and calibration process(5uS).
ADC1->CR2 |= 0x00000001; // Enable: ADC ADC sampling machine
Serial.println("RCC2 ==========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)RCC, 8, 4, 9);
Serial.println("GPIOA =========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)GPIOA, 8, 4, 7);
Serial.println("GPIOC =========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)GPIOC, 8, 4, 7);
Serial.println("ADC1 ==========================="); // Print out memeory/register section
HEX_MEM((uint8_t*)ADC1, 8, 4, 20);
delay(5000); // Just wait 5 seconds
NVIC_SetPriority(ADC1_2_IRQn, 5); // Set the ADC interupt priority
// NVIC_EnableIRQ(ADC1_2_IRQn); // Enable the ADC interupt.
}
void loop() // Add the main program code into the continuous loop() function
{
digitalWrite(PC13, !digitalRead(PC13)); // Turn the LED from off to on, or on to off
delay(1000);
Serial.printf("ADC1 = %i \n", ADC1->DR & 0x0000FFFF);
Serial.printf("ADC2 = %i \n", ADC1->DR >>16);
Serial.printf("ADCcnt = %i \n", ADCcnt);
Serial.printf("ADC_data[0] = %i \n", ADC_data[0] & 0xFFFF);
Serial.printf("ADC_data[1] = %i \n", ADC_data[1] & 0xFFFF);
Serial.println();
}