I am trying to use either the ACLK or the MCLK to get the free running counter in two interrupt service routines. I am not sure of how to actually do this. In my interrupt routines I want to save the current clock tick counter into a variable, then the next interrupt get the new current clock tick counter into a different variable so I can then do some math.
Also, I am using the input capture/compare on channel P6.0, and it says the VREF (from the example code for the LP) is connected to "-terminal" but I don't where this is on the actual board...I am pretty new as you might tell :) - is there a way to change the voltage value in software without changing the value to this hidden -terminal?
The project is trying to use the MSP430F5529 LaunchPad to create a ultrasonic measuring device. I am using Murata MA40S4S and Murata MA40S4R as my ultrasonic sender and receiver. The following code will initialize the device and set up the interrupts (not sure if I need to change these), then it will generate an interrupt every 250 ms and enable the second interrupt to occur.
I have a few possible logic errors, not too worried yet as I can't even get the clock counter into variables. I will probably need to disable the first interrupt while waiting for the second or change it to be action driven, such as a button press. Anyway, here is the code, my most pressing problem again is how to actually get the current counter value into my variables.
/* main.c * I am using the MSP430F5529 launchpad to try an set up ultrasonic measurements * I am using 40kHz ultrasonic transmitter and recievers. * Notes about the MSP430: * MSP430 requires 6 clock cycles before an ISR begins executing * An ISR always finishes with the return from interrupt instruction (reti) requiring 5 cycles * */ #include <msp430f5529.h> void init_device(); unsigned int i; unsigned long int BEGIN_TIME; unsigned long int END_TIME; unsigned long int TOTAL_CLOCK_CYCLES; float DISTANCE; static unsigned int INCHES_IN_FOOT = 12; //12 inches to 1 foot static float SPEED_OF_SOUND = 1116.43; //1115.43 ft/sec at room temperature static unsigned long int MCLK_FREQ = 4000000; //set to 4 MHz?? int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer init_device(); //set up clocks, timers and interrupts for(;;){ //stay in loop forever, we do everything in our interrupts } return 0; } /***********************Functions********************************/ void init_device(){ P4DIR |= BIT7; /* Digital out to a LED just to make sure we work :) */ P1DIR &= 0xFB ; //xxxx x0xx - set out channel 1.2 to an input //P2DIR |= BIT2; //P2.2 set to output P2SEL |= BIT2; // SMCLK sent out to P2.2, this will be my sensor out pin P7DIR |= BIT7; // MCLK sent out to pins 2.4, just to check it, verify correct operation // We will comment this out in the low power mode P7SEL |= BIT7; //select MCLK to output on pin 7.7, we want to test for functionality P5SEL |= BIT2+BIT3; // Port select XT2 (for MCLK) UCSCTL6 &= ~XT2OFF; // enable XT2 /*Set up MCLK, ACLK, and SMCLK*/ UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO UCSCTL4 |= SELA_5 + SELM_5 + SELS_4; // Set MCLK(SELM) to XT2 (4MHz)101b = XT2CLK when available, otherwise DCOCLKDIV // Set SMCLK(SELS) 100b = DCOCLKDIV // SET ACLK (SELA) 101b = XT2CLK when available, otherwise DCOCLKDIV UCSCTL5 |= DIVS_5; //=> SMCLK/32 = 1.277953 MHz /32 = 39.936kHz to use for my signal //101b = f(SMCLK)/32, or we could use DIVS__32 UCSCTL0 = 0x1700; //DCOx = 23? Set DCOx, MODx first half is DCO, second MOD : x x x _ _ _ _ _ | _ _ _ _ _ x x x //Look at DCORSEL on spec sheet, gives range, we now have 32 chances in our range, //trial and error to find the exact value needed here. do // Loop until XT1,XT2 & DCO stabilizes, in our case XT2 and DCO { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag __bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL1 = DCORSEL_2; // Select DCO range up to ~.25MHz to ~ 2.45MHz operation UCSCTL2 = FLLD__1 + 38; // Set DCO Multiplier for // (N + 1) * FLLRef = Fdco // (38 + 1) * 32768 = 1.277953 MHz __bic_SR_register(SCG0); // Enable the FLL control loop // Worst-case settling time for the DCO when the DCO range bits have been // changed 32 x 32 x 1.28MHz / 32,768 Hz = 40000 = MCLK cycles for DCO to settle __delay_cycles(40000); // Setup ComparatorB CBCTL0 |= CBIPEN + CBIPSEL_0; // Enable V+, input channel CB0 CBCTL1 |= CBPWRMD_1; // normal power mode CBCTL2 |= CBRSEL; // VREF is applied to -terminal CBCTL2 |= CBRS_3+CBREFL_1; // R-ladder off; bandgap ref voltage (1.2V) // supplied ref amplifier to get Vcref=1.5V (CBREFL_2) CBCTL3 |= BIT0; // Input Buffer Disable @P6.0/CB0 __delay_cycles(75); // delay for the reference to settle CBINT &= ~(CBIFG + CBIIFG); // Clear any errant interrupts CBINT |= CBIE; // Enable CompB Interrupt on rising edge of CBIFG (CBIES=0) TA0CCR0 = 10000;//We are using SMCLK At 40kHz, 10000 clock cycles = 250 ms //For testing this is how often we want our interrupt to occur //eventually we will set it to occur off an interrupt from audio jack interface //this doesn't work, truncates to 16 bit, which max is 2^16 = 65536 TA0CTL = TASSEL_2 + MC_1; // Timer_A set to ACLK, UPMODE(count up to CCR0 for interrupt to occur) //TASSEL_0 = TACLK //TASSEL_1 = ACLK. //TASSEL_2 = SMCLK //TASSEL_3 = INCLK TA0CCTL0 = CCIE; // CCR0 interrupt enabled __bis_SR_register(GIE); /* Enable maskable interrupts */ _EINT();//enable global interrupts } #pragma vector=TIMER0_A0_VECTOR __interrupt void TIMER0_A0_ISR(void) { P4OUT ^= BIT7;//flash our led to make sure we are getting into our interrupt correctly //take out of low power mode //initialize a measurement cycle //:::::::::::measurement_cycle:::::::::: //get the free running counter from our MCLK right before we send off our signal - PUT INTO BEGIN_TIME BEGIN_TIME = TBR;//this holds the free running counter of when we got into the interrupt //send our signal out on P2.2 for 48 clock cycles (using the SMCLK) P2DIR |= BIT2; //P2.2 set to output for(i=0; i<48 ; i++); //we send out for 48 MCLK clock cycles, which is 5 rising edges of 40kHz out sig //if not enough time, up the amount of clock cycles we output //disable our P2.2 so we don't waste Power //P2DIR &= 0xFB;//1111 1011 = 0xFB, We want to turn off our 2.2 now- update - this makes unstable output pin //enable our Timer1 interrupt for a compare CBCTL1 |= CBON;//enables our compareB channel. Vcompare is on P6.0 //wait until we get a signal back on our input pin P1.2 //Wait for Comparator Interrupt //__bis_SR_register(LPM3_bits + GIE); // Enter LPM3, interrupts enabled //__no_operation(); // For debugger } /*#pragma vector=TIMER0_A1_VECTOR __interrupt void TIMER1_A1_ISR(void)*/ #pragma vector=COMP_B_VECTOR __interrupt void Comp_B_ISR (void) { //As soon as we get a signal from P1.2 (AT0.1) get the free running counter and put into END_TIME END_TIME = TBR;//this holds the free running counter from start of interrupt CBINT &= ~CBIFG;// Clear Interrupt flag CBCTL1 &= 0xFBFF;//disable interrupt 1111 1011 1111 1111 = disable ON bit //:::::::::::::Math on the Clock Cycles::::::::: //We are using the MCLK for measurements on the timer, MCLK = 25MHz? //now we do math on the free running counter, convert the clock cycles to time //might need to check the Timer overflow flag on the MCLK, not sure yet TOTAL_CLOCK_CYCLES = END_TIME - BEGIN_TIME;//we wait for ?? clock cycles sending, then another ?? for incoming) //change the time to distance. DISTANCE = (TOTAL_CLOCK_CYCLES * SPEED_OF_SOUND/(2*MCLK_FREQ*INCHES_IN_FOOT));//distance is in inches //display our DISTANCE out to the user. //TODO: display //eventually we will send via our audiojack interface //send on the microphone in line to display on the phone //__bis_SR_register(LPM3_bits + GIE); // Enter LPM3, interrupts enabled __no_operation(); // For debugger }