How generate REAL random number using STM32 MCU?

后端 未结 4 787
挽巷
挽巷 2021-01-12 13:09

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

4条回答
  •  滥情空心
    2021-01-12 14:01

    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:

    • Read the noisy internal temperature at the fastest speed possible to generate the most ADC noise
    • Run the values through the hardware CRC generator, available on most (all?) STM32 chips

    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);
    

    }

提交回复
热议问题