搜索
bottom↓
回复: 135

想来想去,单片机程序还是用这种结构简单实用

  [复制链接]

出0入0汤圆

发表于 2012-11-9 11:05:10 | 显示全部楼层 |阅读模式
本帖最后由 shuxmpx123 于 2012-11-9 11:07 编辑

刚入门的时候,用的着种结构:

一、
void main(void)
{
    Init(void);

    while(1)
    {
        Task1(void);
        ......
        Taskn(void);
   }
}

后来工作了,一直用下面这种,感觉挺好的:

二、
void main(void)
{
    Init(void);

    while(1)
    {

        if (sys._5ms > 0)
        {
               sys._5ms = 0;
               task_index++;
               if (task_index > n)
               {
                      task_index = 0;
               }
        }

        switch(task_index)
        {
             case 0:  
                       Task1();
                        break;
            case 1:
                     ...
                    break;
            case n:
                    Taskn();
                    break;
            default:
                    break;
        }
   }
}

这种结构函数运行时间间隔的灵活性不是很大,但是函数本身比较自由,形参可有可无,不需要多余的外包,免去了不必要的进出栈,定时器中断 里面处理也很简单,只需将sys._5ms置位;
今天突然想做一个时间间隔控制比较灵活的,这就要用到函数指针,函数的格式就固定了,或者另外给函数打包,而且要逐次查询,就类似系统那样的了,这就有些浪费了,想想还是算了~~



下面这种应该不错,我没用过(我只把意思写出来了,这个还可做优化):

三、
ISR_Time()
{
    if (5ms > 0)
    {
        5ms = 0;
        TASK1 = 1;
    }
    if (nms > 0)
    {
        TASKn = 1;
    }
}

void main(void)
{
    Init(void);

    while(1)
    {
        if (TASK1)
        {
             TASK1 = 0;
            Task1(void);
        }
        ....

       if (TASKn)
        {
            TASKn = 0;
            Taskn(void);
        }
    }
}

觉得第三种最好了,比低二种灵活,但是定时器里面稍微麻烦一点,while(1)里面也需要逐个查询(也还可以优化);
不知道大家现在用的是啥样的, 希望有更好的贴出来分享一下哈···

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

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2012-11-10 12:39:18 | 显示全部楼层
消息机制+状态机架构搞定一切

出0入0汤圆

发表于 2012-11-12 11:18:29 | 显示全部楼层
采用消息来驱动状态机和执行回调函数,对于时间要求很严格的在中断里完成状态机转换,尽量缩短主程序扫描时间,对于一个嵌入式软件来说,数据结构和算法决定了整个系统的执行效率,多研究一下算法,必要时多做一些重构。

出0入0汤圆

发表于 2012-11-12 11:31:39 | 显示全部楼层
我用 轻量级操作系统 Protothread , 结构很清晰, 感觉很不错

使用Protothread实现多任务的最主要的好处在于它的轻量级。每个Protothread不需要拥有自已的堆栈,所有的Protothread 共享同一个堆栈空间,这一点对于RAM资源有限的系统尤为有利

出0入0汤圆

 楼主| 发表于 2013-7-8 11:24:50 | 显示全部楼层
本帖最后由 shuxmpx123 于 2013-7-8 11:30 编辑

下面这个结构用了有一段时间了,突然想贴上来大家讨论讨论·· 我看了一些实时系统的处理方式,相比而言,我觉得这种结构是很不错的:
  1. interrupt void Time_ISR(void)
  2. {
  3.     if ((sys._250us%16) == 0)        // %16 == 0                4ms
  4.     {
  5.         sys.task_4ms++;
  6.         if ((sys._250us%32) == 0)        // %32 == 0                8ms
  7.         {
  8.                 sys.task_8ms++;
  9.                 if ((sys._250us%64) == 0)        // %64 == 0                16ms
  10.                 {
  11.                         sys.task_16ms++;
  12.                         if ((sys._250us%128) == 0) // %128 == 0        // 32ms
  13.                         {
  14.                           sys.task_32ms++;
  15.                           sys._32ms++;
  16.                           if ((sys._32ms%4) == 0) // %4 == 0  128ms
  17.                           {
  18.                                 sys.task_128ms = 0xFF;       
  19.                                   if ((sys._32ms%8) == 0)        // %8 == 0  256ms
  20.                                   {
  21.                                         sys.task_256ms = 0xFF;
  22.                                         if ((sys._32ms%16) == 0)                // %16 == 0  512ms
  23.                                         {
  24.                                                 sys.task_512ms = 0xFF;
  25.                                         }
  26.                                   }
  27.                           }
  28.                   }
  29.             }
  30.         }
  31.   }
  32. }

  33. void main(void)
  34. {
  35.     ......
  36.     while(1)
  37.     {
  38.         if (sys.task_4ms)
  39.        {
  40.         ......
  41.        }
  42.        if (sys.task_8ms)
  43.       {
  44.             ......
  45.             continue;
  46.       }
  47.        if (sys.task_128ms & TASK_BIT0)
  48.        {
  49.             ......
  50.             sys.task_128ms &= ~TASK_BIT0;
  51.             continue;
  52.       }
  53.        .......
  54.    }
  55. }
