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 * @brief Intializes the ADC12 to sample Temperature and Vcc. 177 * 178 * @param none 179 * 180 * @return none 181 *************************************************************************/ 182 void halAdcInitTempVcc(void) 183 { 184 //Sequence of channels, once, 185 adcMode = ADC_TEMP_MODE; 186 UCSCTL8 |= MODOSCREQEN; 187 ADC12CTL0 = ADC12ON + ADC12SHT0_15 + ADC12MSC + + ADC12REFON + ADC12REF2_5V; 188 ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1 + ADC12SSEL_0; 189 ADC12CTL2 = ADC12RES_2; 190 191 ADC12MCTL0 = ADC12SREF_1 + TEMP_CHANNEL; 192 ADC12MCTL1 = ADC12SREF_1 + VCC_CHANNEL + ADC12EOS; 193 } 194 195 /************************************************************************ 196 * @brief Turns off / disable the ADC12. 197 * 198 * @param none 199 * 200 * @return none 201 *************************************************************************/ 202 void halAdcShutDownTempVcc(void) 203 { 204 ADC12CTL0 &= ~ ( ADC12ON + ADC12ENC + ADC12REFON ); 205 adcMode = ADC_OFF_MODE; 206 } 207 208 /************************************************************************ 209 * @brief Sets the conversion type to either Farenheit (F) or Celsius (C). 210 * 211 * @param conversion The #define constant CELSIUS or FAHRENHEIT. 212 * 213 * @return none 214 *************************************************************************/ 215 void halAdcSetTempConversionType(unsigned char conversion) 216 { 217 conversionType = conversion; 218 } 219 220 /************************************************************************ 221 * @brief Set function for the calibrated temperature offset. 222 * 223 * @param offset The temperature offset. 224 * 225 * @return none 226 *************************************************************************/ 227 void halAdcSetTempOffset(long offset) 228 { 229 temperatureOffset = offset; 230 } 231 232 /************************************************************************ 233 * @brief Get function for the current temperature value. 234 * 235 * @param none 236 * 237 * @return The current temperature value. 238 *************************************************************************/ 239 int halAdcGetTemp(void) 240 { 241 return Temperature; 242 } 243 244 /************************************************************************ 245 * @brief Get function for the current Vcc value. 246 * 247 * @param none 248 * 249 * @return The current Vcc value. 250 *************************************************************************/ 251 int halAdcGetVcc(void) 252 { 253 return Vcc; 254 } 255 256 /************************************************************************ 257 * @brief Converts the Vcc and Temp readings from the ADC to BCD format. 258 * 259 * @param none 260 * 261 * @return none 262 *************************************************************************/ 263 void halAdcConvertTempVccFromADC(void) 264 { 265 long multiplier, offset; 266 267 // Convert Vcc 268 Vcc = SavedADC12MEM1; 269 Vcc = Vcc * 50; 270 Vcc = Vcc / 4096; 271 272 // Convert Temperature 273 if (conversionType == CELSIUS) 274 { 275 multiplier = CELSIUS_MUL; 276 offset = temperatureOffset; 277 } 278 else 279 { 280 multiplier = (long) CELSIUS_MUL * 9 /5 ; 281 offset = (long) temperatureOffset * 9 / 5 - 320; 282 } 283 Temperature = (long) SavedADC12MEM0 * multiplier/4096 - offset; 284 } 285 286 /************************************************************************ 287 * @brief Get function for the temperature and Vcc samples in "xxx^C/F" and 288 * "x.xV" format. 289 * 290 * @param TemperatureStr The string that holds the temperature reading 291 * 292 * @param Vcc The string that holds the Vcc reading 293 * 294 * @return none 295 *************************************************************************/ 296 void halAdcReadTempVcc(char *TemperatureStr, char *VccStr) 297 { 298 unsigned char i, leadingZero = 0; 299 long int dummyTemperature, dummyVcc; 300 301 halAdcConvertTempVccFromADC(); 302 dummyTemperature = Temperature; 303 dummyVcc = Vcc; 304 for (i = 0; i < 6; i++) 305 TemperatureStr[i] = '\0'; 306 i=0; 307 //Check for negative 308 if (Temperature < 0) 309 { 310 TemperatureStr[i++]='-'; 311 Temperature = -Temperature; 312 } 313 TemperatureStr[i] ='0'; 314 if (Temperature >= 1000) 315 { 316 TemperatureStr[i]='1'; 317 Temperature -=1000; 318 leadingZero = 1; 319 } 320 if (leadingZero == 1) 321 i++; 322 //100s digit 323 TemperatureStr[i] = '0'; 324 if (Temperature >= 100) 325 { 326 do 327 { 328 TemperatureStr[i]++; 329 Temperature -=100; 330 } 331 while (Temperature >=100); 332 leadingZero = 1; 333 } 334 if (leadingZero == 1) 335 i++; 336 //10s digit 337 TemperatureStr[i] = '0'; 338 if (Temperature >=10) 339 { 340 do 341 { 342 TemperatureStr[i]++; 343 Temperature -=10; 344 } 345 while (Temperature >=10); 346 } 347 348 TemperatureStr[++i] = '^'; 349 if (conversionType == CELSIUS) 350 TemperatureStr[++i]='C'; 351 else 352 TemperatureStr[++i]='F'; 353 354 VccStr[0] = '0'; 355 VccStr[2] = '0'; 356 while (Vcc >= 10) 357 { 358 VccStr[0]++; 359 Vcc -= 10; 360 } 361 VccStr[2] += Vcc; 362 Temperature = dummyTemperature; 363 Vcc = dummyVcc; 364 } 365 366 /*----------------------------------------------------------------------------*/ 367 /************************************************************************ 368 * @brief Starts the ADC conversion. 369 * 370 * @param none 371 * 372 * @return none 373 *************************************************************************/ 374 void halAdcStartRead(void) 375 { 376 ADC12IFG &= ~(BIT1+BIT0); // Clear any pending flags 377 378 if (adcMode == ADC_ACC_MODE) 379 { 380 ADC12CTL0 |= ADC12ENC | ADC12SC ; 381 ADC12IE |= BIT2; 382 } 383 else 384 { 385 ADC12CTL0 |= ADC12REFON; // Turn on ADC12 reference 386 387 // Delay to stabilize ADC12 reference assuming the fastest MCLK of 18 MHz. 388 // 35 us = 1 / 18 MHz * 630 389 __delay_cycles(630); 390 391 ADC12IE |= BIT1; // Enable interrupt 392 ADC12CTL0 |= ADC12ENC | ADC12SC; 393 } 394 } 395 396 /************************************************************************ 397 * @brief Sets the flag that causes an exit into active CPU mode from 398 * the ADC12 ISR. 399 * 400 * @param quit 401 * 402 * - 1 - Exit active from ADC12 ISR 403 * - 0 - Remain in LPMx on exit from ADC12ISR 404 * 405 * @return none 406 *************************************************************************/ 407 void halAdcSetQuitFromISR(unsigned char quit) 408 { 409 exit_active_from_ADC12 = quit; 410 } 411 412 /*----------------------------------------------------------------------------*/ 413 414 #ifdef __GNUC__ 415 __attribute__((interrupt(ADC12_VECTOR))) 416 #endif 417 #ifdef __IAR_SYSTEMS_ICC__ 418 #pragma vector=ADC12_VECTOR 419 __interrupt 420 #endif 421 void ADC12_ISR(void) 422 { 423 SavedADC12MEM0 = ADC12MEM0; // Store the sampled data 424 SavedADC12MEM1 = ADC12MEM1; 425 SavedADC12MEM2 = ADC12MEM2; 426 ADC12IFG = 0; // Clear the interrupt flags 427 ADC12CTL0 &= ~( ADC12ENC | ADC12SC | ADC12REFON); 428 if (exit_active_from_ADC12) __bic_SR_register_on_exit(LPM3_bits); 429 } 430