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打印就是对的
}
}
我这种任务间共享数据的方法是不是有问题????请大家指点一下,谢谢 后面我将OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()换成OSSchedLock()和OSSchedUnlock() 问题依旧 我觉得第一个问题里面,你还需要判断AD是否转换完毕,未转换完则继续挂起自己.
任务1可以给任务2发送消息的(好象是这么叫,不太清楚了).也就是任务一采集完数据后,可以挂起本身,把CPU让给任务2,让任务2打印出来. while(ADCSRA&0x10)
{
NOP();
}
这个就是判断AD是否完成的代码 一直没有找到为什么g_adc_data没有改变的根本原因,使用volatile关键字声明,这种方式不对吗,还是其他的原因?? while(ADCSRA&0x10)
{
OSTimeDlyHMSM(0,0,0,1);
}
至少要这样.你之前那么写起不了作用.后面的那句OSTimeDlyHMSM(0,0,0,1); 可以不要了.想用多任务就不应该出现死等的情况. while(ADCSRA&0x10)
{
OSTimeDlyHMSM(0,0,0,1);
}
//实际进行一次转换上这个要不了1ms啊,是不是有点浪费了
谢谢各位对本贴的关注 一般各位在任务间共享数据采用的是什么方式啊,特别是共享一些数组 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里有什么没有配置好???? 看来我走到死胡同了,无解??? 问一下,你的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编辑过 我现在发现了问题,就是堆栈溢出,导致Task1 挂了,挂了以后,TASK2去访问g_adc_data的数据就会出现g_adc_data每次读出来的数据都是一样的,但是我加大Task1的堆栈,只能保证Task1 跑得久一点,但最终也会挂掉,我将堆栈加大到512字节了,只能跑得更久一点,操作系统是在本网上下载的es_m128_test_board_by_yfzhang\ATmega128实验板里面的程序修改的,在此感谢yfzhang,不知到是不是这个移植的还不够完美,有一点BUG,请大家看看,能否帮帮我,谢谢
点击此处下载armok01146583.rar ???
ucos ii有本挺厚的书,是英文原版翻译过来的.早就出现在国内的.应该至少仔细看看书啊.
全局变量共享,信号量,互斥型信号量,油箱,消息队列,中断.这些都可以实现. 我现在也在研究堆栈溢出问题,不好办呀 这个就是生产者/消费者的模式,其实要实现楼主的功能,1个任务就可以了(除了idle任务以外),这个任务是消费者,生产者用中断服务程序就可以实现了。
大致的流程如下:
// 消费者任务
void consumer (void *)
{
建立消息队列(OSQCreate);
设置ADC中断处理;
启动第一次ADC;
while (1) {
等待消息(OSQPend);
打印数据;
}
}
// 生产者中断服务
isr producer ()
{
读取ADC结果;
将结果数据作为消息发送到消息队列(OSQPost);
启动下一次ADC;
} 谢谢John_Lee,我去试试
页:
[1]