复制代码
这段代码有2个关键的地方: 一个是中断里面 %2 4 8 16 .。。  汇编的处理方式是一条位运算就可以了, 还一个是用到了关键词 continue, 保证 4ms  8ms 等按排列的顺序依次优先运行;

出0入0汤圆

发表于 2012-11-9 11:13:35 | 显示全部楼层
1、5ms处理里的Task执行应该要少于这个过程,并且里面不可包含延时函数(如果有延时函数,具体做法可以借鉴常规的OS来做)。
2、如果碰到有高数据量的通迅交互,建议将通迅放在外面,如果有对处理有高效的也要放在外面。
3、5ms太长,基本上我的定时为100us或1ms。

出0入0汤圆

 楼主| 发表于 2012-11-9 11:20:44 | 显示全部楼层
本帖最后由 shuxmpx123 于 2012-11-9 11:23 编辑

  恩  是的,我做的也如你1、 2点所说,延时函数不需要,因为函数运行的时间间隔是固定的,计算函数本身运行的次数就可知道时间, 像串口发送数据,就直接放在while(1)下面。

出0入0汤圆

发表于 2012-11-9 11:32:40 | 显示全部楼层
本帖最后由 xjmlfm1 于 2012-11-9 11:34 编辑

感觉楼主的几种结构从思想上来看是一样的。
我提出一种需求,看楼主有没有什么好的应对方法。
51的片子,因为有ADC采样中断,而采样的间隔时间要非常精确,而中断的等级只有一级,也就是说不允许除ADC中断以后的其它中断长时间占用CPU。
主函数里面调用3个任务,task1,task2,task3,其中,task1,task2的执行时间不超过1ms,task3的执行时间是8ms。同时这三个任务对时间相对较敏感,不能长时间的不调用。
现在串口通信要求要及时的回答,在波特率比较高(如38400)的时候,要求响应时间小于5ms。
串口的接收是在中断里完成的,task4是串口数据处理函数,主要是查询报文是否合法,如果合法,则回复。
task4的执行时间有长有短,最短只有几十us,最长在6ms左右。
现在的问题是,task4这个函数应该怎么调用?放在哪里调用?

出0入0汤圆

发表于 2012-11-9 11:41:26 | 显示全部楼层
这样会不会更简单些

// ========================================
// 主函数
// ========================================
void main(void)
{
  PT_INIT(&pt1);  // 初始化
  PT_INIT(&pt2);
  
  while(1)
  {
    protothread1(&pt1);
    protothread2(&pt2);
  }
}

出0入0汤圆

发表于 2012-11-9 12:18:20 | 显示全部楼层
按照你提出的这种做法,每个任务执行的时间间隔还是固定的呀,除非你给每个任务分频不同的运行时间

对有延时的任务,不知道有什么好方法不需要死等。os是每个程序有堆栈,没有OS,难道只能用全局变量加状态机的方法吗

出0入0汤圆

发表于 2012-11-9 12:24:17 | 显示全部楼层
普通的方法和你的这种方法,看上去是不是像循环展开的样子

出0入0汤圆

 楼主| 发表于 2012-11-9 12:41:10 | 显示全部楼层
xjmlfm1 发表于 2012-11-9 11:32
感觉楼主的几种结构从思想上来看是一样的。
我提出一种需求,看楼主有没有什么好的应对方法。
51的片子,因 ...


