Перейти к содержанию
    

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

Генерация псеводослучайных чисел, в качестве зерна используется сильная зависимость частоты генератора 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);
}

Изменено пользователем BaN

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...