drv_adc.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-10-07 qiyu first version
  9. */
  10. #include <board.h>
  11. #ifdef BSP_USING_ADC
  12. #include "drv_config.h"
  13. #include "drv_adc.h"
  14. #include "rtdbg.h"
  15. static struct c28x_adc c28x_adc_obj[] =
  16. {
  17. #ifdef BSP_USING_ADC1
  18. ADC1_CONFIG,
  19. #endif
  20. #ifdef BSP_USING_ADC2
  21. ADC2_CONFIG,
  22. #endif
  23. #ifdef BSP_USING_ADC3
  24. ADC3_CONFIG,
  25. #endif
  26. };
  27. static rt_err_t c28x_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled)
  28. {
  29. volatile struct ADC_REGS *c28x_adc_regs;
  30. RT_ASSERT(device != RT_NULL);
  31. volatile struct c28x_adc *c28x_adc_handler;
  32. c28x_adc_handler = (struct c28x_adc *)device->parent.user_data;
  33. c28x_adc_regs = c28x_adc_handler->adc_regs;
  34. if (enabled)
  35. {
  36. /*
  37. * power up the ADC
  38. */
  39. EALLOW;
  40. c28x_adc_regs->ADCCTL1.bit.ADCPWDNZ = 1;
  41. EDIS;
  42. /*
  43. * delay for 1ms to allow ADC time to power up
  44. */
  45. DELAY_US(1000);
  46. }
  47. else
  48. {
  49. /*
  50. * power down the ADC
  51. */
  52. EALLOW;
  53. c28x_adc_regs->ADCCTL1.bit.ADCPWDNZ = 0;
  54. EDIS;
  55. }
  56. return RT_EOK;
  57. }
  58. static rt_uint8_t c28x_adc_get_resolution(struct rt_adc_device *device)
  59. {
  60. struct c28x_adc *c28x_adc_handler;
  61. volatile struct ADC_REGS *c28x_adc_regs;
  62. c28x_adc_handler = (struct c28x_adc *)device->parent.user_data;
  63. c28x_adc_regs = c28x_adc_handler->adc_regs;
  64. RT_ASSERT(device != RT_NULL);
  65. switch(c28x_adc_regs->ADCCTL2.bit.RESOLUTION)
  66. {
  67. case ADC_RESOLUTION_12BIT:
  68. return 12;
  69. case ADC_RESOLUTION_16BIT:
  70. return 16;
  71. default:
  72. return 0;
  73. }
  74. }
  75. static rt_int16_t c28x_adc_get_vref (struct rt_adc_device *device)
  76. {
  77. /*
  78. * TODO
  79. * Get Vref
  80. */
  81. RT_ASSERT(device);
  82. return 3300;
  83. }
  84. static rt_err_t c28x_adc_get_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value)
  85. {
  86. RT_ASSERT(device != RT_NULL);
  87. RT_ASSERT(value != RT_NULL);
  88. struct c28x_adc *c28x_adc_handler = (struct c28x_adc*)device->parent.user_data;
  89. volatile struct ADC_REGS *c28x_adc_regs = c28x_adc_handler->adc_regs;
  90. volatile struct ADC_RESULT_REGS *c28x_adc_result_regs = c28x_adc_handler->adc_results;
  91. /*
  92. * configure channel
  93. * only use SOC0 for now
  94. */
  95. EALLOW;
  96. c28x_adc_regs->ADCSOC0CTL.bit.CHSEL = channel; /* SOC0 will convert pin A0 */
  97. EDIS;
  98. /*
  99. * start conversions immediately via software, ADCA
  100. */
  101. c28x_adc_regs->ADCSOCFRC1.all = 0x0001; //SOC0
  102. /*
  103. * wait for ADCA to complete, then acknowledge flag
  104. */
  105. while(c28x_adc_regs->ADCINTFLG.bit.ADCINT1 == 0);
  106. c28x_adc_regs->ADCINTFLGCLR.bit.ADCINT1 = 1;
  107. /*
  108. * store results
  109. */
  110. *value = (rt_uint32_t)c28x_adc_result_regs->ADCRESULT0;
  111. return RT_EOK;
  112. }
  113. static const struct rt_adc_ops stm_adc_ops =
  114. {
  115. .enabled = c28x_adc_enabled,
  116. .convert = c28x_adc_get_value,
  117. .get_resolution = c28x_adc_get_resolution,
  118. .get_vref = c28x_adc_get_vref,
  119. };
  120. static rt_err_t HAL_ADC_Init(volatile struct ADC_REGS *c28x_adc_handler)
  121. {
  122. int adc_controller_num = 0;
  123. Uint16 acqps;
  124. EALLOW;
  125. /*
  126. * write configurations
  127. */
  128. c28x_adc_handler->ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
  129. if(c28x_adc_handler == &AdcaRegs)
  130. {
  131. adc_controller_num = 0;
  132. }else if(c28x_adc_handler == &AdcbRegs)
  133. {
  134. adc_controller_num = 1;
  135. }
  136. else if(c28x_adc_handler == &AdccRegs)
  137. {
  138. adc_controller_num = 2;
  139. }
  140. else if(c28x_adc_handler == &AdcdRegs)
  141. {
  142. adc_controller_num = 3;
  143. }
  144. AdcSetMode(adc_controller_num, ADC_RESOLUTION, ADC_SIGNALMODE_SINGLE);
  145. c28x_adc_handler->ADCCTL1.bit.INTPULSEPOS = 1;
  146. EDIS;
  147. /*
  148. * determine minimum acquisition window (in SYSCLKS) based on resolution
  149. */
  150. if(ADC_RESOLUTION_12BIT == AdcaRegs.ADCCTL2.bit.RESOLUTION)
  151. {
  152. acqps = 14; //75ns
  153. }
  154. else
  155. {
  156. /*
  157. * resolution is 16-bit
  158. */
  159. acqps = 63; //320ns
  160. }
  161. /*
  162. * Select the channels to convert and end of conversion flag
  163. */
  164. EALLOW;
  165. c28x_adc_handler->ADCSOC0CTL.bit.ACQPS = acqps; //sample window is acqps + 1 SYSCLK cycles
  166. c28x_adc_handler->ADCINTSEL1N2.bit.INT1SEL = 0; //end of SOC0 will set INT1 flag
  167. c28x_adc_handler->ADCINTSEL1N2.bit.INT1E = 1; //enable INT1 flag
  168. c28x_adc_handler->ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
  169. EDIS;
  170. return RT_EOK;
  171. }
  172. static int c28x_adc_init(void)
  173. {
  174. int result = RT_EOK;
  175. /*
  176. * save adc name
  177. */
  178. int i = 0;
  179. /* ADC init */
  180. for (i = 0; i < sizeof(c28x_adc_obj) / sizeof(c28x_adc_obj[0]); i++)
  181. {
  182. if (HAL_ADC_Init(c28x_adc_obj[i].adc_regs) != RT_EOK)
  183. {
  184. LOG_E("%s init failed", c28x_adc_obj[i].name);
  185. result = -RT_ERROR;
  186. }
  187. else
  188. {
  189. /* register ADC device */
  190. if (rt_hw_adc_register(&c28x_adc_obj[i].c28x_adc_device, c28x_adc_obj[i].name, &stm_adc_ops, &c28x_adc_obj[i]) == RT_EOK)
  191. {
  192. LOG_D("%s init success", c28x_adc_obj[i].name);
  193. }
  194. else
  195. {
  196. LOG_E("%s register failed", c28x_adc_obj[i].name);
  197. result = -RT_ERROR;
  198. }
  199. }
  200. }
  201. return result;
  202. }
  203. INIT_BOARD_EXPORT(c28x_adc_init);
  204. #endif /* BSP_USING_ADC */