敏感的任务可以夹杂在次要的任务中间调用,次要的任务拆开分几次执行

出0入0汤圆

发表于 2012-11-9 13:00:40 | 显示全部楼层
...........

出0入0汤圆

发表于 2012-11-9 13:53:05 | 显示全部楼层
请教一下楼主

普通51单片机

task1(); 是8位数码管动态显示任务,需要间隔2ms执行一次。执行过程不超过1ms
task2(); 是键盘扫描任务,需要间隔20ms执行一次。执行过程不超过1ms
task3(); 是读取DS1302实时时钟数据,需要间隔1s读取一次。执行时间大于1ms,不大于2ms
task4(); 是读取DS18B20温度传感器任务。需要间隔1s执行一次。但是此段程序需要等待温度转换时间197ms或者400ms。


请问你有什么好的想法,来设计这个程序结构?

第一次,我是采用时间片轮询法调用各个程序,将task4任务分割成几部分来调用。但是发现数码管有闪烁。

请问楼主能否解决这个问题?不吝赐教

出0入0汤圆

 楼主| 发表于 2012-11-9 14:00:04 | 显示全部楼层
segeal 发表于 2012-11-9 13:53
请教一下楼主

普通51单片机

数码管驱动的程序(驱动部分)放在中断里面执行,2ms执行一次, 另外做一个计时器 来读取温度,不要用延迟等待读取温度;

出0入0汤圆

发表于 2012-11-9 14:03:43 | 显示全部楼层
shuxmpx123 发表于 2012-11-9 14:00
数码管驱动的程序(驱动部分)放在中断里面执行,2ms执行一次, 另外做一个计时器 来读取温度,不要用延 ...

谢谢。
首先,我的错。我的普通51单片机只有两个定时器。
而且我任务函数里面,还有一个串口收发任务函数,已经用掉了一个作为波特率发生器了。

另外一个定时器产生系统基准时间片(我采用的是时间片轮询调用任务)。

所以能请你更详细讲一下 应该怎样去安排程序结构吗?谢谢了!

出0入0汤圆

发表于 2012-11-9 14:03:52 | 显示全部楼层
R10L,按结构说的话,第二种用的多

采用事件中断的比较多。

如何才能体现任务的优先级呢?


11楼,说明你的数码管显示被延迟了,可以采用定时中断,或者继续细分你的task4

出0入0汤圆

发表于 2012-11-9 14:10:52 | 显示全部楼层
jomin 发表于 2012-11-9 14:03
R10L,按结构说的话,第二种用的多

采用事件中断的比较多。

谢谢。

后来我改进了一下,把数码管显示任务放进2ms中断里面,数码管效果很好,很正常。但是有一个问题,执行读取DS18B20的时候,如果中途被数码管显示中断掉了,就读取到错误的信息。也就是说读取DS18B20的时候,老是数据出错,有时候正确,有时候错误。

请问怎样解决。我已经将ds18b20程序细分了,放在主循环按照时间片执行。

出0入0汤圆

发表于 2012-11-9 14:16:23 | 显示全部楼层
简单的程序就用第一种,多模式的程序喜欢用第二种,其它的就混着用

其实只要做到收发自如、满足应用要求,咋用都行

出0入0汤圆

发表于 2012-11-9 14:23:36 | 显示全部楼层
第一种架构可以用在实时性不高的场合,例如用户数据交换,按键100ms响应就可以了。内部执行2-3秒内完成客户可以接受。

第二种和第三种架构其实是一样的,最基本的多任务架构吧,小型单片机程序,实时性要求高点的比较实用。
但是实时性好的前提是牺牲了程序的架构。一个任务可能有多个死循环等待动作,这种架构就是要求将这个任务打散,分成多个状态,
然后判断各种状态完成。程序稍微大一点,10K以上,就惨不忍睹了。因为很散很零乱,而遇到些逻辑性比较强的程序,就很难维护了。

出0入0汤圆

 楼主| 发表于 2012-11-9 14:29:19 | 显示全部楼层
本帖最后由 shuxmpx123 于 2012-11-9 14:34 编辑
segeal 发表于 2012-11-9 14:10
谢谢。

后来我改进了一下,把数码管显示任务放进2ms中断里面,数码管效果很好,很正常。但是有一个问题 ...


