redsnow 发表于 2007-3-13 08:42:08

UCos-II 2.76 MEGA64 16M时钟 tick = 100HZ GCC 任务间共享数据的问题

UCos-II 2.76 MEGA64 16M时钟 GCC 任务间共享数据的问题



volatile unsigned int g_adc_data;//使用关键字声明

//Task1 循环的不停的采集数据

void Task1 (void *data)

{

        unsigned char ADChannel=0;

        data = data;   /* Prevent compiler warning                         */

        ADChannel=0;

        ADMUX = 0x40+(ADChannel);//参考源VCC,右对齐,选择0通道。

        ADCSRA|=(1<<ADSC);//启动转换

        for (;;)

        {

                while(ADCSRA&0x10)

                {

                        NOP();

                }

                g_adc_data= ADC;

                OS_ENTER_CRITICAL();

                g_adc_data = ADC;

                //_delay_us(1);//也不行

                OS_EXIT_CRITICAL();

                OSTimeDlyHMSM(0,0,0,1);////间隔采集数据,问题在这里,如果延时太短小于6ms,感觉g_adc_data就没有被修改,下面任务打印出的都是第一次采集到的数据

                ADCSRA|=(1<<ADSC);//启动下一次转换

        }

}



//Task2 循环的不停的打印采集到的数据

void Task2 (void *data)

{

        for(;;)

        {

                OS_ENTER_CRITICAL();

                Printf("通道数据是 %d\r
",g_adc_data);

                OS_EXIT_CRITICAL();

                OSTimeDlyHMSM(0,0,2,0);//每2秒打印一次数据,如果上面任务中的采集间隔(OSTimeDlyHMSM(0,0,0,6))太短低于6ms就打印出相同的数据,g_adc_data没有被改变过??????,但如果采集间隔大于6ms打印就是对的

        }

}



我这种任务间共享数据的方法是不是有问题????请大家指点一下,谢谢

redsnow 发表于 2007-3-13 08:44:13

后面我将OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()换成OSSchedLock()和OSSchedUnlock() 问题依旧

lzy_ 发表于 2007-3-13 08:58:15

我觉得第一个问题里面,你还需要判断AD是否转换完毕,未转换完则继续挂起自己.

任务1可以给任务2发送消息的(好象是这么叫,不太清楚了).也就是任务一采集完数据后,可以挂起本身,把CPU让给任务2,让任务2打印出来.

redsnow 发表于 2007-3-13 09:00:51

while(ADCSRA&0x10)

      {

         NOP();

      }

这个就是判断AD是否完成的代码

redsnow 发表于 2007-3-13 09:04:55

一直没有找到为什么g_adc_data没有改变的根本原因,使用volatile关键字声明,这种方式不对吗,还是其他的原因??

lzy_ 发表于 2007-3-13 09:07:22

while(ADCSRA&0x10)

      {

         OSTimeDlyHMSM(0,0,0,1);

      }

至少要这样.你之前那么写起不了作用.后面的那句OSTimeDlyHMSM(0,0,0,1); 可以不要了.想用多任务就不应该出现死等的情况.

redsnow 发表于 2007-3-13 09:19:12

while(ADCSRA&0x10)   

      {   

         OSTimeDlyHMSM(0,0,0,1);

      }

//实际进行一次转换上这个要不了1ms啊,是不是有点浪费了



谢谢各位对本贴的关注

redsnow 发表于 2007-3-13 09:55:48

一般各位在任务间共享数据采用的是什么方式啊,特别是共享一些数组

redsnow 发表于 2007-3-14 09:46:51

while(ADCSRA&0x10)   

      {   

         OSTimeDlyHMSM(0,0,0,1);

      }

至少要这样.你之前那么写起不了作用.后面的那句OSTimeDlyHMSM(0,0,0,1); 可以不要了.想用多任务就不应该出现死等的情况.





   我试了一下,问题依旧,而且我还发现一个现象,比如说我两个任务要共享一个全局变量,或者一个数组,A任务修改了全局变量或者数组,B任务要使用该全局变量,一个办法是A任务修改了全局变量或者数组后OSTimeDlyHMSM(0,0,0,6) (而且不能比6小 ),B任务才能够使用到正确的共享数据,OSTimeDlyHMSM太短,如OSTimeDlyHMSM(0,0,0,3),B任务就不能够使用到正确的数据。另外一个办法是,A任务修改了全局变量后OSTimeDlyHMSM(0,0,0,1),然后B在使用该共享数据前OSTimeDlyHMSM(0,0,0,6)或者更久,B也能使用到正确的数据,真是很奇怪,是不是OS_CFG.H里有什么没有配置好????

redsnow 发表于 2007-3-14 10:14:56

看来我走到死胡同了,无解???

gingin 发表于 2007-3-14 19:57:34

问一下,你的Task1和Task2的优先级状况,系统的tick是多少ms?

可以看一下      g_adc_data = ADC;



      OS_ENTER_CRITICAL();

      Printf("通道数据是 %d\r
",g_adc_data);

      OS_EXIT_CRITICAL();

这两段的汇编代码,确认是否是从变量地址读取的。



另外,你只是在那个位置把OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()换成OSSchedLock()和OSSchedUnlock() 效果应该是一样的,任务调度是依赖于定时中断的。
-----此内容被gingin于2007-03-14,19:59:29编辑过

redsnow 发表于 2007-3-15 10:26:43

我现在发现了问题,就是堆栈溢出,导致Task1 挂了,挂了以后,TASK2去访问g_adc_data的数据就会出现g_adc_data每次读出来的数据都是一样的,但是我加大Task1的堆栈,只能保证Task1 跑得久一点,但最终也会挂掉,我将堆栈加大到512字节了,只能跑得更久一点,操作系统是在本网上下载的es_m128_test_board_by_yfzhang\ATmega128实验板里面的程序修改的,在此感谢yfzhang,不知到是不是这个移植的还不够完美,有一点BUG,请大家看看,能否帮帮我,谢谢

点击此处下载armok01146583.rar

lzy_ 发表于 2007-3-15 10:59:58

???

ucos ii有本挺厚的书,是英文原版翻译过来的.早就出现在国内的.应该至少仔细看看书啊.

全局变量共享,信号量,互斥型信号量,油箱,消息队列,中断.这些都可以实现.

mymcu_261 发表于 2007-3-15 13:46:48

我现在也在研究堆栈溢出问题,不好办呀

John_Lee 发表于 2007-3-15 22:55:20

这个就是生产者/消费者的模式,其实要实现楼主的功能,1个任务就可以了(除了idle任务以外),这个任务是消费者,生产者用中断服务程序就可以实现了。

大致的流程如下:

// 消费者任务

void consumer (void *)

{

    建立消息队列(OSQCreate);

    设置ADC中断处理;

    启动第一次ADC;

    while (1) {

      等待消息(OSQPend);

      打印数据;

    }

}

// 生产者中断服务

isr producer ()

{

    读取ADC结果;

    将结果数据作为消息发送到消息队列(OSQPost);

    启动下一次ADC;

}

redsnow 发表于 2007-3-16 09:21:18

谢谢John_Lee,我去试试
页: [1]
查看完整版本: UCos-II 2.76 MEGA64 16M时钟 tick = 100HZ GCC 任务间共享数据的问题