cancel
Showing results for 
Search instead for 
Did you mean: 

Random using ADC

joesoftware
Associate II
Posted on October 12, 2012 at 23:42

Hi, i try to do an elettronic dice with stm32vldiscovery.

I want use 2 value read from adc i try to use this to process my data

m_w = <
choose-initializer
>; /* must not be zero */ 
m_z = <
choose-initializer
>; /* must not be zero */ 
uint get_random() 
{ 
m_z = 36969 * (m_z & 65535) + (m_z >> 16); 
m_w = 18000 * (m_w & 65535) + (m_w >> 16); 
return (m_z << 16) + m_w; /* 32-bit result */ 
} 

where m_z and m_w are 2 random value read from adc. i used this code for adc

#include ''stm32f10x.h'' 
#include ''random.h'' 
#include ''stm32f10x_adc.h'' 
#include ''stm32f10x_dma.h'' 
/* Private typedef -----------------------------------------------------------*/ 
/* Private define ------------------------------------------------------------*/ 
#define ADC1_DR_Address ((uint32_t)0x4001244C) 
/* Private macro -------------------------------------------------------------*/ 
/* Private variables ---------------------------------------------------------*/ 
ADC_InitTypeDef ADC_InitStructure; 
DMA_InitTypeDef DMA_InitStructure; 
__IO uint16_t ADCConvertedValue; 
/* Private function prototypes -----------------------------------------------*/ 
void RCC_Configuration(void); 
void GPIO_Configuration(void); 
/* Private functions ---------------------------------------------------------*/ 
void prova (void) 
{ 
/*!< 
At
this stage the microcontroller clock setting is already configured, 
this is done through SystemInit() function which is called from startup 
file (startup_stm32f10x_xx.s) before to branch to application main. 
To reconfigure the default setting of SystemInit() function, refer to 
system_stm32f10x.c file 
*/ 
/* System clocks configuration ---------------------------------------------*/ 
RCC_Configuration(); 
/* GPIO configuration ------------------------------------------------------*/ 
GPIO_Configuration(); 
/* DMA1 channel1 configuration ----------------------------------------------*/ 
DMA_DeInit(DMA1_Channel1); 
DMA_InitStructure.DMA_PeripheralBaseAddr
= 
ADC1_DR_Address
; 
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue; 
DMA_InitStructure.DMA_DIR
= 
DMA_DIR_PeripheralSRC
; 
DMA_InitStructure.DMA_BufferSize
= 
1
; 
DMA_InitStructure.DMA_PeripheralInc
= 
DMA_PeripheralInc_Disable
; 
DMA_InitStructure.DMA_MemoryInc
= 
DMA_MemoryInc_Enable
; 
DMA_InitStructure.DMA_PeripheralDataSize
= 
DMA_PeripheralDataSize_HalfWord
; 
DMA_InitStructure.DMA_MemoryDataSize
= 
DMA_MemoryDataSize_HalfWord
; 
DMA_InitStructure.DMA_Mode
= 
DMA_Mode_Circular
; 
DMA_InitStructure.DMA_Priority
= 
DMA_Priority_High
; 
DMA_InitStructure.DMA_M2M
= 
DMA_M2M_Disable
; 
DMA_Init(DMA1_Channel1, &DMA_InitStructure); 
/* Enable DMA1 channel1 */ 
DMA_Cmd(DMA1_Channel1, ENABLE); 
/* ADC1 configuration ------------------------------------------------------*/ 
ADC_InitStructure.ADC_Mode
= 
ADC_Mode_Independent
; 
ADC_InitStructure.ADC_ScanConvMode
= 
ENABLE
; 
ADC_InitStructure.ADC_ContinuousConvMode
= 
ENABLE
; 
ADC_InitStructure.ADC_ExternalTrigConv
= 
ADC_ExternalTrigConv_None
; 
ADC_InitStructure.ADC_DataAlign
= 
ADC_DataAlign_Right
; 
ADC_InitStructure.ADC_NbrOfChannel
= 
1
; 
ADC_Init(ADC1, &ADC_InitStructure); 
/* ADC1 regular channel14 configuration */ 
ADC_RegularChannelConfig(ADC1, ADC_Channel_10,1, ADC_SampleTime_55Cycles5); 
/* Enable ADC1 DMA */ 
ADC_DMACmd(ADC1, ENABLE); 
/* Enable ADC1 */ 
ADC_Cmd(ADC1, ENABLE); 
/* Enable ADC1 reset calibration register */ 
ADC_ResetCalibration(ADC1); 
/* Check the end of ADC1 reset calibration register */ 
while(ADC_GetResetCalibrationStatus(ADC1)); 
/* Start ADC1 calibration */ 
ADC_StartCalibration(ADC1); 
/* Check the end of ADC1 calibration */ 
while(ADC_GetCalibrationStatus(ADC1)); 
/* Start ADC1 Software Conversion */ 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); 