2个中断够了,多了反而不好, 你2ms里面驱动数码管的程序很多吗,简化一下  应该不会有问题, 下面这个是我做的单片机的时钟中断,里面也包含了数码管驱动(数码管驱动就两条指令):
#ifdef _COSMIC_
@far @interrupt void TIM4_UPD_OVF_IRQHandler(void)
#else /* _RAISONANCE_ */
void TIM4_UPD_OVF_IRQHandler(void) interrupt 23
#endif /* _COSMIC_ */
{
  /* In order to detect unexpected events during development,
     it is recommended to set a breakpoint on the following instruction.
  */
          if (TIM4->SR1 & 0x01)
          {
                  TIM4->SR1 &= 0xFE;
               
                sys._500us++;
                if (sys._500us >= 12)
                {
                        sys._500us = 0;
                        sys._6ms++;
                }
                if ((sys._500us&0x03) == 0)        //sys._500us%4 == 0
                {
                        sys.led_index++;
                        if (sys.led_index > 6)
                        {
                                sys.led_index = 0;
                        }

                        GPIOC->ODR = LED[sys.led_index];
                        GPIOB->ODR = sys.display_buff[sys.led_index];
                }

                if ((sys._500us == 3)||(sys._500us == 7)||(sys._500us == 11))
                //if ((sys._500us == 2)||(sys._500us == 6)||(sys._500us == 10))
                //if ((sys._500us == 1)||(sys._500us == 5)||(sys._500us == 9))
                {
                        //GPIOB->ODR &= 0xFF;
                        GPIOC->ODR = 0;
                }       
          }                   
        return;
}
#endif /*STM8S903*/

出0入147汤圆

发表于 2012-11-9 14:29:24 | 显示全部楼层
segeal 发表于 2012-11-9 13:53
请教一下楼主

普通51单片机

最简单的办法是调整温度转换函数的读取方式,假设你1ms调用一次,改成如下形式
if (TempTimer == 0){
DS18B20_StartConv();    启动转换的时间 不到1ms
TempTimer = 500;
}
else if (--TempTimer == 0)
{
  DS18B20_GetTemp();
}

出0入0汤圆

发表于 2012-11-9 14:35:24 | 显示全部楼层
shuxmpx123 发表于 2012-11-9 14:29
2个中断够了,多了反而不好, 你2ms里面驱动数码管的程序很多吗,简化一下  应该不会有问题, 下面这个是 ...

嗯,很感谢!

基本明白了。

不过我关键性的问题,在于 task4();的任务中,如果不分开执行。执行时间大概为900多ms了。而其中需要等待的转换时间就有几百ms,所以才请教有什么好的办法解决读取DS18b20的问题。

出0入0汤圆

发表于 2012-11-9 14:37:48 | 显示全部楼层
dreampet 发表于 2012-11-9 14:29
最简单的办法是调整温度转换函数的读取方式,假设你1ms调用一次,改成如下形式
if (TempTimer == 0){
DS1 ...

嗯,万分感谢了。

这个思路应该可行。

我的程序结构是

1、定时器1产生1ms中断。

2.中断后 timer计数加一

3.主循环中判断timer来执行事件。

4.数码管显示放在定时中断里面


请问这段程序放到主循环中,等待时间标志来执行,可行吗?

出0入0汤圆

发表于 2012-11-9 15:02:17 | 显示全部楼层
    2000年以前写单片机程序,用的是LZ的第二种方法,2000年以后,我在单片机上用OS。
    用OS的好处就是:复杂的程序可以分解为几个线程来做,每个线程的处理都很简单,只要处理好各线程之间的同步与通信就可以了。
    这当然需要很懂操作系统才能用好。

出0入0汤圆

发表于 2012-11-9 15:19:55 | 显示全部楼层
ISR_Time()
{
mscnt++;
if(!(mscnt%2)==1)
{Flag2ms = 1;}
if(!(mscnt%10)==1)
{Flag10ms = 1;}
.
.
.
}
void main()
{
while(1)
{
  if(Flag2ms==1)
{
}
if(Flag10ms==1)
{
}
}
}
我是用这种用得多!

出0入0汤圆

发表于 2012-11-9 23:22:11 来自手机 | 显示全部楼层
mark留着慢慢看

出0入264汤圆

发表于 2012-11-10 00:17:20 来自手机 | 显示全部楼层
时间片加状态机解决大部分的问题。

出0入264汤圆

发表于 2012-11-10 00:20:12 来自手机 | 显示全部楼层
裸奔编程配合时间片,状态机再加上简单消息通信才是完美解决方案。

出0入4汤圆

发表于 2012-11-10 00:58:35 | 显示全部楼层
好话题~~~收藏了

出0入0汤圆

发表于 2012-11-10 01:07:58 | 显示全部楼层
楼主你要是用中断的话就真不如上RTOS了...

第二种方法是比较常用的解决方案...不过不是用switch....而是函数数组...

出0入0汤圆

 楼主| 发表于 2012-11-10 09:13:52 | 显示全部楼层
本帖最后由 shuxmpx123 于 2012-11-10 09:15 编辑
adce 发表于 2012-11-10 01:07
楼主你要是用中断的话就真不如上RTOS了...

第二种方法是比较常用的解决方案...不过不是用switch....而是函 ...



RTOS    要管理堆栈,我没做过,但是感觉对单片机来说,有点压力啊···
我在1楼说的函数指针就是 用函数数组的意思,不给函数打包就要给所有函数以固定的格式,感觉有点不方便。。。

出0入0汤圆

 楼主| 发表于 2012-11-10 09:41:01 | 显示全部楼层
mcu_lover 发表于 2012-11-10 00:20
裸奔编程配合时间片,状态机再加上简单消息通信才是完美解决方案。

你说的是不是类似于第三种···

出0入0汤圆

发表于 2012-11-10 10:33:00 | 显示全部楼层
觉得这样的话题,在阿莫中应该多有一些,毕竟思想性的东西极具知道作用!谢谢楼主,真在使用的就是楼主的第三模式。。

出0入0汤圆

发表于 2012-11-10 12:23:41 | 显示全部楼层
不错的话题,留着。

出0入0汤圆

发表于 2012-11-10 13:55:28 | 显示全部楼层
shuxmpx123 发表于 2012-11-10 09:13
RTOS    要管理堆栈,我没做过,但是感觉对单片机来说,有点压力啊···
我在1楼说的函数指针就是 用函 ...


堆栈管理是由RTOS来完成的啊...并不需要您做...大部分单片机运行RTOS都无压力吧....无非就是POP/PUSH寄存器....
如果用中断...那么开销真和RTOS差不多了...且RTOS做延时要方便的多...
建议用FreeRTOS...代码精简功能强...堆栈管理很灵活...
  1. void TASK_Switch(void *pvParameters);
  2. void TASK_Keyboard(void *pvParameters);
  3. void TASK_Transfer(void *pvParameters);

  4. void TASK_Start(void);

  5. int main(void)
  6. {
  7.     TASK_Start();                 
  8. }

  9. void TASK_Start(void)
  10. {
  11.       xTaskCreate( TASK_Transfer     , ( signed portCHAR *) "Transfer"     , 128, NULL, (tskIDLE_PRIORITY + 1), NULL);
  12.       xTaskCreate( TASK_Switch       , ( signed portCHAR *) "Switch"       , 128, NULL, (tskIDLE_PRIORITY + 2), NULL);
  13.       xTaskCreate( TASK_Keyboard     , ( signed portCHAR *) "Keyboard"     , 128, NULL, (tskIDLE_PRIORITY + 3), NULL);
  14.       vTaskStartScheduler();
  15. }
复制代码
2.您那函数格式本身都是一样的好么...

出0入0汤圆

发表于 2012-11-10 14:18:11 | 显示全部楼层
好帖子,受益匪浅!

出0入0汤圆

 楼主| 发表于 2012-11-10 14:18:59 | 显示全部楼层
本帖最后由 shuxmpx123 于 2012-11-10 14:20 编辑
adce 发表于 2012-11-10 13:55
堆栈管理是由RTOS来完成的啊...并不需要您做...大部分单片机运行RTOS都无压力吧....无非就是POP/PUSH寄存 ...


谢谢您的回答,您这么一说,我现在也觉得,开中断和用RTOS的开销差不多,因为一次POP/PUSH占用一个任务的时间比是很小的,有时间再看看RTOS,争取用上这个····

出0入0汤圆

发表于 2012-11-10 19:40:24 | 显示全部楼层
segeal 发表于 2012-11-9 14:37
嗯,万分感谢了。

这个思路应该可行。

你的问题就是慢速设备如何不阻塞其他任务,只能用全局变量+状态机的方法,不能软件延时
如果上os,任务自己有任务栈,相当于全局变量,os调度相当于状态机的状态转移,用时间片轮转还是无法完成
你用任务拆分的方法,实际上用状态机更加清晰

出0入0汤圆

发表于 2012-11-10 20:17:09 | 显示全部楼层
不带任务切换的顺序程序,根本就不可能做到时间片轮转调度。
为何这么说?
按照楼主说的第二种情况,如果某个任务5ms内完成,比如2ms,很明显在5ms内多执行了1次,那么按照真实意图应该把时间让给其他未响应的任务,如果5ms不能执行完,相当于这个任务调度无效,不用也罢;所以按照方法2,不但没有带来预想的结果,反而引入了不可预知隐患
第三种,用中断来刷新时间片,时间虽准,问题反而更加突出,为何这么说?依旧是之前讨论的问题,如果对于任务执行时间估计不准,短时任务分配长时间片,阻塞其他任务,长时任务分配短时间片,结果等任务执行完,任务号都不知道跳了多少次,最后到底是哪个任务能够执行到,根本无法估计,如何体现实时性
而按照第一种,也就是最普通的,每个人都在用的,可以估计的最大任务延迟时间
说来说去,最关键的办法,只能是尽量缩短主循环扫描一遍的时间
用消息事件触发状态机,和不用软件延时,才是真正的王道,因为 你没有干无事也处理和死等,消息事件触发表明你只在监视事件上花功夫,否则你可能连监视事件这个事情都来不及;不要用软件延时表明你没有看着手表等人,完全可以做其他事情

出0入0汤圆

发表于 2012-11-10 20:20:11 | 显示全部楼层
最高级的当然是使用操作系统,否则为何要发展操作系统呢,操作系统的复杂使得任务变得不复杂

出165入0汤圆

发表于 2012-11-10 21:04:05 来自手机 | 显示全部楼层
程序灵魂…至宝!一直转想找最简实用架构.受用.谢楼主

出0入0汤圆

发表于 2012-11-10 21:04:23 | 显示全部楼层
lz的想法其实很好,将每个任务的时间-关键性分类,应该是可以做到更好的管理效果
我想了下,为啥按照lz的想法会出现我提到的问题,关键是背后的调度机制。
假设调度只基于时间事件,例如每个任务执行的时间间隔,那么应该维护一个时间间隔超时处理法则
例如当超时越久,等到空闲时优先调度;如果空闲时还没有一个任务时间间隔超时,此时不调度cpu就会空转,那么查询哪个任务离超时最近则调度,等等
实际情况肯定很复杂,应该具体问题具体分析

出0入0汤圆

发表于 2012-11-10 21:09:11 | 显示全部楼层
最后,就是一个简单的非抢占操作系统的雏形了

出0入0汤圆

发表于 2012-11-10 21:19:00 | 显示全部楼层
myxiaonia 发表于 2012-11-10 19:40
你的问题就是慢速设备如何不阻塞其他任务,只能用全局变量+状态机的方法,不能软件延时
如果上os,任务自 ...

不错。你给了另外一个思路。
我打算用 时间片轮询+状态机 来解决这个问题。
谢谢你的建议。

出0入0汤圆

发表于 2012-11-10 22:24:57 | 显示全部楼层
segeal 发表于 2012-11-10 21:19
不错。你给了另外一个思路。
我打算用 时间片轮询+状态机 来解决这个问题。
谢谢你的建议。 ...

实际上我当时问过慢速设备的问题,当时有人建议借鉴操作系统的方法,一直没理解,但是肯定不能是lz的做法,lz的想法,最终只能达到非抢占的效果,要想强占,必须是抢占式操作系统
,而你的问题,显然是需要延时时干别的事情,就是需要抢占

出0入0汤圆

发表于 2012-11-10 22:31:26 | 显示全部楼层
如果是抢占式的调度,必须把调度程序放在中断中以达到抢占目的,lz的做法无法达到抢占,也就是第3种放在中断的做法是无效的

出165入0汤圆

发表于 2012-11-10 23:06:38 | 显示全部楼层
segeal 发表于 2012-11-10 21:19
不错。你给了另外一个思路。
我打算用 时间片轮询+状态机 来解决这个问题。
谢谢你的建议。 ...

恕我菜鸟:请问这是一种怎样的架构,能给个模板么?时间片轮加状态机??
谢谢。

出0入0汤圆

发表于 2012-11-11 00:03:58 | 显示全部楼层
myxiaonia 发表于 2012-11-10 22:31
如果是抢占式的调度,必须把调度程序放在中断中以达到抢占目的,lz的做法无法达到抢占,也就是第3种放在中 ...

是的。
所以我就是将那个需要抢占的任务,放置中断里面,同时用状态机来写。

出0入0汤圆

发表于 2012-11-12 09:33:13 | 显示全部楼层
Etual 发表于 2012-11-9 14:23
第一种架构可以用在实时性不高的场合,例如用户数据交换,按键100ms响应就可以了。内部执行2-3秒内完成客户 ...

都是牛掰之徒,,

出0入0汤圆

发表于 2012-11-12 10:21:10 | 显示全部楼层
这个是时间片吧

出0入0汤圆

发表于 2012-11-12 10:39:10 | 显示全部楼层
我用的和你第三种类似。

出0入0汤圆

发表于 2012-11-12 11:07:49 | 显示全部楼层
高手们的巅峰切磋!
留个印,经常来看!

出0入0汤圆

 楼主| 发表于 2012-11-12 13:08:52 | 显示全部楼层
holts2 发表于 2012-11-12 11:31
我用 轻量级操作系统 Protothread , 结构很清晰, 感觉很不错

使用Protothread实现多任务的最主要的好处在 ...

共用堆栈,应该比那种每个任务都用独立堆栈的OS要简单些,有空看看···

出0入0汤圆

发表于 2013-7-8 11:31:13 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2013-7-8 11:39:31 | 显示全部楼层
MARK.
稳定可靠是王道。
其他神马OS等等都是浮云。

出0入0汤圆

发表于 2013-7-8 11:48:50 | 显示全部楼层
收藏了                                                                                                                                                                             

出0入0汤圆

发表于 2013-7-8 13:31:32 | 显示全部楼层
不错            收藏

出0入85汤圆

发表于 2013-7-8 14:11:06 | 显示全部楼层
类似于时间片的结构了

出0入0汤圆

发表于 2013-7-8 14:29:45 | 显示全部楼层
现在基本上都用状态机,
操作系统也就自己玩玩,
工作上暂时还用不上。

出0入0汤圆

发表于 2013-7-8 14:48:10 | 显示全部楼层
收藏,55楼的结构很欣赏,可以试试

出0入0汤圆

发表于 2013-7-8 15:14:02 | 显示全部楼层

收藏了      

出0入0汤圆

发表于 2013-7-8 15:43:17 | 显示全部楼层
mark!!!!

出0入0汤圆

发表于 2013-7-8 17:07:37 | 显示全部楼层
收藏了!!!1

出0入0汤圆

发表于 2013-7-8 17:15:15 | 显示全部楼层
挺不错的参考

出0入0汤圆

发表于 2013-7-8 17:24:19 | 显示全部楼层
受用.谢楼主

出0入0汤圆

发表于 2013-7-8 20:25:59 | 显示全部楼层
类似消息的方式用的比较多。

出0入0汤圆

发表于 2013-7-8 20:35:19 | 显示全部楼层
各种不同的方法,值得学习。

出0入0汤圆

发表于 2013-7-8 20:40:41 | 显示全部楼层
MARK.

我经常用第二种

出0入0汤圆

发表于 2013-7-8 20:49:21 | 显示全部楼层
其实还有更好的架构啊,还带优先级的

出0入0汤圆

发表于 2013-7-8 20:51:16 | 显示全部楼层
貌似分一下高低速的更好,如AD转换,高速通信放主函数里,一些跟人机交互或者以s为单位的,数ms或者更长时间轮询一次就好

出0入0汤圆

发表于 2013-7-8 21:11:14 | 显示全部楼层
MRAK。 牛逼


有机会试试

出0入0汤圆

发表于 2013-7-8 21:12:15 来自手机 | 显示全部楼层
编程思想很重要,跟着各位大哥学。

出0入0汤圆

发表于 2013-7-8 21:29:04 | 显示全部楼层
MARK,,考虑优先级的话,自己上RTOS,,ucos也不错,国内RTT也好。

出0入0汤圆

发表于 2013-7-8 21:47:54 来自手机 | 显示全部楼层
学习一下

出100入143汤圆

发表于 2013-7-8 23:03:45 | 显示全部楼层
好好学习一下,自己一般都用switch事件驱动的

出0入0汤圆

发表于 2013-7-8 23:11:51 | 显示全部楼层
LZ的方法吞吐量太小了,请参考时间触发模式的调度器,同样非常简洁,在一个tick之内,一个任务运行完毕接下来运行下一个准备好的任务,不过限定了任务的类型,可以根据自己的需要进行拓展修改。

出0入0汤圆

发表于 2013-7-8 23:32:26 | 显示全部楼层
学习一下。

出0入0汤圆

发表于 2013-7-9 07:44:58 | 显示全部楼层
现在基本上都用状态机

出0入0汤圆

发表于 2013-7-9 07:49:23 | 显示全部楼层
mark一下,学习

出0入0汤圆

发表于 2013-7-9 08:34:55 | 显示全部楼层
裸奔5ms有些大了吧

出0入0汤圆

 楼主| 发表于 2013-7-9 08:59:25 | 显示全部楼层
本帖最后由 shuxmpx123 于 2013-7-9 09:02 编辑
chencc8 发表于 2013-7-8 23:11
LZ的方法吞吐量太小了,请参考时间触发模式的调度器,同样非常简洁,在一个tick之内,一个任务运行完毕接下 ...


请看55楼,应该是达到了你所说的功能!最新的结构在55楼。

出0入0汤圆

发表于 2013-7-9 09:22:03 | 显示全部楼层
好帖,支持楼主!

出0入0汤圆

发表于 2013-7-9 11:19:32 | 显示全部楼层
自己开的习惯就好。

出0入0汤圆

发表于 2013-7-9 15:58:18 | 显示全部楼层
mark,谢谢楼主!

出0入0汤圆

发表于 2013-7-9 16:28:04 来自手机 | 显示全部楼层
segeal 发表于 2012-11-9 14:10
谢谢。

后来我改进了一下,把数码管显示任务放进2ms中断里面,数码管效果很好,很正常。但是有一个问题 ...

可以用串口或Spi来驱动单总线通信

出0入0汤圆

发表于 2013-7-9 16:39:02 | 显示全部楼层
学习了

出0入0汤圆

发表于 2013-7-12 22:52:36 | 显示全部楼层
MARK,裸机一般都是这么写

出0入0汤圆

发表于 2013-7-13 11:45:09 | 显示全部楼层
这个帖子我决定要好好研究一下,吸收下各位牛人的经验,我一直用着楼主说的第一种结构,汗死

出0入0汤圆

发表于 2013-7-13 11:56:31 | 显示全部楼层
此地都是牛人

出0入8汤圆

发表于 2013-7-13 11:59:16 | 显示全部楼层
受用,常用第二种模式

出0入0汤圆

发表于 2013-7-14 15:12:22 | 显示全部楼层
很值得参考,多谢lz

出0入0汤圆

发表于 2013-7-14 15:52:48 | 显示全部楼层
以前从没仔细考虑过多任务结构问题,看来学习的东西还很多!

出140入115汤圆

发表于 2013-7-16 09:00:41 | 显示全部楼层
记号!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1

出870入263汤圆

发表于 2013-7-16 09:25:16 | 显示全部楼层
shuxmpx123 发表于 2012-11-9 11:20
恩  是的,我做的也如你1、 2点所说,延时函数不需要,因为函数运行的时间间隔是固定的,计算函数本身运 ...

对于没有RTOS的应用设计,推荐你是用瑞典大牛Adam Dunkels写的pt,简单易用,灵活直观!

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2013-7-16 11:12:20 | 显示全部楼层
了解下  学习

出0入0汤圆

发表于 2013-7-16 11:21:45 | 显示全部楼层
架构.受用.谢楼主

出0入0汤圆

发表于 2013-7-16 11:28:00 | 显示全部楼层
学习了!

出0入0汤圆

发表于 2013-7-16 11:39:35 | 显示全部楼层
学习学习,记号。

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-8-26 06:20

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

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