搜索
bottom↓
楼主: summarize

结合时间触发+消息+protothread思想+支持优先级的非抢占调度器

  [复制链接]

出0入0汤圆

发表于 2014-4-17 15:23:38 | 显示全部楼层
本帖最后由 nos002 于 2014-4-17 15:27 编辑

看看,真的由os的模样。

出0入0汤圆

发表于 2014-4-17 15:32:36 | 显示全部楼层
楼主真强!!!!

出0入0汤圆

发表于 2014-4-17 16:17:17 | 显示全部楼层
kinsno 发表于 2014-1-23 09:49
技术人员不说万一,我只是习惯性的一种怀疑自己,每一次打样,每一次产品,我都心惊胆颤,尤如初学者,哈哈,自 ...

好像都有点强迫症

出0入0汤圆

发表于 2014-4-17 20:30:49 | 显示全部楼层
mark,,,

出0入0汤圆

发表于 2014-4-22 17:53:18 | 显示全部楼层
请问lz,调度器的占有多大的内存,与ucos相比,我该如何选择?

出0入0汤圆

发表于 2014-4-22 18:11:40 | 显示全部楼层
lyricpoem0726 发表于 2014-4-22 17:53
请问lz,调度器的占有多大的内存,与ucos相比,我该如何选择?

这个东西是协作式的,跟uc/os的区别就是 即使最高优先级的任务也得等正在运行的任务运行完才能 运行,uc/os II只要高优先级一就绪立马抢占正在运行的任务(其实RT-THREAD也不错,还免费)
这个不能叫做操作系统,但是是51 AVR STM8之类小资源MCU的最好选择,消息推送是很不错的功能,你可以尝试下,最好将_LINE_改成uint16类型(如果任务函数超过255行)

出0入0汤圆

发表于 2014-4-23 11:24:05 | 显示全部楼层
rootxie 发表于 2014-4-22 18:11
这个东西是协作式的,跟uc/os的区别就是 即使最高优先级的任务也得等正在运行的任务运行完才能 运行,uc/ ...

请问rootxie 用过RTT吗 我现在刚在接触ucos 用不的不多

出0入0汤圆

发表于 2014-4-23 13:06:09 | 显示全部楼层
lyricpoem0726 发表于 2014-4-23 11:24
请问rootxie 用过RTT吗 我现在刚在接触ucos 用不的不多

用过,不过没用得很复杂,Lwip GUI还正在看,还在消化中。。。

出0入0汤圆

发表于 2014-4-23 23:50:30 | 显示全部楼层
mark,早点看到就好了,有用

出0入0汤圆

 楼主| 发表于 2014-4-28 20:55:23 | 显示全部楼层
summarize 发表于 2013-7-22 01:20
word文档复制过来格式有点不好阅读,大家还是看PDF比较舒服些。
同时如果可以,请版主帮忙更新到LZ位,方便 ...

鉴于C语言中建议尽量不使用"goto"语句,现将“SCHTaskSchedStart()”函数中的“goto”语句去掉,用"if else"逻辑来实现。同时将版本升级为V1.02


修改细节为将如下函数

  1. void SCHTaskSchedStart(void)
  2. {
  3. SCHED_SART:
  4.        
  5.   pCurTCB = pFirstTCB;                        //指向第一个创建的任务,之后按创建时的顺序执行下去

  6.   while (1)                                   //环形链表,可以一直循环下去
  7.   {
  8.     SCHTimeTick();                            //如果任务Tick满足条件,则将其置于可执行状态

  9.     if (SCH_TASK_RUN == pCurTCB->TimeCounter) //任务处于可执行状态
  10.     {
  11.       pCurTCB->TimeCounter = SCH_TASK_PEND;   //设置为挂起状态,保证任务只执行一次

  12.       pCurTCB->pTask();                       //执行当前任务控制块指向的任务

  13.       goto SCHED_SART;                        //每执行完一个任务,都重新查找一次可执行最高优先级任务
  14.     }

  15.     pCurTCB = pCurTCB->pNextTCB;              //指向下一个任务控制块,查找下个任务是否可执行
  16.   }
  17. }
复制代码


改为


  1. void SCHTaskSchedStart(void)
  2. {
  3.   pCurTCB = pFirstTCB;                        //指向第一个创建的任务,之后按创建时的顺序执行下去

  4.   while (1)                                   //环形链表,可以一直循环下去
  5.   {
  6.     SCHTimeTick();                            //如果任务Tick满足条件,则将其置于可执行状态

  7.     if (SCH_TASK_RUN == pCurTCB->TimeCounter) //任务处于可执行状态
  8.     {
  9.       pCurTCB->TimeCounter = SCH_TASK_PEND;   //设置为挂起状态,保证任务只执行一次

  10.       pCurTCB->pTask();                       //执行当前任务控制块指向的任务

  11.       pCurTCB = pFirstTCB;                    //每执行完一个任务,都回到起点重新查找一次可执行最高优先级任务
  12.     }
  13.     else
  14.     {
  15.             pCurTCB = pCurTCB->pNextTCB;            //指向下一个任务控制块,查找下个任务是否可执行
  16.     }
  17.   }
  18. }
复制代码

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-5-24 16:59:13 | 显示全部楼层
努力学习中!

出0入0汤圆

发表于 2014-6-10 10:02:21 | 显示全部楼层
楼主帮忙看下,改成keil 的工程编译不通过啊!

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-6-10 12:30:47 | 显示全部楼层
ppdd 发表于 2014-6-10 10:02
楼主帮忙看下,改成keil 的工程编译不通过啊!

我没有安装KEIL软件啊,很多年没有用过了
1.自己先弄一个正常的工程
2.添加调度器那3个文件进去,要求先编译通过
3.添加相应的时钟节拍和应用代码。

出0入0汤圆

发表于 2014-6-10 12:58:36 | 显示全部楼层
楼主的结构非常好用,十分感谢
已经用该结构做了好几个东西 以下是用STM8+MP2307DN(3R33主芯片) 做得数控电源

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-6-10 13:22:26 | 显示全部楼层
rootxie 发表于 2014-6-10 12:58
楼主的结构非常好用,十分感谢
已经用该结构做了好几个东西 以下是用STM8+MP2307DN(3R33主芯片) 做得数控电 ...

呵呵!看成数字电源了。

出0入0汤圆

发表于 2014-6-11 11:14:54 | 显示全部楼层
谢谢楼主!可以正常编译,但是有个警告!!我把ADC 部分屏蔽掉还是有!
*** WARNING L15: MULTIPLE CALL TO SEGMENT
    SEGMENT: ?PR?_SCHTASKQPOST?SCHEDULE
    CALLER1: ?PR?UART_R_IRQ?8051_IT
    CALLER2: ?C_C51STARTUP

出0入0汤圆

 楼主| 发表于 2014-6-11 11:21:29 | 显示全部楼层
ppdd 发表于 2014-6-11 11:14
谢谢楼主!可以正常编译,但是有个警告!!我把ADC 部分屏蔽掉还是有!
*** WARNING L15: MULTIPLE CALL TO ...

提示多处调用SCHTASKQPOST;一个是启动代码中,一个是串口中断中,没有关系的,本来设计就是为了支持多处调用。但你可以删除掉你的启动代码-->C_C51STARTUP(应该是新建工程时自动添加的)

出0入0汤圆

 楼主| 发表于 2014-6-11 11:28:55 | 显示全部楼层
ppdd 发表于 2014-6-11 11:14
谢谢楼主!可以正常编译,但是有个警告!!我把ADC 部分屏蔽掉还是有!
*** WARNING L15: MULTIPLE CALL TO ...

