dev_accel.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /***************************************************************************//**
  2. * @file dev_accel.c
  3. * @brief Accelerometer driver of RT-Thread RTOS for EFM32
  4. * COPYRIGHT (C) 2011, RT-Thread Development Team
  5. * @author onelife
  6. * @version 0.4 beta
  7. *******************************************************************************
  8. * @section License
  9. * The license and distribution terms for this file may be found in the file
  10. * LICENSE in this distribution or at http://www.rt-thread.org/license/LICENSE
  11. *******************************************************************************
  12. * @section Change Logs
  13. * Date Author Notes
  14. * 2011-07-13 onelife Initial creation for using EFM32 ADC module to
  15. * interface the Freescale MMA7361L
  16. ******************************************************************************/
  17. /***************************************************************************//**
  18. * @addtogroup efm32
  19. * @{
  20. ******************************************************************************/
  21. /* Includes ------------------------------------------------------------------*/
  22. #include "board.h"
  23. #include "drv_adc.h"
  24. #include "dev_accel.h"
  25. #if defined(EFM32_USING_ACCEL)
  26. /* Private typedef -----------------------------------------------------------*/
  27. /* Private define ------------------------------------------------------------*/
  28. /* Private macro -------------------------------------------------------------*/
  29. #ifdef RT_ACCEL_DEBUG
  30. #define accel_debug(format,args...) rt_kprintf(format, ##args)
  31. #else
  32. #define accel_debug(format,args...)
  33. #endif
  34. /* Private constants ---------------------------------------------------------*/
  35. static rt_device_t accel;
  36. static struct efm32_adc_control_t control = \
  37. {ADC_MODE_SCAN, {3, ACCEL_USING_DMA}, {}};
  38. static struct efm32_accel_result_t accelOffset = {0};
  39. static rt_bool_t accelInTime = true;
  40. /* Private variables ---------------------------------------------------------*/
  41. /* Private function prototypes -----------------------------------------------*/
  42. /* Private functions ---------------------------------------------------------*/
  43. /***************************************************************************//**
  44. * @brief
  45. * Get accelerometer output
  46. *
  47. * @details
  48. *
  49. * @note
  50. *
  51. * @param[out] data
  52. * Pointer to output buffer
  53. *
  54. * @return
  55. * Error code
  56. ******************************************************************************/
  57. rt_err_t efm_accel_get_data(struct efm32_accel_result_t *data)
  58. {
  59. RT_ASSERT(accel != RT_NULL);
  60. struct efm32_adc_result_t result;
  61. if (data == RT_NULL)
  62. {
  63. return -RT_ERROR;
  64. }
  65. result.mode = control.mode;
  66. result.buffer = (void *)data;
  67. accel->control(accel, RT_DEVICE_CTRL_RESUME, &result);
  68. accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, &result);
  69. return RT_EOK;
  70. }
  71. /***************************************************************************//**
  72. * @brief
  73. * Accelerometer timeout interrupt handler
  74. *
  75. * @details
  76. *
  77. * @note
  78. *
  79. * @param[in] parameter
  80. * Parameter
  81. ******************************************************************************/
  82. static void efm_accel_timer(void* parameter)
  83. {
  84. accelInTime = false;
  85. }
  86. /***************************************************************************//**
  87. * @brief
  88. * Accelerometer auto-zero calibration function
  89. *
  90. * @details
  91. *
  92. * @note
  93. *
  94. * @param[in] period
  95. * Time period to perform auto-zero calibration
  96. *
  97. * @return
  98. * Error code
  99. ******************************************************************************/
  100. rt_err_t efm_accel_auto_zero(rt_tick_t period)
  101. {
  102. RT_ASSERT(accel != RT_NULL);
  103. rt_timer_t calTimer;
  104. struct efm32_accel_result_t min = {0x7ff, 0x7ff, 0x7ff};
  105. struct efm32_accel_result_t max = {0x7ff, 0x7ff, 0x7ff};
  106. struct efm32_accel_result_t temp;
  107. struct efm32_adc_result_t result;
  108. if ((calTimer = rt_timer_create(
  109. "cal_tmr",
  110. efm_accel_timer,
  111. RT_NULL,
  112. period,
  113. RT_TIMER_FLAG_ONE_SHOT)) == RT_NULL)
  114. {
  115. accel_debug("Accel err: Create timer failed!\n");
  116. return -RT_ERROR;
  117. }
  118. result.mode = control.mode;
  119. result.buffer = (void *)&temp;
  120. accelInTime = true;
  121. rt_timer_start(calTimer);
  122. do
  123. {
  124. accel->control(accel, RT_DEVICE_CTRL_RESUME, &result);
  125. accel->control(accel, RT_DEVICE_CTRL_ADC_RESULT, &result);
  126. if (temp.x < min.x)
  127. {
  128. min.x = temp.x;
  129. }
  130. if (temp.y < min.y)
  131. {
  132. min.y = temp.y;
  133. }
  134. if (temp.z < min.z)
  135. {
  136. min.z = temp.z;
  137. }
  138. if (temp.x > max.x)
  139. {
  140. max.x = temp.x;
  141. }
  142. if (temp.y > max.y)
  143. {
  144. max.y = temp.y;
  145. }
  146. if (temp.z > max.z)
  147. {
  148. max.z = temp.z;
  149. }
  150. rt_thread_sleep(1);
  151. } while (accelInTime);
  152. accelOffset.x = (min.x + max.x) >> 1;
  153. accelOffset.y = (min.y + max.y) >> 1;
  154. accelOffset.z = (min.z + max.z) >> 1;
  155. accel_debug("Accel: Min %x %x %x, max %x %x %x, Offset %x %x %x\n",
  156. min.x, min.y, min.z, max.x, max.y, max.z,
  157. accelOffset.x, accelOffset.y, accelOffset.z);
  158. rt_timer_delete(calTimer);
  159. return RT_EOK;
  160. }
  161. /***************************************************************************//**
  162. * @brief
  163. * Initialize the accelerometer
  164. *
  165. * @details
  166. *
  167. * @note
  168. *
  169. * @return
  170. * Error code
  171. ******************************************************************************/
  172. rt_err_t efm_accel_init(void)
  173. {
  174. ADC_InitScan_TypeDef scanInit = ADC_INITSCAN_DEFAULT;
  175. #if defined(EFM32_G290_DK)
  176. /* Enable accelerometer */
  177. DVK_enablePeripheral(DVK_ACCEL);
  178. /* Select low g-range */
  179. DVK_disablePeripheral(DVK_ACCEL_GSEL);
  180. #endif
  181. do
  182. {
  183. /* Find ADC device */
  184. accel = rt_device_find(ACCEL_USING_DEVICE_NAME);
  185. if (accel == RT_NULL)
  186. {
  187. accel_debug("Accel err: Can't find device: %s!\n", ACCEL_USING_DEVICE_NAME);
  188. break;
  189. }
  190. accel_debug("Accel: Find device %s\n", ACCEL_USING_DEVICE_NAME);
  191. /* Init ADC for scan mode */
  192. scanInit.reference = adcRefVDD;
  193. scanInit.input = ACCEL_X_ADC_CH | ACCEL_Y_ADC_CH | ACCEL_Z_ADC_CH;
  194. control.scan.init = &scanInit;
  195. accel->control(accel, RT_DEVICE_CTRL_ADC_MODE, &control);
  196. accel_debug("Accel: Init OK\n");
  197. return RT_EOK;
  198. } while (0);
  199. accel_debug("Accel err: Init failed!\n");
  200. return -RT_ERROR;
  201. }
  202. /*******************************************************************************
  203. * Export to FINSH
  204. ******************************************************************************/
  205. #ifdef RT_USING_FINSH
  206. #include <finsh.h>
  207. void accel_cal(rt_uint32_t second)
  208. {
  209. efm_accel_auto_zero(RT_TICK_PER_SECOND * second);
  210. rt_kprintf("Calibration done. Offset: 0x%03x, 0x%03x, 0x%03x\n",
  211. accelOffset.x, accelOffset.y, accelOffset.z);
  212. }
  213. FINSH_FUNCTION_EXPORT(accel_cal, auto-zero calibration.)
  214. void list_accel(void)
  215. {
  216. struct efm32_accel_result_t temp;
  217. rt_int32_t x, y, z;
  218. if ((accelOffset.x == 0) && \
  219. (accelOffset.y == 0) && \
  220. (accelOffset.z == 0))
  221. {
  222. rt_kprintf("Please calibrate the device first!\n");
  223. return;
  224. }
  225. efm_accel_get_data(&temp);
  226. x = temp.x - accelOffset.x;
  227. y = temp.y - accelOffset.y;
  228. z = temp.z - accelOffset.z;
  229. rt_kprintf("X: %d, Y: %d, Z: %d\n", x, y, z);
  230. }
  231. FINSH_FUNCTION_EXPORT(list_accel, list accelerometer info.)
  232. #endif
  233. #endif
  234. /***************************************************************************//**
  235. * @}
  236. ******************************************************************************/