/***************************************************************************** * file: adc.c * author: Emil Jovanov * date: 11/14/00 * last change: October 6, 2003 ****************************************************************************/ /* The following are lists of attributes of the various modules used in the * MSP430. These attributes have been copied at the beginning of the section * of code that handles the modules. Any updates to the controls of the * modules should be updated in the attributes list. */ /* * Watchdog Timer has the following attributes: * the clock source was selected to be ACLK, * interval is ACLK * 2^15, * it was initially cleared, * it is in interval timer mode, * RST/NMI input works as a reset input, * a rising edge triggers the NMI (Non-Maskable Interrupt) interrupt, * the WDT is fully active, * * using our 4MHz clock, we create a frequency of 122 Hz, * an interval of 8.2 ms * * Additional information can be obtained from the user's manual * */ #include "config.h" #include "gendef.h" #include #include "rs232.h" #include "leds.h" #define BUFFER_SIZE 200 // stuff in wise.c void delay(void); #define ADCMEM ((int*) 0x0140) // ADC12MEMx definition #define BITS12_15 0xf000 //#define LEDON P1OUT |= BIT0 //#define LEDOFF P1OUT &= ~BIT0 #define ADCMEM ((int*) 0x0140) // ADC12MEMx definition //this will just toggle something on and off #define TOGGLE 0x01 //this is the constant for the CCR0 of the timer //#define TIMER_CONST 60000 //this is the constant for the number of samples to wait before //sending another 0xffff; this number is the number of combined //samples of both channels //#define NUM_SAMPLES_TO_WAIT 200 #define NUM_SAMPLES_TO_WAIT 20 #if 0 /***********************************************************************/ /* Macro definition */ /***********************************************************************/ /* --- void WD_Timer( void ) -----------------------------------------*/ #define WD_Timer() \ WDTCTL=0x5A1C; /* initialize WD as Timer */ \ IE1|=0x01; /* enable WDT interrupt */ \ /* 15 ... 8 7 6 5 4 3 2 1 15 - 8 0x5A (write access) 7 - Hold - 0 counter active 6 - NMIES - 0 NMI edge select 5 - NMI - 0 RESET input 4 - TMSEL - 1 timer mode 3 - CCLR - 1 counter clear 2 - SSEL - 1 ACLK x 2^15 1 - IS1 - 0 0 - IS0 - 0 */ /***********************************************************************/ /* Macro definition */ /***********************************************************************/ /* --- void Timer_A( void ) -----------------------------------------*/ #define Timer_A() \ TACTL=TASSEL0+TACLR; /* initialize TimerA */ \ TACTL|=MC1; /* enable TimerA interrupt */ \ /* 15 ... 10 9 8 7 6 5 4 3 2 1 15 - 10 unused 9 - 8 - Input Select - 01 ACLK 7 - 6 - Input Divider - 00 pass through 5 - 4 - Mode Control - 10 continuous up 3 - N/A - 0 unused 2 - CLR - 1 timer clear 1 - TAIE - 0 overflow interrupt enable 0 - TAIFG - 0 overflow flag */ #endif //global variables //variable to hold number of samples, this will keep track of when to //send another 0xffff synchro signal uint8 num_samples = 0; uint16 rssi = 0; //uint8 buffer[BUFFER_SIZE]; //uint8 buf_head=0; //uint8 buf_tail=0; bool dump_flag = 0; extern uint8 samples[4]; /* void adc_send_byte(uint8 b) { uint8 next = buf_head+1; if (next >= BUFFER_SIZE) next = 0; if (next != buf_tail) { buffer[buf_head] = b; buf_head = next; } } void dump_samples(void) { while (buf_tail != buf_head) { UART1_putchar(buffer[buf_tail++]); if (buf_tail >= BUFFER_SIZE) buf_tail = 0; } } */ void init_adc (void) { /* ADC12 Settings: */ ADC12CTL0 &=~ ENC; // Disable conversion before changing // the ADC12 settings!!! /* to change the channels, just change the INCH_x to the desired channel note: the channels start from zero */ /* to change the number of channels sampled, change the position of the EOS, end of sequence bit */ /* this is referenced on page 326 of reference manual. */ /* selection of reference and input */ ADC12MCTL0 = SREF_1 + INCH_2; ADC12MCTL1 = SREF_1 + INCH_3 + EOS; /* this channel will not be sampled at the same time as the above channels */ ADC12MCTL2 = SREF_1 + INCH_7 + EOS; /* the following are not presently used in conversions */ /* these values are just here to intialize all of the registers, may not be needed*/ ADC12MCTL3 = SREF_1 + INCH_7 + EOS; ADC12MCTL4 = SREF_1 + INCH_7 + EOS; ADC12MCTL5 = SREF_1 + INCH_7 + EOS; ADC12MCTL6 = SREF_1 + INCH_7 + EOS; ADC12MCTL7 = SREF_1 + INCH_7 + EOS; ADC12MCTL8 = SREF_1 + INCH_7 + EOS; ADC12MCTL9 = SREF_1 + INCH_7 + EOS; ADC12MCTL10 = SREF_1 + INCH_7 + EOS; ADC12MCTL11 = SREF_1 + INCH_7 + EOS; ADC12MCTL12 = SREF_1 + INCH_7 + EOS; ADC12MCTL13 = SREF_1 + INCH_7 + EOS; ADC12MCTL14 = SREF_1 + INCH_7 + EOS; ADC12MCTL15 = SREF_1 + INCH_7 + EOS; ADC12CTL1 = SHP + CONSEQ_1; // first conv. result is stored in ADC12MEM0 // ADC12SC bit triggers Sample&Hold // sample pulse is generated by Sampling Timer // Clock Source: ADC12 internal oscillator // Clock divider: 1 // conversion mode: one single conversion ADC12CTL0 = MSH + REF2_5V + REFON + ADC12ON + ADC12OVIE + ADC12TOVIE; // Sample&Hold Time 0 // Sample&Hold Time 1 // Multiple Sample&Hold // reference voltage is on // reference voltage is 2.5V // ADC12 module is switched on // Conversion Time Overflow interrupt enabled // Overflow Interrupt enabled delay(); //delay for tadc12on ?? ADC12IE = 0xFFFF; // enable all ADC interrupts ADC12CTL0 |= ENC; // enable conversion // enable conversion //perform watchdog macro // WD_Timer(); // Timer_A(); // CCR0=TIMER_CONST; //set toggle freq to 100 Hz // CCTL0=CCIE; //interrupt produces a toggle // _EINT(); // enable global interrupts /* end of setup for timer A */ } #if 0 //this is the function to send the two bytes of the ADC register to the PC void SendADCMem(uint8 MemX) { //now send requested data //send lower byte adc_send_byte(ADCMEM[MemX] & 0xFF); //send upper byte adc_send_byte((ADCMEM[MemX] >> 8) & 0x0F); //this is where we check to see if it is time to send another 0xfeff if (num_samples == NUM_SAMPLES_TO_WAIT) { //send 0xffff synchro signal // adc_send_byte(0xff); //lower byte // adc_send_byte(0xfe); //upper byte //reset num_samples to zero num_samples = 0; dump_flag = 1; } //increment the number of samples num_samples++; } #endif interrupt [ADC_VECTOR] void ADC12(void) // ADC INTERRUPT HANDLER { //char overflow[14]="Overflow!\r\0"; //char timing[21]="Timing!\r\0"; //uint16 result; switch (ADC12IV) { case 0x00: // No interrupt break; case 0x02: // ADC overflow break; case 0x04: // ADC timing overflow break; case 0x06: // ADC12MEM0 was loaded (ADC12IFG.0) samples[0] = ADCMEM[0] & 0xFF; samples[1] = (ADCMEM[0] >> 8) & 0x0F; LEDON0; break; case 0x08: // ADC12MEM1 was loaded (ADC12IFG.1) LEDOFF0; samples[2] = ADCMEM[1] & 0xFF; samples[3] = (ADCMEM[1] >> 8) & 0x0F; break; case 0x0A: // ADC12MEM2 was loaded (ADC12IFG.2) rssi = ADCMEM[2]; //SendADCMem(2); break; case 0x0C: // ADC12MEM3 was loaded (ADC12IFG.3) // SendADCMem(3); break; case 0x0E: // ADC12MEM4 was loaded (ADC12IFG.4) // SendADCMem(4); break; case 0x10: // ADC12MEM5 was loaded (ADC12IFG.5) // SendADCMem(5); break; case 0x12: // ADC12MEM6 was loaded (ADC12IFG.6) // SendADCMem(6); break; case 0x14: // ADC12MEM7 was loaded (ADC12IFG.7) // SendADCMem(7); break; case 0x16: // ADC12MEM8 was loaded (ADC12IFG.8) // SendADCMem(8); break; case 0x18: // ADC12MEM9 was loaded (ADC12IFG.9) // SendADCMem(9); break; case 0x1A: // ADC12MEM10 was loaded (ADC12IFG.10) // SendADCMem(10); break; case 0x1C: // ADC12MEM11 was loaded (ADC12IFG.11) // SendADCMem(11); break; case 0x1E: // ADC12MEM12 was loaded (ADC12IFG.12) // SendADCMem(12); break; case 0x20: // ADC12MEM13 was loaded (ADC12IFG.13) // SendADCMem(13); break; case 0x22: // ADC12MEM14 was loaded (ADC12IFG.14) // SendADCMem(14); break; case 0x24: // ADC12MEM15 was loaded (ADC12IFG.15) // SendADCMem(15); break; } } #if 0 /***********************************************************************/ /* Watchdog interrupt service routine */ /***********************************************************************/ /* * This isr takes samples at a rate of 122Hz. * the sample are of analog channels described in the ADC12 setup. * */ /* * Watchdog Timer has the following attributes: * the clock source was selected to be ACLK, * interval is ACLK * 2^15, * it was initially cleared, * it is in interval timer mode, * RST/NMI input works as a reset input, * a rising edge triggers the NMI (Non-Maskable Interrupt) interrupt, * the WDT is fully active, * * using our 4MHz clock, we create a frequency of 122 Hz, * an interval of 8.2 ms * * Additional information can be obtained from the user's manual * starting at page 133 * */ interrupt [WDT_VECTOR] void WD( void ) { uint8 cs,x; P1OUT ^= BIT0; cs = 0; for (x=0;x<4;x++) { cs += samples[x]; UART1_putchar(samples[x]); } UART1_putchar(cs); ADC12CTL0 |= ADC12SC; // start sampling (trigger signal) } #endif /*----------------------------------------------------------------*/ // Timer A interrupt ( Capture Compare for port 0 ) /*----------------------------------------------------------------*/ /* * Timer A has the following attributes: * it was initially cleared, * Continuous mode, * the clock was divided by one, * the clock source was selected to be ACLK. * * Additional information can be obtained from the user's manual * starting at page 141 * */ #if 0 interrupt [TIMERA0_VECTOR] void TAINT0(void) { //increment compare register by constant value CCR0+=TIMER_CONST; //make sure that a conversion is not going on while (ADC12CTL1 & ADC12BUSY); ADC12CTL0 &=~ ENC; // Disable conversion before changing // the ADC12 settings!!! //change the start address of the conversions ADC12CTL1 = CSTARTADD_2 + (ADC12CTL1 & ~BITS12_15); ADC12CTL0 |= ENC; // enable conversion ADC12CTL0 |= ADC12SC; // start sampling (trigger signal) //P1OUT^=0x01; } #endif