#include #include "msp430g2131.h" //------------------------------------------------------------------------------ // Definitions //------------------------------------------------------------------------------ #define LED BIT1 // P1.1 #define PHASE BIT2 // P1.2 #define DIRECTION BIT3 // P1.3 #define ADC_VREF BIT4 // P1.4 #define ENABLE BIT6 // P2.6 //------------------------------------------------------------------------------ // Global variables //------------------------------------------------------------------------------ unsigned int i, m_cnt, counter, flag = 0; unsigned int DutyCycle = 0; // PWM duty cycle unsigned int high, low = 0; unsigned int master_data[12] ; // array to store the 12B data from the master unsigned int slave_data[12] = {0x7E, 0x5D, 0x78, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x00, 0x00, 0x00, 0x00}; // array to store the 12B data from the slave unsigned int *pslaveArray = slave_data; // pointer pointing to slave_data array //------------------------------------------------------------------------------ // Declare functions //------------------------------------------------------------------------------ /* * Function to calculate checksum */ unsigned int checksum(unsigned int array[], int size) { unsigned int sum = 0; unsigned int j = size; for( ; j > 0; j--) { sum += array[j-1]; } return sum; } /* * Function to check the master array */ void master_check(unsigned int master_array[12]) { // Combine both the duty cycle (DC) values from the master as integer values to compare them later unsigned int asked_DC = master_array[3] + master_array[2]; unsigned const int safe_DC = 0x00 + 0x6D; // check if the asked DC from the master is less than the limit DC. // if(asked_DC <= safe_DC) // Yes then change that value into the slave data array accordingly // { DutyCycle = asked_DC; high = DutyCycle; low = 250 - high; /** } else // No then put the limit DC value into the slave data array accordingly { DutyCycle = safe_DC; high = DutyCycle; low = 250 - high; } **/ } /* * Function to initialize values */ void init(void) { IE1 |= WDTIE; // Enable WDT interrupt BCSCTL1 = CALBC1_1MHZ; // Set DCO to 1MHz DCOCTL = CALDCO_1MHZ; P1SEL = LED + PHASE; P1OUT = 0x00; // P1.x Reset P1DIR = 0x56; CCTL0 = CCIS_0 + OUTMOD_4 + CCIE; // CCR0 toggle, interrupt enabled, CCI0A input on CCI CCTL1 = CCIS_0 + OUTMOD_4 + CCIE; TACTL = TASSEL_2 + MC_2 + TAIE; // SMCLK source, continuous mode, int enabled ADC10CTL0 = ADC10SHT_2 + ADC10ON; //+ MSC + ADC10IE; // VCC ref ADC10AE0 |= INCH_0; // P1.0 ADC option select USICTL0 |= USIPE7 + USIPE6 + USIPE5 + USIOE; // Port, SPI slave USICTL1 |= USIIE; // Counter interrupt, flag remains set USICTL0 &= ~USISWRST; // USI released for operation USISRL = 0xCD; // init-load data into the lower byte of the serial register USISRH = 0xEF; // init-load data into the higher byte of the serial register USICNT = USI16B + 16; // init-load counter + enable 16-bit shift register mode } //------------------------------------------------------------------------------ // Main function //------------------------------------------------------------------------------ int main(void) { WDTCTL = WDT_MDLY_8; // Set Watchdog Timer interval to ~30ms // __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt init(); while(1) { _BIS_SR(LPM0_bits + GIE); // Enter LPM0 with interrupts P1OUT |= ADC_VREF; // Enable poti divider ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start while (ADC10IFG & ADC10CTL0); // Wait for conversion complete ADC10CTL0 &= ~ADC10IFG; // Clear converstion flag P1OUT &= ~ADC_VREF; // Disable poti divider // DutyCycle = 63 - (ADC10MEM>>4); // Mask upper 6-bits // LED_Blink = 63 - (ADC10MEM>>4); // Mask upper 6-bits // CCR1 = DutyCycle; // PWM duty cycle to DRV /** if (DIRECTION & P1IN) // Forward direction? { P1OUT |= PHASE; } else // Reverse { P1OUT &= ~PHASE; } **/ } } // Watchdog Timer interrupt service routine #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { _BIC_SR_IRQ(LPM3_bits); // Clear LPM0 bits from 0(SR) } // USI interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USI_VECTOR __interrupt void universal_serial_interface(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USI_VECTOR))) universal_serial_interface (void) #else #error Compiler not supported! #endif { if(flag == 0 || ((USISRH == 0x7E) && (USISRL == 0x5D))) { flag = 1; m_cnt = 0; } if(flag == 1) { master_data[m_cnt] = USISRH; master_data[m_cnt+1] = USISRL; m_cnt = m_cnt + 2; } if (m_cnt >= 10) { flag = 0; if((master_data[0] == 0x7E) && (master_data[1] == 0x5D)) //Check if the master header is right master_check(master_data); } if(counter >= 12) { counter = 0; slave_data[3] = ADC10MEM; //sampling lower 8 bytes first slave_data[4] = ADC10MEM >> 8; //shift the upper 8 bytes to the left to sample them // slave_data[5] = DutyCycle; // slave_data[6] = DutyCycle >> 8; slave_data[5] = CCR1; slave_data[6] = CCR1 >> 8; } pslaveArray = slave_data + counter; USISRL = *(pslaveArray+1); USISRH = *(pslaveArray); USICNT = USI16B + 16; counter = counter + 2; } // Timer A0 interrupt service routine #pragma vector=TIMER0_A0_VECTOR __interrupt void Timer_A0 (void) // Generate 20Hz frequency with 20% constant duty cycle { if(CCTL0 & CCI) // If output currently high { CCR0 += 10000; // 20% high } else { CCR0 += 40000; // 80% low } } // Timer A1 Interrupt Vector (TA0IV) handler #pragma vector=TIMER0_A1_VECTOR __interrupt void Timer_A1(void) // Generate 4KHz frequency for DRV motor { switch( TA0IV ) { case 2: if(CCTL1 & CCI) // If output currently high { //CCR1 += 50; // 20% high //CCR1 += DutyCycle; CCR1 += high; } else { //CCR1 += 200; // 80% low //CCR1 += (250 - DutyCycle); CCR1 += low; } break; default: break; } }