搜索
bottom↓
回复: 88

[模板][下载]LGT开发板测评 内附全状态机快速开发模板

  [复制链接]

出0入296汤圆

发表于 2012-4-20 22:21:18 | 显示全部楼层 |阅读模式
本帖最后由 Gorgon_Meducer 于 2012-4-21 09:59 编辑

    认真说来,昨天下午我就接到了顺风快递的电话,无奈那时那刻我正坐在影院里感受TITANIC的震撼,
于是我很不耐烦地说:“明天再送!”说完后,我就后悔了——阿莫请的螃蟹就这么被拖延了一天。还好,
热乎着~
    一大早拿到快递,阿莫的包装、成品的简洁明快、发货单的免费字样暂且不表,三下五除二,这次测评
的主角就展现在眼前了——厄……原谅我,其实找不到什么形容词……只是稍微对芯片的封装有点吃惊——
感觉有点大。其实路上我就开始盘算,做个什么东西最简单,最能交差。因为手边一无烙铁,而无任何设备,
连万用表都没有,这直接打消了我测量极限功耗的念头。再看看核心小板,又不放心的仔细翻看了两下,
果然连个可控的LED都没接,做啥呢?望着硕大的232接口,俺实在很无奈……总不能再做一个控制台贪吃
蛇吧?
    于是乎抱着走一步看一步的心态,我打开论坛,下载了数据手册,虽然通篇没有AVR,却怎么看怎么
亲切,呵呵……果然如传闻所说阿。论坛上,阿莫已经从环境建立到跑马灯DEMO摆好了入门一条龙服务,
这种推广力度,果然不是我用个随便什么串口DEMO就能交差的,否则不是太有失水准?想到这里,手指
不由得扣扣脑门……貌似也没啥水准哈……算了,就做个Software Framework好了,谁让论坛的DEMO代码
看着那么不爽……

    所谓的Software Framework其实不过是一个框架,对开发很有指导意义。对很多老手来说,Software
Framework并不是一个固定形式的东西,其实心中有就差不多的,是不是每次做项目无论简繁都弄得那么
多文件夹、文件,其实无所谓。但对很多缺乏这种历练的初学者来说,Software Framework的指导意义,
甚至比一些书本知识更重要。层次是层次、模块就是模块,容不得你通融。每一个文件夹就是一个模块,
就是一个黑盒子,从这个角度来说,黑盒子向外界提供服务或者说功能,就是通过一个固定的头文件来实
现的——“你要用这个模块是吧?需要你知道的都写在与文件夹同名的接口头文件里面了,至于功能怎么
实现的就跟你没有关系了”——由此可见对用户来说,最关键的就是那个描述了模块功能的接口头文件。
其实,所谓的系统分层也不过就是几个有层次叠加关系的大模块,比如硬件抽象层(HAL),比如提供各
种硬件无关的系统服务的服务层(Service),由下往上,最上面就是应用层了(APP)——这就是嵌入式
系统最经典的“裸机三层次”。
    说起裸机三层次,挑大梁的其实还是硬件抽象层,很多时候,所谓的Software Framework不过就是为
了这个硬件抽象层而存在的,或者说是一个增强版本的硬件抽象层。那么硬件抽象层是做啥的呢?当然是
硬件抽象咯——就是把硬件提供的功能抽象出来,提供很具体很好用很简洁的API函数集合。通过这个API
集合,上层的开发就基本和硬件没有什么太大的关系了。利用硬件抽象层API函数集合开发的应用,无论
上层结构如何(有没有进一步的Framework都无所谓),只要针对不同的硬件具体编写对应的驱动就可以
很简单的实现项目的移植了——当然具体操作还是有很多细节的,不过总的说来情形就是如此——HAL,
全体工程师为了自己偷懒而诞生的东西——可惜最后人人都没有办法偷懒了——因为每个工程师都有自己
的一套HAL想法,只做自己的项目还好,一旦要移植别人的HAL,基本上就是个人感情色彩夹杂着各类神仙
妖怪的麻烦一起上——最后多半还是用自己的那套系统了。这就是传说中的街头HAL现象。当然,扯远了……

TO BE CONTINUE...

工程文件在build目录下
系统总配置文件在根目录的app_cfg.h中,其他app_cfg.h有两个作用
1、为了传递配置信息而存在的
2、当某个模块单独被提取出来独立使用的时候,可以通过目录中的app_cfg.h对模块进行独立配置

如果要在一个新工程中使用es_framework,只要将es_framework目录复制到对应的工程文件夹中,然后仿照
main.c和根目录的app_cfg.h来进行系统配置就可以了。


DEMO程序:在控制台上以115200波特率实现:周期性显示hello world,同时你键盘输入什么控制台就显示什么,输入的字符不会打乱hello world的输出完整性

引用自uc_uc++的DEMO说明,再次感谢!
我们看主程序,有三个状态机Ping_Pang_Demo,Stream_Output,Hello_World。
状态机Ping_Pang_Demo 有3个状态:Ping_Pang_Demo_Start,Ping_Pang_Demo_Wait_Busy_Flag,Ping_Pang_Demo_Output.
状态机Stream_Output有2个状态,Stream_Out_Start,Stream_Out_Byte_Output
状态机Hello_World有3个状态,HW_Start,HW_Init_Delay,HW_Delay。

状态机Ping_Pang_Demo的功能是等待收到串口一字节数据,然后向串口发送收到的数据。
状态Ping_Pang_Demo_Start等待串口接受到数据,跳转到Ping_Pang_Demo_Wait_Busy_Flag。
状态Ping_Pang_Demo_Wait_Busy_Flag等待s_bBusyFlag为false,跳转到Ping_Pang_Demo_Output
状态Ping_Pang_Demo_Output向串口发送接受到得数据,置s_bBusyFlag为false,跳转到Ping_Pang_Demo_Start。

因为有多个状态机都使用串口,为了保证某一时刻串口只能被一个状态机使用,使用s_bBusyFlag标志,串口互斥访问。

状态机Hello_World周期向串口发送"hello world"字符串。
状态HW_Start等待s_bBusyFlag为false,开始向串口发送字符串,跳转到HW_Init_Delay
状态HW_Init_Delay置s_bBusyFlag为false,初始化状态机等待时间,跳转到HW_Delay
状态HW_Delay等待时间到,跳转到HW_Start

