Jump to content
    

Исходники программ и библиотек

Генерация псеводослучайных чисел, в качестве зерна используется сильная зависимость частоты генератора VLO от внешних воздействий. Запускается 2 таймера: первый отсчитывает N периодов VLO, второй инкрементирует на максимальной частоте (256МГц) регистр счета. После отсчета N тиков VLO в регистре счета будет случайное значение (диапазон изменения этого числа зависит от количества N тиков VLO), которое потом используется в качестве зерна в стандартной функции stdlib rand().

#include <stdlib.h>
#include "intrinsics.h"
#include "io430f5172.h"

void SetVcoreUp (unsigned int level)
{
   // Open PMM registers for write
   PMMCTL0_H = PMMPW_H;              
   // Set SVS/SVM high side new level
   SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
   // Set SVM low side to new level
   SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
   // Wait till SVM is settled
   while ((PMMIFG & SVSMLDLYIFG) == 0);
   // Clear already set flags
   PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
   // Set VCore to new level
   PMMCTL0_L = PMMCOREV0 * level;
   // Wait till new level reached
   if ((PMMIFG & SVMLIFG))
   while ((PMMIFG & SVMLVLRIFG) == 0);
   // Set SVS/SVM low side to new level
   SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
   // Lock PMM registers for write access
   PMMCTL0_H = 0x00;
}

