I\'m working on a project with STM32F103E arm cortex-m3 MCU in keil microvision IDE.
I need to generate random numbers for some purposes, but I don\'t want to use pseud
There is another method I found and tested that works quite well. It can generate true random 32bit numbers, I never checked how fast it is, may take a few milliseconds per number. Here is how it goes:
Repeat a few times, I found 8 times gives pretty good randomness. I checked randomness by sorting the output values in ascending order and plotting them in excel, with good random numbers this generates a straight line, bad randomness or 'clumping' of certain numbers is immediately visible. Here is the the code for STM32F03:
uint32_t getTrueRandomNumber(void) {
ADC_InitTypeDef ADC_InitStructure;
//enable ADC1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
// Initialize ADC 14MHz RC
RCC_ADCCLKConfig(RCC_ADCCLK_HSI14);
RCC_HSI14Cmd(ENABLE);
while (!RCC_GetFlagStatus(RCC_FLAG_HSI14RDY))
;
ADC_DeInit(ADC1);
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Backward;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_TRGO; //default
ADC_Init(ADC1, &ADC_InitStructure);
//enable internal channel
ADC_TempSensorCmd(ENABLE);
// Enable ADCperipheral
ADC_Cmd(ADC1, ENABLE);
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN) == RESET)
;
ADC1->CHSELR = 0; //no channel selected
//Convert the ADC1 temperature sensor, user shortest sample time to generate most noise
ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor, ADC_SampleTime_1_5Cycles);
// Enable CRC clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE);
uint8_t i;
for (i = 0; i < 8; i++) {
//Start ADC1 Software Conversion
ADC_StartOfConversion(ADC1);
//wait for conversion complete
while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) {
}
CRC_CalcCRC(ADC_GetConversionValue(ADC1));
//clear EOC flag
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
}
//disable ADC1 to save power
ADC_Cmd(ADC1, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE);
return CRC_CalcCRC(0xBADA55E5);
}