状态HW_Start向串口发送字符串,又调用了子状态机Stream_Output
子状态机Stream_Output的状态有两个,
Stream_Out_Start检测参数,是否还有数据要发。没有数据,则子状态机返回(返回到父状态机Hello_World)。有数据要发,则跳转到Stream_Out_Byte_Output
Stream_Out_Byte_Output串口发送1字节,跳转到Stream_Out_Start。
  1. static bool s_bBusyFlag = false;

  2. /******************************************************************************
  3. * DEMO APPLICATION: Ping Pang Demo                                           *
  4. ******************************************************************************/

  5. static uint8_t s_chByte;

  6. STATIC_FSM(Ping_Pang_Demo)
  7.     PRIVATE STATE(Ping_Pang_Demo_Start);
  8.     PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag);
  9.     PRIVATE STATE(Ping_Pang_Demo_Output);
  10. END_FSM

  11. PRIVATE STATE(Ping_Pang_Demo_Start) BEGIN

  12.     //! receive new byte
  13.     if (SERIAL_IN(&s_chByte)) {
  14.         //! got one, then tranfer to output state;
  15.         TRANSFER_TO_STATE(Ping_Pang_Demo_Wait_Busy_Flag);

  16.         //! exit current state;
  17.         EXIT_STATE;
  18.     }

  19.     //! keep current state
  20.     REFLEXIVE_STATE;
  21. END

  22. PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag) BEGIN

  23.     if (!s_bBusyFlag) {
  24.         //! free, then set the flag
  25.         s_bBusyFlag = true;
  26.         
  27.         TRANSFER_TO_STATE(Ping_Pang_Demo_Output);

  28.         //! exit current state;
  29.         EXIT_STATE;
  30.     }

  31.     //! keep current state
  32.     REFLEXIVE_STATE;

  33. END


  34. PRIVATE STATE(Ping_Pang_Demo_Output) BEGIN

  35.    
  36.     //! output received byte
  37.     if (SERIAL_OUT(s_chByte)) {
  38.         //! success, then transfer to start state
  39.         TRANSFER_TO_STATE(Ping_Pang_Demo_Start);

  40.         //! clear busy flag
  41.         s_bBusyFlag = false;

  42.         //! exit current state
  43.         EXIT_STATE;
  44.     }

  45.     //! keep current state;
  46.     REFLEXIVE_STATE;
  47. END


  48. /******************************************************************************
  49. * DEMO APPLICATION: Hello world                                              *
  50. ******************************************************************************/

  51. DEF_ARG(ArgStream)
  52.     uint8_t *pchSrc;
  53.     uint8_t chLength;
  54. END_DEF_ARG

  55. /*! \brief sub state machine
  56. */
  57. STATIC_FSM(Stream_Output)
  58.     PRIVATE STATE(Stream_Out_Start);
  59.     PRIVATE STATE(Stream_Out_Byte_Output);
  60. END_FSM


  61. PRIVATE STATE(Stream_Out_Start) BEGIN

  62.     //! check argument
  63.     if (!CHECK_ARG(ArgStream)) {
  64.         //! illegal, just exit sub state machine
  65.         EXIT_STATE;
  66.     }

  67.     if (    (NULL == REF_ARG(ArgStream).pchSrc)
  68.         ||  (0 == REF_ARG(ArgStream).chLength)) {
  69.         //! complete

  70.         
  71.         EXIT_STATE;
  72.     }
  73.         
  74.         
  75.     TRANSFER_TO_STATE(Stream_Out_Byte_Output);


  76.     EXIT_STATE;

  77. END

  78. PRIVATE STATE(Stream_Out_Byte_Output) BEGIN
  79.    
  80.     uint8_t chByte;

  81.     //! check argument
  82.     if (!CHECK_ARG(ArgStream)) {
  83.         //! illegal, just exit sub state machine
  84.         EXIT_STATE;
  85.     }

  86.     chByte = *(REF_ARG(ArgStream).pchSrc);

  87.     //! output received byte
  88.     if (SERIAL_OUT(chByte)) {

  89.         REF_ARG(ArgStream).pchSrc++;
  90.         REF_ARG(ArgStream).chLength--;
  91.         //! success, then transfer to start state
  92.         TRANSFER_TO_STATE(Stream_Out_Start);

  93.         //! exit current state
  94.         EXIT_STATE;
  95.     }

  96.     //! keep current state;
  97.     REFLEXIVE_STATE;

  98. END


  99. //----------------------------------------------------------
  100. //! \brief demo task

  101. FSM(Hello_World,1)
  102.     PRIVATE STATE(HW_Start);
  103.     PRIVATE STATE(HW_Init_Delay);
  104.     PRIVATE STATE(HW_Delay);
  105. END_FSM


  106. uint32_t s_hwDelay = 0;

  107. ARG(ArgStream) s_DemoArg = {0};
  108. SAFE_TASK_ARG s_Arg = {0};

  109. PRIVATE STATE(HW_Start) BEGIN

  110.     if (!s_bBusyFlag) {
  111.         //! free
  112.         s_bBusyFlag = true;    //!< set busy flag

  113.         

  114.         //! initialize argument
  115.         s_DemoArg.pchSrc = (uint8_t *)"Hello world!\r\n";
  116.         s_DemoArg.chLength = sizeof( "Hello world!\r\n");

  117.         s_Arg.pArg = &s_DemoArg;
  118.         s_Arg.hwLength = sizeof(s_DemoArg);

  119.         //! success, then transfer to start state
  120.         CALL_FSM_EX(
  121.             REF_STATE(Stream_Out_Start), &s_Arg,        //!< sub-statemanchine
  122.             REF_STATE(HW_Init_Delay), pArg);  //!< return statemachine

  123.         //! exit current state
  124.         EXIT_STATE;
  125.     }

  126.     REFLEXIVE_STATE;

  127. END


  128. PRIVATE STATE(HW_Init_Delay) BEGIN
  129.    
  130.     //! release busy flag
  131.     s_bBusyFlag = false;

  132.     s_hwDelay = 20000;


  133.     TRANSFER_TO_STATE(HW_Delay);

  134.     EXIT_STATE;
  135. END

  136. PRIVATE STATE(HW_Delay) BEGIN

  137.     if (s_hwDelay) {
  138.         s_hwDelay --;
  139.     } else {
  140.         TRANSFER_TO_STATE(HW_Start);

  141.         EXIT_STATE;
  142.     }

  143.     REFLEXIVE_STATE;

  144. END

  145. static bool app_init(void)
  146. {
  147.     bool bResult = true;
  148.     bResult &= NEW_STATIC_FSM( Ping_Pang_Demo, REF_STATE(Ping_Pang_Demo_Start));
  149.     bResult &= NEW_FSM( Hello_World, REF_STATE(HW_Start));

  150.     return bResult;
  151. }