void MC_Init(void)
{
   __bic_SR_register(GIE);

   // Stop watchdog timer to prevent time out reset
   WDTCTL = WDTPW + WDTHOLD;

   // Настраиваем рабочую частоту для генерирации зерна для гнератора псевдослучайных чисел.
   // Генерировать будем путем подсчета числа тактов Hi-res таймера,
   // работающего на частоте 256МГц от LFCLK кварца, за N периодов VCO генератора.
   // Для этого нам нужно настроить тактовую частоту на 16МГц и потом воспользоваться умножителем Hi-res таймера TimerD.

   // Increase Vcore setting to level2 to support fsystem=16MHz
   // NOTE: Change core voltage one level at a time..
   SetVcoreUp(0x01);
   SetVcoreUp(0x02);

   UCSCTL8 &= ~(ACLKREQEN | MCLKREQEN | SMCLKREQEN);  // Если не сбросить эти биты, то (ACLKREQEN | MCLKREQEN | SMCLKREQEN)
                                                      // ACLK, SMCLK, MCLK могут останться активными в LPM3
   // Настройка системы тактирования
   PJSEL |= BIT4+BIT5;                       // Port select XT1

   UCSCTL6 &= ~(XT1OFF);                     // XT1 On
   UCSCTL6 |= XCAP_1;
   UCSCTL3 = 0;                              // FLL Reference Clock = XT1

   // Loop until XT1 fault flag is cleared
   do
   {
       UCSCTL7 &= ~XT1LFOFFG;                // Clear XT1 fault flags
   }while (UCSCTL7&XT1LFOFFG);               // Test XT1 fault flag

   // Initialize DCO to 16MHz
   __bis_SR_register(SCG0);                  // Disable the FLL control loop
   UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
   UCSCTL1 = DCORSEL_6;                      // Select DCO range 20MHz-40MHz operation
   UCSCTL2 = FLLD_1 + 487;                   // Set DCO Multiplier for 16MHz
                                             // (N + 1) * FLLRef = Fdco
                                             // (487 + 1) * 32768 = 16MHz
                                             // Set FLL Div = fDCOCLK/2
   __bic_SR_register(SCG0);                  // Enable the FLL control loop

   // Worst-case settling time for the DCO when the DCO range bits have been
   // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
   // UG for optimization.
   // 32 x 32 x 25 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
   __delay_cycles(500000);

   // Loop until XT1 & DCO fault flag is cleared
   do
   {
       UCSCTL7 &= ~(XT1LFOFFG + XT1HFOFFG + DCOFFG);
                                               // Clear XT1,DCO fault flags
       SFRIFG1 &= ~OFIFG;                      // Clear fault flags
   }while (SFRIFG1&OFIFG);                     // Test oscillator fault flag

   UCSCTL6 &= ~(XT1DRIVE_3);                   // Xtal is now stable, reduce drive strength

   // Генерируем зерна для гнератора псевдослучайных чисел
   UCSCTL4 &= ~(SELA2|SELA1|SELA0);
   UCSCTL4 |= SELA__VLOCLK;

   TD0R = 0;
   TD1R = 0;
   // Настраиваем счетчик SMCLK (DCO)  with Hi-res mode it's 256MHz
   // Configure TimerD in Hi-Res Regulated Mode
   TD1CTL0 = TDSSEL_2;                         // TDCLK=SMCLK=16MHz=Hi-Res input clk select

   TD1CTL1 |= TDCLKM_1;                        // Select Hi-res local clock
   TD1HCTL0 = TDHM_1 + TDHCALEN + TDHEN;       // Hi-res clock 16x TDCLK, 
                                               // Calibration and Hi-res mode enable
   TD1CTL0 = TDSSEL_2 + CNTL_0 + MC_2 + ID_0;  // SMCLK, Continous up, input divider /1

   while((TD1HINT & TDHLKIFG) == 0);           // Wait for Hi-res freq lock
   TD1HINT |= TDHLKIFG;                        // Clear lock flag

   // Настраиваем счетчик ACLK (VLO)
   TD0CCR0 = 9; // Считаем 10 тиков VLO. При 1000 тиков в TD1R будет полностью случайное значение (все 16 бит).
                //При 10/100 тиках значение будет изменяться в меньшем диапазоне бит.
   TD0CTL0 = TDSSEL_1 + CNTL_0 + MC_2 + ID_0;  // ACLK, count to TDCL0, input divider /1
   //TD1CTL0 |= TDCLR; // Don't clear TD1 timer - it'll add additional random because of variable freq lock time
   // Ожидаем, когда счетчик отсчитает заданное число тиков VLO
   while((TD0CCTL0 & CCIFG) == 0);
   srand(TD1R); // Устанавливаем зерно для генератора псевдослучайных чисел
   TD1CTL0 = 0;
   TD0CTL0 = 0;
   TD0HCTL0 = 0;

   UCSCTL4 &= ~(SELA2|SELA1|SELA0);
   UCSCTL4 |= SELA__XT1CLK;

   // Генерация зерна для генератора псевдослучайных чисел закончена, теперь можно настраивать рабочую частоту на необходимую

   SetVcoreUp(0x00);

   // Initialize DCO to 2.45MHz
   __bis_SR_register(SCG0);                  // Disable the FLL control loop
   UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
   UCSCTL1 = DCORSEL_3;                      // Set RSELx for DCO = 2.45 MHz
   UCSCTL2 = FLLD_1 + 74;                    // Set DCO Multiplier for 2.45MHz
                                             // (N + 1) * FLLRef = Fdco
                                             // (74 + 1) * 32768 = 2.45MHz
                                             // Set FLL Div = fDCOCLK/2
   __bic_SR_register(SCG0);                  // re-enable the FLL control loop  

   // Worst-case settling time for the DCO when the DCO range bits have been
   // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
   // UG for optimization.
   // 32 x 32 x 2.45 MHz / 32,768 Hz = 76563 = MCLK cycles for DCO to settle
   __delay_cycles(76563);

   // Loop until DCO fault flag is cleared
   do
   {
       UCSCTL7 &= ~(DCOFFG);
                                               // Clear XT1,DCO fault flags
       SFRIFG1 &= ~OFIFG;                      // Clear fault flags
   }while (SFRIFG1&OFIFG);                     // Test oscillator fault flag
}


void main( void )
{
   int random_num;
   MC_Init();
   random_num = rand();
   /*
   // Измерение времени генерации случайного числа при помощи rand()
   // При SMCLK = 2.45MHz время равно (78 * 1/2.45MHz) = 32мкс
   TD0R = 0;
   TD0CTL0 = TDSSEL_2 + CNTL_0 + MC_2 + ID_0 + TDCLR;  // SMCLK, Continous up, input divider /1, clear TDR
   rand_num = rand();
   TD0CTL0 = 0;
   rand_time = TD0R;
   */
   while(1);
}

Edited by BaN

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...