2018-06-21 10:37 AM
Hi, I have a problem with my code and I dont know where it is. I have a stm 32f100 rb and i am trying to read two values of the adc. If you know how I can solve, teach me please. My code is the next. Thank you
//=============================================================================
#include 'stm32f10x.h'#include 'antilib_gpio.h'#include 'antilib_adc.h'//=============================================================================// Defines//=============================================================================#define LED_BLUE_GPIO GPIOC#define LED_BLUE_PIN 8#define LED_GREEN_GPIO GPIOC
#define LED_GREEN_PIN 9//=============================================================================// Global variables//=============================================================================int AIN[4]; // table for conversions results//=============================================================================// main function//=============================================================================int main(void){RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_USART1EN;RCC->AHBENR |= RCC_AHBENR_DMA1EN;#if (LED_BLUE_PIN > 7)
LED_BLUE_GPIO->CRH = (LED_BLUE_GPIO->CRH & CONFMASKH(LED_BLUE_PIN)) | GPIOPINCONFH(LED_BLUE_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#else LED_BLUE_GPIO->CRL = (LED_BLUE_GPIO->CRL & CONFMASKL(LED_BLUE_PIN)) | GPIOPINCONFL(LED_BLUE_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#endif#if (LED_GREEN_PIN > 7)
LED_GREEN_GPIO->CRH = (LED_GREEN_GPIO->CRH & CONFMASKH(LED_GREEN_PIN)) | GPIOPINCONFH(LED_GREEN_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#else LED_GREEN_GPIO->CRL = (LED_GREEN_GPIO->CRL & CONFMASKL(LED_GREEN_PIN)) | GPIOPINCONFL(LED_GREEN_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#endifAFIO->MAPR = AFIO_MAPR_TIM3_REMAP; // Full TIM3 remapTIM3->PSC = 239; // Set prescaler to 24 000 (PSC + 1)
TIM3->ARR = 500; // Auto reload value 500TIM3->CCR3 = 0; // Start PWM duty for channel 3
TIM3->CCR4 = 0; // Start PWM duty for channel 4TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 |
TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // PWM mode on channel 3 & 4TIM3->CCER = TIM_CCER_CC4E | TIM_CCER_CC3E; // Enable compare on channel 3 & 4
TIM3->CR1 = TIM_CR1_CEN; // Enable timerTIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
NVIC_EnableIRQ(ADC1_IRQn); // Enable interrupt from ADC1 (NVIC level)GPIOA->CRL = (GPIOA->CRL & 0xFFFF0000) |
GPIOPINCONFL(0, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG)) | GPIOPINCONFL(1, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG)) | GPIOPINCONFL(2, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG)) | GPIOPINCONFL(3, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG));ADC1->CR2 = ADC_CR2_ADON | // turn on ADC
ADC_CR2_CONT | // enable continuos mode ADC_CR2_DMA; // enable DMA modeADC1->CR1 = ADC_CR1_SCAN; // enable scan mode
ADC1->SQR1 = ADC_SEQUENCE_LENGTH(3); // four channels in sequence
ADC1->SQR3 = ADC_SEQ1(0) | // channel 0 is first in sequence
ADC_SEQ2(1) | // channel 1 is second in sequence ADC_SEQ3(2) | // channel 2 is third in sequence ADC_SEQ4(3) ; // channel 3 is fourth in sequenceADC1->SMPR2 = ADC_SAMPLE_TIME0(SAMPLE_TIME_239_5) | // sample time for first channel in sequence
ADC_SAMPLE_TIME1(SAMPLE_TIME_239_5) | // sample time for second channel in sequence ADC_SAMPLE_TIME2(SAMPLE_TIME_239_5) | // sample time for third channel in sequence ADC_SAMPLE_TIME3(SAMPLE_TIME_239_5) ; // sample time for fourth channel in sequenceDMA1_Channel1->CPAR = (uint32_t)(&(ADC1->DR)); // peripheral (source) address
DMA1_Channel1->CMAR = (uint32_t)AIN; // memory (desination) addressDMA1_Channel1->CNDTR = 4; // 4 transfersDMA1_Channel1->CCR |= DMA_CCR1_CIRC | // circular mode enable
DMA_CCR1_MINC | // memory increment mode enable DMA_CCR1_MSIZE_0 | // memory size 16 bits DMA_CCR1_PSIZE_0; // peripheral size 16 bitsDMA1_Channel1->CCR |= DMA_CCR1_EN ; // Enable channel
ADC1->CR2 |= ADC_CR2_ADON; // Turn on conversion
while (1);
}//=============================================================================// adc1 Interrupt Handler//=============================================================================void ADC1_IRQHandler(void){if(ADC1->SR & ADC_SR_EOC) // if UIF flag is set { ADC1->SR &= ~ADC_SR_EOC; // clear UIF flag TIM3->CCR3 = AIN[0]; TIM3->CCR4 = AIN[1]; }}2018-06-21 11:06 AM
Sorry not going to slog through your register level code.
You should use the DMA TC interrupt, or more preferably HT/TC, to determine when a particular run of ADC results has been completed.
https://community.st.com/0D50X00009XkiAHSAZ
2018-06-21 01:03 PM
Hello Daniel, the problem I identify in your code is related to not enabling the ADC interrupt into the ADC peripheral. You only enable the interrupt on NVIC. Also you try to use the DMA feature but never enable the DMA interrupt as suggested by Clive in his previous post. If you want to use DMA then you don't need to use the ADC interrupt. Often these operating modes are not used together, just only one.
I suggest you to check for application notes related to ADC + DMA, available at
web site. Another suggestion is to use some library to control your peripherals. It can be the Standard Peripheral Library or better try to use STM32CubeMX. You can find more information regarding Cube at:https://www.st.com/en/development-tools/stm32cubemx.html
This utility helps you to create an initial project, ready to test, where you can customize to fit all your needs.
If you have any other question don't hesitate to ask.
Best regards, Yosmany.
2018-06-23 05:49 AM
Thank you for your answer.
The problem is that I dont know how to use the stm cube and I broke another micro trying the program. I have another problem if i dont use the interrupt on adc, and it is that de second adc that i use give me a value that is not 0 like the first. Because my objective is take this values on adcs and move it to a out in pwm that is connect to the leds. The first work perfect, but the second give me a value and the led is on without any voltage in his imput.
I hope your reply
2018-06-23 07:21 AM
The cube is very easy to use and necessary for MCUs with many pins and functions all cross mapped.
The cube wont make your program, but it will initialise everything,,,, mostly.
Which IDE is you choose ?
It is not easy to get started on this equipment.
with the correct IDE you can single step, then you will know where your program is failing.
my code is 1000s of lines long.
you need a print console, easy to use the UART to PC Terminal emulator @ 230400 baud
I tried semihosting once, it was snail's pace maybe 50baud.
1000s of lines before you will know what you are doing.
2018-07-01 08:58 AM
Hello again, if i want to use a interrupt of the dma how i can do it?? some like this:
//=============================================================================
// STM32VLDISCOVERY tutorial// Lesson 9. Analog to digital converter (ADC) with direct memory access (DMA)// Copyright : Radoslaw Kwiecien//
https://community.st.com/external-link.jspa?url=http%3A%2F%2Fen.radzio.dxp.pl
// e-mail : radek(at)dxp.pl//=============================================================================#include 'stm32f10x.h'#include 'antilib_gpio.h'#include 'antilib_adc.h'//=============================================================================// Defines//=============================================================================#define USART_RX_GPIO GPIOA#define USART_RX_PIN 10#define USART_TX_GPIO GPIOA
#define USART_TX_PIN 9#define LED_BLUE_GPIO GPIOC
#define LED_BLUE_PIN 8#define LED_GREEN_GPIO GPIOC
#define LED_GREEN_PIN 9//=============================================================================// Send single char//=============================================================================void USART_PutChar(uint8_t ch){ while(!(USART1->SR & USART_SR_TXE)); USART1->DR = ch;}//=============================================================================// Send text//=============================================================================void USART_PutString(uint8_t * str){while(*str != 0) { USART_PutChar(*str); str++; }}//=============================================================================
// Global variables//=============================================================================vu16 AIN[4]; // table for conversions resultschar str[32]; // buffer for text//=============================================================================// main function//=============================================================================int main(void){vu32 dly;RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_USART1EN;RCC->AHBENR |= RCC_AHBENR_DMA1EN;RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_USART1EN;RCC->AHBENR |= RCC_AHBENR_DMA1EN;#if (USART_RX_PIN > 7)
USART_RX_GPIO->CRH = (USART_RX_GPIO->CRH & CONFMASKH(USART_RX_PIN)) | GPIOPINCONFH(USART_RX_PIN, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULLUPDOWN));#elseUSART_RX_GPIO->CRL = (USART_RX_GPIO->CRL & CONFMASKL(USART_RX_PIN)) | GPIOPINCONFL(USART_RX_PIN, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULLUPDOWN));#endif#if (USART_TX_PIN > 7)
USART_TX_GPIO->CRH = (USART_TX_GPIO->CRH & CONFMASKH(USART_TX_PIN)) | GPIOPINCONFH(USART_TX_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#elseUSART_TX_GPIO->CRL = (USART_TX_GPIO->CRL & CONFMASKL(USART_TX_PIN)) | GPIOPINCONFL(USART_TX_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#endif#if (LED_BLUE_PIN > 7)
LED_BLUE_GPIO->CRH = (LED_BLUE_GPIO->CRH & CONFMASKH(LED_BLUE_PIN)) | GPIOPINCONFH(LED_BLUE_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#else LED_BLUE_GPIO->CRL = (LED_BLUE_GPIO->CRL & CONFMASKL(LED_BLUE_PIN)) | GPIOPINCONFL(LED_BLUE_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#endif#if (LED_GREEN_PIN > 7)
LED_GREEN_GPIO->CRH = (LED_GREEN_GPIO->CRH & CONFMASKH(LED_GREEN_PIN)) | GPIOPINCONFH(LED_GREEN_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#else LED_GREEN_GPIO->CRL = (LED_GREEN_GPIO->CRL & CONFMASKL(LED_GREEN_PIN)) | GPIOPINCONFL(LED_GREEN_PIN, GPIOCONF(GPIO_MODE_OUTPUT2MHz, GPIO_CNF_AFIO_PUSHPULL));#endifAFIO->MAPR = AFIO_MAPR_TIM3_REMAP; // Full TIM3 remapTIM3->PSC = 239; // Set prescaler to 24 000 (PSC + 1)
TIM3->ARR = 500; // Auto reload value 500TIM3->CCR3 = 0; // Start PWM duty for channel 3
TIM3->CCR4 = 0; // Start PWM duty for channel 4TIM3->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1 |
TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; // PWM mode on channel 3 & 4TIM3->CCER = TIM_CCER_CC4E | TIM_CCER_CC3E; // Enable compare on channel 3 & 4
TIM3->CR1 = TIM_CR1_CEN; // Enable timerTIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
NVIC_EnableIRQ(DMA1_Channel1_IRQn); // Enable interrupt from ADC1 (NVIC level)GPIOA->CRL = (GPIOA->CRL & 0xFFFF0000) |
GPIOPINCONFL(0, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG)) | GPIOPINCONFL(1, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG)) | GPIOPINCONFL(2, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG)) | GPIOPINCONFL(3, GPIOCONF(GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG));ADC1->CR2 = ADC_CR2_ADON | // turn on ADC
ADC_CR2_CONT | // enable continuos mode ADC_CR2_DMA; // enable DMA modeADC1->CR1 = ADC_CR1_SCAN; // enable scan mode
ADC1->SQR1 = ADC_SEQUENCE_LENGTH(3); // four channels in sequence
ADC1->SQR3 = ADC_SEQ1(0) | // channel 0 is first in sequence
ADC_SEQ2(1) | // channel 1 is second in sequence ADC_SEQ3(2) | // channel 2 is third in sequence ADC_SEQ4(3) ; // channel 3 is fourth in sequenceADC1->SMPR2 = ADC_SAMPLE_TIME0(SAMPLE_TIME_239_5) | // sample time for first channel in sequence
ADC_SAMPLE_TIME1(SAMPLE_TIME_239_5) | // sample time for second channel in sequence ADC_SAMPLE_TIME2(SAMPLE_TIME_239_5) | // sample time for third channel in sequence ADC_SAMPLE_TIME3(SAMPLE_TIME_239_5) ; // sample time for fourth channel in sequenceDMA1_Channel1->CPAR = (uint32_t)(&(ADC1->DR)); // peripheral (source) address
DMA1_Channel1->CMAR = (uint32_t)AIN; // memory (desination) addressDMA1_Channel1->CNDTR = 4; // 4 transfersDMA1_Channel1->CCR |= DMA_CCR1_CIRC | // circular mode enable
DMA_CCR1_MINC | // memory increment mode enable DMA_CCR1_MSIZE_0 | // memory size 16 bits DMA_CCR1_PSIZE_0; // peripheral size 16 bitsDMA1_Channel1->CCR |= DMA_CCR1_EN ; // Enable channel
ADC1->CR2 |= ADC_CR2_ADON; // Turn on conversion
USART1->CR1 = USART_CR1_UE | USART_CR1_TE;
USART1->BRR = (SystemCoreClock / 115200);USART_PutString('STM32VLDISCOVERY tutorial lesson 9\r');
while (1);
}//=============================================================================// TIM3 Interrupt Handler//=============================================================================void DMA1_Channel1_IRQHandler(void){if(DMA1->ISR & DMA_ISR_TCIF1) // if UIF flag is set { DMA1->ISR &= ~DMA_ISR_TCIF1; // clear UIF flag TIM3->CCR3 = AIN[0]; TIM3->CCR4 = AIN[1];}}I haven´t got idea of how use a interrupt here with multi adc, interrupt of dma or adc. But I need, help me please. Thanks
2018-07-01 11:14 AM
>>I haven´t got idea of how use a interrupt here with multi adc, interrupt of dma or adc. But I need, help me please.
The interrupt tells you when the array contains a new set of values, you can either manage that in the interrupt handler, or flag\semaphore for some other task.
If you can separate yourself from a sequential/linear mindset, you could compute new parameters in the IRQ handler.
One thing to consider is if the interrupt is occurring too frequently, or if you need to double up the buffer so you can inspect the half that is not currently active.
If you are trying to record the samples, consider a much larger buffer to allow time for data to be written to storage media.
2018-07-01 05:58 PM
Maybe you can get an ADC example running.
Try to find an ADC DMA example for your board.
without the cube, I cannot help, I don't know if your setup is correct,
You could be chasing your tail with a single typo or character out of place or line missing, in the setup.
Do you work for Protel / DXP ?