复制代码


相关下载


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2012-4-20 22:24:17 | 显示全部楼层
恭喜楼主,但是,怎么用啊。。。

出0入296汤圆

 楼主| 发表于 2012-4-20 22:25:48 | 显示全部楼层
yaoyyie2003 发表于 2012-4-20 22:24
恭喜楼主,但是,怎么用啊。。。

吃饭回去再说……

出0入0汤圆

发表于 2012-4-20 22:32:22 | 显示全部楼层
本帖最后由 laign 于 2012-4-20 22:33 编辑

同问一个,,怎么用呢

出0入296汤圆

 楼主| 发表于 2012-4-20 22:52:44 | 显示全部楼层
laign 发表于 2012-4-20 22:32
同问一个,,怎么用呢

build文件夹里面有工程文件

出0入0汤圆

发表于 2012-4-20 23:04:34 | 显示全部楼层
怎么不用printf?

出0入296汤圆

 楼主| 发表于 2012-4-20 23:12:11 | 显示全部楼层
agnd 发表于 2012-4-20 23:04
怎么不用printf?

之前的printf是block代码,如果波特率低,就会极大地浪费CPU 16M的优势……

出0入0汤圆

发表于 2012-4-20 23:18:45 | 显示全部楼层
楼主辛苦了! 这个是源自ATMEL的framework?
回头我们也学习学习~

出0入296汤圆

 楼主| 发表于 2012-4-20 23:36:55 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2012-4-20 23:38 编辑
LGT 发表于 2012-4-20 23:18
楼主辛苦了! 这个是源自ATMEL的framework?
回头我们也学习学习~


厄……我不认可这种说法。SF的做法是通行的标准,不是哪家专属的东西。不过没有SF很可能就是比较特殊的情形了……
一般认为SF会降低系统的效率,这种说法只在SF追求通用的前提下是成立的。
嵌入式系统本来就是专用系统,所以做一个通用的SF,这里的专用就和通用冲突了。只能说,在一定定义明确的范围内通用。
所以,要做SF,最好是针对几个明确的市场应用创建针对其应用场景高度优化的专用SF。

希望对你们有所帮助。

出0入618汤圆

发表于 2012-4-21 00:57:36 | 显示全部楼层
这个SF太霸气了,用C语言写出Pascal的语法和HDL的感觉了。

出0入0汤圆

发表于 2012-4-21 04:58:26 | 显示全部楼层
收藏。

也订了块LGT,到时移植IAR C++。

出0入0汤圆

发表于 2012-4-21 07:31:16 | 显示全部楼层
拜读傻孩子的大作。

出100入0汤圆

发表于 2012-4-21 08:14:39 | 显示全部楼层
傻孩子每次发的是大作,写的内容很详细,而且总能带领我们写代码的思维进入新的层次!
新手表示得好好向傻孩子学习!

出0入0汤圆

发表于 2012-4-21 08:17:35 | 显示全部楼层
唉,都怪俺水平太低了,全是E文的,看不下去了!

出0入0汤圆

发表于 2012-4-21 08:38:38 | 显示全部楼层
楼主,你那个签名是啥意思?

出0入0汤圆

发表于 2012-4-21 09:00:19 | 显示全部楼层
难道楼主又要出新书了?

出0入0汤圆

发表于 2012-4-21 09:00:53 | 显示全部楼层
置酷前顶一个
头像被屏蔽

出0入0汤圆

发表于 2012-4-21 09:09:17 | 显示全部楼层
COOL !

出0入296汤圆

 楼主| 发表于 2012-4-21 10:03:59 | 显示全部楼层
gzhuli 发表于 2012-4-21 00:57
这个SF太霸气了,用C语言写出Pascal的语法和HDL的感觉了。

哈哈~要的就是这种感觉~
如果只是普通的格式修改,我还不会这么嘚瑟,其实还有更多把戏在后面……真正做到非轮询的进程间阻塞、通讯、同步~我正在移植操作系统中进程通讯的部分,以求做到当线程逻辑上被阻塞时,对应的状态不会处于空转(轮询)状态。

出0入296汤圆

 楼主| 发表于 2012-4-21 10:05:18 | 显示全部楼层
lengshuicha 发表于 2012-4-21 08:38
楼主,你那个签名是啥意思?

正在修订深入浅出AVR,准备出第二版。主要是把口水去掉,加入状态机入门训练,改用gcc……

出0入0汤圆

发表于 2012-4-21 10:34:33 | 显示全部楼层
仁兄把编程也搞成富有艺术性,实在是苦中作乐啊。

出0入296汤圆

 楼主| 发表于 2012-4-21 10:44:37 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2012-4-21 11:06 编辑

为了丰富例子,增加可读性,证明这个software framework不是离开了调度器就不能活了,
特此增加一个不使用调度器实现同样功能的例子——当然是使用传统状态机结构。

特别说明
调度器是通过在顶层app_cfg.h中的配置宏来控制的

  1. //! \name configure safe task service
  2. //! @{
  3. #define TASK_SCHEDULER                      DISABLED
  4. #define SAFE_TASK_CALL_STACK                ENABLED

  5. #define SAFE_TASK_QUEUE_POOL_SIZE           (1u)        //!< task queue pool size
  6. #define SAFE_TASK_POOL_SIZE                 (3u)        //!< task pool size

  7. #define TASK_EVENT                          DISABLED    //!< enable task event system
  8. #define TASK_EVENT_POOL_SIZE                (4u)        //!< event pool size
  9. #define TASK_EVENT_EMBEDDED_SCANNER         ENABLED     //!< scan events in scheduler
  10. //! @}
