有时项目中需要用到随机数,但并不是每种单片机都有真随机数发生器,如何在没有随机数发生器的单片机中生成随机数呢?
这里分享两种单片机产生随机数的方法,这些也是我在项目中经常会用到的。

方法一:C库函数 rand()

最方便快捷也是最经典的方法就是直接使用C库函数 rand() 来生成随机数。

extern _ARMABI int rand(void);
   /*
    * Computes a sequence of pseudo-random integers in the range 0 to RAND_MAX.
    * Uses an additive generator (Mitchell & Moore) of the form:
    *   Xn = (X[n-24] + X[n-55]) MOD 2^31
    * This is described in section 3.2.2 of Knuth, vol 2. It's period is
    * in excess of 2^55 and its randomness properties, though unproven, are
    * conjectured to be good. Empirical testing since 1958 has shown no flaws.
    * Returns: a pseudo-random integer.
    */

使用方法:
rand()函数的使用方法就不贴上来了,这个是C语言的基础函数之一,大家肯定都会的。

方法二:利用ADC噪声

由于热噪声和生产误差等因素,ADC原始数据的最低1位总会有波动,我们可以利用这些波动生成随机数。

拿stm32来举例,可以利用stm32测内核温度的ADC通道来生成随机数。

生成代码如下,ADC初始化部分的就不放上来了,就是普通的DMA模式采集数据的ADC初始化,打开ADC1的通道16。利用DMA连续转换32个ADC原始数据,取每个数据的最低位依次拼接成一个32bit随机数。

uint32_t adc_randnum;
uint16_t adc_data[32];
void DMA1_Channel1_IRQHandler(void)
{
  static __IO uint8_t count = 0;
  
  if(DMA_GetITStatus(DMA1_INT_TC1) == SET)
  {
    DMA_ClearFlag(DMA1_INT_TC1);
    ADC_DMACtrl(ADC1, DISABLE);
    ADC_Ctrl(ADC1, DISABLE);
    
    for(uint32_t i = 0; i < 32; i += 4)
    {
      adc_randnum += (adc_data[i] & 0x0001) << i;
      adc_randnum += (adc_data[i+1] & 0x0001) << i;
      adc_randnum += (adc_data[i+2] & 0x0001) << i;
      adc_randnum += (adc_data[i+3] & 0x0001) << i;
    }
    
    ADC_DMACtrl(ADC1, ENABLE);
    ADC_Ctrl(ADC1, ENABLE);
    ADC_SoftwareStartConvCtrl(ADC1, ENABLE);
  }
}

更多推荐

单片机没有随机数发生器如何生成随机数——2022.07.26