2014-06-22 04:14 AM
Hi , i am reading a value from an lm35 value with the adc .When it reaches a specified level , i trigger pin 8 on gpio A for a certain delay then shut it down and wait the same delay to restart the process if this value is reached again.
I get things to work by using a simple loop to make a delay but after that i decided to get more precise delay and wrote a code for a delay with timers. I tried the 2 delay function to toggle a led and it worked but when i introduced them with the ADC ,this one doesn't give anymore correct reading values. I am using stm32f0 discovery. Here is my code:#include <
stm32f0xx_tim.h
>
#include ''stm32f0xx.h''
#include<
stm32f0xx_gpio.h
>
#include<
stm32f0xx_rcc.h
>
#include<
stm32f0xx_pwr.h
>
#include<
stm32f0xx_adc.h
>
void configTimer() {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;
TIM_TimeBaseInitStruct.TIM_Prescaler = 8000 - 1;
TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
//TIM_SetCounter(TIM2,42000);
TIM_Cmd(TIM2, ENABLE);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//TIM_PrescalerConfig()
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct2;
TIM_TimeBaseInitStruct2.TIM_Period = 60000 - 1;
TIM_TimeBaseInitStruct2.TIM_Prescaler = 8000 - 1;
TIM_TimeBaseInitStruct2.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct2.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct2.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct2);
TIM_Cmd(TIM3, ENABLE);
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
}
void delay10() {
while (1) {
if (TIM_GetFlagStatus(TIM2, TIM_FLAG_Update) != RESET) {
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
break;
}
}
}
void delay60() {
while (1) {
if (TIM_GetFlagStatus(TIM3, TIM_FLAG_Update) != RESET) {
TIM_ClearFlag(TIM3, TIM_FLAG_Update);
break;
}
}
}
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStruct ;
void AdcConfiguration(){
ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
/* Initialize the ADC_ContinuousConvMode member */
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
/* Initialize the ADC_ExternalTrigConvEdge member */
ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
/* Initialize the ADC_ExternalTrigConv member */
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO;
/* Initialize the ADC_DataAlign member */
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
/* Initialize the ADC_ScanDirection member */
ADC_InitStruct.ADC_ScanDirection = ADC_ScanDirection_Upward ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADC_Init(ADC1,&ADC_InitStruct);
ADC_ChannelConfig( ADC1,ADC_Channel_1, ADC_SampleTime_239_5Cycles);
ADC_Cmd(ADC1, ENABLE);
ADC_StartOfConversion(ADC1);
}
void InitPins()
{RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure2;
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure2.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure2);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void delay()
{long j=0;
while (j<
50000000
)// delay 15 secondes
{
j++;
}
}
void main(void)
{int
j
=
0
;
uint16_t
value
=
0
;
float
temp
=
0
;
AdcConfiguration();
configTimer();
InitPins();
ADC_StartOfConversion(ADC1);
GPIO_ResetBits( GPIOA,GPIO_Pin_8);
while(1)
{ ADC_StartOfConversion(ADC1);
while (j<20)
{
value
=
ADC_GetConversionValue
(ADC1)+value;
j
=j+1;
}
j
=
0
;
value
=value/20;
temp
=
100
*(value*3.3/4096+0.015);
if (temp>32)
{GPIO_SetBits( GPIOC,GPIO_Pin_8);
GPIO_SetBits( GPIOA,GPIO_Pin_8);
delay10();
GPIO_ResetBits( GPIOA,GPIO_Pin_8);
GPIO_ResetBits( GPIOC,GPIO_Pin_8);
delay10();
ADC_StopOfConversion(ADC1);
value=0;
temp=0;
}
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{
}
}
void PWR_BackupAccessCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the Backup Domain Access */
PWR->CR |= PWR_CR_DBP;
}
else
{
/* Disable the Backup Domain Access */
PWR->CR &= (uint32_t)~((uint32_t)PWR_CR_DBP);
}
}
#endif
2014-06-22 09:47 AM
I am not sure results can be guaranteed using the F0 library with an F4 processor.
The ADC DR register is read repeatedly without a test for a new conversion complete. Cheers, Hal2014-06-22 12:54 PM
My bad , i am using f0 (sorry for that ).
I guess i will try that and keep you updated!Thank you.2014-06-22 01:35 PM
Are you even sure it's getting to the GPIO/Delay code? As indicated above you really should wait on the ADC EOC before reading the result.
You seem to throw away a lot of precision with the way you're doing the math there, and I'm pretty sure all the DISCO boards run at 3.0V and not 3.3V2014-06-22 01:41 PM
uint32_t value=0; // can't use 16-bit 20*4096 > 65535
float temp=0;
..
// value=value/20;
// temp=100*(value*3.3/4096+0.015);
temp = 0f * (((float)value * 3.0f) / (40f * 0f)) + 0.015f);
2014-06-23 01:09 AM
while (1) {
ADC_StartOfConversion(ADC1);
while (j <
20
) {
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET)
{
}
ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
value
=
ADC_GetConversionValue
(ADC1) + value;
j
= j + 1;
}
j
=
0
;
value
= value / 20;
temp
=
100
* (value * 3 / 4096 + 0.015);
if (temp > 32) {
GPIO_SetBits(GPIOC, GPIO_Pin_8);
GPIO_SetBits(GPIOA, GPIO_Pin_8);
delay10();
GPIO_ResetBits(GPIOA, GPIO_Pin_8);
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
delay60();
}
ADC_StopOfConversion(ADC1);
value = 0;
temp = 0;
}
}
I found a new bug now:the program seems to run the 10 seconds delay but never the 60 seconds.I inversed the 60 seconds function with the 10 seconds but then the led was never shut down.
Another point : i replaced delay60 by calling 6 times delay10 then i simulated the temperature level a first time and every thing seemed to be ok until i tried to simulate it again then i noticed that the LED blinked slightly to finally start the cycle normally again after a 'random' period of time.
Can somebody help me to solve this problem?
Thank you for your attention.
2014-06-23 07:23 AM
I don't know what your processor speed is, but 60 seconds is billions of ticks at 24 MHz, and I'm not sure your timer factors with get you there.
Suggest you setup a 1ms SysTick, and wait for 60000 ticks.
2014-06-24 09:07 AM
Actually i used both delay functions on simple gpio toggle and it was fine but when i introduced the adc it didn''t seem to work.
2014-06-24 09:09 AM
And the value of temp is what?