复制代码
当TASK_SCHEDULER被设置为除ENABLED以外的任何值,就会关闭调度器,编译时不会生成任何
调度器相关的代码。特别说明下,SAFE_TASK_POOL_SIZE直接决定了调度器开启的时候,允许
同时处于活跃状态的状态机数目(不是状态机状态的数目,也不是状态机的数目,而是同时处于
活跃状态的状态机数目)



  1. /***************************************************************************
  2. *   Copyright(C)2009-2012 by Gorgon Meducer<Embedded_zhuoran@hotmail.com> *
  3. *                                                                         *
  4. *   This program is free software; you can redistribute it and/or modify  *
  5. *   it under the terms of the GNU Lesser General Public License as        *
  6. *   published by the Free Software Foundation; either version 2 of the    *
  7. *   License, or (at your option) any later version.                       *
  8. *                                                                         *
  9. *   This program is distributed in the hope that it will be useful,       *
  10. *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  11. *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  12. *   GNU General Public License for more details.                          *
  13. *                                                                         *
  14. *   You should have received a copy of the GNU Lesser General Public      *
  15. *   License along with this program; if not, write to the                 *
  16. *   Free Software Foundation, Inc.,                                       *
  17. *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  18. ***************************************************************************/

  19. /*============================ INCLUDES ======================================*/
  20. #include ".\app_cfg.h"
  21. #include ".\es_framework\platform.h"

  22. /*============================ MACROS ========================================*/
  23. /*============================ MACROFIED FUNCTIONS ===========================*/

  24. //! \brief macro for sending byte to serial port in none-block style
  25. #define SERIAL_OUT(__BYTE)    usart_serial_out_byte(&USART[0],(__BYTE))

  26. //! \brief macro for receiving byte from serial port in none-block style
  27. #define SERIAL_IN(__ADDR)     usart_serial_in_byte(&USART[0],(__ADDR))

  28. /*============================ TYPES =========================================*/
  29. /*============================ GLOBAL VARIABLES ==============================*/
  30. /*============================ LOCAL VARIABLES ===============================*/
  31. /*============================ PROTOTYPES ====================================*/
  32. static bool app_init(void);
  33. static bool task_ping_pang(void);
  34. static bool task_hello_world(void);

  35. /*============================ IMPLEMENTATION ================================*/



  36. /*! \note initialize system
  37. *  \param none
  38. *  \retval true system initialization succeeded.
  39. *  \retval false system initialization failed
  40. */
  41. static bool system_init( void )
  42. {
  43.     bool bResult = true;

  44.     /*! initialize platform */
  45.     bResult &= platform_init();

  46.     /*! add your application initialization here */
  47.     bResult &= app_init();

  48.     return bResult;
  49. }


  50. #if TASK_SCHEDULER == ENABLED
  51. /*! \note system idle task
  52. *! \param none
  53. *! \return none
  54. */
  55. static void idle_task( void )
  56. {
  57. #ifdef ON_BEFORE_SLEEP_EVENT
  58.     ON_BEFORE_SLEEP_EVENT
  59. #endif
  60.     //! try to enter a max allowed sleep mode
  61.     try_to_sleep();
  62.    
  63. #ifdef ON_AFTER_SLEEP_EVENT
  64.     ON_AFTER_SLEEP_EVENT
  65. #endif
  66.    
  67. }
  68. #endif



  69. /*! \note main function
  70. *  \param none
  71. *  \return none
  72. */
  73. #if __IS_COMPILER_IAR__
  74. __task void main( void )
  75. #elif __IS_COMPILER_GCC__
  76. int main( void )
  77. #endif
  78. {
  79.     /* initialize whole system */
  80.     system_init();

  81.     while(true) {                       //!< super loop
  82.     #ifdef INSERT_SUPPER_LOOP
  83.         INSERT_SUPPER_LOOP
  84.     #endif

  85.     #if TASK_SCHEDULER == ENABLED
  86.         if (!scheduler()) {             //!< scheduler
  87.             idle_task();                //!< idle state
  88.         }
  89.     #endif


  90.         task_ping_pang();               //!< task 1
  91.         task_hello_world();             //!< task 2
  92.     }

  93. #if __IS_COMPILER_GCC__
  94.     return 0;
  95. #endif
  96. }


  97. static bool s_bBusyFlag = false;

  98. /******************************************************************************
  99. * DEMO APPLICATION: Ping Pang Demo                                           *
  100. ******************************************************************************/

  101. /*
  102. static uint8_t s_chByte;

  103. STATIC_FSM(Ping_Pang_Demo)
  104.     PRIVATE STATE(Ping_Pang_Demo_Start);
  105.     PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag);
  106.     PRIVATE STATE(Ping_Pang_Demo_Output);
  107. END_FSM

  108. PRIVATE STATE(Ping_Pang_Demo_Start) BEGIN

  109.     //! receive new byte
  110.     if (SERIAL_IN(&s_chByte)) {
  111.         //! got one, then tranfer to output state;
  112.         TRANSFER_TO_STATE(Ping_Pang_Demo_Wait_Busy_Flag);

  113.         //! exit current state;
  114.         EXIT_STATE;
  115.     }

  116.     //! keep current state
  117.     REFLEXIVE_STATE;
  118. END

  119. PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag) BEGIN

  120.     if (!s_bBusyFlag) {
  121.         //! free, then set the flag
  122.         s_bBusyFlag = true;
  123.         
  124.         TRANSFER_TO_STATE(Ping_Pang_Demo_Output);

  125.         //! exit current state;
  126.         EXIT_STATE;
  127.     }

  128.     //! keep current state
  129.     REFLEXIVE_STATE;

  130. END


  131. PRIVATE STATE(Ping_Pang_Demo_Output) BEGIN
  132.     //! output received byte
  133.     if (SERIAL_OUT(s_chByte)) {
  134.         //! success, then transfer to start state
  135.         TRANSFER_TO_STATE(Ping_Pang_Demo_Start);

  136.         //! clear busy flag
  137.         s_bBusyFlag = false;

  138.         //! exit current state
  139.         EXIT_STATE;
  140.     }

  141.     //! keep current state;
  142.     REFLEXIVE_STATE;
  143. END
  144. */

  145. #define PING_PANG_START                 0
  146. #define PING_PANG_WAIT_BUSY_FLAG        1
  147. #define PING_PANG_OUTPUT                2

  148. static bool task_ping_pang(void)
  149. {
  150.     static uint8_t s_chState = 0;
  151.     static uint8_t s_chByte;

  152.     switch(s_chState) {
  153.         case PING_PANG_START:
  154.             if (SERIAL_IN(&s_chByte)) {
  155.                 s_chState = PING_PANG_WAIT_BUSY_FLAG;
  156.             }
  157.             break;
  158.         case PING_PANG_WAIT_BUSY_FLAG:
  159.              if (!s_bBusyFlag) {
  160.                  s_bBusyFlag = true;
  161.                  s_chState = PING_PANG_OUTPUT;
  162.              }
  163.              break;
  164.         case PING_PANG_OUTPUT:
  165.              if (SERIAL_OUT(s_chByte)) {
  166.                  s_bBusyFlag = false;
  167.                  s_chState = PING_PANG_START;
  168.              }
  169.              break;
  170.        
  171.     }

  172.     return true;
  173. }


  174. /******************************************************************************
  175. * DEMO APPLICATION: Hello world                                              *
  176. ******************************************************************************/

  177. /*
  178. DEF_ARG(ArgStream)
  179.     uint8_t *pchSrc;
  180.     uint8_t chLength;
  181. END_DEF_ARG

  182. //! \brief sub state machine
  183. STATIC_FSM(Stream_Output)
  184.     PRIVATE STATE(Stream_Out_Start);
  185.     PRIVATE STATE(Stream_Out_Byte_Output);
  186. END_FSM


  187. PRIVATE STATE(Stream_Out_Start) BEGIN

  188.     //! check argument
  189.     if (!CHECK_ARG(ArgStream)) {
  190.         //! illegal, just exit sub state machine
  191.         EXIT_STATE;
  192.     }

  193.     if (    (NULL == REF_ARG(ArgStream).pchSrc)
  194.         ||  (0 == REF_ARG(ArgStream).chLength)) {
  195.         //! complete

  196.         
  197.         EXIT_STATE;
  198.     }
  199.         
  200.         
  201.     TRANSFER_TO_STATE(Stream_Out_Byte_Output);
  202.     EXIT_STATE;

  203. END

  204. PRIVATE STATE(Stream_Out_Byte_Output) BEGIN
  205.    
  206.     uint8_t chByte;

  207.     //! check argument
  208.     if (!CHECK_ARG(ArgStream)) {
  209.         //! illegal, just exit sub state machine
  210.         EXIT_STATE;
  211.     }

  212.     chByte = *(REF_ARG(ArgStream).pchSrc);

  213.     //! output received byte
  214.     if (SERIAL_OUT(chByte)) {

  215.         REF_ARG(ArgStream).pchSrc++;
  216.         REF_ARG(ArgStream).chLength--;
  217.         //! success, then transfer to start state
  218.         TRANSFER_TO_STATE(Stream_Out_Start);

  219.         //! exit current state
  220.         EXIT_STATE;
  221.     }

  222.     //! keep current state;
  223.     REFLEXIVE_STATE;

  224. END
  225. */
  226. #define STREAM_OUT_START                0
  227. #define STREAM_OUT_BYTE_OUTPUT          1

  228. static bool stream_out(uint8_t *pchStream, uint8_t chLength)
  229. {
  230.     static uint8_t s_chState = 0;
  231.     static uint8_t s_chLength;
  232.     static uint8_t *s_pchSrc;

  233.     if (STREAM_OUT_START == s_chState) {
  234.         s_pchSrc = pchStream;
  235.         s_chLength = chLength;
  236.         s_chState = STREAM_OUT_BYTE_OUTPUT;
  237.     } else if (STREAM_OUT_BYTE_OUTPUT == s_chState) {

  238.         if ((0 == s_chLength) || (NULL == s_pchSrc)) {
  239.             s_chState = STREAM_OUT_START;
  240.             return false;
  241.         }

  242.         if (SERIAL_OUT(*s_pchSrc)) {
  243.             s_pchSrc++;
  244.             s_chLength--;
  245.         }
  246.     }

  247.     return true;
  248. }

  249. //----------------------------------------------------------
  250. //! \brief demo task
  251. /*
  252. FSM(Hello_World,1)
  253.     PRIVATE STATE(HW_Start);
  254.     PRIVATE STATE(HW_Init_Delay);
  255.     PRIVATE STATE(HW_Delay);
  256. END_FSM


  257. uint32_t s_hwDelay = 0;

  258. ARG(ArgStream) s_DemoArg = {0};
  259. SAFE_TASK_ARG s_Arg = {0};

  260. PRIVATE STATE(HW_Start) BEGIN

  261.     if (!s_bBusyFlag) {
  262.         //! free
  263.         s_bBusyFlag = true;    //!< set busy flag

  264.         //! initialize argument
  265.         s_DemoArg.pchSrc = (uint8_t *)"Hello world!\r\n";
  266.         s_DemoArg.chLength = sizeof( "Hello world!\r\n");

  267.         s_Arg.pArg = &s_DemoArg;
  268.         s_Arg.hwLength = sizeof(s_DemoArg);

  269.         //! success, then transfer to start state
  270.         CALL_FSM_EX(
  271.             REF_STATE(Stream_Out_Start), &s_Arg,        //!< sub-statemanchine
  272.             REF_STATE(HW_Init_Delay), pArg);  //!< return statemachine

  273.         //! exit current state
  274.         EXIT_STATE;
  275.     }

  276.     REFLEXIVE_STATE;

  277. END


  278. PRIVATE STATE(HW_Init_Delay) BEGIN
  279.    
  280.     //! release busy flag
  281.     s_bBusyFlag = false;
  282.     s_hwDelay = 20000;

  283.     TRANSFER_TO_STATE(HW_Delay);

  284.     EXIT_STATE;
  285. END

  286. PRIVATE STATE(HW_Delay) BEGIN

  287.     if (s_hwDelay) {
  288.         s_hwDelay --;
  289.     } else {
  290.         TRANSFER_TO_STATE(HW_Start);

  291.         EXIT_STATE;
  292.     }

  293.     REFLEXIVE_STATE;

  294. END
  295. */

  296. #define STREAM_OUT(__STR)    stream_out((__STR),sizeof(__STR))

  297. #define HW_START                    0
  298. #define HW_PRINT_STR                1
  299. #define HW_DELAY                    2

  300. static bool task_hello_world(void)
  301. {
  302.     static uint8_t s_tState = 0;
  303.     static uint32_t s_wDelay;
  304.     switch (s_tState) {
  305.         case HW_START:
  306.             if (!s_bBusyFlag) {
  307.                 s_bBusyFlag = true;
  308.                 s_tState = HW_PRINT_STR;
  309.             }
  310.             break;
  311.         case HW_PRINT_STR:
  312.             if (!STREAM_OUT("Hello world!\r\n")) {
  313.                 //! return false means complete
  314.                 s_bBusyFlag = false;
  315.                 s_wDelay = 20000;
  316.                 s_tState = HW_DELAY;
  317.             }
  318.             break;
  319.         case HW_DELAY:
  320.             if (s_wDelay) {
  321.                 s_wDelay--;
  322.             } else {
  323.                 s_tState = HW_START;
  324.             }
  325.             break;
  326.        
  327.     }

  328.     return true;

  329. }

  330. static bool app_init(void)
  331. {
  332.     bool bResult = true;
  333.     //bResult &= NEW_STATIC_FSM( Ping_Pang_Demo, REF_STATE(Ping_Pang_Demo_Start));
  334.     //bResult &= NEW_FSM( Hello_World, REF_STATE(HW_Start));

  335.     return bResult;
  336. }



  337. /* EOF */

