打印
[AVR单片机]

GCC优化疑问,请高手支着

[复制链接]
3871|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cooperate|  楼主 | 2008-3-21 11:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
    本周用tiny24做了一个曼码解码的程序,前后台方式,用Timer0匹配中断定时.平台选用avrStudio4.12 + GCC.

    当选择优化级别0时,结果与预期相同。但当选择级别1/2/s时就不行了,后来换avrStudio4.13和GCC各种版本,都是一样。因为Tiny24只有2K的空间,不优化又没办法再加点灯光驱动代码。

    折腾了3天,实在没辙,换ICC6.31后搞掂。而且ICC6.31编译出来的代码长度比GCC不优化时生成的代码小,难道真是天下没有免费的午餐?应该不会啊,以前也用GCC做了M8的小项目,也没问题。

    难道是GCC不能很好支持ATtiny24的原因?难道是俺电脑中上海政府版XP版(盗版)的问题?难道是....?郁闷中,恳请高手指点

相关帖子

沙发
cooperate|  楼主 | 2008-3-21 11:19 | 只看该作者

主要代码如下

#pragma interrupt_handler    Timer0_Int:iv_TIMER0_COMPA

void Timer0_Int(void)                //Timer0匹配中断
{
    //解码过程相关
    if(scan_card_online)
     {
            if(timer0_counter < PLUS_LONG_MAX) timer0_counter++;
     }
     else timer0_counter = 0;
    
     //系统定时时钟相关
     if(system_counter < SYSTEM_CYCLE) system_counter++;
     else
     {
            system_counter = 0;
            system_clock = 1;
     }
}

int main(void)
{
     //Initial_System();
     Initial_Cpu();
    
     Buzzer_On();
     Delay_100us(252);
     Buzzer_Off();
     scan_interval_value = VALID_INTERVAL_VALUE;
     
        //设置中断变量
     TIMSK0 = (1 << OCIE0A);                //Timer0匹配A中断允许
     //D7        D6        D5        D4        D3        D2        D1        D0    
     //-            -        -        -        -        OCIE0B    OCIE0A    TOIE0
    WDTCSR = (1 << WDCE) | (1 <<WDE);
     WDTCSR = (1 << WDE) | (1 << WDP2) | (1 << WDP0);        //定时0.52s
     sei();                        //开总中断  

     while(1)
     {
            //系统任务1:解码及处理    
        if(scan_card_ok)   //解码成功,进行处理     
        {    
                scan_card_ok = 0;
                Output_Wegn(); 
                
                buzzer_mode = 1;
                buzzer_counter = 0;
            scan_interval_counter=1;
            }
        else                    //未解码成功,每16ms进行一次刷卡扫描                       
            {
               if(scan_card_enable)
              {
                    scan_card_enable = 0;    

                    scan_card_online = 1;
                    Plus_Width_Compare();
                    //脉冲宽度正常则解码,以避免占用太多的主循环时间
                    if(plus_width_ok)
                    {
                        plus_width_ok = 0;
                        scan_card_online = 1;
                        Scan_Card();    
                    }
                    else 
                    {
                        if(card_same_counter) card_same_counter--;
                    }
                }           
            }
                                                   
            //任务2:刷新16ms定时任务
            if(system_clock)
            {    
                Refresh_16ms_Task();
                system_clock = 0;
            }
    }
    return(0);
}


void Initial_Cpu(void)
{
   cli();

    //定义蜂鸣器、知识灯驱动引脚为输出
    DDRA = 0x7F;                //除曼码输入外,其它均为输出
    PORTA = (1 << BUZZER) | (1 << BLUE_LED) | (1 << RED_LED) | (1 << RF_IN);
    //DDRB = 0x04;    

    //比较匹配时触发OC1A翻转,产生载波脉冲输出
    TCCR1A = (1 << COM1A0);                            
    //D7        D6        D5        D4        D3        D2        D1        D0    
    //COM1A1    COM1A0    COM1B1    COM1B0    FOC1A    FOC1B    WGM11    WGM10
    TCCR1B = (1 << WGM12) | (1 << CS11);        //T/C1时钟源为系统时钟/8,Timer1工作于CTC模式
    //D7        D6        D5        D4        D3        D2        D1        D0    
    //ICNC1        ICES1            WGM13    WGM12    CS12    CS11    CS10
    OCR1A = 3;                //Foc1a = Fclk / 2N(1 + OCR1A)
    TCNT1 = 0;

    //设置Timer0中断60us
    TCCR0A = (1 << WGM01);                        //Timer0工作于CTC模式,
    //D7        D6        D5        D4        D3        D2        D1        D0    
    //COM0A1    COM0A0    COM0B1    COM0B0    -        -        WGM01    WGM00
    TCCR0B = (1 << CS01);                        //T/C0时钟源为系统时钟/8
    //D7        D6        D5        D4        D3        D2        D1        D0    
    //FOC0A        FOC0B    -        -        WGM02    CS02    CS01    CS00    
    OCR0A = PRESCALE_VAL - 1;
    TCNT0 = 0;
}


