1 /** 2 * @file hal_adc.c 3 * 4 * Copyright 2008 Texas Instruments, Inc. 5 ***************************************************************************/ 6 7 #include "hal_adc.h" 8 9 #include <msp430x54x.h> 10 #include "hal_compat.h" 11 12 static int SavedADC12MEM0 = 0, SavedADC12MEM1 = 0, SavedADC12MEM2 = 0; 13 static int Acc_x = 0, Acc_y = 0, Acc_z = 0; 14 static int Acc_x_offset = 0, Acc_y_offset = 0, Acc_z_offset = 0; 15 static long int Vcc = 0, Temperature = 0; 16 static long int temperatureOffset = CELSIUS_OFFSET; 17 static unsigned char conversionType = CELSIUS, adcMode = ADC_OFF_MODE; 18 static unsigned char exit_active_from_ADC12 = 0; 19 20 /************************************************************************ 21 * @brief Turns on and initializes ADC12, accelerometer in order to 22 * sample x, y, z-axis inputs. 23 * 24 * @param none 25 * 26 * @return none 27 *************************************************************************/ 28 void halAccelerometerInit(void) 29 { 30 adcMode = ADC_ACC_MODE; 31 ACC_PORT_SEL |= ACC_X_PIN + ACC_Y_PIN; //Enable A/D channel inputs 32 ACC_PORT_DIR &= ~(ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN); 33 ACC_PORT_DIR |= ACC_PWR_PIN; //Enable ACC_POWER 34 ACC_PORT_OUT |= ACC_PWR_PIN; 35 36 //Sequence of channels, once, ACLK 37 ADC12CTL0 = ADC12ON + ADC12SHT02 + ADC12MSC; 38 ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1 + ADC12SSEL_0; 39 ADC12CTL2 = ADC12RES_2; 40 ADC12MCTL0 = ACC_X_CHANNEL; 41 ADC12MCTL1 = ACC_Y_CHANNEL; 42 ADC12MCTL2 = ACC_Z_CHANNEL + ADC12EOS; 43 44 // Allow the accelerometer to settle before sampling any data 45 46 // 4.5.3-20110706-2 doesn't allow for 32-bit delay cycles 47 int i; 48 for (i=0;i<10;i++){ 49 __delay_cycles(20000); 50 } 51 UCSCTL8 |= MODOSCREQEN; 52 } 53 54 /************************************************************************ 55 * @brief Calibrates the offset values for x, y, and z axes. 56 * 57 * @param none 58 * 59 * @return none 60 *************************************************************************/ 61 void halAccelerometerCalibrate(void) 62 { 63 unsigned char tempQuit; 64 65 tempQuit = exit_active_from_ADC12; 66 halAdcSetQuitFromISR( 1 ); 67 halAdcStartRead(); 68 69 __bis_SR_register(LPM3_bits + GIE); 70 __no_operation(); 71 72 halAccelerometerReadWithOffset(&Acc_x_offset, &Acc_y_offset, &Acc_z_offset); 73 halAdcSetQuitFromISR( tempQuit ); 74 } 75 76 /************************************************************************ 77 * @brief Set function for the calibrated offsets for the x, y, and z axes. 78 * 79 * @param x Calibrated offset for the x-axis 80 * 81 * @param y Calibrated offset for the y-axis 82 * 83 * @param z Calibrated offset for the z-axis 84 * 85 * @return none 86 *************************************************************************/ 87 void halAccelerometerSetCalibratedOffset( int x, int y, int z ) 88 { 89 Acc_x_offset = x; 90 Acc_y_offset = y; 91 Acc_z_offset = z; 92 } 93 94 /************************************************************************ 95 * @brief Get function for the x, y, and z axes calibrated offsets 96 * 97 * @param x Pointer to the calibrated offset for the x-axis 98 * 99 * @param y Pointer to the calibrated offset for the y-axis 100 * 101 * @param z Pointer to the calibrated offset for the z-axis 102 * 103 * @return none 104 *************************************************************************/ 105 void halAccelerometerGetCalibratedOffset(int *x, int *y, int *z) 106 { 107 *x = Acc_x_offset; 108 *y = Acc_y_offset; 109 *z = Acc_y_offset; 110 } 111 112 /************************************************************************ 113 * @brief Get function for the x, y, and z accelerometer samples, 114 * including the calibrated offsets. 115 * 116 * @param x Pointer to the accelerometer reading (x-axis) 117 * 118 * @param y Pointer to the accelerometer reading (y-axis) 119 * 120 * @param z Pointer to the accelerometer reading (z-axis) 121 * 122 * @return none 123 *************************************************************************/ 124 void halAccelerometerRead(int *x, int *y, int *z) 125 { 126 Acc_x = SavedADC12MEM0; 127 Acc_y = SavedADC12MEM1; 128 Acc_z = SavedADC12MEM2; 129 130 *x = Acc_x - Acc_x_offset; 131 *y = Acc_y - Acc_y_offset; 132 *z = Acc_z - Acc_z_offset; 133 } 134 135 /************************************************************************ 136 * @brief Get function for the x, y, and z accelerometer samples, 137 * excluding the calibrated offsets. 138 * 139 * @param x Pointer to the accelerometer reading (x-axis) 140 * 141 * @param y Pointer to the accelerometer reading (y-axis) 142 * 143 * @param z Pointer to the accelerometer reading (z-axis) 144 * 145 * @return none 146 *************************************************************************/ 147 void halAccelerometerReadWithOffset(int *x, int *y, int *z) 148 { 149 *x = SavedADC12MEM0; 150 *y = SavedADC12MEM1; 151 *z = SavedADC12MEM2; 152 } 153 154 /************************************************************************ 155 * @brief Disables the ADC12, accelerometer that sampled x, y, z-axis inputs. 156 * 157 * @param none 158 * 159 * @return none 160 *************************************************************************/ 161 void halAccelerometerShutDown(void) 162 { 163 //Turn off ADC Module 164 ADC12CTL0 &= ~( ADC12ON + ADC12ENC ); 165 ACC_PORT_OUT &= ~ACC_PWR_PIN; //Disable ACC_POWER 166 167 //Disable A/D channel inputs 168 ACC_PORT_SEL &= ~(ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN); 169 ACC_PORT_DIR |= (ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN + ACC_PWR_PIN); 170 ACC_PORT_OUT &= ~(ACC_X_PIN + ACC_Y_PIN + ACC_Z_PIN + ACC_PWR_PIN); 171 172 adcMode = ADC_OFF_MODE; 173 } 174 175 /*----------------------------------------------------------------------------*/ 176 /************************************************************************ 177 * @brief Intializes the ADC12 to sample Temperature and Vcc. 178 * 179 * @param none 180 * 181 * @return none 182 *************************************************************************/ 183 void halAdcInitTempVcc(void) 184 { 185 //Sequence of channels, once, 186 adcMode = ADC_TEMP_MODE; 187 UCSCTL8 |= MODOSCREQEN; 188 ADC12CTL0 = ADC12ON + ADC12SHT0_15 + ADC12MSC + + ADC12REFON + ADC12REF2_5V; 189 ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1 + ADC12SSEL_0; 190 ADC12CTL2 = ADC12RES_2; 191 192 ADC12MCTL0 = ADC12SREF_1 + TEMP_CHANNEL; 193 ADC12MCTL1 = ADC12SREF_1 + VCC_CHANNEL + ADC12EOS; 194 } 195 196 /************************************************************************ 197 * @brief Turns off / disable the ADC12. 198 * 199 * @param none 200 * 201 * @return none 202 *************************************************************************/ 203 void halAdcShutDownTempVcc(void) 204 { 205 ADC12CTL0 &= ~ ( ADC12ON + ADC12ENC + ADC12REFON ); 206 adcMode = ADC_OFF_MODE; 207 } 208 209 /************************************************************************ 210 * @brief Sets the conversion type to either Farenheit (F) or Celsius (C). 211 * 212 * @param conversion The #define constant CELSIUS or FAHRENHEIT. 213 * 214 * @return none 215 *************************************************************************/ 216 void halAdcSetTempConversionType(unsigned char conversion) 217 { 218 conversionType = conversion; 219 } 220 221 /************************************************************************ 222 * @brief Set function for the calibrated temperature offset. 223 * 224 * @param offset The temperature offset. 225 * 226 * @return none 227 *************************************************************************/ 228 void halAdcSetTempOffset(long offset) 229 { 230 temperatureOffset = offset; 231 } 232 233 /************************************************************************ 234 * @brief Get function for the current temperature value. 235 * 236 * @param none 237 * 238 * @return The current temperature value. 239 *************************************************************************/ 240 int halAdcGetTemp(void) 241 { 242 return Temperature; 243 } 244 245 /************************************************************************ 246 * @brief Get function for the current Vcc value. 247 * 248 * @param none 249 * 250 * @return The current Vcc value. 251 *************************************************************************/ 252 int halAdcGetVcc(void) 253 { 254 return Vcc; 255 } 256 257 /************************************************************************ 258 * @brief Converts the Vcc and Temp readings from the ADC to BCD format. 259 * 260 * @param none 261 * 262 * @return none 263 *************************************************************************/ 264 void halAdcConvertTempVccFromADC(void) 265 { 266 long multiplier, offset; 267 268 // Convert Vcc 269 Vcc = SavedADC12MEM1; 270 Vcc = Vcc * 50; 271 Vcc = Vcc / 4096; 272 273 // Convert Temperature 274 if (conversionType == CELSIUS) 275 { 276 multiplier = CELSIUS_MUL; 277 offset = temperatureOffset; 278 } 279 else 280 { 281 multiplier = (long) CELSIUS_MUL * 9 /5 ; 282 offset = (long) temperatureOffset * 9 / 5 - 320; 283 } 284 Temperature = (long) SavedADC12MEM0 * multiplier/4096 - offset; 285 } 286 287 /************************************************************************ 288 * @brief Get function for the temperature and Vcc samples in "xxx^C/F" and 289 * "x.xV" format. 290 * 291 * @param TemperatureStr The string that holds the temperature reading 292 * 293 * @param Vcc The string that holds the Vcc reading 294 * 295 * @return none 296 *************************************************************************/ 297 void halAdcReadTempVcc(char *TemperatureStr, char *VccStr) 298 { 299 unsigned char i, leadingZero = 0; 300 long int dummyTemperature, dummyVcc; 301 302 halAdcConvertTempVccFromADC(); 303 dummyTemperature = Temperature; 304 dummyVcc = Vcc; 305 for (i = 0; i < 6; i++) 306 TemperatureStr[i] = '\0'; 307 i=0; 308 //Check for negative 309 if (Temperature < 0) 310 { 311 TemperatureStr[i++]='-'; 312 Temperature = -Temperature; 313 } 314 TemperatureStr[i] ='0'; 315 if (Temperature >= 1000) 316 { 317 TemperatureStr[i]='1'; 318 Temperature -=1000; 319 leadingZero = 1; 320 } 321 if (leadingZero == 1) 322 i++; 323 //100s digit 324 TemperatureStr[i] = '0'; 325 if (Temperature >= 100) 326 { 327 do 328 { 329 TemperatureStr[i]++; 330 Temperature -=100; 331 } 332 while (Temperature >=100); 333 leadingZero = 1; 334 } 335 if (leadingZero == 1) 336 i++; 337 //10s digit 338 TemperatureStr[i] = '0'; 339 if (Temperature >=10) 340 { 341 do 342 { 343 TemperatureStr[i]++; 344 Temperature -=10; 345 } 346 while (Temperature >=10); 347 } 348 349 TemperatureStr[++i] = '^'; 350 if (conversionType == CELSIUS) 351 TemperatureStr[++i]='C'; 352 else 353 TemperatureStr[++i]='F'; 354 355 VccStr[0] = '0'; 356 VccStr[2] = '0'; 357 while (Vcc >= 10) 358 { 359 VccStr[0]++; 360 Vcc -= 10; 361 } 362 VccStr[2] += Vcc; 363 Temperature = dummyTemperature; 364 Vcc = dummyVcc; 365 } 366 367 /*----------------------------------------------------------------------------*/ 368 /************************************************************************ 369 * @brief Starts the ADC conversion. 370 * 371 * @param none 372 * 373 * @return none 374 *************************************************************************/ 375 void halAdcStartRead(void) 376 { 377 ADC12IFG &= ~(BIT1+BIT0); // Clear any pending flags 378 379 if (adcMode == ADC_ACC_MODE) 380 { 381 ADC12CTL0 |= ADC12ENC | ADC12SC ; 382 ADC12IE |= BIT2; 383 } 384 else 385 { 386 ADC12CTL0 |= ADC12REFON; // Turn on ADC12 reference 387 388 // Delay to stabilize ADC12 reference assuming the fastest MCLK of 18 MHz. 389 // 35 us = 1 / 18 MHz * 630 390 __delay_cycles(630); 391 392 ADC12IE |= BIT1; // Enable interrupt 393 ADC12CTL0 |= ADC12ENC | ADC12SC; 394 } 395 } 396 397 /************************************************************************ 398 * @brief Sets the flag that causes an exit into active CPU mode from 399 * the ADC12 ISR. 400 * 401 * @param quit 402 * 403 * - 1 - Exit active from ADC12 ISR 404 * - 0 - Remain in LPMx on exit from ADC12ISR 405 * 406 * @return none 407 *************************************************************************/ 408 void halAdcSetQuitFromISR(unsigned char quit) 409 { 410 exit_active_from_ADC12 = quit; 411 } 412 413 /*----------------------------------------------------------------------------*/ 414 415 #ifdef __GNUC__ 416 __attribute__((interrupt(ADC12_VECTOR))) 417 #endif 418 #ifdef __IAR_SYSTEMS_ICC__ 419 #pragma vector=ADC12_VECTOR 420 __interrupt 421 #endif 422 void ADC12_ISR(void) 423 { 424 SavedADC12MEM0 = ADC12MEM0; // Store the sampled data 425 SavedADC12MEM1 = ADC12MEM1; 426 SavedADC12MEM2 = ADC12MEM2; 427 ADC12IFG = 0; // Clear the interrupt flags 428 ADC12CTL0 &= ~( ADC12ENC | ADC12SC | ADC12REFON); 429 if (exit_active_from_ADC12) __bic_SR_register_on_exit(LPM3_bits); 430 } 431