搜索
bottom↓
回复: 2

求教,程序从Mega16A移植到Mega8A程序无法进入中断。

[复制链接]

出0入0汤圆

发表于 2011-12-14 11:04:15 | 显示全部楼层 |阅读模式
一个从Mega16移植过来的程序,在Mega16上可正常进入中断,在Mega8a上却无法进入。
相关程序如下,各位大侠帮忙分析一下,在下已经郁闷2两天了。
********************************************************************/
#include <ctype.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#include <util/crc16.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/delay_basic.h>
#include "7299.h"
/*******************************************************************/
typedef unsigned char unchar;
typedef unsigned int  unint;
typedef unsigned long unlong;
/*******************************************************************/
#define key_set1 0xB8
#define key_set2 0xBA
#define key_up   0xB9
#define key_down 0xBB

// TWI状态定义-MT 主方式传输  MR 主方式接收
#define START                    0x08
#define RE_START                 0x10
#define MT_SLA_ACK               0x18
#define MT_SLA_NOACK             0x20
#define MT_DATA_ACK              0x28
#define MT_DATA_NOACK            0x30
#define MR_SLA_ACK               0x40
#define MR_SLA_NOACK             0x48
#define MR_DATA_ACK              0x50
#define MR_DATA_NOACK            0x58
//常用TWI操作(主模式写和主模式读)
#define Start()                        (TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN))
#define Stop()                        (TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN))
#define Wait()                               {while(!(TWCR&(1<<TWINT)));}
#define TestAck()                     (TWSR&0xf8)
#define SetAck()                    (TWCR|=(1<<TWEA))
#define SetNoAck()              (TWCR&=~(1<<TWEA))
#define Twi()                              (TWCR=(1<<TWINT)|(1<<TWEN))
#define Write8Bit(x)            {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);}
//显示常用操作
#define Display() I2c_WriteN(Reg7299_DisDate0R,dis_data,5)
//modbus
#define mb_idle 0 //MB总线空闲状态
#define mb_send 1 //正在发送数据
#define mb_received 2 //接收完数据
#define tx_en PORTD = PORTD|0x04 //串口发送控制使能
#define rx_en PORTD = PORTD&0xFB //串口接收控制使能
/*********************************************************/
//定义功能函数
void  Initialize(void);
unsigned char I2c_Write(unsigned char SubAddress, unsigned char Wdata);
unsigned char I2c_WriteN(unsigned char SubAddress,unsigned char *p,unsigned char N);
unsigned char I2c_Read(unsigned char SubAddress,unsigned char *StoreAddr);
void AD7705_Writereg(unsigned char com, unsigned char reg);
unsigned int AD7705_Read(unsigned char com);
void AD7705_Ini(void);
void Measure(void);
void relay_set(void);
void DAC(void);

void menu(void);
void LP_Set(void);
void ALA1_Set(void);
void ALA2_Set(void);
void HYS_Set(void);
void ADD_Set(void);
void BAUD_Set(void);


void USART_Ini(void);
void Mbtimer_On(void);
void Mb_Response(void);
void Mbdata_Send(void);
unint Crc_Received(void);
void Crc_Send(void);
/******************************************************************/
ISR(TIMER0_OVF_vect)//定时器0溢出中断服务程序,菜单计时
{
        secs++;
}
/******************************************************************/
ISR(INT1_vect)
{
        I2c_Read(Reg7299_KeyValue,&key);
        //I2c_Write(Reg7299_DisFlash0,0xff);
}
/******************************************************************/
ISR(TIMER2_OVF_vect)//定时器2溢出中断服务程序,中断时表明一次命令接收已经完成
{
        TIMSK &= 0xBF;//关闭定时器2溢出中断
        mb_status = mb_received;
        receive_no = 0;
}

/******************************************************************/
ISR(USART_RXC_vect)//串行口接收一帧数据结束中断
{
        unchar i;
        i = UDR;
        if((receive_no < 8)&&(mb_status == mb_idle))
        {
                mb_receive[receive_no] = i;
                receive_no++;
        }
        Mbtimer_On();
}
/******************************************************************/
ISR(USART_TXC_vect)//串行口发送一帧数据结束中断
{
        send_no = 0;
        rx_en;//释放总线,转入接收状态
        //UCSRB = 0xD8;
        mb_status = mb_idle;
}
/******************************************************************/
ISR(USART_UDRE_vect)//串行口发送寄存器空中断
{
        if(send_no <= 6)
        {
                UDR = send_data[send_no];
                send_no++;
        }
        else
        {
                UCSRB = 0xD8;//数据传送完后关闭寄存器空中断,否则将陷入死循环
        }
}
/******************************************************************/

