This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430G2553: Random Number Generator

Part Number: MSP430G2553

Tool/software: Code Composer Studio

Hi,

I want to generate a random binary number to turn on P1.0 at different frequencies each time. At the same time, I want to generate a PWM on P1.6. 

To generate a random number, I am using the timing difference between DCO and VLO. I set DCO using TA0 and VLO using TA1. Then I use an interrupt vector to pause TA0 and TA1 and save the number of ticks in SMCLK. I then use an if loop to toggle P1.0 based on the LSB of the number of ticks recorded each time. 

Pausing of TA0 and TA1 causes the PWM to stop working. Also, P1.0 is always at high. Can you help me figure out the mistake I am making.

Please see the below code: 

//RNG

#include "msp430G2553.h"
#include  <stdint.h>

void main( void )
{
  WDTCTL   = (WDTPW | WDTHOLD);                       	// Stop watchdog timer

  BCSCTL1  = CALBC1_16MHZ;                             	// Set range to 16MHz
  DCOCTL   = CALDCO_16MHZ;                             	// Set DCO step and modulation to 16MHz

  P1SEL    |= 0x40;                                   	// Set special function of P1.6 to timer module
  P1DIR    |= 0x41;                                    	// Set P1.6, P1.0 to output direction
  P1OUT    |= 0x00;                           			// Set P1 OFF

  //Setting DCO
  TA0CCR0  = 400;                               		//PWM Frequency 40kHz
  TA0CCR1  = 65;                                      	//PWM Duty cycle
  TA0CCTL0 = CAP | CM_1 | CCIS_1 | OUTMOD_7;
  TA0CTL   = (TASSEL_2 | ID_0 | MC_1 | TACLR | TAIE); 	// SMCLK, divider 1, up-mode, clear, interrupt enabled

  //Setting VLO
  TA1CCR0 = 1200;
  TA1CCTL0 = CCIE | OUTMOD_3;
  TA1CTL = TASSEL_1 | MC_1;

  _BIS_SR(GIE);                                  		// Enable global interrupts

  while( 1 );                                         	// Endless loop
}