复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-4-21 10:50:53 | 显示全部楼层
本帖最后由 uc_c++ 于 2012-4-21 10:58 编辑

状态机编程非常实用。
现在写程序,基本上就是状态机来,状态机去。

出0入0汤圆

发表于 2012-4-21 11:04:35 | 显示全部楼层
学习了,谢谢

出0入0汤圆

发表于 2012-4-21 12:02:45 | 显示全部楼层
LZ能发你用的超级终端给我吗?一直苦于在WIN7下找不到好用的超级终端

出0入0汤圆

发表于 2012-4-21 12:12:44 | 显示全部楼层
学无止境啊。

出0入0汤圆

发表于 2012-4-21 12:29:33 | 显示全部楼层
这个强,学习了

出0入296汤圆

 楼主| 发表于 2012-4-21 13:28:36 来自手机 | 显示全部楼层
ghostxdy 发表于 2012-4-21 12:02
LZ能发你用的超级终端给我吗?一直苦于在WIN7下找不到好用的超级终端

就是从xp里面弄出来的

出0入0汤圆

发表于 2012-4-21 14:40:32 | 显示全部楼层
傻孩子,你的《深入浅出AVR》改成《深入浅出LGT》得了。

出0入618汤圆

发表于 2012-4-21 15:58:36 | 显示全部楼层
ghostxdy 发表于 2012-4-21 12:02
LZ能发你用的超级终端给我吗?一直苦于在WIN7下找不到好用的超级终端