移植好之后,共享出来如何?这里正缺少KEIL的例程,让其他新手少走弯路。

出0入0汤圆

发表于 2014-6-11 13:32:15 | 显示全部楼层
正在努力!
我已经把启动文件删除了,工程里面,甚至keil安装目录里面,都删除了。 还是有警告!
现在P1.0在闪动,串口循环输出02 00 02  00。。。看来还没弄好。弄好了上传整个工程。

出0入0汤圆

发表于 2014-6-15 13:59:45 | 显示全部楼层
attach://199154.png
转移到keil,串口通讯成功,在调试的时候发现一点限制: 单次发送超过10byte,容易出错。(间隔100ms)(串口缓存为20)

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-15 14:13:56 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-15 14:51 编辑

上电后,第一帧数据,没有返回!
我也是纳闷了很久,自动ISP,老是不稳定,有时候行,有时候不行。
发现只要串口能在收到第二帧数据,能正常返回(通讯正常)后,自动ISP功能就正常了。



本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-6-15 17:04:04 | 显示全部楼层
ppdd 发表于 2014-6-15 14:13
上电后,第一帧数据,没有返回!
我也是纳闷了很久,自动ISP,老是不稳定,有时候行,有时候不行。
发现只 ...

1.先不用调度器,禅奔测试ISP稳定工作.

2.重新加入调度器,再测试.

出0入0汤圆

 楼主| 发表于 2014-6-15 18:05:20 | 显示全部楼层
rootxie 发表于 2014-4-17 13:19
楼主还在吗?这个东西挺有意思的,请教个问题

SCH_CURR_LINE                (SCH_UINT8)(__LINE__+(!__LINE__)) ...

这个根据自己的须要修改定义就行了

出0入0汤圆

发表于 2014-6-16 09:42:38 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-16 09:48 编辑
summarize 发表于 2014-6-15 17:04
1.先不用调度器,禅奔测试ISP稳定工作.

2.重新加入调度器,再测试.


首次下载不成功的问题找到了。
具体过程是这样的,在Keil项目选SST89C58, Small:variables in DATA, 编译不错误!
*** ERROR L118: REFERENCE MADE TO ERRONEOUS EXTERNAL
    SYMBOL:  PCURTCB
    MODULE:  .\uart_treatment.obj (UART_TREATMENT)
    ADDRESS: 0611H
*** ERROR L118: REFERENCE MADE TO ERRONEOUS EXTERNAL
    SYMBOL:  PCURTCB
    MODULE:  .\uart_treatment.obj (UART_TREATMENT)
    ADDRESS: 0613H
*** ERROR L118: REFERENCE MADE TO ERRONEOUS EXTERNAL
    SYMBOL:  G_U8SCHEDTICKSCNT
    MODULE:  .\8051_it.obj (8051_IT)
    ADDRESS: 0822H
Program Size: data=180.0 xdata=0 code=2085
Target not created
使用idata 关键字定义静态数组,问题得以解决!首次IAP下载成功不再报错!

  1. static idata uint8_t s_u8RxBuffer[UART_RX_BUF_SIZE];
  2. 。。。。
  3. static idata uint8_t s_u8TxBuffer[UART_TX_BUF_SIZE];
  4. 。。。
  5. istatic idata uint8_t s_u8IsrRxBuffer[UART_ISR_RX_BUF_SIZE];
复制代码


可以参考这篇文章:
http://blog.163.com/wk_technolog ... 359200992215136376/

编译正常如下:

  1. Build target 'C51-PT-thread'
  2. compiling main.c...
  3. compiling peripherals_init.c...
  4. compiling data_initial.c...
  5. compiling schedule.c...
  6. compiling uart_treatment.c...
  7. compiling 8051_it.c...
  8. linking...
  9. *** WARNING L15: MULTIPLE CALL TO SEGMENT
  10.     SEGMENT: ?PR?_SCHTASKQPOST?SCHEDULE
  11.     CALLER1: ?PR?UART_R_IRQ?8051_IT
  12.     CALLER2: ?C_C51STARTUP
  13. Program Size: data=180.0 xdata=0 code=2085
  14. creating hex file from "c51thread"...
  15. "c51thread" - 0 Error(s), 1 Warning(s).

复制代码

出0入0汤圆

发表于 2014-6-16 09:56:07 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-16 09:57 编辑

新问题! 发送10字节(11.22.33.44.55.66.77.88.99.aa),缓存调整为32,成功率不高,正常应该返回(22.33.44.55.66.77.88.99.AA.BB),第10数据时常会丢失!而且串口会失去相应!!



运作指示灯,正常!串口死掉!

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-16 10:03:41 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-16 10:05 编辑

循环发送9字节数据(11.22.33.44.55.66.77.88.aa)返回正常! 时间长了串口死掉! 有可能是USB转串口的原因,要找个232的串口来确认下!




工程文件:






本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-16 11:06:47 | 显示全部楼层
把usb转串口,和单片机部分分开供电; 稳定很多,数据可以正常收发:21186条。 但串口还是卡死了,重新复位usb转串口芯片,串口仍然没有反映,还得再看看程序。

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-6-16 12:24:55 | 显示全部楼层
ppdd 发表于 2014-6-16 11:06
把usb转串口,和单片机部分分开供电; 稳定很多,数据可以正常收发:21186条。 但串口还是卡死了,重新复位 ...

usb转串口的原因较大,可以把定时发送的时间改慢些,如改为500ms

出0入0汤圆

 楼主| 发表于 2014-6-16 12:29:03 | 显示全部楼层
ppdd 发表于 2014-6-16 09:42
首次下载不成功的问题找到了。
具体过程是这样的,在Keil项目选SST89C58, Small:variables in DATA, 编译 ...

谢谢分享你的经验!

出0入0汤圆

发表于 2014-6-17 16:10:34 | 显示全部楼层
连续发送,串口死掉的,问题初步找到!
在串口中断中屏蔽消息查询:
//if (SCHTaskGetQFree(&UartRxTcb) == SCH_Q_FREE)

发送10万次数据百万bit无错误(115200Bps)。具体为什么会这样,还不清楚!

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-17 16:19:38 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-17 16:24 编辑

楼主帮忙分析下!我该回9600再试试!

改成9600数据,丢失!

出0入0汤圆

发表于 2014-6-17 16:26:11 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-17 16:28 编辑

但是串口,不会再死掉啦!!
500ms循环发送,都会数据错误!!肯定是那里有问题! 我找不到,再找找。。。

出0入0汤圆

 楼主| 发表于 2014-6-17 16:58:28 | 显示全部楼层
本帖最后由 summarize 于 2014-6-17 17:17 编辑
ppdd 发表于 2014-6-17 16:10
连续发送,串口死掉的,问题初步找到!
在串口中断中屏蔽消息查询:
//if (SCHTaskGetQFree(&UartRxTcb)  ...


如果是用115200来发送,单片机在接收到数据后,再回发是要时间的,当来不及处理时,中断中的消息查询结果就为假,从而不回发(数据丢失),如果屏蔽则一定能回发(数据不一定对),但是串口接收处理任务中的消息池充当了缓冲区的角色,使得数据没有被覆盖,从而数据正确。

//补充---------------------
在115200这样高的速率下,发送也应该改为中断发送方式,才能及时发送出去,而且接收缓冲区也应该加大。

出0入0汤圆

 楼主| 发表于 2014-6-17 17:04:26 | 显示全部楼层
ppdd 发表于 2014-6-17 16:26
但是串口,不会再死掉啦!!
500ms循环发送,都会数据错误!!肯定是那里有问题! 我找不到,再找找。。。 ...