/******************************************************************/
void menu(void)
{
        void (*Menu_Step2[6])(void)=
        {
                LP_Set,
                ALA1_Set,
                ALA2_Set,
                HYS_Set,
                ADD_Set,
                BAUD_Set,
        };
        TIMSK |= 1<<TOIE0;
        menu_item = 0;
        key = 1;
        secs = 0;
        while(secs < 211)
        {
                wdt_reset();
                if(key)
                {
                        secs = 0;
                        switch(key)
                        {
                                case key_set1:        secs = 211;                                                break;
                                case key_set2:        (*Menu_Step2[menu_item])();                break;
                                case key_up:        menu_item = (menu_item + 1)%6;        break;
                                case key_down:        menu_item--;                                        break;
                                default:                 break;
                        }
                        if(menu_item == 255)
                        {
                                menu_item = 5;
                        }
                        key = 0;
               
                        switch(menu_item)
                        {
                                case 0:
                                        {
                                                dis_data[0] = 0x1A;
                                                dis_data[1] = 0x1B;
                                                dis_data[2] = 0x10;
                                                dis_data[3] = 0x10;
                                         }
                                        break;        //显示"LP"

                                case 1:       
                                        {
                                                dis_data[0] = 0x0A;
                                                dis_data[1] = 0x1A;
                                                dis_data[2] = 0x0A;
                                                dis_data[3] = 0x01;
                                         }
                                        break;        //显示"ALA1"
                                case 2:       
                                        {
                                                dis_data[0] = 0x0A;
                                                dis_data[1] = 0x1A;
                                                dis_data[2] = 0x0A;
                                                dis_data[3] = 0x02;
                                         }
                                        break;        //显示"ALA2"
                                case 3:       
                                        {
                                                dis_data[0] = 0x19;
                                                dis_data[1] = 0x1D;
                                                dis_data[2] = 0x05;
                                                dis_data[3] = 0x10;
                                         }
                                        break;        //显示"HYS"
                                case 4:       
                                        {
                                                dis_data[0] = 0x0A;
                                                dis_data[1] = 0x0D;
                                                dis_data[2] = 0x0D;
                                                dis_data[3] = 0x10;
                                         }
                                        break;        //显示"ADD"
                                case 5:       
                                        {
                                                dis_data[0] = 0x0B;
                                                dis_data[1] = 0x0A;
                                                dis_data[2] = 0x1C;
                                                dis_data[3] = 0x0D;
                                         }
                                        break;        //显示"BAUD"

                                default:        break;
                                }               
                        Display();
                }
        }
        TIMSK &= 0xFE;        //关闭定制器0溢出中断
}
/******************************************************************/
void Initialize(void)
{
        DDRD  = 0x84;
        PORTD = 0x09;
       
        DDRB  = 0x2B;
        PORTB = 0x14;

        PORTC = 0x30;//TWI使能内部上拉电阻

        MCUCR = 0x08;
        GICR =  0x80; //使能外部中断1(键盘中断),下降沿有效
        key = 0;
        TWBR = 0x67;   //设定I2C总线波特率为1/222 CPU主频(11.0592)

        TCCR0 = 0x05;        //初始化定时器0,1024主时钟分频;
    //初始化计时器1为快速PWM模式(WGM13:0= 0B1110),设置成占空比50%的频率发生器
        OCR1AH = 0x08;      
        OCR1AL = 0xF2;
        ICR1H = 0x11;
        ICR1L = 0xE5;   //初始化25摄氏度时的频率
        TCCR1A = 0x82;
        TCCR1B = 0x18;



        /*EEPROM设定数据加载 */
        eeprom_busy_wait();
        relay1 = eeprom_read_word((const unint*)0);
        eeprom_busy_wait();
        relay2 = eeprom_read_word((const unint*)2);
        eeprom_busy_wait();
        RTD_type = eeprom_read_byte((const unchar*)4);
        eeprom_busy_wait();
        hys = eeprom_read_byte((const unchar*)7);
        eeprom_busy_wait();
        com_add = eeprom_read_byte((const unchar*)8);
        eeprom_busy_wait();
        com_baud = eeprom_read_byte((const unchar*)9);

        USART_Ini();

        AD7705_Ini();

        I2c_Write(Reg7299_DisDecode0,0xff);//设定LED显示当前组为译码显示
        I2c_Write(Reg7299_DisFlash0,0x00); //所有位均不闪烁

        sei();                                        //使能全局中断使能       
        wdt_enable(WDTO_2S );
        wdt_reset();
       
}

/******************************************************************/
int main(void)
{
        Initialize();
        while(1)
        {
                wdt_reset();//喂狗
                if(key == key_set1)
                {
                        menu();
                        key = 0;
                }

                //if(mb_status == mb_received)//响应MODBUS通讯
                //{
                //        Mb_Response();
                //}
                //menu();
                //Measure();       
                //relay_set();//报警点输出
       
                Display();
        }
        return 0;
}

/******************************************************************/
如上程序,无法进入键盘中断,键盘中断是INT1,已经用示波器看过,按键后中断电平变化没有问题。
如果修改主程序,将if(key = key_set1)改为if(1)强制进入菜单,或者在主循环中直接调用菜单,都能进入菜单,且进入菜单后键盘正常响应。
不修改主程序,在中断中加入显示闪烁命令,按键时也无反应。
编译环境:AVR STUDIO 4.18 + WINAVR20100110,无优化,下载器用的双龙USB ISP II
熔丝位 低字节 7F 高字节D9

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2011-12-14 15:06:49 | 显示全部楼层
回复【楼主位】xionghuioo7
-----------------------------------------------------------------------
自己顶一下,这个问题实在太奇怪了,这么简单的主程序,没有任何有关中断寄存器的操作,就是不能进中断,强行进入菜单后中断一切正常,但是菜单中也没有关于中断1的寄存器操作,太想不通了。怀疑是芯片问题,芯片我都换过了,还是一样啊。

出0入0汤圆

 楼主| 发表于 2011-12-15 11:14:56 | 显示全部楼层
回复【1楼】xionghuioo7
-----------------------------------------------------------------------
终于找到问题了,Mega8A的中断1服务程序,不能调用带参数的函数,我试了N种办法,只要调用带参数的函数,就失去中断响应。但是非常非常奇怪,在功能函数里中断能正常运行,在主函数里就是不行。当然以上结论只适用与本菜的这个程序,不知道在其他程序里有没有这样的问题。俺主要是搞硬件设计,C语言很菜,哪位大侠指点迷津啊。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-26 08:58

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

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