PuTTY好使。

出0入0汤圆

发表于 2012-4-21 16:02:56 | 显示全部楼层
应该是《浅入深出AVR》,看了看不懂。

出0入0汤圆

发表于 2012-4-21 16:13:19 | 显示全部楼层
俺用的是Tera Term。。

状态机,俺还只会简单的。。。。

出0入0汤圆

发表于 2012-4-21 16:21:53 | 显示全部楼层
看了大作后有种购买套件的欲望

出0入0汤圆

发表于 2012-4-23 10:51:56 | 显示全部楼层
拜读~~
用avr studio怎么打开工程,源文件找不到?

出50入0汤圆

发表于 2012-4-23 11:09:05 | 显示全部楼层
楼主的程序思路很有意思,抽时间的仔细研究一下。

出0入0汤圆

发表于 2012-4-23 11:11:43 | 显示全部楼层
这个一定要拜读!!

出0入0汤圆

发表于 2012-4-23 11:12:58 | 显示全部楼层
这不是傻孩子的头像吗?
不过论坛能像pudn那样贴代码,好爽。
头像被屏蔽

出0入0汤圆

发表于 2012-4-23 11:14:12 | 显示全部楼层
傻孩子果然出手不凡啊!

傻孩子还需要多少样片或其它的资源,随时找我。

出0入12汤圆

发表于 2012-4-23 11:14:33 | 显示全部楼层
学习....

出0入0汤圆

发表于 2012-4-23 11:48:19 | 显示全部楼层
看了一下代码,难道是C++吗?

出0入0汤圆

发表于 2012-4-23 12:41:55 | 显示全部楼层
偶居然看不懂了,好晕!

出0入0汤圆

发表于 2012-4-23 12:49:38 | 显示全部楼层
高手出手,就是不一样!

出0入131汤圆

发表于 2012-4-23 13:01:57 | 显示全部楼层
我觉得我单片机还没入门。。。

出0入618汤圆

发表于 2012-4-23 13:12:53 | 显示全部楼层
我在想这SF发展完善下去会不会把Arduino干翻?

出0入0汤圆

发表于 2012-4-23 13:47:23 | 显示全部楼层
帮顶个 事实上07年后面那个活儿就是用这种思想做的 维护方便啊~
但是如果客户老修改需求 这么个整法还是蛮痛苦的 要改动的东西不少

出0入296汤圆

 楼主| 发表于 2012-4-24 09:52:44 来自手机 | 显示全部楼层
gzhuli 发表于 2012-4-23 13:12
我在想这SF发展完善下去会不会把Arduino干翻?

先完善再说

出0入296汤圆

 楼主| 发表于 2012-4-24 09:53:52 来自手机 | 显示全部楼层
menghong_4 发表于 2012-4-23 10:51
拜读~~
用avr studio怎么打开工程,源文件找不到?

studio的bug手工加入文件看看?

出0入296汤圆

 楼主| 发表于 2012-4-24 09:54:40 来自手机 | 显示全部楼层
armok 发表于 2012-4-23 11:14
傻孩子果然出手不凡啊!

傻孩子还需要多少样片或其它的资源,随时找我。 ...

多谢老大支持~

出0入0汤圆

发表于 2012-4-24 10:15:22 | 显示全部楼层
我觉得 我要重新学习了。。。

出0入296汤圆

 楼主| 发表于 2012-4-24 10:16:35 来自手机 | 显示全部楼层
logicgreen 发表于 2012-4-21 16:02
应该是《浅入深出AVR》,看了看不懂。

呵呵,哪里看不懂?一般都是抱怨太水

出0入0汤圆