回发时没有用到中断发送,而是用延时+查询的方法,见下面的代码。用的是9600下的延时-->1ms,所以如果你用115200,这个延时时间一定没有问题。

                for (i = 0; i < u16DataSize; i++)
                {
                        if (SciaRegs.SCIFFTX.bit.TXFFST==0)//Transmit FIFO is empty?
                        {
                                SciaRegs.SCITXBUF = s_u16TxBuffer;
                        }

                        //延时发送1个字节所须要的时间                        *************************************************
                        SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);//实测在9600下1ms即可
                }

但是改回9600后,要注意看最后一个字节有没有完整发送出去。如果没有,则在最后多加一个1ms的延时试试,代码修改如下:

                for (i = 0; i < u16DataSize; i++)
                {
                        if (SciaRegs.SCIFFTX.bit.TXFFST==0)//Transmit FIFO is empty?
                        {
                                SciaRegs.SCITXBUF = s_u16TxBuffer;
                        }

                        //延时发送1个字节所须要的时间                        *************************************************
                        SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);//实测在9600下1ms即可
                }

                //增加一个延时---------------------------------------------------------------------------------
                SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);//实测在9600下1ms即可

出0入0汤圆

发表于 2014-6-17 17:53:34 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-17 17:57 编辑

是的,最后一个字节会丢失!

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-17 18:00:08 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-17 18:07 编辑

看来楼主也在修改代码,是用了,环形数组吗?
好像不行!!
按说9600BPS,20ms循环发送,应该能正常返回数据才对呀!
我看楼主的代码,接收用了双缓存! 测试数据协议(结束码0xAA),怎么就不能准确的返回数据呢?

出0入0汤圆

 楼主| 发表于 2014-6-17 20:07:26 | 显示全部楼层
ppdd 发表于 2014-6-17 18:00
看来楼主也在修改代码,是用了,环形数组吗?
好像不行!!
按说9600BPS,20ms循环发送,应该能正常返回数据 ...

我是给你修改代码然后测试的建议,因为你说的情况我在stm8s里没有出现,或者每个详细的项目工程不一样导致结果不一样,又或者51的单片机又不同。如果你帮忙测试出我给的例程有bug。当然非常感谢,不然我就误导了他人了。我随后再仔细看看代码,可能是在边界上有bug.

出0入0汤圆

 楼主| 发表于 2014-6-17 20:42:39 | 显示全部楼层
ppdd 发表于 2014-6-17 17:53
是的,最后一个字节会丢失!

不好意思,133,134楼误导了你,之前没有看你的代码(之前一直下载不了,今晚才发现是浏览器的问题,用google浏览器不行,用IE下载就OK),

自己直接按照目前在做的项目的思维来回复你了,上面贴的代码是DSP项目的,你可以直接忽略了。

51是不同的,51的串口收发都是通过中断来进行的。而且我发现你修改了“sch_cfg.h”文件,其中的:

#define SCH_SYS_TICKS_MS             10                 //定义调度系统时钟节拍时间(ms),无特殊情况不建议更改此项

修改成了:

#define SCH_SYS_TICKS_MS             1                 //定义调度系统时钟节拍时间(ms),无特殊情况不建议更改此项

这里会有问题的,51单片机的速度比较慢,我当时用STC89C52来测试,好像是如果设置为小于4ms就会异常,

但因为我知道是51速度慢造成的,就没有去深究原因;所以在我写的使用说明里,51单片机是建议设置为5ms或10ms以上的:

“第①个为定义调度系统时钟节拍时间,单位是ms,一般配置为1~10ms即可,对于执行速度快的单片机选如stm8s、avr等配置1ms,传统的51单片机速度慢的选5ms以上比较好,实在不懂就选个10ms吧。”


所以,建议你先将这个调度系统时间节拍配置改回去再测试吧。

出0入0汤圆

发表于 2014-6-17 22:22:13 | 显示全部楼层
这个程序风格,我是很喜欢的。 想调试好了作为自己以后写程序的模板使用! 之前用过汇编,C是自己瞎弄的,看了使用环形队列的感觉好像效率要高点,但C水平太差了,弄不了,而且用起来也有些限制,时时要想着维护指针链!
楼主的凤格真是我想要的,用缓存拷贝的方法共享串口!
我用的STC12C5A60S2 ,按照老姚的说法:1个时钟周期/机器周期、,也就是一条指令只要1/11.0592us≈0.1uS不到. 100uS的中断间隙足够跑好多指令了.
按照1ms的速度扫描任务,应该是够了!不够的时候还没遇到.

出0入0汤圆

发表于 2014-6-17 22:23:26 | 显示全部楼层
summarize 发表于 2014-6-17 20:07
我是给你修改代码然后测试的建议,因为你说的情况我在stm8s里没有出现,或者每个详细的项目工程不一样导 ...

是我弄错了. 按你说的增加了1ms延时,不再丢失最后一个字节数据了!

出0入0汤圆

 楼主| 发表于 2014-6-18 05:53:37 | 显示全部楼层
ppdd 发表于 2014-6-17 22:23
是我弄错了. 按你说的增加了1ms延时,不再丢失最后一个字节数据了!

谢谢你的测试并提供测试结果,我今天抽时间分析原因。

出0入0汤圆

 楼主| 发表于 2014-6-18 09:11:44 | 显示全部楼层
本帖最后由 summarize 于 2014-6-18 09:29 编辑
ppdd 发表于 2014-6-17 22:23
是我弄错了. 按你说的增加了1ms延时,不再丢失最后一个字节数据了!


关于例程中51单片机串口发送会丢失最后一个字节数据的原因分析:

其它单片机的串口发送用的是查询+延时的方式,代码如下

  1.     for (i = 0; i < u8DataSize; )
  2.     {
  3.       if(发送完成标志)
  4.       {
  5.         发送完成标志= 0;
  6.         RX_BUF = s_u8TxBuffer[i++];
  7.         SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);        //延时发送1个字节所须要的时间
  8.       }
  9.       else
  10.       {
  11.         SCHCurTaskDly(0 / SCH_SYS_TICKS_MS);        //无延时,下次直接进来查询
  12.       }
  13.     }
复制代码


即在每次给赋值给串口发送寄存器后,都会有相应字节发送的时间延时,如上面在9600波特率下的1ms延时,所以没有问题。

而51单片机的串口收发中断不能单独开关,所以开了串口接收中断,发送也跟着开了,所以其串口发送也是用中断方式,所以不用原来的查询+延时方式(注释掉),在中断中发送并对发送长度计数器自减,代码如下:

发送中断中:

  1.       SBUF = *pTxDataBuffer;
  2.       pTxDataBuffer++;
  3.       --UartTxTcb.Size;                //这里的长度减1时并没有延时,即在没有真正发送完成前可能会出现数据被覆盖,从而使得最后一个字节丢失。
复制代码


串口发送任务中:

//  for (i = 0; i < u8DataSize; )
//  {
//    if(SCON_bit.TI)
//    {
//      SCON_bit.TI = 0;
//                        SBUF = s_u8TxBuffer[i++];
//                        SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);        //延时发送1个字节所须要的时间
//    }
//    else
//    {
//      SCHCurTaskDly(0 / SCH_SYS_TICKS_MS);        //无延时,下次直接进来查询
//    }
//        }

        //增加的代码,查询是否发送完,如发送完则任务重新等消息。
    if (UartTxTcb.Size > 0) //等待发送完成
    {
      SCHCurTaskDly(10 / SCH_SYS_TICKS_MS);        //未完成,延时10ms再查询        ,完成后,任务重新进入空闲状态。
    }

//因为在“UartTxTcb.Size”为零时,数据并不一定真正发送出去。即在没有真正发送完成前可能会出现数据被覆盖,从而使得最后一个字节丢失。
//所以应该在此增加一个字节的发送时间的延时,上述问题则得到解决。

  1. SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);        //延时发送1个字节所须要的时间
复制代码



//补充:
如果是485通信,一般在发送完时会将状态改回接收状态。但是485芯片的发送是会有延时的,此时也要注意,上述的两种情况都应该在发送的最后增加一定延时,以保证485芯片能正确完全发送出去再转回接收状态

1.查询+延时方式:在发送一帧数据完成后,再增加一定延时,如1ms,然后再将其发送状态改回接收状态。

2.中断发送方式:如上所述问题,可直接将发送数据长度为零后,增加的延时时间加大点,如将延时1ms改成2ms。

小结:为了提高兼容性,建议大家在发送完后,增加两个字节发送时间的延时,如在9600下,延时2ms,以后如果要用到485,就直接在发送完成,延时两字节时间之后将发送状态改回接收状态

出0入0汤圆

发表于 2014-6-18 10:40:26 | 显示全部楼层
学习下别人编程思想也有利于提高自己,代码风格挺好

出0入0汤圆

发表于 2014-6-18 18:16:53 | 显示全部楼层
串口卡死,问题找到,希望楼主给个解释。我是试出来的!
红色部分代码串口会卡死,Keil/ STC12C5A60S2/11.0592Mhz,9600bps。
蓝色不会。

  1. //*/
  2. //查询消息列队状态,是否是自由(可用)或忙(不可用),调用SCHTaskQpend()时会将其设置为自由状态
  3. SCH_UINT8 SCHTaskGetQFree(SCH_TCB   *pTaskTCB)
  4. {
  5. [color=Red]  //if (pTaskTCB->pMSGQ == ((void *)0)) [/color]
  6. [color=Blue]  if (pTaskTCB->TimeCounter==SCH_TASK_PEND)        [/color]

  7.   {
  8.     return SCH_Q_FREE;
  9.   }
  10.   else
  11.   {
  12.     return SCH_Q_BUSY;
  13.   }
  14. }
  15. //*/

复制代码

出0入0汤圆

发表于 2014-6-18 18:18:07 | 显示全部楼层
怎么不显示颜色啊!

出0入0汤圆

