📄 inter.c
字号:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
#include <avr/delay.h>
#include <compat/twi.h>
#include "main.h"
#include "init.h"
#include "inter.h"
volatile uint8_t flag0; //中断事件标志
volatile uint8_t remote[4]; //保存捕捉值
extern volatile uint16_t cnt_t0; //记录t0发生的次数
/*外部中断0*/
SIGNAL(SIG_INTERRUPT0);
/*外部中断1*/
SIGNAL(SIG_INTERRUPT1)
{
uint8_t i,tem;
uint16_t temp=0,t=0;
uint16_t temp1=0;
GICR &= ~_BV(INT1); //关外部中断
SREG |= 0x80;
sei();
tem = cnt_t0;
while((cnt_t0-tem) <= 8);
if((PIND & 0x08)==0) //开始沿
{
delay_ms(1);
t = 0;
while((PIND & 0x08) == 0)//等上升沿
{
t++;
delay_us(1);
if(t >= 2550)
break;
}
cnt_t0=0;
while(cnt_t0<=25);
if((PIND & 0x08) == 0x00 ) //连续按键
{
flag0 |= _BV(FLAG0_KEEP);
}
else //开始正常接收码
{
t = 0;
while((PIND & 0x08) == 0x08) //等待下降沿
{
t++;
delay_us(1);
if(t >= 2550)
break;
}
for(i=0;i<16;i++)
{
t = 0;
while((PIND & 0x08) == 0) //等待上升沿
{
t++;
delay_us(1);
if(t >= 2550)
break;
}
cnt_t0 = 0;
while(cnt_t0 <= 8);
if((PIND & 0x08) == 0) //此脉冲为0
{
temp<<=1;
}
else //此脉冲为1
{
temp<<=1;
temp |=1;
t = 0;
while((PIND & 0x08) == 0x08) //等待下降沿
{
t++;
delay_us(1);
if(t >= 2550) //
break;
}
}
}
for(i=0;i<16;i++)
{
t = 0;
while((PIND & 0x08) == 0) //等待上升沿
{
t++;
delay_us(1);
if(t >= 2550) //
break;
}
cnt_t0 = 0;
while(cnt_t0<=8);
if((PIND & 0x08) == 0) //此脉冲为0
{
temp1<<=1;
}
else //此脉冲为1
{
temp1<<=1;
temp1 |=1;
t = 0;
while((PIND & 0x08) == 0x08) //等待下降沿
{
t++;
delay_us(1);
if(t >= 2550) //
break;
}
}
}
remote[0]=(uchar)(temp&0x00ff);/*家族码*/
remote[1]=(uchar)((temp>>8)&0x00ff);/*家族码反码*/
remote[2]=(uchar)(temp1&0x00ff); //按键码
remote[3]=(uchar)((temp1>>8)&0x00ff); //按键码反码
flag0 |= _BV(FLAG0_CODE);
/*注意此处等待停止位容易死等状态,加定时器中断跳出 */
t = 0;
while((PIND & 0x08) == 0) //等待停止位上升沿
{
t++;
delay_us(1);
if(t >= 2550) //
break;
}
}
}
GIFR |= _BV(INTF1);
GICR |= _BV(INT1); //打开外部中断
sei();
}
/*定时器2溢出*/
SIGNAL(SIG_OVERFLOW2) ;
/*定时器1捕获事件*/
SIGNAL(SIG_INPT_CAPTURE1);
/*定时器1比较匹配A*/
SIGNAL(SIG_OUTPUT_COMPARE1A);
/*定时器1比较匹配B*/
SIGNAL(SIG_OUTPUT_COMPARE1B);
/*定时器1溢出*/
SIGNAL(SIG_OVERFLOW1) ;
/*定时器0溢出*/
SIGNAL(SIG_OVERFLOW0)
{
TCNT0 = 0x9B; //set count 100个数定时0.1毫秒
// flag0 |= _BV(FLAG0_T0);
++cnt_t0;
wdt_reset();
}
/*SPI传输完成*/
EMPTY_INTERRUPT(SIG_SPI);
/*串口正确收到1字节*/
EMPTY_INTERRUPT(SIG_UART_RECV);
/*发送寄存器空*/
EMPTY_INTERRUPT(SIG_UART_DATA);
/*串口成功发送一字节*/
EMPTY_INTERRUPT(SIG_UART_TRANS);
/*ADC转换完成*/
EMPTY_INTERRUPT(SIG_ADC);
/*EEPROM准备好*/
EMPTY_INTERRUPT(SIG_EEPROM_READY);
/*模拟比较器中断*/
EMPTY_INTERRUPT(SIG_COMPARATOR);
/*TWI中断*/
/*EMPTY_INTERRUPT(SIG_2WIRE_SERIAL)
{//IIC中断
unsigned char action,state,status;
action=strTWI.SLA&TW_READ; //取操作模式
state=strTWI.STATE;
status=TWSR&0xF8; //屏蔽预分频位
if ((status>=0x60)||(status==0x00))
{//总线错误或从机模式引发的中断,不予处理
return;
}
switch(state)
{
case ST_START: //START状态检查
if(status==TW_START)
{//发送start信号成功
TWDR=strTWI.SLA&0xFE; //发送器件地址写SLAW
TWCR=TW_ACT; //触发下一步动作,同时清start发送标志
}
else
{//发送start信号出错
state=ST_FAIL;
}
break;
case ST_SLAW: //SLAW状态检查
if(status==TW_MT_SLA_ACK)
{//发送器件地址成功
TWDR=strTWI.ADDR; //发送eeprom地址
TWCR=TW_ACT; //触发下一步动作
}
else
{//发送器件地址出错
state=ST_FAIL;
}
break;
case ST_WADDR: //ADDR状态检查
if(status==TW_MT_DATA_ACK)
{//发送eeprom地址成功
if (action==TW_READ)
{//读操作模式
TWCR=(1<<TWSTA)|TW_ACT; //发送restart信号,下一步将跳到RESTART分支
}
else
{//写操作模式
TWDR=*strTWI.pBUF++; //写第一个字节
strTWI.DATALEN--;
state=ST_WDATA-1; //下一步将跳到WDATA分支
TWCR=TW_ACT; //触发下一步动作
}
}
else
{//发送eeprom地址出错
state=ST_FAIL;
}
break;
case ST_RESTART: //RESTART状态检查,只有读操作模式才能跳到这里
if(status==TW_REP_START)
{//发送restart信号成功
TWDR=strTWI.SLA; //发器件地址读SLAR
TWCR=TW_ACT; //触发下一步动作,同时清start发送标志
}
else
{//重发start信号出错
state=ST_FAIL;
}
break;
case ST_SLAR: //SLAR状态检查,只有读操作模式才能跳到这里
if(status==TW_MR_SLA_ACK)
{//发送器件地址成功
if (strTWI.DATALEN--)
{//多个数据
TWCR=(1<<TWEA)|TW_ACT; //设定ACK,触发下一步动作
}
else
{//只有一个数据
TWCR=TW_ACT; //设定NAK,触发下一步动作
}
}
else
{//发送器件地址出错
state=ST_FAIL;
}
break;
case ST_RDATA: //读取数据状态检查,只有读操作模式才能跳到这里
state--; //循环,直到读完指定长度数据
if(status==TW_MR_DATA_ACK)
{//读取数据成功,但不是最后一个数据
*strTWI.pBUF++=TWDR;
if (strTWI.DATALEN--)
{//还有多个数据
TWCR=(1<<TWEA)|TW_ACT; //设定ACK,触发下一步动作
}
else
{//准备读最后一个数据
TWCR=TW_ACT; //设定NAK,触发下一步动作
}
}
else if(status==TW_MR_DATA_NACK)
{//已经读完最后一个数据
*strTWI.pBUF++=TWDR;
TWCR=(1<<TWSTO)|TW_ACT; //发送停止信号,不会再产生中断了
strTWI.STATUS=TW_OK;
}
else
{//读取数据出错
state=ST_FAIL;
}
break;
case ST_WDATA: //写数据状态检查,只有写操作模式才能跳到这里
state--; //循环,直到写完指定长度数据
if(status==TW_MT_DATA_ACK)
{//写数据成功
if (strTWI.DATALEN)
{//还要写
TWDR=*strTWI.pBUF++;
strTWI.DATALEN--;
TWCR=TW_ACT; //触发下一步动作
}
else
{//写够了
TWCR=(1<<TWSTO)|TW_ACT; //发送停止信号,不会再产生中断了
strTWI.STATUS=TW_OK;
//启动写命令后需要10ms(最大)的编程时间才能真正的把数据记录下来
//编程期间器件不响应任何命令
}
}
else
{//写数据失败
state=ST_FAIL;
}
break;
default:
//错误状态
state=ST_FAIL;
break;
}
if (state==ST_FAIL)
{//错误处理
strTWI.FAILCNT++;
if (strTWI.FAILCNT<FAIL_MAX)
{//重试次数未超出最大值,
TWCR=(1<<TWSTA)|TW_ACT; //发生错误,启动start信号
}
else
{//否则停止
TWCR=(1<<TWSTO)|TW_ACT; //发送停止信号,不会再产生中断了
strTWI.STATUS=TW_FAIL;
}
}
state++;
strTWI.STATE=state; //保存状态
}*/
/*写程序存储器准备好*/
EMPTY_INTERRUPT(SIG_SPM_READY);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -