[模板][下载]LGT开发板测评 内附全状态机快速开发模板
本帖最后由 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。static bool s_bBusyFlag = false;
/******************************************************************************
* DEMO APPLICATION: Ping Pang Demo *
******************************************************************************/
static uint8_t s_chByte;
STATIC_FSM(Ping_Pang_Demo)
PRIVATE STATE(Ping_Pang_Demo_Start);
PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag);
PRIVATE STATE(Ping_Pang_Demo_Output);
END_FSM
PRIVATE STATE(Ping_Pang_Demo_Start) BEGIN
//! receive new byte
if (SERIAL_IN(&s_chByte)) {
//! got one, then tranfer to output state;
TRANSFER_TO_STATE(Ping_Pang_Demo_Wait_Busy_Flag);
//! exit current state;
EXIT_STATE;
}
//! keep current state
REFLEXIVE_STATE;
END
PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag) BEGIN
if (!s_bBusyFlag) {
//! free, then set the flag
s_bBusyFlag = true;
TRANSFER_TO_STATE(Ping_Pang_Demo_Output);
//! exit current state;
EXIT_STATE;
}
//! keep current state
REFLEXIVE_STATE;
END
PRIVATE STATE(Ping_Pang_Demo_Output) BEGIN
//! output received byte
if (SERIAL_OUT(s_chByte)) {
//! success, then transfer to start state
TRANSFER_TO_STATE(Ping_Pang_Demo_Start);
//! clear busy flag
s_bBusyFlag = false;
//! exit current state
EXIT_STATE;
}
//! keep current state;
REFLEXIVE_STATE;
END
/******************************************************************************
* DEMO APPLICATION: Hello world *
******************************************************************************/
DEF_ARG(ArgStream)
uint8_t *pchSrc;
uint8_t chLength;
END_DEF_ARG
/*! \brief sub state machine
*/
STATIC_FSM(Stream_Output)
PRIVATE STATE(Stream_Out_Start);
PRIVATE STATE(Stream_Out_Byte_Output);
END_FSM
PRIVATE STATE(Stream_Out_Start) BEGIN
//! check argument
if (!CHECK_ARG(ArgStream)) {
//! illegal, just exit sub state machine
EXIT_STATE;
}
if ( (NULL == REF_ARG(ArgStream).pchSrc)
||(0 == REF_ARG(ArgStream).chLength)) {
//! complete
EXIT_STATE;
}
TRANSFER_TO_STATE(Stream_Out_Byte_Output);
EXIT_STATE;
END
PRIVATE STATE(Stream_Out_Byte_Output) BEGIN
uint8_t chByte;
//! check argument
if (!CHECK_ARG(ArgStream)) {
//! illegal, just exit sub state machine
EXIT_STATE;
}
chByte = *(REF_ARG(ArgStream).pchSrc);
//! output received byte
if (SERIAL_OUT(chByte)) {
REF_ARG(ArgStream).pchSrc++;
REF_ARG(ArgStream).chLength--;
//! success, then transfer to start state
TRANSFER_TO_STATE(Stream_Out_Start);
//! exit current state
EXIT_STATE;
}
//! keep current state;
REFLEXIVE_STATE;
END
//----------------------------------------------------------
//! \brief demo task
FSM(Hello_World,1)
PRIVATE STATE(HW_Start);
PRIVATE STATE(HW_Init_Delay);
PRIVATE STATE(HW_Delay);
END_FSM
uint32_t s_hwDelay = 0;
ARG(ArgStream) s_DemoArg = {0};
SAFE_TASK_ARG s_Arg = {0};
PRIVATE STATE(HW_Start) BEGIN
if (!s_bBusyFlag) {
//! free
s_bBusyFlag = true; //!< set busy flag
//! initialize argument
s_DemoArg.pchSrc = (uint8_t *)"Hello world!\r\n";
s_DemoArg.chLength = sizeof( "Hello world!\r\n");
s_Arg.pArg = &s_DemoArg;
s_Arg.hwLength = sizeof(s_DemoArg);
//! success, then transfer to start state
CALL_FSM_EX(
REF_STATE(Stream_Out_Start), &s_Arg, //!< sub-statemanchine
REF_STATE(HW_Init_Delay), pArg);//!< return statemachine
//! exit current state
EXIT_STATE;
}
REFLEXIVE_STATE;
END
PRIVATE STATE(HW_Init_Delay) BEGIN
//! release busy flag
s_bBusyFlag = false;
s_hwDelay = 20000;
TRANSFER_TO_STATE(HW_Delay);
EXIT_STATE;
END
PRIVATE STATE(HW_Delay) BEGIN
if (s_hwDelay) {
s_hwDelay --;
} else {
TRANSFER_TO_STATE(HW_Start);
EXIT_STATE;
}
REFLEXIVE_STATE;
END
static bool app_init(void)
{
bool bResult = true;
bResult &= NEW_STATIC_FSM( Ping_Pang_Demo, REF_STATE(Ping_Pang_Demo_Start));
bResult &= NEW_FSM( Hello_World, REF_STATE(HW_Start));
return bResult;
}
相关下载
恭喜楼主,但是,怎么用啊。。。 yaoyyie2003 发表于 2012-4-20 22:24 static/image/common/back.gif
恭喜楼主,但是,怎么用啊。。。
吃饭回去再说…… 本帖最后由 laign 于 2012-4-20 22:33 编辑
同问一个,,怎么用呢 laign 发表于 2012-4-20 22:32 static/image/common/back.gif
同问一个,,怎么用呢
build文件夹里面有工程文件 怎么不用printf? agnd 发表于 2012-4-20 23:04 static/image/common/back.gif
怎么不用printf?
之前的printf是block代码,如果波特率低,就会极大地浪费CPU 16M的优势…… 楼主辛苦了! 这个是源自ATMEL的framework?
回头我们也学习学习~ 本帖最后由 Gorgon_Meducer 于 2012-4-20 23:38 编辑
LGT 发表于 2012-4-20 23:18 static/image/common/back.gif
楼主辛苦了! 这个是源自ATMEL的framework?
回头我们也学习学习~
厄……我不认可这种说法。SF的做法是通行的标准,不是哪家专属的东西。不过没有SF很可能就是比较特殊的情形了……
一般认为SF会降低系统的效率,这种说法只在SF追求通用的前提下是成立的。
嵌入式系统本来就是专用系统,所以做一个通用的SF,这里的专用就和通用冲突了。只能说,在一定定义明确的范围内通用。
所以,要做SF,最好是针对几个明确的市场应用创建针对其应用场景高度优化的专用SF。
希望对你们有所帮助。 这个SF太霸气了,用C语言写出Pascal的语法和HDL的感觉了。 收藏。
也订了块LGT,到时移植IAR C++。 拜读傻孩子的大作。 傻孩子每次发的是大作,写的内容很详细,而且总能带领我们写代码的思维进入新的层次!
新手表示得好好向傻孩子学习! 唉,都怪俺水平太低了,全是E文的,看不下去了! 楼主,你那个签名是啥意思? 难道楼主又要出新书了? 置酷前顶一个 COOL ! gzhuli 发表于 2012-4-21 00:57 static/image/common/back.gif
这个SF太霸气了,用C语言写出Pascal的语法和HDL的感觉了。
哈哈~要的就是这种感觉~
如果只是普通的格式修改,我还不会这么嘚瑟,其实还有更多把戏在后面……真正做到非轮询的进程间阻塞、通讯、同步~我正在移植操作系统中进程通讯的部分,以求做到当线程逻辑上被阻塞时,对应的状态不会处于空转(轮询)状态。 lengshuicha 发表于 2012-4-21 08:38 static/image/common/back.gif
楼主,你那个签名是啥意思?
正在修订深入浅出AVR,准备出第二版。主要是把口水去掉,加入状态机入门训练,改用gcc…… 仁兄把编程也搞成富有艺术性,实在是苦中作乐啊。 本帖最后由 Gorgon_Meducer 于 2012-4-21 11:06 编辑
为了丰富例子,增加可读性,证明这个software framework不是离开了调度器就不能活了,
特此增加一个不使用调度器实现同样功能的例子——当然是使用传统状态机结构。
特别说明
调度器是通过在顶层app_cfg.h中的配置宏来控制的
//! \name configure safe task service
//! @{
#define TASK_SCHEDULER DISABLED
#define SAFE_TASK_CALL_STACK ENABLED
#define SAFE_TASK_QUEUE_POOL_SIZE (1u) //!< task queue pool size
#define SAFE_TASK_POOL_SIZE (3u) //!< task pool size
#define TASK_EVENT DISABLED //!< enable task event system
#define TASK_EVENT_POOL_SIZE (4u) //!< event pool size
#define TASK_EVENT_EMBEDDED_SCANNER ENABLED //!< scan events in scheduler
//! @}
当TASK_SCHEDULER被设置为除ENABLED以外的任何值,就会关闭调度器,编译时不会生成任何
调度器相关的代码。特别说明下,SAFE_TASK_POOL_SIZE直接决定了调度器开启的时候,允许
同时处于活跃状态的状态机数目(不是状态机状态的数目,也不是状态机的数目,而是同时处于
活跃状态的状态机数目)
/***************************************************************************
* Copyright(C)2009-2012 by Gorgon Meducer<Embedded_zhuoran@hotmail.com> *
* *
* This program is free software; you can redistribute it and/or modify*
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 2 of the *
* License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA02111-1307, USA. *
***************************************************************************/
/*============================ INCLUDES ======================================*/
#include ".\app_cfg.h"
#include ".\es_framework\platform.h"
/*============================ MACROS ========================================*/
/*============================ MACROFIED FUNCTIONS ===========================*/
//! \brief macro for sending byte to serial port in none-block style
#define SERIAL_OUT(__BYTE) usart_serial_out_byte(&USART,(__BYTE))
//! \brief macro for receiving byte from serial port in none-block style
#define SERIAL_IN(__ADDR) usart_serial_in_byte(&USART,(__ADDR))
/*============================ TYPES =========================================*/
/*============================ GLOBAL VARIABLES ==============================*/
/*============================ LOCAL VARIABLES ===============================*/
/*============================ PROTOTYPES ====================================*/
static bool app_init(void);
static bool task_ping_pang(void);
static bool task_hello_world(void);
/*============================ IMPLEMENTATION ================================*/
/*! \note initialize system
*\param none
*\retval true system initialization succeeded.
*\retval false system initialization failed
*/
static bool system_init( void )
{
bool bResult = true;
/*! initialize platform */
bResult &= platform_init();
/*! add your application initialization here */
bResult &= app_init();
return bResult;
}
#if TASK_SCHEDULER == ENABLED
/*! \note system idle task
*! \param none
*! \return none
*/
static void idle_task( void )
{
#ifdef ON_BEFORE_SLEEP_EVENT
ON_BEFORE_SLEEP_EVENT
#endif
//! try to enter a max allowed sleep mode
try_to_sleep();
#ifdef ON_AFTER_SLEEP_EVENT
ON_AFTER_SLEEP_EVENT
#endif
}
#endif
/*! \note main function
*\param none
*\return none
*/
#if __IS_COMPILER_IAR__
__task void main( void )
#elif __IS_COMPILER_GCC__
int main( void )
#endif
{
/* initialize whole system */
system_init();
while(true) { //!< super loop
#ifdef INSERT_SUPPER_LOOP
INSERT_SUPPER_LOOP
#endif
#if TASK_SCHEDULER == ENABLED
if (!scheduler()) { //!< scheduler
idle_task(); //!< idle state
}
#endif
task_ping_pang(); //!< task 1
task_hello_world(); //!< task 2
}
#if __IS_COMPILER_GCC__
return 0;
#endif
}
static bool s_bBusyFlag = false;
/******************************************************************************
* DEMO APPLICATION: Ping Pang Demo *
******************************************************************************/
/*
static uint8_t s_chByte;
STATIC_FSM(Ping_Pang_Demo)
PRIVATE STATE(Ping_Pang_Demo_Start);
PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag);
PRIVATE STATE(Ping_Pang_Demo_Output);
END_FSM
PRIVATE STATE(Ping_Pang_Demo_Start) BEGIN
//! receive new byte
if (SERIAL_IN(&s_chByte)) {
//! got one, then tranfer to output state;
TRANSFER_TO_STATE(Ping_Pang_Demo_Wait_Busy_Flag);
//! exit current state;
EXIT_STATE;
}
//! keep current state
REFLEXIVE_STATE;
END
PRIVATE STATE(Ping_Pang_Demo_Wait_Busy_Flag) BEGIN
if (!s_bBusyFlag) {
//! free, then set the flag
s_bBusyFlag = true;
TRANSFER_TO_STATE(Ping_Pang_Demo_Output);
//! exit current state;
EXIT_STATE;
}
//! keep current state
REFLEXIVE_STATE;
END
PRIVATE STATE(Ping_Pang_Demo_Output) BEGIN
//! output received byte
if (SERIAL_OUT(s_chByte)) {
//! success, then transfer to start state
TRANSFER_TO_STATE(Ping_Pang_Demo_Start);
//! clear busy flag
s_bBusyFlag = false;
//! exit current state
EXIT_STATE;
}
//! keep current state;
REFLEXIVE_STATE;
END
*/
#define PING_PANG_START 0
#define PING_PANG_WAIT_BUSY_FLAG 1
#define PING_PANG_OUTPUT 2
static bool task_ping_pang(void)
{
static uint8_t s_chState = 0;
static uint8_t s_chByte;
switch(s_chState) {
case PING_PANG_START:
if (SERIAL_IN(&s_chByte)) {
s_chState = PING_PANG_WAIT_BUSY_FLAG;
}
break;
case PING_PANG_WAIT_BUSY_FLAG:
if (!s_bBusyFlag) {
s_bBusyFlag = true;
s_chState = PING_PANG_OUTPUT;
}
break;
case PING_PANG_OUTPUT:
if (SERIAL_OUT(s_chByte)) {
s_bBusyFlag = false;
s_chState = PING_PANG_START;
}
break;
}
return true;
}
/******************************************************************************
* DEMO APPLICATION: Hello world *
******************************************************************************/
/*
DEF_ARG(ArgStream)
uint8_t *pchSrc;
uint8_t chLength;
END_DEF_ARG
//! \brief sub state machine
STATIC_FSM(Stream_Output)
PRIVATE STATE(Stream_Out_Start);
PRIVATE STATE(Stream_Out_Byte_Output);
END_FSM
PRIVATE STATE(Stream_Out_Start) BEGIN
//! check argument
if (!CHECK_ARG(ArgStream)) {
//! illegal, just exit sub state machine
EXIT_STATE;
}
if ( (NULL == REF_ARG(ArgStream).pchSrc)
||(0 == REF_ARG(ArgStream).chLength)) {
//! complete
EXIT_STATE;
}
TRANSFER_TO_STATE(Stream_Out_Byte_Output);
EXIT_STATE;
END
PRIVATE STATE(Stream_Out_Byte_Output) BEGIN
uint8_t chByte;
//! check argument
if (!CHECK_ARG(ArgStream)) {
//! illegal, just exit sub state machine
EXIT_STATE;
}
chByte = *(REF_ARG(ArgStream).pchSrc);
//! output received byte
if (SERIAL_OUT(chByte)) {
REF_ARG(ArgStream).pchSrc++;
REF_ARG(ArgStream).chLength--;
//! success, then transfer to start state
TRANSFER_TO_STATE(Stream_Out_Start);
//! exit current state
EXIT_STATE;
}
//! keep current state;
REFLEXIVE_STATE;
END
*/
#define STREAM_OUT_START 0
#define STREAM_OUT_BYTE_OUTPUT 1
static bool stream_out(uint8_t *pchStream, uint8_t chLength)
{
static uint8_t s_chState = 0;
static uint8_t s_chLength;
static uint8_t *s_pchSrc;
if (STREAM_OUT_START == s_chState) {
s_pchSrc = pchStream;
s_chLength = chLength;
s_chState = STREAM_OUT_BYTE_OUTPUT;
} else if (STREAM_OUT_BYTE_OUTPUT == s_chState) {
if ((0 == s_chLength) || (NULL == s_pchSrc)) {
s_chState = STREAM_OUT_START;
return false;
}
if (SERIAL_OUT(*s_pchSrc)) {
s_pchSrc++;
s_chLength--;
}
}
return true;
}
//----------------------------------------------------------
//! \brief demo task
/*
FSM(Hello_World,1)
PRIVATE STATE(HW_Start);
PRIVATE STATE(HW_Init_Delay);
PRIVATE STATE(HW_Delay);
END_FSM
uint32_t s_hwDelay = 0;
ARG(ArgStream) s_DemoArg = {0};
SAFE_TASK_ARG s_Arg = {0};
PRIVATE STATE(HW_Start) BEGIN
if (!s_bBusyFlag) {
//! free
s_bBusyFlag = true; //!< set busy flag
//! initialize argument
s_DemoArg.pchSrc = (uint8_t *)"Hello world!\r\n";
s_DemoArg.chLength = sizeof( "Hello world!\r\n");
s_Arg.pArg = &s_DemoArg;
s_Arg.hwLength = sizeof(s_DemoArg);
//! success, then transfer to start state
CALL_FSM_EX(
REF_STATE(Stream_Out_Start), &s_Arg, //!< sub-statemanchine
REF_STATE(HW_Init_Delay), pArg);//!< return statemachine
//! exit current state
EXIT_STATE;
}
REFLEXIVE_STATE;
END
PRIVATE STATE(HW_Init_Delay) BEGIN
//! release busy flag
s_bBusyFlag = false;
s_hwDelay = 20000;
TRANSFER_TO_STATE(HW_Delay);
EXIT_STATE;
END
PRIVATE STATE(HW_Delay) BEGIN
if (s_hwDelay) {
s_hwDelay --;
} else {
TRANSFER_TO_STATE(HW_Start);
EXIT_STATE;
}
REFLEXIVE_STATE;
END
*/
#define STREAM_OUT(__STR) stream_out((__STR),sizeof(__STR))
#define HW_START 0
#define HW_PRINT_STR 1
#define HW_DELAY 2
static bool task_hello_world(void)
{
static uint8_t s_tState = 0;
static uint32_t s_wDelay;
switch (s_tState) {
case HW_START:
if (!s_bBusyFlag) {
s_bBusyFlag = true;
s_tState = HW_PRINT_STR;
}
break;
case HW_PRINT_STR:
if (!STREAM_OUT("Hello world!\r\n")) {
//! return false means complete
s_bBusyFlag = false;
s_wDelay = 20000;
s_tState = HW_DELAY;
}
break;
case HW_DELAY:
if (s_wDelay) {
s_wDelay--;
} else {
s_tState = HW_START;
}
break;
}
return true;
}
static bool app_init(void)
{
bool bResult = true;
//bResult &= NEW_STATIC_FSM( Ping_Pang_Demo, REF_STATE(Ping_Pang_Demo_Start));
//bResult &= NEW_FSM( Hello_World, REF_STATE(HW_Start));
return bResult;
}
/* EOF */
本帖最后由 uc_c++ 于 2012-4-21 10:58 编辑
状态机编程非常实用。
现在写程序,基本上就是状态机来,状态机去。
学习了,谢谢 LZ能发你用的超级终端给我吗?一直苦于在WIN7下找不到好用的超级终端 学无止境啊。 这个强,学习了{:loveliness:} ghostxdy 发表于 2012-4-21 12:02
LZ能发你用的超级终端给我吗?一直苦于在WIN7下找不到好用的超级终端
就是从xp里面弄出来的 傻孩子,你的《深入浅出AVR》改成《深入浅出LGT》得了。 ghostxdy 发表于 2012-4-21 12:02 static/image/common/back.gif
LZ能发你用的超级终端给我吗?一直苦于在WIN7下找不到好用的超级终端
PuTTY好使。 应该是《浅入深出AVR》,看了看不懂。 俺用的是Tera Term。。
状态机,俺还只会简单的。。。。
看了大作后有种购买套件的欲望 拜读~~
用avr studio怎么打开工程,源文件找不到? 楼主的程序思路很有意思,抽时间的仔细研究一下。 这个一定要拜读!! 这不是傻孩子的头像吗?
不过论坛能像pudn那样贴代码,好爽。 傻孩子果然出手不凡啊!
傻孩子还需要多少样片或其它的资源,随时找我。 学习.... 看了一下代码,难道是C++吗?{:sad:} 偶居然看不懂了,好晕! 高手出手,就是不一样! 我觉得我单片机还没入门。。。 我在想这SF发展完善下去会不会把Arduino干翻? 帮顶个 事实上07年后面那个活儿就是用这种思想做的 维护方便啊~
但是如果客户老修改需求 这么个整法还是蛮痛苦的 要改动的东西不少 gzhuli 发表于 2012-4-23 13:12
我在想这SF发展完善下去会不会把Arduino干翻?
先完善再说 menghong_4 发表于 2012-4-23 10:51
拜读~~
用avr studio怎么打开工程,源文件找不到?
studio的bug手工加入文件看看? armok 发表于 2012-4-23 11:14
傻孩子果然出手不凡啊!
傻孩子还需要多少样片或其它的资源,随时找我。 ...
多谢老大支持~ 我觉得 我要重新学习了。。。 logicgreen 发表于 2012-4-21 16:02
应该是《浅入深出AVR》,看了看不懂。
呵呵,哪里看不懂?一般都是抱怨太水 还是第一次见人这么写c 水品还不行,慢慢研究{:sweat:} 好!~学习软件框架,收藏了 谢谢分享 要消化,有点吃力。 调度器的原理解析,看这个帖子的讨论,61楼
http://www.ourdev.cn/forum.php?mod=viewthread&tid=5468237&page=2&extra=#pid5812295 自己顶一下 帮大师顶一下{:lol:} 拜读大作,这个编程风格很有意思啊 学习大师的作品 激动,回来用putty试试 观望楼主,很强大,但是我不会用!! 非常喜欢傻孩子的状态机,哈哈。很喜欢 /*
ew 深入浅出AVR 伏案编写中...全新DEMO圣诞节火热出炉
>> 追加全新第四篇
a. 裸机多任务入门 b. 工程构架从零搭建 c. 模块封装全实践 d. 近二十个状态机实验 e. 菜单技术面面观f. 高级串行通信技术
*/
圣诞节出炉吗?听着章节的名字都很期待呀 Gorgon_Meducer 发表于 2012-4-21 10:05 static/image/common/back.gif
正在修订深入浅出AVR,准备出第二版。主要是把口水去掉,加入状态机入门训练,改用gcc…… ...
我还会再买一本的,只是这本书发现的有点晚,现在还没有拜读完。非常好,讲一般书籍不讲的知识。 cumt_123456 发表于 2012-11-9 00:28 static/image/common/back.gif
非常喜欢傻孩子的状态机,哈哈。很喜欢
这个状态机引擎最近一直在更新,请关注这个帖子
http://www.amobbs.com/thread-4319119-1-1.html
B.T.W 头像是你女朋友么?{:lol:} 本帖最后由 cumt_123456 于 2012-11-9 20:37 编辑
Gorgon_Meducer 发表于 2012-11-9 09:56 static/image/common/back.gif
这个状态机引擎最近一直在更新,请关注这个帖子
http://www.amobbs.com/thread-4319119-1-1.html
{:lol:} 这都被你看出来了,哈哈。
小心我注册个账号,用你的头像。嘿嘿。
不过很多我真的看不懂,很是着急。 cumt_123456 发表于 2012-11-9 20:36 static/image/common/back.gif
这都被你看出来了,哈哈。
小心我注册个账号,用你的头像。嘿嘿。
着急没必要吧?有啥问题具体问我啊。 嗯,谢谢,一定会的。好多看不懂的,多看N遍就解决了。 是十八层地狱,还是九层天堂 cumtcmeeczm 发表于 2012-11-12 16:31 static/image/common/back.gif
是十八层地狱,还是九层天堂
取决于你现在在哪里。 怎么打开啊,avr studio吗,找不到文件?!!! cumtcmeeczm 发表于 2012-11-13 19:22 static/image/common/back.gif
怎么打开啊,avr studio吗,找不到文件?!!!
Avr studio4的工程管理器用的是绝对路径,所以会找不到文件。这不影响编译的。你也可以手工重新指定文件位置。 为实时嵌入式系统提供轻量级的,基于状态机的应用程序框架。 Gorgon_Meducer 发表于 2012-11-13 23:44 static/image/common/back.gif
Avr studio4的工程管理器用的是绝对路径,所以会找不到文件。这不影响编译的。你也可以手工重新指定文件 ...
有详细点的文档没?最新的版本哪儿有下呀?3x! celticzy 发表于 2013-3-10 17:24 static/image/common/back.gif
有详细点的文档没?最新的版本哪儿有下呀?3x!
在我专栏里面。ESSF 3.x的那个帖子。 本帖最后由 NIC 于 2013-3-13 11:32 编辑
Gorgon_Meducer 发表于 2013-3-10 21:30 static/image/common/back.gif
在我专栏里面。ESSF 3.x的那个帖子。
傻孩子,又要请教你了,哈,我大概看了一下你这个程序,有以下几点不清楚。
你说了这个状态机没有调度器同样可以用,那加了调度器与不加有哪些不同或好处?
这个程序就是在一直在循环中执行两个任务,好象事件触发这块没有,也没看到register_event()这个函数在哪被调用?
如果通过模拟IIC或SPI连续读写外部存储数据的执行时间过长,如擦除一片Flash扇区需要几十ms、需要一次写入的数据量过大,是否
也要将读写函数写成状态机模式?
SAFE_TASK_QUEUE_POOL_SIZE这个宏定义>1的时候是不是表示存在多个Ready任务队列,这部分看得有点头晕,有什么用处? NIC 发表于 2013-3-13 11:25 static/image/common/back.gif
傻孩子,又要请教你了,哈,我大概看了一下你这个程序,有以下几点不清楚。
你说了这个状态机没有调度器 ...
你能在正确的帖子里问问题么?否则都不知道你说哪个。LGT这个版本我已经没更新了。
要看我板块里面的。另外,你对EVENT理解太字面了。状态机状态迁移本身就是事件驱
动的。我在调度器里提供了互斥,临界区,事件和普通信号量,它们都可以实现事件驱动 本帖最后由 NIC 于 2013-3-14 11:15 编辑
Gorgon_Meducer 发表于 2013-3-13 18:12 static/image/common/back.gif
你能在正确的帖子里问问题么?否则都不知道你说哪个。LGT这个版本我已经没更新了。
要看我板块里面的。另 ...
我本来说的就是这个贴,ESSF 3.x那个帖的程序我也大致看过,基本的东西是差不多的,但我还是有几个问题
相比于单纯的状态机,有哪些好处和优点?加了调度器有一个不好的地方就是每执行一次任务或一个状态转换都需要重新注册任务
我觉的你之前的下面这个调度方式不是效率更高吗,不用反复做注册任务操作
void Process_Task(void)
{
static uint8_t n = 0;
if (s_ProcPCB.State == PROC_READY) //处理进程
{
PROC_STATE State = s_ProcPCB.fnProcess(&s_ProcPCB);
if (PROC_NULL != s_ProcPCB.State)
{
SAFE_CODE_PERFORMANCE
(
s_ProcPCB.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、需要一次写入的数据量过大,是否
也要将读写函数写成状态机模式?
本帖最后由 Gorgon_Meducer 于 2013-3-15 03:10 编辑
NIC 发表于 2013-3-13 23:48 static/image/common/back.gif
我本来说的就是这个贴,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通常都要用状态机。
看不懂啊。 牛啊!!! 高手都来助阵了? 不太喜欢楼主的状态机模板。:)没有冒犯之意
我目前找到的最直观的模板是这个:http://ehiti.de/machine_objects/不过用的是C++的。内部实现好像用了动态内存分配,所以状态之间的切换时性能可能会受影响。
这个也不错的,http://www.codeproject.com/Articles/406116/Generic-Finite-State-Machine-FSM
boost库里也有FSM的实现,不过我没有仔细研究过。 Pony279 发表于 2013-5-18 17:43 static/image/common/back.gif
不太喜欢楼主的状态机模板。:)没有冒犯之意
我目前找到的最直观的模板是这个:http://ehiti.de/machine_o ...
我也没有草木皆兵的小气,放出来就是期待有交流的,如果你能说说不喜欢的原因,我想对我更有帮助——你知道,
有时候你告诉别人你的东西不招人喜欢,然后又不说原因,会急死人的……特别是对我这种有追求接近完美的情节的
人。 一直想入手LGT,期待兼容mega16的片子哦!标记,LGT程序框架。 楼主辛苦了 楼主辛苦了 好像很霸气的!虽然没弄懂,但还是要回帖
页:
[1]