luat_lib_pwm.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /*
  2. @module pwm
  3. @summary PWM模块
  4. @version 1.0
  5. @date 2020.07.03
  6. @demo pwm
  7. @tag LUAT_USE_PWM
  8. @usage
  9. -- 本库支持2套API风格
  10. -- 1. 传统API, open和close
  11. -- 2. 新的API(推荐使用), setup,start,stop,setDuty,setFreq
  12. -- 传统API
  13. pwm.open(1, 1000, 50) -- 打开PWM1, 频率1kHz, 占空比50%
  14. sys.wait(5000) -- 等待5秒
  15. pwm.close(1) -- 关闭PWM1
  16. -- 新API
  17. pwm.setup(1, 1000, 50) -- 设置PWM1, 频率1kHz, 占空比50%
  18. pwm.start(1) -- 启动PWM1
  19. sys.wait(5000) -- 等待5秒
  20. pwm.setFreq(1, 2000) -- 设置PWM1频率2kHz
  21. sys.wait(5000) -- 等待5秒
  22. pwm.setDuty(1, 25) -- 设置PWM1占空比25%
  23. sys.wait(5000) -- 等待5秒
  24. pwm.stop(1) -- 关闭PWM1
  25. -- 提醒: pwm.setFreq和pwm.setDuty的, 仅在start/open状态下立即生效, stop/close状态是不会生效的
  26. */
  27. #include "luat_base.h"
  28. #include "luat_pwm.h"
  29. #include "luat_mem.h"
  30. #define LUAT_LOG_TAG "pwm"
  31. #include "luat_log.h"
  32. static uint32_t s_state = 0;
  33. static luat_pwm_conf_t* confs[12];
  34. /**
  35. 开启指定的PWM通道
  36. @api pwm.open(channel, period, pulse, pnum, precision)
  37. @int PWM通道
  38. @int 频率, 1-N,单位Hz. N受限于具体硬件能力
  39. @int 占空比 0-分频精度
  40. @int 输出周期 0为持续输出, 1为单次输出, 其他为指定脉冲数输出
  41. @int 分频精度, 100/256/1000, 默认为100, 若设备不支持会有日志提示
  42. @return boolean 处理结果,成功返回true,失败返回false
  43. @usage
  44. -- 打开PWM5, 频率1kHz, 占空比50%
  45. pwm.open(5, 1000, 50)
  46. -- 打开PWM5, 频率10kHz, 分频为 31/256
  47. pwm.open(5, 10000, 31, 0, 256)
  48. */
  49. static int l_pwm_open(lua_State *L) {
  50. luat_pwm_conf_t conf = {
  51. .pnum = 0,
  52. .precision = 100
  53. };
  54. conf.channel = luaL_checkinteger(L, 1);
  55. conf.period = luaL_checkinteger(L, 2);
  56. conf.pulse = luaL_optnumber(L, 3,0);
  57. if (lua_isnumber(L, 4) || lua_isinteger(L, 4)){
  58. conf.pnum = luaL_checkinteger(L, 4);
  59. }
  60. if (lua_isnumber(L, 5) || lua_isinteger(L, 5)){
  61. conf.precision = luaL_checkinteger(L, 5);
  62. }
  63. int ret = luat_pwm_setup(&conf);
  64. if (ret == 0) {
  65. s_state |= (1 << conf.channel);
  66. }
  67. lua_pushboolean(L, ret == 0 ? 1 : 0);
  68. return 1;
  69. }
  70. /**
  71. 关闭指定的PWM通道
  72. @api pwm.close(channel)
  73. @int PWM通道
  74. @return nil 无处理结果
  75. @usage
  76. -- 关闭PWM5
  77. pwm.close(5)
  78. */
  79. static int l_pwm_close(lua_State *L) {
  80. int channel = luaL_checkinteger(L, 1);
  81. luat_pwm_close(channel);
  82. s_state &= ~(1 << channel);
  83. return 0;
  84. }
  85. /**
  86. PWM捕获
  87. @api pwm.capture(channel)
  88. @int PWM通道
  89. @int 捕获频率
  90. @return boolean 处理结果,成功返回true,失败返回false
  91. @usage
  92. -- PWM0捕获
  93. while 1 do
  94. pwm.capture(0,1000)
  95. local ret,channel,pulse,pwmH,pwmL = sys.waitUntil("PWM_CAPTURE", 2000)
  96. if ret then
  97. log.info("PWM_CAPTURE","channel"..channel,"pulse"..pulse,"pwmH"..pwmH,"pwmL"..pwmL)
  98. end
  99. end
  100. */
  101. static int l_pwm_capture(lua_State *L) {
  102. int ret = luat_pwm_capture(luaL_checkinteger(L, 1),luaL_checkinteger(L, 2));
  103. lua_pushboolean(L, ret == 0 ? 1 : 0);
  104. return 1;
  105. }
  106. // 新的API系列, 封装老的版本, bsp层暂时不改
  107. /*
  108. 初始化指定的PWM通道
  109. @api pwm.setup(channel, period, pulse, pnum, precision)
  110. @int PWM通道
  111. @int 频率, 1-N,单位Hz. N受限于具体硬件能力
  112. @int 占空比 0-分频精度
  113. @int 输出周期 0为持续输出, 1为单次输出, 其他为指定脉冲数输出
  114. @int 分频精度, 100/256/1000, 默认为100, 若设备不支持会有日志提示
  115. @return boolean 处理结果,成功返回true,失败返回false
  116. @usage
  117. -- 设置PWM5, 频率1kHz, 占空比50%
  118. pwm.setup(5, 1000, 50)
  119. */
  120. static int l_pwm_setup(lua_State *L) {
  121. luat_pwm_conf_t conf = {
  122. .pnum = 0,
  123. .precision = 100
  124. };
  125. conf.channel = luaL_checkinteger(L, 1);
  126. conf.period = luaL_checkinteger(L, 2);
  127. conf.pulse = luaL_optnumber(L, 3,0);
  128. if (lua_isnumber(L, 4) || lua_isinteger(L, 4)){
  129. conf.pnum = luaL_checkinteger(L, 4);
  130. }
  131. if (lua_isnumber(L, 5) || lua_isinteger(L, 5)){
  132. conf.precision = luaL_checkinteger(L, 5);
  133. }
  134. if (conf.channel > 5 || conf.channel < 0) {
  135. return 0;
  136. }
  137. if (confs[conf.channel] == NULL) {
  138. confs[conf.channel] = luat_heap_malloc(sizeof(luat_pwm_conf_t));
  139. if (confs[conf.channel] == NULL) {
  140. LLOGE("pwm_setup malloc fail");
  141. return 0;
  142. }
  143. }
  144. memcpy(confs[conf.channel], &conf, sizeof(luat_pwm_conf_t));
  145. lua_pushboolean(L, 1);
  146. return 1;
  147. }
  148. static int check_channel(lua_State *L) {
  149. int channel = luaL_checkinteger(L, 1);
  150. if (channel >= 12 || channel < 0) {
  151. return -1;
  152. }
  153. if (confs[channel] == NULL) {
  154. LLOGE("请先调用pwm.setup!! %d", channel);
  155. return -1;
  156. }
  157. return channel;
  158. }
  159. /*
  160. 启动指定的PWM通道
  161. @api pwm.start(channel)
  162. @int PWM通道
  163. @return boolean 处理结果,成功返回true,失败返回false
  164. @usage
  165. -- 启动PWM1
  166. pwm.start(1)
  167. */
  168. static int l_pwm_start(lua_State *L) {
  169. int channel = check_channel(L);
  170. if (channel < 0) {
  171. return 0;
  172. }
  173. int ret = luat_pwm_setup(confs[channel]);
  174. if (ret == 0) {
  175. s_state |= (1 << channel);
  176. }
  177. lua_pushboolean(L, ret == 0 ? 1 : 0);
  178. return 1;
  179. }
  180. /*
  181. 停止指定的PWM通道
  182. @api pwm.stop(channel)
  183. @int PWM通道
  184. @return boolean 处理结果,成功返回true,失败返回false
  185. @usage
  186. -- 停止PWM1
  187. pwm.stop(1)
  188. */
  189. static int l_pwm_stop(lua_State *L) {
  190. int channel = check_channel(L);
  191. if (channel < 0) {
  192. return 0;
  193. }
  194. luat_pwm_close(channel);
  195. luat_heap_free(confs[channel]);
  196. confs[channel] = NULL;
  197. s_state &= ~(1 << channel);
  198. lua_pushboolean(L, 1);
  199. return 1;
  200. }
  201. /*
  202. 设置指定PWM通道的占空比
  203. @api pwm.setDuty(channel, duty)
  204. @int PWM通道
  205. @int 占空比
  206. @return boolean 处理结果,成功返回true,失败返回false
  207. @usage
  208. -- 设置PWM1占空比25%
  209. pwm.setDuty(1, 25)
  210. */
  211. static int l_pwm_set_duty(lua_State *L) {
  212. int channel = check_channel(L);
  213. if (channel < 0) {
  214. return 0;
  215. }
  216. confs[channel]->pulse = luaL_checkinteger(L, 2);
  217. luat_pwm_conf_t conf = *confs[channel];
  218. // 如果已经是打开状态, 需要重新setup一下
  219. if (s_state & (1 << channel)) {
  220. int ret = luat_pwm_setup(&conf);
  221. lua_pushboolean(L, ret == 0 ? 1 : 0);
  222. }
  223. else {
  224. lua_pushboolean(L, 1);
  225. }
  226. return 1;
  227. }
  228. /*
  229. 设置指定PWM通道的频率
  230. @api pwm.setFreq(channel, freq)
  231. @int PWM通道
  232. @int 频率, 1-N,单位Hz. N受限于具体硬件能力
  233. @return boolean 处理结果,成功返回true,失败返回false
  234. @usage
  235. -- 设置PWM5频率2kHz
  236. pwm.setFreq(5, 2000)
  237. */
  238. static int l_pwm_set_freq(lua_State *L) {
  239. int channel = check_channel(L);
  240. if (channel < 0) {
  241. return 0;
  242. }
  243. confs[channel]->period = luaL_checkinteger(L, 2);
  244. luat_pwm_conf_t conf = *confs[channel];
  245. // 如果已经是打开状态, 需要重新setup一下
  246. if (s_state & (1 << channel)) {
  247. int ret = luat_pwm_setup(&conf);
  248. lua_pushboolean(L, ret == 0 ? 1 : 0);
  249. }
  250. else {
  251. lua_pushboolean(L, 1);
  252. }
  253. return 1;
  254. }
  255. #include "rotable2.h"
  256. static const rotable_Reg_t reg_pwm[] =
  257. {
  258. { "open" , ROREG_FUNC(l_pwm_open )},
  259. { "close" , ROREG_FUNC(l_pwm_close)},
  260. { "capture" , ROREG_FUNC(l_pwm_capture)},
  261. // 新api, setup,start,stop
  262. { "setup" , ROREG_FUNC(l_pwm_setup )},
  263. { "start" , ROREG_FUNC(l_pwm_start )},
  264. { "stop" , ROREG_FUNC(l_pwm_stop )},
  265. { "setDuty" , ROREG_FUNC(l_pwm_set_duty )},
  266. { "setFreq" , ROREG_FUNC(l_pwm_set_freq )},
  267. { NULL, ROREG_INT(0) }
  268. };
  269. LUAMOD_API int luaopen_pwm( lua_State *L ) {
  270. luat_newlib2(L, reg_pwm);
  271. return 1;
  272. }