|
一个从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来反美的!
|