找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3840|回复: 0
收起左侧

ProtoThreads多线程实例

[复制链接]
ID:112317 发表于 2016-4-9 20:14 | 显示全部楼层 |阅读模式
发一个我前段时间用ProtoThreads写的一个读取Serial角度并用模拟的方式驱动舵机
关于ProtoThreads的介绍:http://www.51hei.com/bbs/dpj-47836-1.html
代码如下

  1.     #include <PT_timer.h>
  2.     #include <pt.h>
  3.     int servopin=8;//定义舵机接口数字接口7
  4.     int myangle=100;//定义角度变量
  5.     int val=0;
  6.     static struct pt pt1,pt2;
  7.     PT_timer servotimer;
  8.     static int servoMove(struct pt *pt)
  9.     {  
  10.       PT_BEGIN(pt);  
  11.       while(1)
  12.       {
  13.             servotimer.setTimer(25);
  14.             PT_WAIT_UNTIL(pt,servotimer.Expired());
  15.             int pulsewidth;//定义脉宽变量
  16.             myangle%=156;//视舵机而定,防止越界
  17.             pulsewidth=myangle*11+500;//将角度转化为500-2205的脉宽值
  18.             digitalWrite(servopin,HIGH);//将舵机接口电平至高
  19.             delayMicroseconds(pulsewidth);//延时脉宽值的微秒数
  20.             digitalWrite(servopin,LOW);//将舵机接口电平至低
  21.       }
  22.       PT_END(pt);
  23.     }

  24.     String inString = "";
  25.     static int angleRead(struct pt *pt)
  26.     {
  27.       PT_BEGIN(pt);
  28.       while(1) {   
  29.         PT_WAIT_UNTIL(pt, Serial.available()>0);
  30.             int inChar = Serial.read();
  31.         if (isDigit(inChar))
  32.           inString += (char)inChar;
  33.         if (inChar == ' '||inChar=='\n') {
  34.           myangle=inString.toInt();
  35.               Serial.print("myangle=");
  36.               Serial.println(myangle);
  37.           inString = "";
  38.             }
  39.       }
  40.       PT_END(pt);
  41.     }
  42.     void setup()
  43.     {
  44.       pinMode(servopin,OUTPUT);//设定舵机接口为输出接口
  45.       PT_INIT(&pt1);
  46.       PT_INIT(&pt2);
  47.       Serial.begin(9600);
  48.     }
  49.     void loop()//
  50.     {
  51.         servoMove(&pt1);
  52.         angleRead(&pt2);
  53.     }
复制代码

ServoMove呢就是自己模拟出来的舵机函数,为什么不用servo库呢?因为arduino自身的servo库有很多限制,第一PWM不能用了,第二最小角度只有1度,当然这个程序里舵机的精度也是1度,只要把相应的变量改成float就能精确到小数了,不过最大的好处是舵机脚可以任意设定
servomove中限定了最大角度为155度,这个与舵机有关
angleRead中使用了stringtoInt,每次可以输入一个角度,角度可以以 空格 或 回车 结尾(操蛋的VC2010 SerialMonitor发送数据不带 回车的。。那就空格了)
程序中使用了定时器,自己用C++写的,第一次写库,照葫芦画瓢了。。。
感谢czad的扩展库翻译:http://www.51hei.com/bbs/dpj-47837-1.html
这个库用起来非常简单:
PT_Timer t;//定义一个定时器
t.setTimer(unsinged long time) //定时时间,单位ms
t.Expired()//判断定时器是否溢出,是返回值>0
在上面的代码中,一个舵机周期是20ms,前面的约2.5毫秒是信号周期,剩下的10多ms全是无用的低电平,然而又必不可少,所以果断用定时器取代delay
ok