void Refresh_16ms_Task(void)
{
   asm("WDR");

    //16ms级别的任务一:解码时间间隔判断
     if(scan_interval_counter)
     {
            if(scan_interval_counter >= scan_interval_value) 
            {
                scan_interval_counter=0;
                scan_card_enable = 1;
            }
            else scan_interval_counter++;    
     }
     else 
     {
            scan_card_enable = 1;
     }
    
     //32ms任务二:蜂鸣器控制
    if(buzzer_mode)
    {
            if(buzzer_counter >= VALID_BUZZER_MAX)
            {
                buzzer_mode=0;buzzer_counter=0;
                Buzzer_Off();Blue_Led_Off(); 
            }
            else
            {
                Buzzer_On();Blue_Led_On();
            }
            buzzer_counter++; 
     }
    else 
     {
            if(led_status == 0)
        { 
                PORTA |= (1 <<RED_LED);
                led_status = 1;
         }
         else
         {
                PORTA &= ~(1 << RED_LED);
                led_status = 0;    
         }
        }         
}

使用特权

评论回复
板凳
ATmega32L| | 2008-3-21 18:39 | 只看该作者

注意中断与主程序共用的全局变量要定义成volatile

注意中断与主程序共用的全局变量要定义成volatile

使用特权

评论回复
地板
cooperate|  楼主 | 2008-3-22 16:50 | 只看该作者

多谢楼上关注和指点,我再试试

使用特权

评论回复
5
wylinder| | 2008-3-28 13:44 | 只看该作者

我也碰到如上朋友碰到的GCC编译的问题

我也碰到如上朋友碰到的GCC编译的问题,我采用的ATMEGA168芯片,本来考虑这个产品采用8,或者88就应该足够了,调试的时候保险起见用的168进行调试的,没想到最终软件编译完成后代码空间要大于16K,采用-01,0S方案进行了优化,代码空间减少近1半,但是正如上面朋友提到的,运行不下来。折腾了挺久,实在不行了,切换到汇编页面,用单步执行的方法跟踪,发现有些本来有用的语句被他给优化掉了,当然程序工作不正常了。后来没辙了,只能将程序空间的一些const变量放进EEPROM中,总算节省了些空间,才算搞定。GCC这个编译器真是很差劲,还有哪些朋友使用过,请共享一下经验好吧?注:我这个程序没有采用中断方式。另,请楼上的朋友告知,ICC6.31这个软件那里可以下载?是否有**版本的?能否支持avrstudio?谢谢!

使用特权

评论回复
6
simon21ic| | 2008-3-30 17:23 | 只看该作者

GCC很差劲吗?

我怎么从来没有碰到问题,代码当然基本都是-Os优化。
GCC的优化,可能会使得一些在中断中使用的易变的变量在主循环中没有更新,或者优化掉了GCC认为的无意义的延时代码。

使用特权

评论回复
7
ATmega32L| | 2008-3-31 09:13 | 只看该作者

GCC是非常优秀的编译器

GCC是非常优秀的编译器。不会优化是使用者自身的问题。

使用特权

评论回复
8
cooperate|  楼主 | 2008-4-1 11:17 | 只看该作者

感谢ATmega32L

    大虾就好人做到底,给俺们菜鸟讲讲GCC的优化技巧.不胜感激.
    
    wylinder网友,baidu以下就有了,然后再找一个注册机就可以了.注意要声明自己是学习用哦,呵呵

使用特权

评论回复
9
dai_weis| | 2008-4-1 12:14 | 只看该作者

讲优化技巧,还是建议看看C的数据结构和逻辑关系

很多情况下是数据的访问之间逻辑关系不够清晰导致。

使用特权

评论回复
10
au_szsj| | 2008-4-6 15:48 | 只看该作者

有同感!!

也是相类似的问题,在更改了优化级**,就出现了有用代码给删除的现象。


有没有高手可以讲讲怎么解决这个问题?

使用特权

评论回复
11
cooperate|  楼主 | 2008-4-8 10:56 | 只看该作者

希望有高手能指点一二

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

230

帖子

0

粉丝