rt_drv_pwm.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * Copyright (c) 2006-2021, 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. */
  10. #include <drivers/rt_drv_pwm.h>
  11. static rt_err_t _pwm_control(rt_device_t dev, int cmd, void *args)
  12. {
  13. rt_err_t result = RT_EOK;
  14. struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev;
  15. if (pwm->ops->control)
  16. {
  17. result = pwm->ops->control(pwm, cmd, args);
  18. }
  19. return result;
  20. }
  21. /*
  22. pos: channel
  23. void *buffer: rt_uint32_t pulse[size]
  24. size : number of pulse, only set to sizeof(rt_uint32_t).
  25. */
  26. static rt_size_t _pwm_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  27. {
  28. rt_err_t result = RT_EOK;
  29. struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev;
  30. rt_uint32_t *pulse = (rt_uint32_t *)buffer;
  31. struct rt_pwm_configuration configuration = {0};
  32. configuration.channel = pos;
  33. if (pwm->ops->control)
  34. {
  35. result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration);
  36. if (result != RT_EOK)
  37. {
  38. return 0;
  39. }
  40. *pulse = configuration.pulse;
  41. }
  42. return size;
  43. }
  44. /*
  45. pos: channel
  46. void *buffer: rt_uint32_t pulse[size]
  47. size : number of pulse, only set to sizeof(rt_uint32_t).
  48. */
  49. static rt_size_t _pwm_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  50. {
  51. rt_err_t result = RT_EOK;
  52. struct rt_device_pwm *pwm = (struct rt_device_pwm *)dev;
  53. rt_uint32_t *pulse = (rt_uint32_t *)buffer;
  54. struct rt_pwm_configuration configuration = {0};
  55. configuration.channel = pos;
  56. if (pwm->ops->control)
  57. {
  58. result = pwm->ops->control(pwm, PWM_CMD_GET, &configuration);
  59. if (result != RT_EOK)
  60. {
  61. return 0;
  62. }
  63. configuration.pulse = *pulse;
  64. result = pwm->ops->control(pwm, PWM_CMD_SET, &configuration);
  65. if (result != RT_EOK)
  66. {
  67. return 0;
  68. }
  69. }
  70. return size;
  71. }
  72. #ifdef RT_USING_DEVICE_OPS
  73. static const struct rt_device_ops pwm_device_ops =
  74. {
  75. RT_NULL,
  76. RT_NULL,
  77. RT_NULL,
  78. _pwm_read,
  79. _pwm_write,
  80. _pwm_control
  81. };
  82. #endif /* RT_USING_DEVICE_OPS */
  83. rt_err_t rt_device_pwm_register(struct rt_device_pwm *device, const char *name, const struct rt_pwm_ops *ops, const void *user_data)
  84. {
  85. rt_err_t result = RT_EOK;
  86. rt_memset(device, 0, sizeof(struct rt_device_pwm));
  87. #ifdef RT_USING_DEVICE_OPS
  88. device->parent.ops = &pwm_device_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 = _pwm_read;
  94. device->parent.write = _pwm_write;
  95. device->parent.control = _pwm_control;
  96. #endif /* RT_USING_DEVICE_OPS */
  97. device->parent.type = RT_Device_Class_PWM;
  98. device->ops = ops;
  99. device->parent.user_data = (void *)user_data;
  100. result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR);
  101. return result;
  102. }
  103. rt_err_t rt_pwm_enable(struct rt_device_pwm *device, int channel)
  104. {
  105. rt_err_t result = RT_EOK;
  106. struct rt_pwm_configuration configuration = {0};
  107. if (!device)
  108. {
  109. return -RT_EIO;
  110. }
  111. configuration.channel = (channel > 0) ? (channel) : (-channel); /* Make it is positive num forever */
  112. configuration.complementary = (channel > 0) ? (RT_FALSE) : (RT_TRUE); /* If nagetive, it's complementary */
  113. result = rt_device_control(&device->parent, PWM_CMD_ENABLE, &configuration);
  114. return result;
  115. }
  116. rt_err_t rt_pwm_disable(struct rt_device_pwm *device, int channel)
  117. {
  118. rt_err_t result = RT_EOK;
  119. struct rt_pwm_configuration configuration = {0};
  120. if (!device)
  121. {
  122. return -RT_EIO;
  123. }
  124. configuration.channel = (channel > 0) ? (channel) : (-channel); /* Make it is positive num forever */
  125. configuration.complementary = (channel > 0) ? (RT_FALSE) : (RT_TRUE); /* If nagetive, it's complementary */
  126. result = rt_device_control(&device->parent, PWM_CMD_DISABLE, &configuration);
  127. return result;
  128. }
  129. rt_err_t rt_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse)
  130. {
  131. rt_err_t result = RT_EOK;
  132. struct rt_pwm_configuration configuration = {0};
  133. if (!device)
  134. {
  135. return -RT_EIO;
  136. }
  137. configuration.channel = channel;
  138. configuration.period = period;
  139. configuration.pulse = pulse;
  140. result = rt_device_control(&device->parent, PWM_CMD_SET, &configuration);
  141. return result;
  142. }
  143. rt_err_t rt_pwm_get(struct rt_device_pwm *device, struct rt_pwm_configuration *cfg)
  144. {
  145. rt_err_t result = RT_EOK;
  146. if (!device)
  147. {
  148. return -RT_EIO;
  149. }
  150. result = rt_device_control(&device->parent, PWM_CMD_GET, cfg);
  151. return result;
  152. }
  153. #ifdef RT_USING_FINSH
  154. #include <stdlib.h>
  155. #include <finsh.h>
  156. static int pwm_enable(int argc, char **argv)
  157. {
  158. int result = 0;
  159. struct rt_device_pwm *device = RT_NULL;
  160. if (argc != 3)
  161. {
  162. rt_kprintf("Usage: pwm_enable pwm1 1\n");
  163. rt_kprintf(" pwm_enable <pwm_dev> <channel/-channel>\n");
  164. result = -RT_ERROR;
  165. goto _exit;
  166. }
  167. device = (struct rt_device_pwm *)rt_device_find(argv[1]);
  168. if (!device)
  169. {
  170. result = -RT_EIO;
  171. goto _exit;
  172. }
  173. /* If channel is complementary(1), make the channel number to nagetive */
  174. result = rt_pwm_enable(device, atoi(argv[2]));
  175. _exit:
  176. return result;
  177. }
  178. MSH_CMD_EXPORT(pwm_enable, pwm_enable <pwm_dev> <channel/-channel>);
  179. static int pwm_disable(int argc, char **argv)
  180. {
  181. int result = 0;
  182. struct rt_device_pwm *device = RT_NULL;
  183. if (argc != 3)
  184. {
  185. rt_kprintf("Usage: pwm_disable pwm1 1\n");
  186. rt_kprintf(" pwm_disable <pwm_dev> <channel/-channel> \n");
  187. result = -RT_ERROR;
  188. goto _exit;
  189. }
  190. device = (struct rt_device_pwm *)rt_device_find(argv[1]);
  191. if (!device)
  192. {
  193. result = -RT_EIO;
  194. goto _exit;
  195. }
  196. /* If channel is complementary(1), make the channel number to nagetive */
  197. result = rt_pwm_disable(device, atoi(argv[2]));
  198. _exit:
  199. return result;
  200. }
  201. MSH_CMD_EXPORT(pwm_disable, pwm_disable <pwm_dev> <channel/-channel>);
  202. static int pwm_set(int argc, char **argv)
  203. {
  204. int result = 0;
  205. struct rt_device_pwm *device = RT_NULL;
  206. if (argc != 5)
  207. {
  208. rt_kprintf("Usage: pwm_set pwm1 1 100 50\n");
  209. rt_kprintf("Usage: pwm_set <pwm_dev> <channel> <period> <pulse>\n");
  210. result = -RT_ERROR;
  211. goto _exit;
  212. }
  213. device = (struct rt_device_pwm *)rt_device_find(argv[1]);
  214. if (!device)
  215. {
  216. result = -RT_EIO;
  217. goto _exit;
  218. }
  219. result = rt_pwm_set(device, atoi(argv[2]), atoi(argv[3]), atoi(argv[4]));
  220. _exit:
  221. return result;
  222. }
  223. MSH_CMD_EXPORT(pwm_set, pwm_set <pwm_dev> <channel> <period> <pulse>);
  224. static int pwm_get(int argc, char **argv)
  225. {
  226. int result = 0;
  227. struct rt_device_pwm *device = RT_NULL;
  228. struct rt_pwm_configuration cfg = {0};
  229. if (argc != 3)
  230. {
  231. rt_kprintf("Usage: pwm_get pwm1 1\n");
  232. rt_kprintf(" pwm_get <pwm_dev> <channel>\n");
  233. result = -RT_ERROR;
  234. goto _exit;
  235. }
  236. device = (struct rt_device_pwm *)rt_device_find(argv[1]);
  237. if (!device)
  238. {
  239. result = -RT_EIO;
  240. goto _exit;
  241. }
  242. cfg.channel = atoi(argv[2]);
  243. result = rt_pwm_get(device, &cfg);
  244. if (result != RT_EOK)
  245. {
  246. rt_kprintf("Get info of device: [%s] error.\n", argv[1]);
  247. }
  248. else
  249. {
  250. rt_kprintf("Get info of device: [%s]:\n", argv[1]);
  251. rt_kprintf("period : %d\n", cfg.period);
  252. rt_kprintf("pulse : %d\n", cfg.pulse);
  253. rt_kprintf("Duty cycle : %d%%\n", (int)(((double)(cfg.pulse)/(cfg.period)) * 100));
  254. }
  255. _exit:
  256. return result;
  257. }
  258. MSH_CMD_EXPORT(pwm_get, pwm_get <pwm_dev> <channel>);
  259. #endif /* RT_USING_FINSH */