Full source code of project bellow. //******************************************* // Running on Launchpad // MSP430G2231 // ------------------ // /|\| XIN|- // | | | // --|RST XOUT|- // | | // Vin+ -->|A1+ P1.2 | // |A1- = VSS P1.0|-->LED // | P1.1|-->TX RS232 // | P1.4|<--CLOCK CALIPER // | P1.5|<--DATA CALIPER // // Maris Sprancis viltnieks@gmail.com http://robocombo.blogspot.com //******************************************* #include <msp430g2231.h> int value = 0; // value received from caliper unsigned char clock_active = 0; // any clock activity during last 32msec? unsigned char ready_for_data = 0;// idle between clock burts, ready for next one unsigned char bits_so_far = 0; // current bit count during value "assembly" // how many CPU cycles between bits #define Bitime 104 //9600 Baud, SMCLK=1MHz (1MHz/9600)=104 unsigned char BitCnt; // Bit count, used when transmitting byte unsigned int TXByte; // Value sent over UART when Transmit() is called #define LED BIT0 // LED on P1.0 #define TXPIN BIT1 // RS232 TX on P1.1 #define CLOCK BIT4 // Clock on P1.4 #define DATA BIT5 // Data on P1.5 void Transmit(void); void main(void) { DCOCTL = 0x00; // Safe Flow BCSCTL1 = CALBC1_1MHZ; // run at 1Mhz DCOCTL = CALDCO_1MHZ; //WDT as 32 ms interval counter. If no action on clock withing 32msec, // we are ready to receive next "number" WDTCTL = WDT_MDLY_32; // default timer 32 msec IE1 |= WDTIE; // Enable WDT interrupt P1DIR |= LED; // Set P1.0 to output direction P1OUT |= LED; // LED ON, we'r ready P1SEL |= TXPIN; P1DIR |= TXPIN; // Set P1.1 to output direction // Set up CLOCK input pin P1DIR &= ~CLOCK; // sets input direction P1OUT |= CLOCK; // pull-up is selected P1REN |= CLOCK; // pull-up/pull-down enabled P1IES &= ~CLOCK; // interrupt triggered on low-to-high P1IFG &= ~CLOCK; // reset interrupt flag to 0. needs to be reset on start P1IE |= CLOCK; // interrupt enabled for CLOCK // Set up DATA input pin P1DIR &= ~DATA; // sets input direction P1OUT |= DATA; // pull-up is selected P1REN |= DATA; // pull-up/pull-down enabled P1IES &= ~DATA; // interrupt triggered on low-to-high P1IFG &= ~DATA; // reset interrupt flag to 0. needs to be reset on start P1IE &= ~DATA; // interrupt disabled for DATA // sending something over serial while (1) { __bis_SR_register(LPM0_bits + GIE); // after we went into low power mode, program counter is at this instruction // (next one after where you entered LPM), but it's not moving until you enable active mode // within main loop. That can be done with __bic_SR_register_on_exit(LPM0_bits) in ISR _NOP(); // sending next value. value has been assembled by CLOCL interrupt function // value is 16 bit, TXByte should be 8, sending in two parts TXByte = value >> 8; // first byte (most significant bits) Transmit(); TXByte = value & 0xFF; // second byte (least significant) Transmit(); P1OUT ^= LED; // blink LED } } // Function Transmits Character from TXByte void Transmit() { CCTL0 = OUT; // TXD Idle as Mark TACTL = TASSEL_2 + MC_2; // SMCLK, continuous mode BitCnt = 0xA; // Load Bit counter, 8 bits + ST/SP CCR0 = TAR; CCR0 += Bitime; // Set time till first bit TXByte |= 0x100; // Add stop bit to TXByte (which is logical 1) TXByte = TXByte << 1; // Add start bit (which is logical 0) CCTL0 = CCIS0 + OUTMOD0 + CCIE; // Set signal, intial value, enable interrupts while ( CCTL0 & CCIE ); // Wait for TX completion TACTL = TASSEL_2; // SMCLK, timer off (for power consumption) } // Timer A0 interrupt service routine. Used to send bits over RS232 #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A (void) { CCR0 += Bitime; // Add Offset to CCR0 if ( BitCnt == 0) // If all bits TXed, disable interrupt CCTL0 &= ~ CCIE; else { CCTL0 |= OUTMOD2; // TX Space if (TXByte & 0x01) CCTL0 &= ~ OUTMOD2; // TX Mark TXByte = TXByte >> 1; BitCnt --; } } // Button is pressed #pragma vector=PORT1_VECTOR __interrupt void PORT1_ISR(void) { static unsigned char port; port = P1IN; // read DATA port value as soon as possible (otherwise it might be gone) P1IFG &= ~CLOCK; // Clear interrupt flag clock_active = 1; if (ready_for_data) { if (bits_so_far && bits_so_far <= 16){ // first bit is start bit, ignore it. Total we have 24 bits. But we need only 16 if (!(port & DATA)) // if 0 recived, invert = >1 value |=0x8000; // then set most significant bit value = value >> 1; // and move it one right }else if (bits_so_far == 21){ // 21st bit indicates sighn (+/-) if (!(port & DATA)) value = (~value)+1; // make it negative }else if (bits_so_far >= 23){ // we'r done, got all bits ready_for_data = 0; // warchdog timer will set it __bic_SR_register_on_exit(LPM0_bits); // wake up main from LPM sleep } bits_so_far++; } } // watchdog used as 30msec timer for detecting start of new bit burst on clock #pragma vector=WDT_VECTOR __interrupt void WDT_ISR(void) { if (ready_for_data) return; if (clock_active){ clock_active = 0; // clear flag, will wait another 32msec to see if there have been any activity of clock ready_for_data = 0; // not yet ready }else{ ready_for_data = 1; // nothing within last 32msec, ready for next clock burst value = 0; // init of value bits_so_far = 0; // init of bit counter } }
C Source Code - MSP430 Launchpad with Digital Caliper
This is full C source code for MSP430 Launchpad project described in post Interfacing TI Launchpad to Digital Caliper.
Subscribe to:
Posts (Atom)