uint32_t 
m_z
= 
ADCConvertedValue
; /* must not be zero */ 
uint32_t 
m_w
= 
ADCConvertedValue
; /* must not be zero */ 
m_z
= 
36969
* (m_z & 65535) + (m_z >> 16); 
m_w = 18000 * (m_w & 65535) + (m_w >> 16); 
int caso = ((m_z << 16) + m_w) << 31; 

} 
/** 
* @brief Configures the different system clocks. 
* @param None 
* @retval None 
*/ 
void RCC_Configuration(void) 
{ 
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) 
/* ADCCLK = PCLK2/2 */ 
RCC_ADCCLKConfig(RCC_PCLK2_Div2); 
#else 
/* ADCCLK = PCLK2/4 */ 
RCC_ADCCLKConfig(RCC_PCLK2_Div4); 
#endif 
/* Enable peripheral clocks ------------------------------------------------*/ 
/* Enable DMA1 clock */ 
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 
/* Enable ADC1 and GPIOC clock */ 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE); 
} 
/** 
* @brief Configures the different GPIO ports. 
* @param None 
* @retval None 
*/ 
void GPIO_Configuration(void) 
{ 
GPIO_InitTypeDef GPIO_InitStructure; 
/* Configure PC.04 (ADC Channel14) as analog input -------------------------*/ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 
GPIO_Init(GPIOC, &GPIO_InitStructure); 
} 

Adc work good cause in debug i can see how change ADCConvertedValue in realtime, but m_w and m_z give me an error and no value comes back. I think i can't assign good the value from adc to my variable, someone can help me? thx.
7 REPLIES 7
raptorhal2
Lead
Posted on October 13, 2012 at 14:59

The code initializes PC0 instead of PC4 in analog mode.

Cheers, Hal

joesoftware
Associate II
Posted on October 13, 2012 at 15:15

i know, but it is just a comment, i want to use pc0 not pc4, and it's work good, in livewatch, but i can't give that value to a new variable this is my problem.

raptorhal2
Lead
Posted on October 13, 2012 at 16:43

If you step through the code, are m_z and m_w set equal to ADCConvertedValue ?

m_z
= 
36969
* (m_z & 65535) + (m_z >> 16); 
m_w = 18000 * (m_w & 65535) + (m_w >> 16); 
int caso = ((m_z << 16) + m_w) << 31; 

In the above code (m_z >> 16) and (m_w>>16) will always be zero after being set to a maximum of 4095 from ADCConvertedValue. In the last line, the result will always be zero after conversion to int. Perhaps the code this came from used circular shifts and not arithmetic shifts. Cheers, Hal
joesoftware
Associate II
Posted on October 13, 2012 at 21:12 i tryed to comment some line to

uint32_t m_z = ADCConvertedValue; /* must not be zero */ 
uint32_t m_w = ADCConvertedValue; /* must not be zero */ 
//m_z = 36969 * (m_z & 65535) + (m_z >> 16); 
//m_w = 18000 * (m_w & 65535) + (m_w >> 16); 
//int caso = ((m_z << 16) + m_w) << 31;

but m_z and m_w give me ad error ''can't take address m_w or m_z'',
raptorhal2
Lead
Posted on October 13, 2012 at 22:03

I am guessing here, but perhaps equating a nonvolatile variable to a volatile variable is the problem. Try:

__IO uint32_t m_z = ADCConvertedValue; /* must not be zero */ 
__IO uint32_t m_w = ADCConvertedValue; /* must not be zero */
 Cheers, Hal 

frankmeyer9
Associate II
Posted on October 15, 2012 at 17:10

By the way, why do you try to use the ADC for this purpose ?

You could instead measure the length of a (manual) key press with a fast timer (clock xx kHz), and use the result of ((countcycles % 6) + 1) as random number.

I have made a electronic dice with TTL chips about 25 years ago, using this principle.

joesoftware
Associate II
Posted on October 15, 2012 at 20:22

Thanks, for new solution.

I solved in this way.

Bye