发表于 2014-6-18 21:21:49 | 显示全部楼层
现在效果基本满意! 就是偶尔有数据错误和丢失。
是在这里按照楼主的分析增加了延时,但是没有想太明白!
这只是延迟了启动串口中断发送,上电第一次返回丢最后一个字节的问题都解决了。 解决连续发送丢最后一个字节好理解,解决首帧丢最后一个字节的道理有点想不通!

  1. /**************************************************************************************************
  2. 串口发送任务
  3. //*/
  4. void tsk_vUartDataSend(void)
  5. {
  6.   static idata uint8_t s_u8TxBuffer[UART_TX_BUF_SIZE];
  7.   static uint8_t i;
  8.   static uint8_t *pDataBuffer, u8DataSize;

  9.   SCHTaskBegin()


  10.   while (1)
  11.   {
  12.     SCHTaskQpend();           //任务等待消息(任务空闲) UartRxTcb
  13.                                                                                                     
  14.     pDataBuffer = (uint8_t *)UartTxTcb.pMSGQ; //读取UartTxTask,消息内容(有消息,则忙)
  15.     u8DataSize  = UartTxTcb.Size;

  16.    
  17.         if (u8DataSize > UART_TX_BUF_SIZE)
  18.     {
  19.       u8DataSize = UART_TX_BUF_SIZE;
  20.       //出错处理
  21.     }
  22.        


  23.         for (i = 0; i < UartTxTcb.Size; i++)
  24.     {
  25.           s_u8TxBuffer[i] = *pDataBuffer; //copy to s_u8TxBuffer
  26.       pDataBuffer++;
  27.         }
  28. [color=Red][b]        SCHCurTaskDly(3 / SCH_SYS_TICKS_MS);   //delay 1ms[/b][/color]

  29.     UartTxTcb.pMSGQ = &s_u8TxBuffer[0];        //从发送缓存,取第一个数据(有消息,表明忙)
  30.     SBUF = s_u8TxBuffer[0];     //启动串口中断发送,后续数据在中断内发送。


复制代码

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-18 21:25:14 | 显示全部楼层
放个工程 供参考! 串口稳定了,就要加载别的模块了。

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-6-19 08:45:09 | 显示全部楼层
ppdd 发表于 2014-6-18 21:21
现在效果基本满意! 就是偶尔有数据错误和丢失。
是在这里按照楼主的分析增加了延时,但是没有想太明白!
...

连续和首帧不是一个东西吗?看142楼的说明。

出0入0汤圆

 楼主| 发表于 2014-6-19 09:14:18 | 显示全部楼层
本帖最后由 summarize 于 2014-6-19 09:18 编辑
ppdd 发表于 2014-6-18 18:16
串口卡死,问题找到,希望楼主给个解释。我是试出来的!
红色部分代码串口会卡死,Keil/ STC12C5A60S2/11.0 ...


仔细看了你的代码,发现你改动了我的源码,我的调度器只有“sch_cfg.h”是开放给用户配置的,另外两个文件不要动(后来升级忘记把这两个文件设置为只读了)。别的地方我就不对比了,只说下面这句:

#define SCHTaskQpend() {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_PEND;pCurTCB->pData=(void *)0;pCurTCB->Size=0;}return;case SCH_CURR_LINE:

被你修改成了:

#define SCHTaskQpend()                                                        \
        {                                                                                \
                  SchLc=SCH_CURR_LINE;                                        \
                  pCurTCB->TimeCounter=SCH_TASK_PEND;        \
                  pCurTCB->pMSGQ=(void *)0;                                \
                  pCurTCB->Size=0;                                                \
                }return;                                                                \
                case SCH_CURR_LINE:       


表面上只是格式变动了,而且还好看些,但是“case SCH_CURR_LINE”就发生了变化,这条名句取得的当前行号不再是“#define SCHTaskQpend() ”的行号,后果未知。

我的源码有些写得很长,看起来很不舒服,但我还是没有像你一样分行,就是这个原因。

建议,LZ恢复使用我的源码,只修改“sch_cfg.h”文件,再测试--期待你的测试结果。


编辑原因:修改错别字

出0入0汤圆

 楼主| 发表于 2014-6-19 09:16:01 | 显示全部楼层
ppdd 发表于 2014-6-18 21:25
放个工程 供参考! 串口稳定了,就要加载别的模块了。


大家注意,“ppdd”发的这个版本是修改了我的调度器源码的(不建议修改的地方),后果未知。

出0入0汤圆

发表于 2014-6-19 10:44:36 | 显示全部楼层
summarize 发表于 2014-6-19 08:45
连续和首帧不是一个东西吗?看142楼的说明。

你一提醒,看来我的的理解是有的问题。 仔细想了下我的理解,我想我的意思是是:上电后系统返回发出的首个数据包,为首帧!
我也感觉怪怪的,循环开始后,还真不好说那个是首帧!
之前发现这样的问题,上电第一帧数据丢,之后接连都是好的。 所以提出了这个个首帧。

出0入0汤圆

发表于 2014-6-19 10:48:02 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-19 10:51 编辑
summarize 发表于 2014-6-19 09:14
仔细看了你的代码,发现你改动了我的源码,我的调度器只有“sch_cfg.h”是开放给用户配置的,另外两个文 ...


我也只是,为了好看,但是编译后有没有差别,我真不知道。用C本来就不多,我也看了smset的调度器,对这个也很困惑。
如果这样,我会按照你的建议,使用你的V1.02的版本,重新测试!

出0入0汤圆

发表于 2014-6-19 10:51:54 | 显示全部楼层
楼主能否把stm32的iar工程改为keil mdk工程啊

出0入0汤圆

发表于 2014-6-19 12:07:08 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-19 12:46 编辑
ppdd 发表于 2014-6-19 10:44
你一提醒,看来我的的理解是有的问题。 仔细想了下我的理解,我想我的意思是是:上电后系统返回发出的首 ...


丢是末字节的问题,想明白了,也看明白了! 楼主正解!首帧,连续是一个道理。( 初始化能不能导致类似的问题?)
我再多说一句,问题的导致和这种调度模式有紧密联系:
虽说,启动了发送,数据是在中断内部发送;但是,串口发送任务是个消息驱动的无限循环任务。
如果数据没有发送完成,串口发送任务重新进入空闲状态通过执行:SCHTaskQpend();           //任务等待消息(任务空闲) UartRxTcb
看下SCHTaskQpend();   的宏定义:
#define SCHTaskQpend() {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_PEND;pCurTCB->pMSGQ=(void *)0;pCurTCB->Size=0;}return;case SCH_CURR_LINE:
数据指针,数据个数都进行了清零!
也就是提前结束了串口中断发送!!
也就是说,串口发送任务在串口数据发送过程中始终要处于忙的状态,直到数据发送完毕,再重新进入空闲,等待消息的状态!!
贴段代码,以示庆贺:

  1. /**************************************************************************************************
  2. 串口发送任务
  3. //*/
  4. void tsk_vUartDataSend(void)
  5. {
  6.   static idata uint8_t s_u8TxBuffer[UART_TX_BUF_SIZE];
  7.   static uint8_t i;
  8.   static uint8_t *pDataBuffer, u8DataSize;

  9.   SCHTaskBegin()


  10.   while (1)
  11.   {
  12.     SCHTaskQpend();           //任务等待消息(任务空闲) UartRxTcb
  13.                                                                                                     
  14.     pDataBuffer = (uint8_t *)UartTxTcb.pMSGQ; //读取UartTxTask,消息内容(有消息,则忙)
  15.     u8DataSize  = UartTxTcb.Size;

  16.    
  17.         if (u8DataSize > UART_TX_BUF_SIZE)
  18.     {
  19.       u8DataSize = UART_TX_BUF_SIZE;
  20.       //出错处理
  21.     }
  22.        


  23.         for (i = 0; i < UartTxTcb.Size; i++)
  24.     {
  25.           s_u8TxBuffer[i] = *pDataBuffer; //copy to s_u8TxBuffer
  26.       pDataBuffer++;
  27.         }
  28.        
  29.         SCHCurTaskDly(2 / SCH_SYS_TICKS_MS);   //delay 3ms 增加延时可以解决。 要点是保证,数据不发完,不循环到:SCHTaskQpend();  

  30.     UartTxTcb.pMSGQ = &s_u8TxBuffer[0];        //取第一个数据&指明待发数据的起始位置
  31.     SBUF = s_u8TxBuffer[0];     //发首个数据,导致串口中断,后续数据在中断内发送。


  32. // 51单片机的串口收发中断不能单独开关,所以开了串口接收中断,发送也跟着开了,因而把下面的发送放到中断中
  33. //  for (i = 0; i < u8DataSize; )
  34. //  {
  35. //    if(SCON_bit.TI)
  36. //    {
  37. //      SCON_bit.TI = 0;
  38. //                        SBUF = s_u8TxBuffer[i++];
  39. //                        SCHCurTaskDly(1 / SCH_SYS_TICKS_MS);        //延时发送1个字节所须要的时间
  40. //    }
  41. //    else
  42. //    {
  43. //      SCHCurTaskDly(0 / SCH_SYS_TICKS_MS);        //无延时,下次直接进来查询
  44. //    }
  45. //        }

  46.     if (UartTxTcb.Size > 0) //等待发送完成
  47.     {
  48.       SCHCurTaskDly(10 / SCH_SYS_TICKS_MS);        //未完成,延时10ms再查询        ,完成后,任务重新进入空闲状态。
  49.     }

  50.   }

  51.   SCHTaskEnd()
  52. }  



复制代码

出0入0汤圆

 楼主| 发表于 2014-6-19 12:27:56 | 显示全部楼层
aming2046 发表于 2014-6-19 10:51
楼主能否把stm32的iar工程改为keil mdk工程啊

你向PPDD取经自己移植吧。

出0入0汤圆

发表于 2014-6-19 12:28:45 | 显示全部楼层
建议将TCB->TimeCounter 在任务登记的时候赋初始值,这样每个定时任务可以在不同tick 下执行,更有效率

出0入0汤圆

 楼主| 发表于 2014-6-19 20:09:33 | 显示全部楼层
rootxie 发表于 2014-6-19 12:28
建议将TCB->TimeCounter 在任务登记的时候赋初始值,这样每个定时任务可以在不同tick 下执行,更有效率 ...

好建议,后续升级加入此项。

出0入0汤圆

发表于 2014-6-19 20:23:26 | 显示全部楼层
程序架构很优雅 非常值得学习!!多谢!

出0入0汤圆

发表于 2014-6-19 20:47:59 | 显示全部楼层
本帖最后由 zflood 于 2014-6-19 21:51 编辑

刚测试了一下,让LED以500ms闪亮,程序运行后无效果,请各位给看看哪里出错了。STC89C52单片机 晶振12M
自己没读明白,已搞定,谢!
#include <reg52.h>
#include "schedule.h"

SCH_TCB LedTestTcb;
sbit LED = P1^3;

void tsk_vLedTest(void)
{
  SCHTaskBegin();

  while (1)
  {
    LED = !LED;
    SCHCurTaskDly(500 / SCH_SYS_TICKS_MS);  //delay 500ms
  }
  SCHTaskEnd();
}

void vUserTaskCreate(void)
{
        SCHTaskCreate(&LedTestTcb, tsk_vLedTest);
}
void Tim_Init(void)
{
        TMOD = 0x02;   //定时器0 方式1
        TH0 = 0xfc;           //1ms
        TL0 = 0x18;       

        ET0 = 1;
        TR0 = 1;
}
void main()
{

         EA = 0;
         Tim_Init(); //初始化定时器
         vUserTaskCreate();
         EA = 1;
       
         SCHTaskSchedStart();
               
}
代码修改!

出0入0汤圆

 楼主| 发表于 2014-6-19 22:17:36 | 显示全部楼层
zflood 发表于 2014-6-19 20:47
刚测试了一下,让LED以500ms闪亮,程序运行后无效果,请各位给看看哪里出错了。STC89C52单片机 晶振12M
自 ...


自己哪里没有读明白?

分享出来让其他坛友少走弯路啊!

出0入0汤圆

发表于 2014-6-20 13:19:20 | 显示全部楼层
summarize 发表于 2014-6-19 22:17
自己哪里没有读明白?

分享出来让其他坛友少走弯路啊!

编译出来 ,data空间占得比较大啊,这怎么破? 我编译完成data = 226

出0入0汤圆

发表于 2014-6-20 14:25:01 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-20 14:32 编辑
zflood 发表于 2014-6-20 13:19
编译出来 ,data空间占得比较大啊,这怎么破? 我编译完成data = 226


同问!
确实比较耗RAM,能算到的大头 32+32+32+4+4=104+(30估计)≌134,编译后后占用231-134≌97(不知道的消耗)!




上传工程文件,调度器,使用楼主 Schedule V1.02.rar (3.91 KB, 下载次数: 35) ,一字未改!
http://www.amobbs.com/forum.php? ... TF8NTUzNDkwNw%3D%3D
运行界面如下: 02 00 AD值部分内容还没有看!




本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2014-6-20 14:48:42 | 显示全部楼层
本帖最后由 ppdd 于 2014-6-20 14:59 编辑

请楼主帮忙分析下这两问题:
问题1:

问题如图,在中断中调用消息发送函数,串口数据错误。
问题2:

是接收处理,还是别的原因导致。我这里实测如此!

顺便吐槽下,ch341串口转换芯片,容易丢数据,高速循环20ms,居然死机!改成100ms,还是死机,蓝屏出现个什么东东ch341*.sys,要dump硬盘,怕怕啊! 于是就把手上的USB串口线测试了下:
最好z-Tek: FT232(1ms循环不死机,收发数据错)丢包率低
其次Z-Tek:PL2303(10ms循环不死机,收发数据错)丢包率稍高
这个会杀人: ch341
这个没用过:CP2101
这个PV8651和PL2303据听说兼容。
相关网络资料:
http://www.cnblogs.com/sean6/p/3799332.html

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-6-20 17:30:27 | 显示全部楼层
ppdd 发表于 2014-6-20 14:25
同问!
确实比较耗RAM,能算到的大头 32+32+32+4+4=104+(30估计)≌134,编译后后占用231-134≌97(不知 ...

02 00是AD部分报上来的值,如果单纯测试串口稳定性,建议把AD部分的上报禁止了.另外不知道你想问什么

出0入0汤圆

发表于 2014-6-20 18:31:22 | 显示全部楼层
串口按照我最后提的两个问题改动,自己感觉稳定了。 那两个问题,不知道能不能算问题,反正我这里那样改了,就不出错了!
这个调度器好像很好RAM!能分析下RAM耗在那里最好,不能。我这里也不是问题。
串口已经稳定,ADC数据返回,已经看过了02 00就是512,只发了两个字节上来!

就剩下最后的两个改动,心理有点打鼓!

楼主最好,能增加一个信号触发的宏,比如程序执行到那里,要等一个条件信号;好像和消息有点重复,有有点不一样。 楼主多费心! 再出一个新版!!!

出0入0汤圆

发表于 2014-6-20 18:39:02 | 显示全部楼层
summarize 发表于 2014-6-20 17:30
02 00是AD部分报上来的值,如果单纯测试串口稳定性,建议把AD部分的上报禁止了.另外不知道你想问什么 ...

两处改动,在我这里对串口稳定影响很大!
想知道,是我的问题还是确实什么导致的!
一个是重入的情况,姑且这样解释吧。另一个是空指针。 我只能想到这里,具体是不是这样;是怎么样的的机理,我说出来! 也有可能是Keil和IAR的差别吧。
要不楼主给个能破解的IAR我再测试下!!

出0入0汤圆

发表于 2014-6-20 20:16:34 | 显示全部楼层
summarize 发表于 2014-6-20 17:30
02 00是AD部分报上来的值,如果单纯测试串口稳定性,建议把AD部分的上报禁止了.另外不知道你想问什么 ...

请教:任务创建函数 void SCHTaskCreate(SCH_TCB *pNewTCB, void (*pNewTask)(void)),它的功能是不是将要创建的任务 以链表的形式 组成一个环?

出0入0汤圆

 楼主| 发表于 2014-6-20 20:18:58 | 显示全部楼层
zflood 发表于 2014-6-20 13:19
编译出来 ,data空间占得比较大啊,这怎么破? 我编译完成data = 226

请你列出各个占用RAM的地方,特别是每个任务占用的RAM情况。

出0入0汤圆

 楼主| 发表于 2014-6-20 20:19:33 | 显示全部楼层
zflood 发表于 2014-6-20 20:16
请教:任务创建函数 void SCHTaskCreate(SCH_TCB *pNewTCB, void (*pNewTask)(void)),它的功能是不是将 ...

是这样。

出0入0汤圆

 楼主| 发表于 2014-6-20 20:22:01 | 显示全部楼层
ppdd 发表于 2014-6-20 18:39
两处改动,在我这里对串口稳定影响很大!
想知道,是我的问题还是确实什么导致的!
一个是重入的情况,姑 ...

实在没看明白你改动后的最终是怎么样的,8051的IAR本坛就有,自己下载吧。不过估计那个51指针可能真的比较弱。

出0入0汤圆

发表于 2014-6-20 21:18:05 | 显示全部楼层
summarize 发表于 2014-6-20 20:22
实在没看明白你改动后的最终是怎么样的,8051的IAR本坛就有,自己下载吧。不过估计那个51指针可能真的比 ...

我想我也说不明白的,C太弱了!

第一个:就是Ke编译il有警告,同时串口不稳定,经常不能自动发命令IAP, 就把中断内部的消息函数脱光了; 这样警告没有了,串口下载也稳定了。

第二个:无意中看到,讲空指针的,同时串口在循环发数据的时候,老是停止相应;后来加载了ADC模块才知道,只是接收停止了相应; 就把哪个检测空指针的和串口接收有关的消息检测函数的检查条件改了。于是乎,串口不再崩溃了!!

但这都是野路子,所以想弄个明白!
说了半天,还是不明白。。。我晕。。。只能先保留着吧!

出0入0汤圆

发表于 2014-6-20 21:20:06 | 显示全部楼层

有个小疑问, 在串口接收中断函数里面,void UART_R_IRQ(void) interrupt 4 //using 3
  if (SCHTaskGetQFree(&UartRxTcb) == SCH_Q_FREE)
        {
                 SCHTaskQpost(&UartRxTcb,&s_u8IsrRxBuffer[0],s_u8IsrRxCounter);        //*/ 调用这个函数之后, 结构体UartRxTcb的pMSGQ、Size、TimeCounter在函数内部不是已经赋值了吗,下面三条语句又有何用???
                UartRxTcb.pMSGQ = &s_u8IsrRxBuffer[0]; //信号启动接受数据处理
                UartRxTcb.Size  = s_u8IsrRxCounter;
                UartRxTcb.TimeCounter = SCH_TASK_RUN;
        }
请楼主指点一下,看不太懂??

出0入0汤圆

 楼主| 发表于 2014-6-20 21:30:23 | 显示全部楼层
zflood 发表于 2014-6-20 21:20
有个小疑问, 在串口接收中断函数里面,void UART_R_IRQ(void) interrupt 4 //using 3
  if (SCHTaskGet ...

请重新下载我的源码,仔细查看.

出0入0汤圆

 楼主| 发表于 2014-6-20 21:36:39 | 显示全部楼层
本帖最后由 summarize 于 2014-6-20 21:45 编辑
ppdd 发表于 2014-6-20 21:18
我想我也说不明白的,C太弱了!

第一个:就是Ke编译il有警告,同时串口不稳定,经常不能自动发命令IAP,  ...


1.Keil不支持函数重入(如在中断内外都调用同一个函数),当将函数改成了语句,即中断内外没有同时调用相同函数,也就不会有警告了.结论可能是Keil不支持函数重入

2.串口不能响应,说明指针变量传送出了问题(用整形变量却OK),也许是51的指针比较弱,也可能是Keil编译器的问题,所以期待你用IAR来测试比较下.

//补充---------------------------------
针对第1点,Keil好像是要设置哪里,就可以支持函数重入了.以前看small RTOS的时候有讲到,你自行百度一下吧.

出0入0汤圆

 楼主| 发表于 2014-6-20 22:10:30 | 显示全部楼层
ppdd 发表于 2014-6-20 18:31
串口按照我最后提的两个问题改动,自己感觉稳定了。 那两个问题,不知道能不能算问题,反正我这里那样改了 ...

你说得对,重复了,不增加.

出0入0汤圆

 楼主| 发表于 2014-6-24 21:07:51 | 显示全部楼层
本帖最后由 summarize 于 2014-6-24 21:13 编辑
ppdd 发表于 2014-6-20 21:18
我想我也说不明白的,C太弱了!

第一个:就是Ke编译il有警告,同时串口不稳定,经常不能自动发命令IAP,  ...


在淘宝上买了STC串口下载器来当USB转串口用,今晚测试了IAR工程下的代码,在发送后增加10ms延时且屏蔽ADC上报(用的是STC89C52RC单片机,速度慢,设置最小节拍是10ms).

测试几千字节数据(自动发送间隔50ms),一切正常.见下图




接收到的数据比发送数据多是因为打开串口时,STC下载器会自给单片机断电再上电(硬件复位)而导致的.


由此可知,是Keil编译器的问题(不管是函数重入导致,或是指针出错导致),但后续我会将消息处理相关函数升级为宏,以避免Keil不支持函数重入的问题,

判断消息是否空闲也改为判断消息的长度是否为零.而不用原来的判断指针为空的方法,明显判断字符数据优于判断指针(指针变量本身最少是2个字节长度).

而且也会采纳156楼(rootxie)的建议 :将TCB->TimeCounter 在任务登记的时候赋初始值,这样每个定时任务可以在不同tick 下执行,更有效率.

感谢"rootxie"的好建议,感谢你的测试.

编辑原因:改错别字.

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-7-26 09:02:20 | 显示全部楼层
ppdd 发表于 2014-6-20 21:18
我想我也说不明白的,C太弱了!

第一个:就是Ke编译il有警告,同时串口不稳定,经常不能自动发命令IAP,  ...

最新版本调度器V2.0的51单片机KEIL版本出来了。

请移步:

http://www.amobbs.com/thread-5589227-1-1.html

出0入0汤圆

发表于 2014-7-27 12:13:16 | 显示全部楼层
LZ,请问一下这个SCHCurTaskDly()函数,一定要与SCHTaskBegin()、SCHTaskEnd()一起使用方可?
如果我再任务里调用的函数,子函数里需要延时,那是不是也要一起调用SCHTaskBegin()、SCHTaskEnd()函数呢?

出0入0汤圆

发表于 2014-7-27 19:49:27 | 显示全部楼层
0520kuang 发表于 2014-7-27 12:13
LZ,请问一下这个SCHCurTaskDly()函数,一定要与SCHTaskBegin()、SCHTaskEnd()一起使用方可?
如果我再任务 ...

如果是在这情况下,貌似进入子函数delay退出后,等待时间到了也进入不了 userFun();函数了,请问这情况改如何解决
  1. void vTest(void)
  2. {
  3.   SCHTaskBegin();

  4.   while (1)
  5.   {
  6.     fun1();//子函数没有调用延时函数
  7.     fun2();//子函数没有调用延时函数
  8.     fun3();//子函数没有调用延时函数
  9.     userFun();//.....子函数里面又调用延时函数
  10.     fun4();//子函数没有调用延时函数

  11.     SCHCurTaskDly(500 / SCH_SYS_TICKS_MS);  //delay 500ms
  12.   }

  13.   SCHTaskEnd();
  14. }

  15. void userFun(void)
  16. {
  17.   SCHTaskBegin();

  18.   while (1)
  19.   {
  20.     ....;
  21.     ....;

  22.     SCHCurTaskDly(100 / SCH_SYS_TICKS_MS);  //delay 100ms

  23.     ....;
  24.     ....;
  25.   }

  26.   SCHTaskEnd();
  27. }
复制代码

出0入0汤圆

发表于 2014-7-27 21:12:54 来自手机 | 显示全部楼层
感谢楼主的无私

出0入0汤圆

 楼主| 发表于 2014-7-27 21:17:35 | 显示全部楼层
0520kuang 发表于 2014-7-27 19:49
如果是在这情况下,貌似进入子函数delay退出后,等待时间到了也进入不了 userFun();函数了,请问这情况改 ...

  1. //任务内调用子任务
  2. #define SCHTaskCallSub(SubTaskName)                                                     \
  3. {                                                                                       \
  4.   {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_RUN;}return;case SCH_CURR_LINE:    \
  5.   pCurTCB->TimeCounter = SCH_TASK_RUN;                                                  \
  6.   SubTaskName();                                                                        \
  7.   if (pCurTCB->TimeCounter != SCH_TASK_RUN)                                             \
  8.     return ;                                                                            \
  9. }
复制代码


子任务的格式与主任务相同.

出0入0汤圆

发表于 2014-7-27 23:05:05 | 显示全部楼层
summarize 发表于 2014-7-27 21:17
子任务的格式与主任务相同.

是不是说调用这个函数后,主任务里有子任务,子任务里又有子任务,这样可以一直调用下去?

出0入0汤圆

 楼主| 发表于 2014-7-28 06:04:38 | 显示全部楼层
0520kuang 发表于 2014-7-27 23:05
是不是说调用这个函数后,主任务里有子任务,子任务里又有子任务,这样可以一直调用下去? ...

是的。           

出0入0汤圆

发表于 2014-7-28 07:23:08 | 显示全部楼层
这是协程的特点

出0入0汤圆

发表于 2014-7-28 12:11:14 | 显示全部楼层
summarize 发表于 2014-7-27 21:17
子任务的格式与主任务相同.

LZ,貌似主任务里嵌套字任务有个bug,从串口log上看进入不了子函数下面的程序。这跟我想要的结果不一样(预想结果是两LED都闪烁,现在只有一个LED闪烁),莫非SCHTaskCallSub()不是这么应用?
  1. void vLed2Test(void)
  2. {
  3.         SCHTaskBegin();
  4.        
  5.         while (1)
  6.         {
  7.                 gpio_set(LED2,1);print1("666",3);
  8.                
  9.                 SCHCurTaskDly(250 / SCH_SYS_TICKS_MS);print1("777",3);

  10.                 gpio_set(LED2,0);print1("888",3);

  11.                 SCHCurTaskDly(250 / SCH_SYS_TICKS_MS);print1("999",3);
  12.         }
  13.        
  14.         SCHTaskEnd();
  15. }

  16. void vLed1Test(void)
  17. {
  18.         SCHTaskBegin();
  19.        
  20.         while (1)
  21.         {
  22.                 gpio_set(LED1,1);print1("111",3);

  23.                 SCHTaskCallSub(vGPSLedTest);print1("222",3);
  24.                
  25.                 SCHCurTaskDly(500 / SCH_SYS_TICKS_MS);print1("333",3);

  26.                 gpio_set(LED1,0);print1("444",3);

  27.                 SCHCurTaskDly(500 / SCH_SYS_TICKS_MS);print1("555",3);
  28.         }
  29.        
  30.         SCHTaskEnd();
  31. }

  32. 串口LOG:
  33. 111666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666777888999666
复制代码

出0入0汤圆

发表于 2014-7-28 12:47:48 | 显示全部楼层
0520kuang 发表于 2014-7-28 12:11
LZ,貌似主任务里嵌套字任务有个bug,从串口log上看进入不了子函数下面的程序。这跟我想要的结果不一样( ...

哦  这个我知道了,把子任务里的while 去掉就好了。。。。

出0入0汤圆

发表于 2014-7-28 14:47:09 | 显示全部楼层
0520kuang 发表于 2014-7-28 12:47
哦  这个我知道了,把子任务里的while 去掉就好了。。。。

关于SCHTaskCallSub()函数里面的第一个return是否可以去掉的问题。

  1. //任务内调用子任务
  2. #define SCHTaskCallSub(SubTaskName)                                                     \
  3. {                                                                                       \
  4.   {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_RUN;}return;case SCH_CURR_LINE:    \
  5.   pCurTCB->TimeCounter = SCH_TASK_RUN;                                                  \
  6.   SubTaskName();                                                                        \
  7.   if (pCurTCB->TimeCounter != SCH_TASK_RUN)                                             \
  8.     return ;                                                                            \
  9. }
复制代码


我再主任务里嵌套了一个子任务,子任务里又嵌套了一个子任务,但是从log看:程序运行的顺序不是我预想的结果。因为第一次调用SCHTaskCallSub()函数后return了,程序就会继续往下执行去了。
LOG:
  1. 111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666777888999###222444555111***222444555111666
复制代码


如果我把SCHTaskCallSub()函数里的第一个return去掉后,程序执行的顺序就是我想要的,从log上看:
LOG:
  1. 111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999###222444555111***666777888999##
复制代码

  1. void vGPSLedTest(void)
  2. {
  3.         SCHTaskBegin();
  4.        
  5.         gpio_set(GPS_LED,1);print1("666",3);
  6.        
  7.         SCHCurTaskDly(250 / SCH_SYS_TICKS_MS);print1("777",3);

  8.         gpio_set(GPS_LED,0);print1("888",3);

  9.         SCHCurTaskDly(250 / SCH_SYS_TICKS_MS);print1("999",3);
  10.        
  11.         SCHTaskEnd();
  12. }

  13. void vPrint(void)
  14. {
  15.         SCHTaskBegin();
  16.         print1("***",3);
  17.         SCHTaskCallSub(vGPSLedTest);
  18.         print1("###",3);
  19.         SCHTaskEnd();       
  20. }

  21. void vGSMLedTest(void)
  22. {
  23.         SCHTaskBegin();
  24.        
  25.         while (1)
  26.         {
  27.                 gpio_set(GSM_LED,1);print1("111",3);

  28.                 SCHTaskCallSub(vPrint);print1("222",3);
  29.                
  30. //                SCHCurTaskDly(500 / SCH_SYS_TICKS_MS);print1("333",3);

  31.                 gpio_set(GSM_LED,0);print1("444",3);

  32.                 SCHCurTaskDly(500 / SCH_SYS_TICKS_MS);print1("555",3);
  33.         }
  34.        
  35.         SCHTaskEnd();
  36. }
复制代码

出0入0汤圆

发表于 2014-7-28 21:47:26 | 显示全部楼层
  楼主现在你的任务还是不能超过255行吗?怎么修改才能超过255行?
我看了下,总体架构还是基于定时器模式的,假如1个低优先级的任务正在运行,来了一个高优先级的,例如串口中断,还是要等到低优先级任务完成才能执行高优先级!假如低优先级霸占住程序.......

出0入0汤圆

发表于 2014-7-28 22:29:20 | 显示全部楼层
embeddev_1 发表于 2014-7-28 21:47
楼主现在你的任务还是不能超过255行吗?怎么修改才能超过255行?
我看了下,总体架构还是基于 ...

改进型的合作式调度器,是不支持抢占的。

出0入0汤圆

 楼主| 发表于 2014-7-28 22:59:28 | 显示全部楼层
0520kuang 发表于 2014-7-28 14:47
关于SCHTaskCallSub()函数里面的第一个return是否可以去掉的问题。

不好意思,183楼的回复有误,误导了你.

实际上只支持嵌套一级子函数,原因如下,注释部分:

  1. //任务内调用子任务
  2. #define SCHTaskCallSub(SubTaskName)                                                     \
  3. {                                                                                       \
  4.   {SchLc=SCH_CURR_LINE;pCurTCB->TimeCounter=SCH_TASK_RUN;}return;case SCH_CURR_LINE:    \  //调用子函数将任务设置为运行状态,然后返回,下次进来直接运行.先返回是为了释放CPU,避免主任务运行一段时间后又接着运行子函数,占用时间过长.
  5.   pCurTCB->TimeCounter = SCH_TASK_RUN;                                                  \
  6.   SubTaskName();                                                                        \
  7.   if (pCurTCB->TimeCounter != SCH_TASK_RUN)                                             \            //如果子函数没有运行结束,则直接返回,但判断条件是"pCurTCB->TimeCounter != SCH_TASK_RUN",如果再调用一级子函数,又会执行"TimeCounter=SCH_TASK_RUN"
  8.                                                                                                                         //则这里主任务就就会判断为第一个子函数已经运行结束(实际上没有运行完).从而导致得不到想要的效果.                                                               
  9.     return ;                                                                            \
  10. }
复制代码



其实不建议嵌套那么多带等待条件的子函数,最好做法是:主任务利用状态机思想(例程格式就是状态机)将任务分为多个状态,分时执行,从而提高效果,子函数就是各个状态对应要完成的事情(无延时或等待,一次执行到结束).

如你的例子改成下面的格式:

void vTest(void)
{
  SCHTaskBegin();

  while (1)
  {
    fun1();//状态1要完成的事务

    //延时或等待消息

    fun2();//状态2要完成的事务

    //延时或等待消息

    fun3();//状态3要完成的事务

    //延时或等待消息
  }

  SCHTaskEnd();
}

出0入0汤圆

 楼主| 发表于 2014-7-28 23:05:48 | 显示全部楼层
embeddev_1 发表于 2014-7-28 21:47
楼主现在你的任务还是不能超过255行吗?怎么修改才能超过255行?
我看了下,总体架构还是基于 ...


见190楼,如果按照这样的方式,是不会超过255行的.

但如果你一定要改,则可以在"schedule.h"中



#define SCHTaskBegin()        static SCH_UINT8 SchLc=0; switch(SchLc){ case 0://跳转开始,中间可插入延时,调用子函数;(适用主/子函数)

改为

#define SCHTaskBegin()        static SCH_UINT16 SchLc=0; switch(SchLc){ case 0://跳转开始,中间可插入延时,调用子函数;(适用主/子函数)

注意:要先将"schedule.h"文件的只读属性去掉,才能修改.

出0入0汤圆

发表于 2014-8-3 21:35:36 | 显示全部楼层
支持一下 有空再详细看看

出0入0汤圆

发表于 2014-8-21 13:51:32 | 显示全部楼层
楼主现在不更新了吗?

出0入0汤圆

发表于 2014-8-21 20:15:01 | 显示全部楼层
谢谢分享

出0入0汤圆

 楼主| 发表于 2014-8-22 08:39:40 | 显示全部楼层
craigtao 发表于 2014-8-21 13:51
楼主现在不更新了吗?

你认为我应该更新什么东西?

出0入0汤圆

发表于 2014-8-22 08:42:36 | 显示全部楼层
summarize 发表于 2014-8-22 08:39
你认为我应该更新什么东西?

不知道,我只是看到这个帖子是13年的,个人以为你已经不更新了,

出0入0汤圆

 楼主| 发表于 2014-8-22 09:18:33 | 显示全部楼层
craigtao 发表于 2014-8-22 08:42
不知道,我只是看到这个帖子是13年的,个人以为你已经不更新了,

仔细再看一次标题时间.

出0入0汤圆

发表于 2014-8-22 10:40:52 | 显示全部楼层
受教了   

出0入0汤圆

发表于 2014-8-22 12:28:44 | 显示全部楼层
summarize 发表于 2014-8-22 09:18
仔细再看一次标题时间.

没有mdk版本的吗?

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-25 15:33

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

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