// Timer0 A1 interrupt service routine
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer0_A1_ISR( void )
{
	static uint8_t random = 0;	//register to save the random number

	 TA0CTL = MC_0;	//Pause TA0
         TA1CTL = MC_0; 	//Pause TA1
	 random = TA0R; 	//Save number of ticks SMCLK

  	 TA0CTL &= ~TAIFG;

if (random)
	 {
		P1OUT = 0X01;
	 }
else
	{
	P1OUT = 0X00;
	}
}


  • You are not using the LSB, you are testing all 16 bits.

    If you don't want to stop the timer, then don't stop the timer. To read both timer values, configure a CCR of one timer to output a pulse at a specified time, configure a CCR of the second timer for capturing, and connect the first CCR's output to the second CCR's input.
  • Thank you for your suggestions. Sorry about sounding naive, I am still learning about timers.

    Are you suggesting the following:
    // DCCO
    TA0CCR0 = 400; //PWM Frequency 40kHz
    TA0CCR1 = 65; //PWM Duty cycle
    TA0CCTL0 = OUTMOD_7;

    //VCO
    TA1CCR0 = TA0CCR0;
    TA1CCTL0 = CAP | CCIE | OUTMOD_3;

    And inside the interrupt loop, I can just read the timer A register (random = TA0R & 1) without pausing the time?
  • To capture events, you need to set the capture mode (CM*) because default (0) is "no capture", and the output mode is not interesting. When the event happens, TA1R is copied into TA1CCR0, so you don't need to set the latter. In the interrupt handler, you can then read TA1CCR0.
  • Thank you very much! That helped a lot and now both the PWM and the RNG work. However, the RNG only works in the debug mode. As soon as I exit debug mode, P1.0 goes high (3V) instead of outputting pulses at random intervals.

    Any suggestions?

    Thank you,
  • So after some research, I thought that the problem with the program only working in debug mode might be because the launchpad did not come with an external crystal and using the internal crystal had limitations such as the program only working in debug mode. 

    So I installed the 32KHz crystal that comes with the launchpad along with two 12pF capacitors on C21 and C22. I ran the code below which works both in debug and edit mode. The problem I have now is that the random number generator is not very random. It looks pretty predictable when I look at P1.0 on the oscilloscope. This was not the case when I did not have the crystal installed but the program only worked in debug mode. 

    I also realized that I was not telling MSP430 which crystal (the  internal or the external) to use. So I referred to the user guide which suggests that I set LFXT1Sx = 11, and XCAPx = 00 to use the external crystal. I did that by adding the following line:  BCSCTL3 |= LFXT1S_3 + XCAP_0. This made the RGN stop working completely.  

    Here are my question:

    1. Is it correct that I need to use an external crystal to prevent the program from crashing when existing debug mode?

    2. If so, what registers do I need to set to use the external crystal vs the internal one?

    3. Is it possible that the internal crystal is less accurate so it would generate more random numbers than when using an external crystal?

    Thanks a lot!

    Here is my code: 

    //RGN Test
    
    #include "msp430G2553.h"
    #include  <stdint.h>
    
    
    
    void main( void )
    {
    
    
      WDTCTL   = (WDTPW | WDTHOLD);                       	// Stop watchdog timer
    
      BCSCTL1  = CALBC1_16MHZ;                             	// Set range to 8MHz
      DCOCTL   = CALDCO_16MHZ;                             	// Set DCO step and modulation to 8MHz
    
    
      P1SEL    |= 0x40;                                   	// Set special function of P1.6 to timer module
      P1DIR    |= 0x41;                                    	// Set P1.6, P1.0, P1.1 to output direction
      P1OUT    |= 0x00;                           			// Set P1.0 ON, P1.1 OFF
    
      //PWM
      TA0CCR0  = 400;                               		// Frequency 40kHz, 25us
      TA0CCR1  = 60;                                      	// Duty cycle
      TA0CCTL1 = OUTMOD_7;                                	// Reset / set
      TA0CTL   = (TASSEL_2 | ID_0 | MC_1 | TACLR | TAIE); 	// SMCLK, divider 1, up-mode, clear, interrupt enabled
    
    
    
      //Setting VLO
      TA1CCTL0 = CAP | CM_1 | CCIS_1 ;
      TA1CTL = TASSEL_1 | MC_2;
    
    
      _BIS_SR(GIE);                                  		// Enable global interrupts
    
      while( 1 );                                         	// Endless loop
    }
    
    
    
    // Timer0 A1 interrupt service routine
    #pragma vector = TIMER0_A1_VECTOR
    __interrupt void Timer0_A1_ISR( void )
    {
    	volatile unsigned char random = 0;	//register to save the random number
    
    	random = TA1R & 1; 	//Save number of ticks SMCLK
    
    	TA0CTL &= ~TAIFG;
    	TA1CTL &= ~TAIFG;
    
    	if (random)
    	 {
    		P1OUT = 0X01;
    		}
    	else
    		{
    		P1OUT = 0X00;
    		}
    	  	        }
    

  • Sahar Elyahoodayan said:
    1. Is it correct that I need to use an external crystal to prevent the program from crashing when existing debug mode?

    No, Your problem of "not running w/o debugger" is elsewere: you set 16MHz DCO right after microcontroller is released from reset - at that moment VCC is not yet reached nominal level (>= 3.3VDC) for 16MHz operation and chip crashes in result. This is typical msp430 newbie error:) External crystal setup code most likely wait for oscillator start, during this time VCC is good, crash does not occur and it miraculously works w/o debugger at 16MHz.

    To safely set high DCO frequency, you shall add delay which accounts for VCC ramp-up after power-on:

    WDTCTL   = (WDTPW | WDTHOLD);
    __delay_cycles(100000); // 100ms delay @ 1MHz CPU freq
    BCSCTL1  = CALBC1_16MHZ;
    DCOCTL   = CALDCO_16MHZ;
    

  • Thank you Ilmars, but this did not resolve the issue. It is still not running w/o debugger.
    I am wondering how I can use the external crystal to generate random numbers. When I tried using the external crystal, the numbers that were generated looked pretty predictable.
    Is that because the the external crystal is more accurate, so the time difference between DCO and the crystal vary less?
  • Sahar Elyahoodayan said:
    Is that because the the external crystal is more accurate, so the time difference between DCO and the crystal vary less?

    Most likely. Thou I have no experience building RNG out of msp430. Did you check document I suggested? Look, you can have external crystal yet still use VLO for ACLK. Also you shall find where is your problem with " no debugger" config. Perhaps reset problem then. Note that this forum is full of questions and answers regarding problem you have - you are advised to use search.

  • I did a lot of research and still could not resolve the problem. I ended up using a floating ADC pin and used the LSB as the random bit. It works very well.
    Thank you for your help.

**Attention** This is a public forum