打印
[STM32F0]

STM32F072使用ADC产生伪随机数

[复制链接]
1940|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
capturesthe|  楼主 | 2016-7-22 16:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
srand和rand()配合使用产生伪随机数序列。
rand函数在产生随机数前,需要系统提供的生成伪随机数序列的种子,rand根据这个种子的值产生一系列随机数。
如果系统提供的种子没有变化,每次调用rand函数生成的伪随机数序列都是一样的。
srand(unsigned seed)通过参数seed改变系统提供的种子值,从而可以使得每次调用rand函数生成的伪随机数序列不同,从而实现真正意义上的“随机”。
通常可以利用系统时间来改变系统的种子值,即srand(time(NULL)),可以为rand函数提供不同的种子值,进而产生不同的随机数序列。
当然,STM32 F2和F4系列中有硬件实现的真随机数发生器。
我这里使用STM32F072的ADC产生随机数。读取某个悬空引脚的ADC值作为种子来获得随机数。也算是一种方法,我看其他人也用过,拿来共同学习下。
上个程序:ADC_Random.c
<p>#include "adc_random.h"

uint16_t Get_ADC_RandomSeek(void);</p><p>
/*初始化ADC*/
void ADC_RandomConfig(void)
{
ADC_InitTypeDef ADC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHBPeriphClockCmd(ADC_RANDOM_GPIO_CLK, ENABLE);
RCC_APB2PeriphClockCmd(ADC_RANDOM_CLK, ENABLE);

GPIO_InitStructure.GPIO_Pin = ADC_RANDOM_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(ADC_RANDOM_GPIO_PORT, &GPIO_InitStructure);

ADC_DeInit(ADC_RANDOM);
ADC_StructInit(&ADC_InitStructure);

ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
ADC_Init(ADC_RANDOM, &ADC_InitStructure);
ADC_ChannelConfig(ADC_RANDOM, ADC_RANDOM_CHANNEL , ADC_SampleTime_1_5Cycles);
ADC_GetCalibrationFactor(ADC_RANDOM);
ADC_Cmd(ADC_RANDOM, ENABLE);
while(!ADC_GetFlagStatus(ADC_RANDOM, ADC_FLAG_ADRDY));
}

/采集4次ADC的值,每次取采集的第四位,拼成16位作为种子*/
uint16_t Get_ADC_RandomSeek(void)
{
uint8_t Count;
uint16_t ADC_RandomSeek = 0;
ADC_StartOfConversion(ADC_RANDOM);
for(Count = 0; Count < 4; Count++){
while(ADC_GetFlagStatus(ADC_RANDOM, ADC_FLAG_EOC) == RESET){
;
}
ADC_RandomSeek <<= 4;
ADC_RandomSeek += ADC_GetConversionValue(ADC_RANDOM) & 0x000f;
}
ADC_StopOfConversion(ADC_RANDOM);
return ADC_RandomSeek;
}

/*拿种子产生随机数*/
uint16_t Get_ADC_Random(void)
{
srand(Get_ADC_RandomSeek());
return rand();
}
</p>


沙发
capturesthe|  楼主 | 2016-7-22 16:19 | 只看该作者
接下来再主函数中需要的地方调用就可以了:
int main(void)
{
  uint16_t RandomNumber, RandomSeek;

  USART2_GPIO_Init();
        
  ADC_RandomConfig();
  
  while (1)
  {
    RandomSeek = Get_ADC_Random();
    srand(RandomSeek);
    RandomNumber = rand();
    printf("RandomSeek = %d\t\tRandomNumber = %d\n", RandomSeek, RandomNumber);
    delay_ms(500);
  }
}


使用特权

评论回复
板凳
mmuuss586| | 2016-7-22 16:39 | 只看该作者
谢谢楼主分享;

使用特权

评论回复
地板
598330983| | 2016-7-22 20:20 | 只看该作者
我觉得用时间函数取随机数比较靠谱,在定时器里取,直接读取某个变量的值,可以是时间分钟秒,毫秒。。。

使用特权

评论回复
5
598330983| | 2016-7-23 13:40 | 只看该作者
如果定时器内部有个速度快的变量,可以搞出来,每次取随机数就直接取那个计时的最小时间变量

使用特权

评论回复
6
Bjorn| | 2016-7-23 19:18 | 只看该作者
产生伪随机数序列干什么用的

使用特权

评论回复
7
309030| | 2016-7-23 20:56 | 只看该作者
计算机中的随机函数是按照一定算法模拟产生的,其结果是确定的,是可见的。我们可以这样认为这个可预见的结果其出现的概率是100%。所以用计算机随机函数所产生的"随机数"并不随机,是伪随机数。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

22

主题

136

帖子

1

粉丝