发表于 2012-4-24 18:10:52 | 显示全部楼层
还是第一次见人这么写c

出0入0汤圆

发表于 2012-4-24 21:43:54 | 显示全部楼层
水品还不行,慢慢研究

出0入0汤圆

发表于 2012-4-25 11:03:08 | 显示全部楼层
好!~学习软件框架,收藏了

出0入0汤圆

发表于 2012-4-25 11:25:37 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-5-8 18:56:17 | 显示全部楼层
要消化,有点吃力。

出0入296汤圆

 楼主| 发表于 2012-5-10 23:58:05 | 显示全部楼层
调度器的原理解析,看这个帖子的讨论,61楼
http://www.ourdev.cn/forum.php?m ... p;extra=#pid5812295

出0入296汤圆

 楼主| 发表于 2012-7-26 18:48:10 | 显示全部楼层
自己顶一下

出90入0汤圆

发表于 2012-7-26 20:01:54 | 显示全部楼层
帮大师顶一下

出10入18汤圆

发表于 2012-7-27 18:46:37 | 显示全部楼层
拜读大作,这个编程风格很有意思啊

出0入0汤圆

发表于 2012-9-3 09:34:39 | 显示全部楼层
学习大师的作品

出0入0汤圆

发表于 2012-9-18 04:05:09 来自手机 | 显示全部楼层
激动,回来用putty试试

出0入0汤圆

发表于 2012-9-20 19:42:40 | 显示全部楼层
观望楼主,很强大,但是我不会用!!

出0入4汤圆

发表于 2012-11-9 00:28:38 | 显示全部楼层
非常喜欢傻孩子的状态机,哈哈。很喜欢

出0入4汤圆

发表于 2012-11-9 09:07:25 | 显示全部楼层
/*
ew 深入浅出AVR 伏案编写中...全新DEMO圣诞节火热出炉
>> 追加全新第四篇
a. 裸机多任务入门 b. 工程构架从零搭建 c. 模块封装全实践 d. 近二十个状态机实验 e. 菜单技术面面观  f. 高级串行通信技术
*/
圣诞节出炉吗?听着章节的名字都很期待呀

出0入4汤圆

发表于 2012-11-9 09:12:26 | 显示全部楼层
Gorgon_Meducer 发表于 2012-4-21 10:05
正在修订深入浅出AVR,准备出第二版。主要是把口水去掉,加入状态机入门训练,改用gcc…… ...

我还会再买一本的,只是这本书发现的有点晚,现在还没有拜读完。非常好,讲一般书籍不讲的知识。

出0入296汤圆

 楼主| 发表于 2012-11-9 09:56:04 | 显示全部楼层
cumt_123456 发表于 2012-11-9 00:28
非常喜欢傻孩子的状态机,哈哈。很喜欢

这个状态机引擎最近一直在更新,请关注这个帖子
http://www.amobbs.com/thread-4319119-1-1.html

B.T.W 头像是你女朋友么?

出0入4汤圆

发表于 2012-11-9 20:36:07 | 显示全部楼层
本帖最后由 cumt_123456 于 2012-11-9 20:37 编辑
Gorgon_Meducer 发表于 2012-11-9 09:56
这个状态机引擎最近一直在更新,请关注这个帖子
http://www.amobbs.com/thread-4319119-1-1.html


这都被你看出来了,哈哈。

小心我注册个账号,用你的头像。嘿嘿。

不过很多我真的看不懂,很是着急。

出0入296汤圆

 楼主| 发表于 2012-11-9 21:34:40 | 显示全部楼层
cumt_123456 发表于 2012-11-9 20:36
这都被你看出来了,哈哈。

小心我注册个账号,用你的头像。嘿嘿。

着急没必要吧?有啥问题具体问我啊。

出0入4汤圆

发表于 2012-11-9 22:20:43 | 显示全部楼层
嗯,谢谢,一定会的。好多看不懂的,多看N遍就解决了。

出0入0汤圆

发表于 2012-11-12 16:31:27 | 显示全部楼层
是十八层地狱,还是九层天堂

出0入296汤圆

 楼主| 发表于 2012-11-13 10:01:22 | 显示全部楼层
cumtcmeeczm 发表于 2012-11-12 16:31
是十八层地狱,还是九层天堂

取决于你现在在哪里。

出0入0汤圆

发表于 2012-11-13 19:22:33 | 显示全部楼层
怎么打开啊,avr studio吗,找不到文件?!!!

出0入296汤圆

 楼主| 发表于 2012-11-13 23:44:41 | 显示全部楼层
cumtcmeeczm 发表于 2012-11-13 19:22
怎么打开啊,avr studio吗,找不到文件?!!!

Avr studio4的工程管理器用的是绝对路径,所以会找不到文件。这不影响编译的。你也可以手工重新指定文件位置。

出0入0汤圆

发表于 2013-2-28 18:39:01 | 显示全部楼层
为实时嵌入式系统提供轻量级的,基于状态机的应用程序框架。

出0入0汤圆

发表于 2013-3-10 17:24:59 | 显示全部楼层
Gorgon_Meducer 发表于 2012-11-13 23:44
Avr studio4的工程管理器用的是绝对路径,所以会找不到文件。这不影响编译的。你也可以手工重新指定文件 ...

有详细点的文档没?最新的版本哪儿有下呀?3x!

出0入296汤圆

 楼主| 发表于 2013-3-10 21:30:45 | 显示全部楼层
celticzy 发表于 2013-3-10 17:24
有详细点的文档没?最新的版本哪儿有下呀?3x!

在我专栏里面。ESSF 3.x的那个帖子。

出0入0汤圆

发表于 2013-3-13 11:25:08 | 显示全部楼层
本帖最后由 NIC 于 2013-3-13 11:32 编辑
Gorgon_Meducer 发表于 2013-3-10 21:30
在我专栏里面。ESSF 3.x的那个帖子。


傻孩子,又要请教你了,哈,我大概看了一下你这个程序,有以下几点不清楚。

你说了这个状态机没有调度器同样可以用,那加了调度器与不加有哪些不同或好处?

这个程序就是在一直在循环中执行两个任务,好象事件触发这块没有,也没看到register_event()这个函数在哪被调用?

如果通过模拟IIC或SPI连续读写外部存储数据的执行时间过长,如擦除一片Flash扇区需要几十ms、需要一次写入的数据量过大,是否
也要将读写函数写成状态机模式?

