2014-05-04 12:41 AM
Hi everyone,
I'm trying to read temperature from temperature sensor in stm32f4-discovery kit I've configured ADC1 and then read converted value and do some math on it now when debugging it goes tohard fault
why ?? I don't knowand if there're other notes on this code ?? <b>/* *In this project I need to read the temperature sensor, convert it into digital and *send this reading to be displayed on the PC (RealTerm)using USART. */ #include ''stm32f4_discovery.h'' /**************************************************************************************/void delay(uint32_t);void RCC_Configuration(void){ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);} /**************************************************************************************/ void ADC_Configuration(void){ /* * In stm32f4-discovery kit, the temperature sensor is connected to ADC1_IN16 */ ADC_CommonInitTypeDef ADC_CommonInitStruct; ADC_InitTypeDef ADC_InitStruct; ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div8; ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStruct); ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; ADC_InitStruct.ADC_ScanConvMode = DISABLE; ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStruct.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStruct); //The next statement configures the ADC1 channel, rank and sample time ADC_RegularChannelConfig(ADC1, ADC_Channel_TempSensor, 1, ADC_SampleTime_144Cycles); //ADC_Channel_TempSensor = ADC_Channel_16 /* Then we enable the internal temperature sensor * Bit 23 TSVREFE: Temperature sensor and VREFINT enable * This bit is set and cleared by software to enable/disable the temperature sensor and the * VREFINT channel. * ADC->CCR |= (uint32_t)ADC_CCR_TSVREFE; */ ADC_TempSensorVrefintCmd(ENABLE); //The next statement enables ADC1 ADC_Cmd(ADC1, ENABLE);} /**************************************************************************************/ #define BUFFERSIZE 128uint16_t ADCConvertedValues[BUFFERSIZE]; //an array to hold the converted values int main(void){ static volatile float TemperatureValue = 0; RCC_Configuration(); ADC_Configuration(); STM_EVAL_LEDInit(LED3); // Configure LEDs to monitor program status STM_EVAL_LEDOn(LED3); // Turn LED3 on while(1) // Don't want to exit { ADC_SoftwareStartConv(ADC1); //Start the conversion while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET) ; //Processing the conversion /* * To calculate the temperature we follow this formula * Temperature (in C) = {(Vsense - V25)/(Avg_Slope)}+25 * Vsense = 0.76V, Avg_Slope = 2.5mV * Temperature = */ TemperatureValue = ADC_GetConversionValue(ADC1); //Return the converted data TemperatureValue *= 3300; TemperatureValue /= 0xfff; //Reading in mV TemperatureValue /= (float)1000.0; //Reading in Volts TemperatureValue -= (float)0.760; // Subtract the reference voltage at 25°C TemperatureValue /= (float).0025; // Divide by slope 2.5mV TemperatureValue += (float)25.0; // Add the 25°C /* Toggle LED3 and delay */ STM_EVAL_LEDToggle(LED3); delay(3*1000000); }}//delay functionvoid delay(uint32_t cnt){while(cnt-->0);}
</b>
Thanks a lot for your time2014-05-04 01:32 AM
Hard to say without looking more deeply into the project construction, I might guess it's an issue with enabling the FPU, and code in SystemInit() to do that, or set defines for the project via ''Use FPU'' or some such. If not enabled FPU instructions will Hard Fault, a Divide by Zero might also, but can't see one here.
Analyze the Hard Fault to determine the instruction, registers, and processor context when it occurred. Also be aware that the STM32F4-DISCO is running at 3V, and you can represent floats as say 1000.0f you don't need to cast. TemperatureValue *= 3300; TemperatureValue /= 0xfff; //Reading in mV TemperatureValue /= (float)1000.0; //Reading in Volts Could be done as TemperatureValue *= (3.0f / 4096.0f); // 3V over 12-bit range, Reading in Volts2014-05-04 02:02 AM
Thanks for your reply
I might guess it's an issue with enabling the FPU, and code in SystemInit() to do that, or set defines for the project via ''Use FPU'' or some such. If not enabled FPU instructions will Hard FaultI think it's some issues with FPU cause the hard fault happens during the mathematical operations on the measured value.How can I enable FPU?Analyze the Hard Fault to determine the instruction, registers, and processor context when it occurred.I don't know any thing about analyzing the hard fault. would you please explain in more detailsAlso be aware that the STM32F4-DISCO is running at 3V, and you can represent floats as say 1000.0f you don't need to cast. TemperatureValue *= 3300; TemperatureValue /= 0xfff; //Reading in mV TemperatureValue /= (float)1000.0; //Reading in VoltsCould be done asTemperatureValue *= (3.0f / 4096.0f); // 3V over 12-bit range, Reading in VoltsHonestly I don't understand the purpose of these math operations ?? I've copied and pasted a ready code from some blog and modified it but I don't know why do we have to multiply with 3300 and divide by 0xfff then divide by 1000
And how would 3V(the kit is running at) affect my code?
2014-05-04 04:37 AM
Ok this has devolved into a much more fundamental ''how does this work'' problem.
So the board runs a 3V, it affects your code because the voltage going to VREF+, the reference voltage for the ADC/DAC, defines the maximal range of measurements. The measurements are 12-bit, this means a range 0..4095 represents DC to VREF. There are 2N ''steps''. In order to convert the ADC number into a voltage you must use math the SCALE the number space from one set of units to another, so units of VREF/4096 to Volts or Millivolts Why 3300, well that's a representation of 3.3V in mV Why mV, well because the code you lifted used INTEGERs, and in order to retain any useful precision you'd want that integer to represent mV rather than V (0,1,2,3 optimistically) Why f(x) = (x * 3300) / 4096, this is that scaling thing, we multiply by the primary conversion value to maintain the accuracy of the integer, we are using a 32-bit variable, with a 12-bit range, and 3.3V VREF, and finally the division gets us the scale of the 12-bit ADC (2N). I think that 4096 is a better representation than 4095, the difference will be fractional at best, and the binary math for 4096 is much easier (X >> 12)2014-05-04 04:49 AM
As you've decided to use floating point, and voltage, the math representation becomes simpler, but more complicated for the CPU.
The scaling can be done with constants, these can be folded, and you can use multiplies which are computationally more efficient than divides. To get from units of VREF/4096 to VOLTS, we can multiple the 12-bit value by (3.0f / 4096.0f), the compiler will fold these constants into 0.000732421875f For the Hard Fault check out some of the handlers described by Joseph Yiu, in his Cortex books, and on the net. These can print out the processor state. You can examine the failing code through a disassembly of the running code, either in the debugger, or as a listing file of the code. For Keil there is a ''Use FPU'' check box in one of the target panes, in SystemInit() within system_stm32f4xx.c there is code to enable the FPU based on compiler set defines. The example/template projects for the part should have all this set up properly, examine those, as if you set up a project from scratch you might have missed something critical. All I can see is the code you pasted, which doesn't look like it should fault from a cursory analysis.2014-05-04 01:44 PM
For Keil there is a ''Use FPU'' check box in one of the target panes,
Ok, the ''Use FPU'' option is checked in project optionsin SystemInit() within system_stm32f4xx.c there is code to enable the FPU based on compiler set defines. SystemInit() with in system_stm32f4xx.c .. here's the code found and I can't find anything related to FPU enabling<b>void SystemInit(void){ /* Reset the RCC clock configuration to the default reset state ------------*/ /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; /* Reset CFGR register */ RCC->CFGR = 0x00000000; /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset PLLCFGR register */ RCC->PLLCFGR = 0x24003010; /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Disable all interrupts */ RCC->CIR = 0x00000000;#ifdef DATA_IN_ExtSRAM SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */ /* Configure the System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/ SetSysClock(); /* Configure the Vector Table location add offset address ------------------*/#ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */#else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */#endif}</b>The example/template projects for the part should have all this set up properly, examine those, as if you set up a project from scratch you might have missed something critical. I'm modifying an example and not beginning from scratch.. Here's the deassembly of the portion of code causes the hard fault <b> 108: TemperatureValue *= (3.0f / 4096.0f); // 3V over 12-bit range, Reading in Volts 0x080009D8 6820 LDR r0,[r4,#0x00]
0x080009DA EDDF0A1E VLDR s1,[pc,#0x78]
0x080009DE EE000A10 VMOV s0,r00x080009E2 EEB80A40 VCVT.F32.U32 s0,s00x080009E6 EE200A20 VMUL.F32 s0,s0,s10x080009EA EEBC0AC0 VCVT.U32.F32 s0,s00x080009EE EE100A10 VMOV r0,s00x080009F2 6020 STR r0,[r4,#0x00]</b>specifically the red line causes the hard faultSo what ??2014-05-04 03:36 PM
STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Project\STM32F4xx_StdPeriph_Templates\system_stm32f4xx.c
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL <<
10
*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
...
2014-05-04 04:36 PM
Ok, I've reloaded this file instead of the one I had in my project but the problem still the same, Hard Fault
I'm sorry for bothering but I don't know what to do