adc.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-05-07 aozima the first version
  9. * 2018-11-16 Ernest Chen add finsh command and update adc function
  10. * 2022-05-11 Stanley Lwin add finsh voltage conversion command
  11. */
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #define DBG_TAG "adc"
  17. #define DBG_LVL DBG_INFO
  18. #include <rtdbg.h>
  19. static rt_ssize_t _adc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  20. {
  21. rt_err_t result;
  22. rt_size_t i;
  23. struct rt_adc_device *adc = (struct rt_adc_device *)dev;
  24. rt_uint32_t *value = (rt_uint32_t *)buffer;
  25. for (i = 0; i < size; i++)
  26. {
  27. result = adc->ops->convert(adc, pos, value);
  28. if (result != RT_EOK)
  29. {
  30. return 0;
  31. }
  32. value++;
  33. }
  34. return i;
  35. }
  36. static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
  37. {
  38. rt_adc_device_t adc = (struct rt_adc_device *)dev;
  39. rt_err_t result;
  40. if (cmd == RT_ADC_CMD_ENABLE && adc->ops->enabled)
  41. {
  42. result = adc->ops->enabled(adc, (rt_int8_t)(rt_base_t)args, RT_TRUE);
  43. }
  44. else if (cmd == RT_ADC_CMD_DISABLE && adc->ops->enabled)
  45. {
  46. result = adc->ops->enabled(adc, (rt_int8_t)(rt_base_t)args, RT_FALSE);
  47. }
  48. else if (cmd == RT_ADC_CMD_GET_RESOLUTION && adc->ops->get_resolution && args)
  49. {
  50. rt_uint8_t resolution = adc->ops->get_resolution(adc);
  51. if (resolution != 0)
  52. {
  53. *((rt_uint8_t *)args) = resolution;
  54. LOG_D("resolution: %d bits", resolution);
  55. result = RT_EOK;
  56. }
  57. }
  58. else if (cmd == RT_ADC_CMD_GET_VREF && adc->ops->get_vref && args)
  59. {
  60. rt_int16_t value = adc->ops->get_vref(adc);
  61. if (value != 0)
  62. {
  63. *((rt_int16_t *)args) = value;
  64. result = RT_EOK;
  65. }
  66. }
  67. return result;
  68. }
  69. #ifdef RT_USING_DEVICE_OPS
  70. const static struct rt_device_ops adc_ops =
  71. {
  72. RT_NULL,
  73. RT_NULL,
  74. RT_NULL,
  75. _adc_read,
  76. RT_NULL,
  77. _adc_control,
  78. };
  79. #endif
  80. rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data)
  81. {
  82. RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL);
  83. rt_err_t result;
  84. device->parent.type = RT_Device_Class_ADC;
  85. device->parent.rx_indicate = RT_NULL;
  86. device->parent.tx_complete = RT_NULL;
  87. #ifdef RT_USING_DEVICE_OPS
  88. device->parent.ops = &adc_ops;
  89. #else
  90. device->parent.init = RT_NULL;
  91. device->parent.open = RT_NULL;
  92. device->parent.close = RT_NULL;
  93. device->parent.read = _adc_read;
  94. device->parent.write = RT_NULL;
  95. device->parent.control = _adc_control;
  96. #endif
  97. device->ops = ops;
  98. device->parent.user_data = (void *)user_data;
  99. result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);
  100. return result;
  101. }
  102. rt_uint32_t rt_adc_read(rt_adc_device_t dev, rt_int8_t channel)
  103. {
  104. RT_ASSERT(dev);
  105. rt_uint32_t value;
  106. rt_err_t result;
  107. result = dev->ops->convert(dev, channel, &value);
  108. if (result != RT_EOK)
  109. return 0;
  110. return value;
  111. }
  112. rt_err_t rt_adc_enable(rt_adc_device_t dev, rt_int8_t channel)
  113. {
  114. RT_ASSERT(dev);
  115. rt_err_t result;
  116. if (dev->ops->enabled != RT_NULL)
  117. {
  118. result = dev->ops->enabled(dev, channel, RT_TRUE);
  119. }
  120. else
  121. {
  122. result = -RT_ENOSYS;
  123. }
  124. return result;
  125. }
  126. rt_err_t rt_adc_disable(rt_adc_device_t dev, rt_int8_t channel)
  127. {
  128. RT_ASSERT(dev);
  129. rt_err_t result;
  130. if (dev->ops->enabled != RT_NULL)
  131. {
  132. result = dev->ops->enabled(dev, channel, RT_FALSE);
  133. }
  134. else
  135. {
  136. result = -RT_ENOSYS;
  137. }
  138. return result;
  139. }
  140. rt_int16_t rt_adc_voltage(rt_adc_device_t dev, rt_int8_t channel)
  141. {
  142. RT_ASSERT(dev);
  143. rt_uint32_t value;
  144. rt_int16_t vref, voltage;
  145. rt_uint8_t resolution;
  146. rt_err_t result;
  147. /*get the resolution in bits*/
  148. resolution = dev->ops->get_resolution(dev);
  149. /*get the reference voltage*/
  150. vref = dev->ops->get_vref(dev);
  151. if (vref == 0)
  152. goto _voltage_exit;
  153. /*read the value and convert to voltage*/
  154. result = dev->ops->enabled(dev, channel, RT_TRUE);
  155. if (result != RT_EOK)
  156. goto _voltage_exit;
  157. result = dev->ops->convert(dev, channel, &value);
  158. if (result != RT_EOK)
  159. goto _voltage_exit;
  160. result = dev->ops->enabled(dev, channel, RT_FALSE);
  161. if (result != RT_EOK)
  162. goto _voltage_exit;
  163. voltage = value * vref / ((1 << resolution) - 1);
  164. _voltage_exit:
  165. return voltage;
  166. }
  167. #ifdef RT_USING_FINSH
  168. static int adc(int argc, char **argv)
  169. {
  170. int value = 0;
  171. rt_int16_t voltage = 0;
  172. rt_err_t result = -RT_ERROR;
  173. static rt_adc_device_t adc_device = RT_NULL;
  174. char *result_str;
  175. if (argc > 1)
  176. {
  177. if (!strcmp(argv[1], "probe"))
  178. {
  179. if (argc == 3)
  180. {
  181. adc_device = (rt_adc_device_t)rt_device_find(argv[2]);
  182. result_str = (adc_device == RT_NULL) ? "failure" : "success";
  183. rt_kprintf("probe %s %s \n", argv[2], result_str);
  184. }
  185. else
  186. {
  187. rt_kprintf("adc probe <device name> - probe adc by name\n");
  188. }
  189. }
  190. else
  191. {
  192. if (adc_device == RT_NULL)
  193. {
  194. rt_kprintf("Please using 'adc probe <device name>' first\n");
  195. return -RT_ERROR;
  196. }
  197. if (!strcmp(argv[1], "enable"))
  198. {
  199. if (argc == 3)
  200. {
  201. result = rt_adc_enable(adc_device, atoi(argv[2]));
  202. result_str = (result == RT_EOK) ? "success" : "failure";
  203. rt_kprintf("%s channel %d enables %s \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), result_str);
  204. }
  205. else
  206. {
  207. rt_kprintf("adc enable <channel> - enable adc channel\n");
  208. }
  209. }
  210. else if (!strcmp(argv[1], "read"))
  211. {
  212. if (argc == 3)
  213. {
  214. value = rt_adc_read(adc_device, atoi(argv[2]));
  215. rt_kprintf("%s channel %d read value is 0x%08X \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), value);
  216. }
  217. else
  218. {
  219. rt_kprintf("adc read <channel> - read adc value on the channel\n");
  220. }
  221. }
  222. else if (!strcmp(argv[1], "disable"))
  223. {
  224. if (argc == 3)
  225. {
  226. result = rt_adc_disable(adc_device, atoi(argv[2]));
  227. result_str = (result == RT_EOK) ? "success" : "failure";
  228. rt_kprintf("%s channel %d disable %s \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), result_str);
  229. }
  230. else
  231. {
  232. rt_kprintf("adc disable <channel> - disable adc channel\n");
  233. }
  234. }
  235. else if (!strcmp(argv[1], "voltage"))
  236. {
  237. if (argc == 3)
  238. {
  239. voltage = rt_adc_voltage(adc_device, atoi(argv[2]));
  240. rt_kprintf("%s channel %d voltage is %d.%03dV \n", adc_device->parent.parent.name, (rt_base_t)atoi(argv[2]), voltage / 1000, voltage % 1000);
  241. }
  242. else
  243. {
  244. rt_kprintf("adc convert voltage <channel> \n");
  245. }
  246. }
  247. else
  248. {
  249. rt_kprintf("Unknown command. Please enter 'adc' for help\n");
  250. }
  251. }
  252. }
  253. else
  254. {
  255. rt_kprintf("Usage: \n");
  256. rt_kprintf("adc probe <device name> - probe adc by name\n");
  257. rt_kprintf("adc read <channel> - read adc value on the channel\n");
  258. rt_kprintf("adc disable <channel> - disable adc channel\n");
  259. rt_kprintf("adc enable <channel> - enable adc channel\n");
  260. rt_kprintf("adc voltage <channel> - read voltage on the channel\n");
  261. result = -RT_ERROR;
  262. }
  263. return RT_EOK;
  264. }
  265. MSH_CMD_EXPORT(adc, adc [option]);
  266. #endif /* RT_USING_FINSH */