SAFE_TASK_QUEUE_POOL_SIZE这个宏定义>1的时候是不是表示存在多个Ready任务队列,这部分看得有点头晕,有什么用处?

出0入296汤圆

 楼主| 发表于 2013-3-13 18:12:33 | 显示全部楼层
NIC 发表于 2013-3-13 11:25
傻孩子,又要请教你了,哈,我大概看了一下你这个程序,有以下几点不清楚。

你说了这个状态机没有调度器 ...

你能在正确的帖子里问问题么?否则都不知道你说哪个。LGT这个版本我已经没更新了。
要看我板块里面的。另外,你对EVENT理解太字面了。状态机状态迁移本身就是事件驱
动的。我在调度器里提供了互斥,临界区,事件和普通信号量,它们都可以实现事件驱动

出0入0汤圆

发表于 2013-3-13 23:48:21 | 显示全部楼层
本帖最后由 NIC 于 2013-3-14 11:15 编辑
Gorgon_Meducer 发表于 2013-3-13 18:12
你能在正确的帖子里问问题么?否则都不知道你说哪个。LGT这个版本我已经没更新了。
要看我板块里面的。另 ...


我本来说的就是这个贴,ESSF 3.x那个帖的程序我也大致看过,基本的东西是差不多的,但我还是有几个问题

相比于单纯的状态机,有哪些好处和优点?加了调度器有一个不好的地方就是每执行一次任务或一个状态转换都需要重新注册任务
我觉的你之前的下面这个调度方式不是效率更高吗,不用反复做注册任务操作

void Process_Task(void)
{
    static uint8_t n = 0;
   
    if (s_ProcPCB[n].State == PROC_READY)                  //处理进程
    {
        PROC_STATE State = s_ProcPCB[n].fnProcess(&s_ProcPCB[n]);
        if (PROC_NULL != s_ProcPCB[n].State)
        {
            SAFE_CODE_PERFORMANCE
            (
                s_ProcPCB[n].State = State;
            )
        }
    }        
   
    n ++;
    if (n >= UBOUND(s_ProcPCB))
    {
        n = 0;
        #if 0
        g_cScheduleTest = MIN(g_cScheduleTest + 1,254);
        #endif
    }



SAFE_TASK_QUEUE_POOL_SIZE这个宏定义>1的时候是不是表示存在多个Ready任务队列,这个什么情况下用的?

如果通过模拟IIC或SPI连续读写外部存储数据的执行时间过长,如擦除一片Flash扇区需要几十ms、需要一次写入的数据量过大,是否
也要将读写函数写成状态机模式?

出0入296汤圆

 楼主| 发表于 2013-3-15 03:07:15 | 显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-3-15 03:10 编辑
NIC 发表于 2013-3-13 23:48
我本来说的就是这个贴,ESSF 3.x那个帖的程序我也大致看过,基本的东西是差不多的,但我还是有几个问题

...


兄弟,让你好好看看ESSF 3.x,你不听,问得问题就直接反应出来了:


相比于单纯的状态机,有哪些好处和优点?加了调度器有一个不好的地方就是每执行一次任务或一个状态转换都需要重新注册任务
我觉的你之前的下面这个调度方式不是效率更高吗,不用反复做注册任务操作


答:重新注册是为了方便讲解模型,实际并不重新注册,你要实际看代码。所以不存在你说的这个问题。
    另外,推荐你先看这个帖子http://www.amobbs.com/thread-5507175-1-1.html
    理解了以后再看这个帖子http://www.amobbs.com/thread-5509424-1-1.html




SAFE_TASK_QUEUE_POOL_SIZE这个宏定义>1的时候是不是表示存在多个Ready任务队列,这个什么情况下用的?

答:乱序执行,反“汇编跟踪”用的。




如果通过模拟IIC或SPI连续读写外部存储数据的执行时间过长,如擦除一片Flash扇区需要几十ms、需要一次写入的数据量过大,是否
也要将读写函数写成状态机模式?

答:如果这段时间还要允许别的任务执行,则状态机是必须的。对FLASH写入来说,写FLASH的时候通常不允许其它任务执行,所以
不需要状态机——反之则需要。对通信来说,SPI一般速度较快(需要具体评估)也不需要。IIC通常都要用状态机。

出0入0汤圆

发表于 2013-4-9 14:37:28 | 显示全部楼层
看不懂啊。

出0入0汤圆

发表于 2013-4-20 09:16:49 | 显示全部楼层
牛啊!!!

出0入0汤圆

发表于 2013-5-9 17:08:32 | 显示全部楼层
高手都来助阵了?

出0入0汤圆

发表于 2013-5-18 17:43:03 | 显示全部楼层
不太喜欢楼主的状态机模板。:)没有冒犯之意
我目前找到的最直观的模板是这个:http://ehiti.de/machine_objects/  不过用的是C++的。内部实现好像用了动态内存分配,所以状态之间的切换时性能可能会受影响。
这个也不错的,http://www.codeproject.com/Artic ... e-State-Machine-FSM
boost库里也有FSM的实现,不过我没有仔细研究过。

出0入296汤圆

 楼主| 发表于 2013-5-19 00:36:45 | 显示全部楼层
Pony279 发表于 2013-5-18 17:43
不太喜欢楼主的状态机模板。:)没有冒犯之意
我目前找到的最直观的模板是这个:http://ehiti.de/machine_o ...

我也没有草木皆兵的小气,放出来就是期待有交流的,如果你能说说不喜欢的原因,我想对我更有帮助——你知道,
有时候你告诉别人你的东西不招人喜欢,然后又不说原因,会急死人的……特别是对我这种有追求接近完美的情节的
人。

出0入0汤圆

发表于 2014-3-24 17:28:27 | 显示全部楼层
一直想入手LGT,期待兼容mega16的片子哦!标记,LGT程序框架。

出0入0汤圆

发表于 2014-3-24 18:44:12 | 显示全部楼层
楼主辛苦了

出0入0汤圆

发表于 2014-3-24 18:44:27 | 显示全部楼层
楼主辛苦了

出0入0汤圆

发表于 2014-10-16 19:33:50 | 显示全部楼层
好像很霸气的!虽然没弄懂,但还是要回帖
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 06:38

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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