⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inter.c

📁 这是Mega8I2c通讯时的主机访问程序.
💻 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 + -