pt.h
  1. /*
  2. * Copyright (c) 2004-2006, Swedish Institute of Computer Science.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. *    notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. *    notice, this list of conditions and the following disclaimer in the
  12. *    documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the Institute nor the names of its contributors
  14. *    may be used to endorse or promote products derived from this software
  15. *    without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. *
  29. * Author: Adam Dunkels <adam@sics.se>
  30. *
  31. * $Id: pt.h,v 1.6 2006/06/03 11:29:43 adam Exp $
  32. */

  33. /**
  34. * \addtogroup pt
  35. * @{
  36. */

  37. /**
  38. * \file
  39. * Protothreads implementation.
  40. * \author
  41. * Adam Dunkels <adam@sics.se>
  42. *
  43. */

  44. #ifndef __PT_H__
  45. #define __PT_H__

  46. #include "lc.inc"


  47. struct pt {
  48.   lc_t lc;
  49. };

  50. #define PT_WAITING 0
  51. #define PT_EXITED  1
  52. #define PT_ENDED   2
  53. #define PT_YIELDED 3

  54. /**
  55. * \name Initialization
  56. * @{
  57. */

  58. /**
  59. * Initialize a protothread.
  60. *
  61. * Initializes a protothread. Initialization must be done prior to
  62. * starting to execute the protothread.
  63. *
  64. * \param pt A pointer to the protothread control structure.
  65. *
  66. * \sa PT_SPAWN()
  67. *
  68. * \hideinitializer
  69. */
  70. #define PT_INIT(pt)   LC_INIT((pt)->lc)

  71. /** @} */

  72. /**
  73. * \name Declaration and definition
  74. * @{
  75. */

  76. /**
  77. * Declaration of a protothread function.
  78. *
  79. * This macro is used to declare a protothread function. Protothreads
  80. * function should be declared with this macro, but can also be
  81. * declared as regular C functions that return an integer value.
  82. *
  83. * \param name_args The name and arguments of the C function
  84. * implementing the protothread.
  85. *
  86. * \hideinitializer
  87. */
  88. #define PT_THREAD(name_args) char name_args

  89. /**
  90. * Declare the start of a protothread inside the C function
  91. * implementing the protothread.
  92. *
  93. * This macro is used to declare the starting point of a
  94. * protothread. It should be placed at the start of the function in
  95. * which the protothread runs. All C statements above the PT_BEGIN()
  96. * invokation will be executed each time the protothread is scheduled.
  97. *
  98. * \param pt A pointer to the protothread control structure.
  99. *
  100. * \hideinitializer
  101. */
  102. #define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)

  103. /**
  104. * Declare the end of a protothread.
  105. *
  106. * This macro is used for declaring that a protothread ends. It must
  107. * always be used together with a matching PT_BEGIN() macro.
  108. *
  109. * \param pt A pointer to the protothread control structure.
  110. *
  111. * \hideinitializer
  112. */
  113. #define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
  114.                    PT_INIT(pt); return PT_ENDED; }

  115. /** @} */

  116. /**
  117. * \name Blocked wait
  118. * @{
  119. */

  120. /**
  121. * Block and wait until condition is true.
  122. *
  123. * This macro blocks the protothread until the specified condition is
  124. * true.
  125. *
  126. * \param pt A pointer to the protothread control structure.
  127. * \param condition The condition.
  128. *
  129. * \hideinitializer
  130. */
  131. #define PT_WAIT_UNTIL(pt, condition)                \
  132.   do {                                                \
  133.     LC_SET((pt)->lc);                                \
  134.     if(!(condition)) {                                \
  135.       return PT_WAITING;                        \
  136.     }                                                \
  137.   } while(0)

  138. /**
  139. * Block and wait while condition is true.
  140. *
  141. * This function blocks and waits while condition is true. See
  142. * PT_WAIT_UNTIL().
  143. *
  144. * \param pt A pointer to the protothread control structure.
  145. * \param cond The condition.
  146. *
  147. * \hideinitializer
  148. */
  149. #define PT_WAIT_WHILE(pt, cond)  PT_WAIT_UNTIL((pt), !(cond))

  150. /** @} */

  151. /**
  152. * \name Hierarchical protothreads
  153. * @{
  154. */

  155. /**
  156. * Block and wait until a child protothread completes.
  157. *
  158. * This macro schedules a child protothread. The current protothread
  159. * will block until the child protothread completes.
  160. *
  161. * \note The child protothread must be manually initialized with the
  162. * PT_INIT() function before this function is used.
  163. *
  164. * \param pt A pointer to the protothread control structure.
  165. * \param thread The child protothread with arguments
  166. *
  167. * \sa PT_SPAWN()
  168. *
  169. * \hideinitializer
  170. */
  171. #define PT_WAIT_THREAD(pt, thread) PT_WAIT_WHILE((pt), PT_SCHEDULE(thread))

  172. /**
  173. * Spawn a child protothread and wait until it exits.
  174. *
  175. * This macro spawns a child protothread and waits until it exits. The
  176. * macro can only be used within a protothread.
  177. *
  178. * \param pt A pointer to the protothread control structure.
  179. * \param child A pointer to the child protothread's control structure.
  180. * \param thread The child protothread with arguments
  181. *
  182. * \hideinitializer
  183. */
  184. #define PT_SPAWN(pt, child, thread)                \
  185.   do {                                                \
  186.     PT_INIT((child));                                \
  187.     PT_WAIT_THREAD((pt), (thread));                \
  188.   } while(0)

  189. /** @} */

  190. /**
  191. * \name Exiting and restarting
  192. * @{
  193. */

  194. /**
  195. * Restart the protothread.
  196. *
  197. * This macro will block and cause the running protothread to restart
  198. * its execution at the place of the PT_BEGIN() call.
  199. *
  200. * \param pt A pointer to the protothread control structure.
  201. *
  202. * \hideinitializer
  203. */
  204. #define PT_RESTART(pt)                                \
  205.   do {                                                \
  206.     PT_INIT(pt);                                \
  207.     return PT_WAITING;                        \
  208.   } while(0)

  209. /**
  210. * Exit the protothread.
  211. *
  212. * This macro causes the protothread to exit. If the protothread was
  213. * spawned by another protothread, the parent protothread will become
  214. * unblocked and can continue to run.
  215. *
  216. * \param pt A pointer to the protothread control structure.
  217. *
  218. * \hideinitializer
  219. */
  220. #define PT_EXIT(pt)                                \
  221.   do {                                                \
  222.     PT_INIT(pt);                                \
  223.     return PT_EXITED;                        \
  224.   } while(0)

  225. /** @} */

  226. /**
  227. * \name Calling a protothread
  228. * @{
  229. */

  230. /**
  231. * Schedule a protothread.
  232. *
  233. * This function shedules a protothread. The return value of the
  234. * function is non-zero if the protothread is running or zero if the
  235. * protothread has exited.
  236. *
  237. * \param f The call to the C function implementing the protothread to
  238. * be scheduled
  239. *
  240. * \hideinitializer
  241. */
  242. #define PT_SCHEDULE(f) ((f) == PT_WAITING)

  243. /** @} */

  244. /**
  245. * \name Yielding from a protothread
  246. * @{
  247. */

  248. /**
  249. * Yield from the current protothread.
  250. *
  251. * This function will yield the protothread, thereby allowing other
  252. * processing to take place in the system.
  253. *
  254. * \param pt A pointer to the protothread control structure.
  255. *
  256. * \hideinitializer
  257. */
  258. #define PT_YIELD(pt)                                \
  259.   do {                                                \
  260.     PT_YIELD_FLAG = 0;                                \
  261.     LC_SET((pt)->lc);                                \
  262.     if(PT_YIELD_FLAG == 0) {                        \
  263.       return PT_YIELDED;                        \
  264.     }                                                \
  265.   } while(0)

  266. /**
  267. * \brief      Yield from the protothread until a condition occurs.
  268. * \param pt   A pointer to the protothread control structure.
  269. * \param cond The condition.
  270. *
  271. *             This function will yield the protothread, until the
  272. *             specified condition evaluates to true.
  273. *
  274. *
  275. * \hideinitializer
  276. */
  277. #define PT_YIELD_UNTIL(pt, cond)                \
  278.   do {                                                \
  279.     PT_YIELD_FLAG = 0;                                \
  280.     LC_SET((pt)->lc);                                \
  281.     if((PT_YIELD_FLAG == 0) || !(cond)) {        \
  282.       return PT_YIELDED;                        \
  283.     }                                                \
  284.   } while(0)

  285. /** @} */

  286. #endif /* __PT_H__ */

  287. /** @} */
复制代码

附上
ProtoThreads Timer.rar (13.23 KB, 下载次数: 11)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表