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.
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; } }
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;
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.
**Attention** This is a public forum