hal_adc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /**************************************************************************************************
  2. Filename: hal_adc.c
  3. Revised: $Date: 2009-03-13 05:45:44 -0700 (Fri, 13 Mar 2009) $
  4. Revision: $Revision: 19408 $
  5. Description: This file contains the interface to the HAL ADC.
  6. Copyright 2006-2007 Texas Instruments Incorporated. All rights reserved.
  7. IMPORTANT: Your use of this Software is limited to those specific rights
  8. granted under the terms of a software license agreement between the user
  9. who downloaded the software, his/her employer (which must be your employer)
  10. and Texas Instruments Incorporated (the "License"). You may not use this
  11. Software unless you agree to abide by the terms of the License. The License
  12. limits your use, and you acknowledge, that the Software may not be modified,
  13. copied or distributed unless embedded on a Texas Instruments microcontroller
  14. or used solely and exclusively in conjunction with a Texas Instruments radio
  15. frequency transceiver, which is integrated into your product. Other than for
  16. the foregoing purpose, you may not use, reproduce, copy, prepare derivative
  17. works of, modify, distribute, perform, display or sell this Software and/or
  18. its documentation for any purpose.
  19. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  20. PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  21. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  22. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  23. TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
  24. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  25. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  26. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  27. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  28. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  29. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  30. Should you have any questions regarding your right to use this Software,
  31. contact Texas Instruments Incorporated at www.TI.com.
  32. **************************************************************************************************/
  33. /**************************************************************************************************
  34. * INCLUDES
  35. **************************************************************************************************/
  36. #include "hal_mcu.h"
  37. #include "hal_defs.h"
  38. #include "hal_types.h"
  39. #include "hal_adc.h"
  40. /**************************************************************************************************
  41. * CONSTANTS
  42. **************************************************************************************************/
  43. #define HAL_ADC_EOC 0x80 /* End of Conversion bit */
  44. #define HAL_ADC_START 0x40 /* Starts Conversion */
  45. #define HAL_ADC_STSEL_EXT 0x00 /* External Trigger */
  46. #define HAL_ADC_STSEL_FULL 0x10 /* Full Speed, No Trigger */
  47. #define HAL_ADC_STSEL_T1C0 0x20 /* Timer1, Channel 0 Compare Event Trigger */
  48. #define HAL_ADC_STSEL_ST 0x30 /* ADCCON1.ST =1 Trigger */
  49. #define HAL_ADC_RAND_NORM 0x00 /* Normal Operation */
  50. #define HAL_ADC_RAND_LFSR 0x04 /* Clock LFSR */
  51. #define HAL_ADC_RAND_SEED 0x08 /* Seed Modulator */
  52. #define HAL_ADC_RAND_STOP 0x0c /* Stop Random Generator */
  53. #define HAL_ADC_RAND_BITS 0x0c /* Bits [3:2] */
  54. #define HAL_ADC_REF_125V 0x00 /* Internal 1.25V Reference */
  55. #define HAL_ADC_REF_AIN7 0x40 /* AIN7 Reference */
  56. #define HAL_ADC_REF_AVDD 0x80 /* AVDD_SOC Pin Reference */
  57. #define HAL_ADC_REF_DIFF 0xc0 /* AIN7,AIN6 Differential Reference */
  58. #define HAL_ADC_REF_BITS 0xc0 /* Bits [7:6] */
  59. #define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */
  60. #define HAL_ADC_DEC_128 0x10 /* Decimate by 128 : 10-bit resolution */
  61. #define HAL_ADC_DEC_256 0x20 /* Decimate by 256 : 12-bit resolution */
  62. #define HAL_ADC_DEC_512 0x30 /* Decimate by 512 : 14-bit resolution */
  63. #define HAL_ADC_DEC_BITS 0x30 /* Bits [5:4] */
  64. #define HAL_ADC_CHN_AIN0 0x00 /* AIN0 */
  65. #define HAL_ADC_CHN_AIN1 0x01 /* AIN1 */
  66. #define HAL_ADC_CHN_AIN2 0x02 /* AIN2 */
  67. #define HAL_ADC_CHN_AIN3 0x03 /* AIN3 */
  68. #define HAL_ADC_CHN_AIN4 0x04 /* AIN4 */
  69. #define HAL_ADC_CHN_AIN5 0x05 /* AIN5 */
  70. #define HAL_ADC_CHN_AIN6 0x06 /* AIN6 */
  71. #define HAL_ADC_CHN_AIN7 0x07 /* AIN7 */
  72. #define HAL_ADC_CHN_A0A1 0x08 /* AIN0,AIN1 */
  73. #define HAL_ADC_CHN_A2A3 0x09 /* AIN2,AIN3 */
  74. #define HAL_ADC_CHN_A4A5 0x0a /* AIN4,AIN5 */
  75. #define HAL_ADC_CHN_A6A7 0x0b /* AIN6,AIN7 */
  76. #define HAL_ADC_CHN_GND 0x0c /* GND */
  77. #define HAL_ADC_CHN_VREF 0x0d /* Positive voltage reference */
  78. #define HAL_ADC_CHN_TEMP 0x0e /* Temperature sensor */
  79. #define HAL_ADC_CHN_VDD3 0x0f /* VDD/3 */
  80. #define HAL_ADC_CHN_BITS 0x0f /* Bits [3:0] */
  81. #define HAL_ADC_STSEL HAL_ADC_STSEL_ST
  82. #define HAL_ADC_RAND_GEN HAL_ADC_RAND_STOP
  83. #define HAL_ADC_REF_VOLT HAL_ADC_REF_AVDD
  84. #define HAL_ADC_DEC_RATE HAL_ADC_DEC_064
  85. #define HAL_ADC_SCHN HAL_ADC_CHN_VDD3
  86. #define HAL_ADC_ECHN HAL_ADC_CHN_GND
  87. /* Vdd limit values */
  88. static __code const uint16 HalAdcVddLimit[] =
  89. {
  90. 0x369C, /* VDD Limit - 1.6v */
  91. 0x3A06, /* VDD Limit - 1.7v */
  92. 0x3D70, /* VDD Limit - 1.8v */
  93. 0x40D9, /* VDD Limit - 1.9v */
  94. 0x4443, /* VDD Limit - 2.0v */
  95. 0x47AD, /* VDD Limit - 2.1v */
  96. 0x4B17, /* VDD Limit - 2.2v */
  97. 0x4E81, /* VDD Limit - 2.3v */
  98. 0x51EA, /* VDD Limit - 2.4v */
  99. };
  100. /**************************************************************************************************
  101. * MACROS
  102. **************************************************************************************************/
  103. #define HAL_ADC_CLR_EOC() asm("PUSH A"); asm("MOV A,ADCL"); asm("MOV A,ADCH"); asm("POP A");
  104. /**************************************************************************************************
  105. * TYPEDEFS
  106. **************************************************************************************************/
  107. /**************************************************************************************************
  108. * GLOBAL VARIABLES
  109. **************************************************************************************************/
  110. /**************************************************************************************************
  111. * FUNCTIONS - API
  112. **************************************************************************************************/
  113. extern bool HalAdcCheckVdd (uint8 limit);
  114. /**************************************************************************************************
  115. * @fn HalAdcInit
  116. *
  117. * @brief Initialize ADC Service
  118. *
  119. * @param None
  120. *
  121. * @return None
  122. **************************************************************************************************/
  123. void HalAdcInit (void)
  124. {
  125. #if (HAL_ADC == TRUE)
  126. volatile uint8 tmp;
  127. ADCCON1 = HAL_ADC_STSEL | HAL_ADC_RAND_GEN | 0x03;
  128. ADCCON2 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_SCHN;
  129. /*
  130. * After reset, the first ADC reading of the extra conversion always reads GND level.
  131. * We will do a few dummy conversions to bypass this bug.
  132. */
  133. tmp = ADCL; /* read ADCL,ADCH to clear EOC */
  134. tmp = ADCH;
  135. ADCCON3 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_ECHN;
  136. while ((ADCCON1 & HAL_ADC_EOC) != HAL_ADC_EOC); /* Wait for conversion */
  137. tmp = ADCL; /* read ADCL,ADCH to clear EOC */
  138. tmp = ADCH;
  139. ADCCON3 = HAL_ADC_REF_VOLT | HAL_ADC_DEC_RATE | HAL_ADC_ECHN;
  140. while ((ADCCON1 & HAL_ADC_EOC) != HAL_ADC_EOC); /* Wait for conversion */
  141. tmp = ADCL; /* read ADCL,ADCH to clear EOC */
  142. tmp = ADCH;
  143. #endif
  144. }
  145. /**************************************************************************************************
  146. * @fn HalAdcRead
  147. *
  148. * @brief Read the ADC based on given channel and resolution
  149. *
  150. * @param channel - channel where ADC will be read
  151. * @param resolution - the resolution of the value
  152. *
  153. * @return 16 bit value of the ADC in offset binary format.
  154. * Note that the ADC is "bipolar", which means the GND (0V) level is mid-scale.
  155. **************************************************************************************************/
  156. uint16 HalAdcRead (uint8 channel, uint8 resolution)
  157. {
  158. int16 reading = 0;
  159. #if (HAL_ADC == TRUE)
  160. uint8 i, resbits;
  161. uint8 adctemp;
  162. volatile uint8 tmp;
  163. uint8 adcChannel = 1;
  164. /*
  165. * If Analog input channel is AIN0..AIN7, make sure corresponing P0 I/O pin is enabled. The code
  166. * does NOT disable the pin at the end of this function. I think it is better to leave the pin
  167. * enabled because the results will be more accurate. Because of the inherent capacitance on the
  168. * pin, it takes time for the voltage on the pin to charge up to its steady-state level. If
  169. * HalAdcRead() has to turn on the pin for every conversion, the results may show a lower voltage
  170. * than actuality because the pin did not have time to fully charge.
  171. */
  172. if (channel < 8)
  173. {
  174. for (i=0; i < channel; i++)
  175. {
  176. adcChannel <<= 1;
  177. }
  178. }
  179. /* Enable channel */
  180. ADCCFG |= adcChannel;
  181. /* Convert resolution to decimation rate */
  182. switch (resolution)
  183. {
  184. case HAL_ADC_RESOLUTION_8:
  185. resbits = HAL_ADC_DEC_064;
  186. break;
  187. case HAL_ADC_RESOLUTION_10:
  188. resbits = HAL_ADC_DEC_128;
  189. break;
  190. case HAL_ADC_RESOLUTION_12:
  191. resbits = HAL_ADC_DEC_256;
  192. break;
  193. case HAL_ADC_RESOLUTION_14:
  194. default:
  195. resbits = HAL_ADC_DEC_512;
  196. break;
  197. }
  198. /* read ADCL,ADCH to clear EOC */
  199. tmp = ADCL;
  200. tmp = ADCH;
  201. /* Setup Sample */
  202. adctemp = ADCCON3;
  203. adctemp &= ~(HAL_ADC_CHN_BITS | HAL_ADC_DEC_BITS | HAL_ADC_REF_BITS);
  204. adctemp |= channel | resbits | HAL_ADC_REF_VOLT;
  205. /* writing to this register starts the extra conversion */
  206. ADCCON3 = adctemp;
  207. /* Wait for the conversion to be done */
  208. while (!(ADCCON1 & HAL_ADC_EOC));
  209. /* Disable channel after done conversion */
  210. ADCCFG &= (adcChannel ^ 0xFF);
  211. /* Read the result */
  212. reading = (int16) (ADCL);
  213. reading |= (int16) (ADCH << 8);
  214. /* Treat small negative as 0 */
  215. if (reading < 0)
  216. reading = 0;
  217. switch (resolution)
  218. {
  219. case HAL_ADC_RESOLUTION_8:
  220. reading >>= 8;
  221. break;
  222. case HAL_ADC_RESOLUTION_10:
  223. reading >>= 6;
  224. break;
  225. case HAL_ADC_RESOLUTION_12:
  226. reading >>= 4;
  227. break;
  228. case HAL_ADC_RESOLUTION_14:
  229. default:
  230. break;
  231. }
  232. #else
  233. // unused arguments
  234. (void) channel;
  235. (void) resolution;
  236. #endif
  237. return ((uint16)reading);
  238. }
  239. /**************************************************************************************************
  240. * @fn HalAdcCheckVdd
  241. *
  242. * @brief Check the Vdd and return TRUE if it greater than or equal the limit
  243. *
  244. * @param limit - limit that needs to be checked with the Vdd
  245. *
  246. * @return TRUE if Vdd >= limit, FALSE otherwise
  247. *
  248. **************************************************************************************************/
  249. bool HalAdcCheckVdd (uint8 limit)
  250. {
  251. uint16 value;
  252. /* Clear ADC interrupt flag */
  253. ADCIF = 0;
  254. /* Setup the new value for conversion */
  255. ADCCON3 = (HAL_ADC_REF_125V | HAL_ADC_DEC_064 | HAL_ADC_CHN_VDD3);
  256. /* Wait for the conversion to finish */
  257. while ( !ADCIF );
  258. /* Get the result */
  259. value = ADCL;
  260. value |= ((uint16) ADCH) << 8;
  261. /* Check the limit and return */
  262. return ( value >= HalAdcVddLimit[limit] );
  263. }
  264. /**************************************************************************************************
  265. **************************************************************************************************/