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

📄 main.c

📁 这是Mega8I2c通讯时的主机访问程序.
💻 C
字号:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/delay.h>
#include <avr/wdt.h>
#include <compat/twi.h>
#include "main.h"
#include "init.h"
#include "inter.h"
#include "func.h"

#define rd_device_add 0xa1 //读地址:0b10100001
#define wr_device_add 0xa0 //写地址:0b10100000
#define EE_READ							0xf0
#define EE_READ_OK					0x50
#define EE_WRITE						0x0f
#define EE_WRITE_OK					0x05
#define EE_WRITE_OVER				0xa5

#define Start()						(TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE))
//清除中断标志位,在总线上发出起始信号,激活TWI功能,开放TWI中断
#define Stop()						(TWCR=((1<<TWINT)|(1<<TWSTO)|(1<<TWEN))&(~(1<<TWIE)))
//清除中断标志位,在总线上发出终止信号,激活TWI功能,关闭TWI中断
#define TestAck() (TWSR&0xf8)
//TWSR--I2C状态寄存器,检查TWI状态,应该将预分频位屏蔽(第三位是保留位)
#define MT_NACK						(TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE))
//清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下不对SDA线作应答
#define MT_ACK						(TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA))
//清除中断标志位,使能TWI功能,开放TWI中断,在主控接收状态下对SDA线作应答
#define TWItransmit(x)		{TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);}
//写入8位数据到数据寄存器中,同时清除中断标志位,使能TWI功能,开放TWI中断



uchar charData;//TWI中断中,传送的数据
uchar charAddr;//TWI中断中,数据所处的EEPROM地址
uchar charState;//TWI中断中,中断所处的状态


 
/**********************ATEEPROM读写过程*********************************
	字节写:Start→器件地址&W→应答→选ROM地址→应答→写数据→应答→Stop
中断过程	START→MT_SLA_ACK→MT_DATA_ACK(地址)→MT_DATA_ACK(数据)(STOP中止)

	页面写:Start→器件地址&W→应答→选ROM地址→应答→写数据→应答→写NEXT地址数据→应答→。。。写NEXT地址数据→应答→Stop
中断过程	START→MT_SLA_ACK→MT_DATA_ACK(地址)→MT_DATA_ACK(数据)→MT_DATA_ACK(数据)→。。。MT_DATA_ACK(数据)(STOP中止)
						 
	字节读:Start→器件地址&W→应答→选ROM地址→应答→Restart→器件地址&R→应答→读数据→无应答→Stop
中断过程	START→MT_SLA_ACK→MT_DATA_ACK(地址)→RE_START→MR_SLA_ACK→MR_DATA_NOACK(STOP中止)
				
	页面读:Start→器件地址&W→应答→选ROM地址→应答→Restart→器件地址&R→应答→读数据→应答→读NEXT地址数据→应答→。。。读NEXT地址数据→无应答→Stop
中断过程	START→MT_SLA_ACK→MT_DATA_ACK(地址)→RE_START→MR_SLA_ACK→MR_DATA_ACK→MR_DATA_ACK→。。。MR_DATA_NOACK(STOP中止)		
*************************************************************************/



extern volatile uchar flag0;
extern volatile uint16_t cnt_t0;
extern volatile uint8_t remote[4];        




SIGNAL(SIG_2WIRE_SERIAL)
{//IIC中断
    switch (TestAck())//检查状态标志字
	 {
		case TW_START:
		 {putchar(1);
			TWItransmit(wr_device_add);
			//选取I2C从器件地址,进行主控写模式
			break;
		 }
		case TW_REP_START:
		 {
			TWItransmit(rd_device_add);
			//选取I2C从器件地址,进行主控读模式
			break;
		 }
		case TW_MT_SLA_ACK:
		//Slave器件被识别并产生应答
		 {putchar(2);
			TWItransmit(charAddr);
			//写24C02ROM的字地址
			break;
		 }
		case TW_MT_DATA_ACK:
		//主控发送数据,并得到响应
		 {
			switch(charState)
			 {
				case EE_WRITE://写数据到24C02的ROM
				 {
					TWItransmit(charData);
					charState=EE_WRITE_OVER;
					break;
				 }
				case EE_WRITE_OVER://I2C停止
				 {
					Stop();
					charState=EE_WRITE_OK;
					break;
				 }
				case EE_READ:
				 {
					Start();
					break;
				 }
				//I2C重新启动
			 }
			break;
		 }
		case TW_MR_SLA_ACK:
		 {
			MT_NACK;
			break;
		 }
		//启动主I2C读方式
		case TW_MR_DATA_NACK:
		 {
			charData=TWDR;
			Stop();
			charState=EE_READ_OK;
			break;
		 }
		//读取I2C接收数据,I2C停止
		default:
			putchar(9);
			putchar(TestAck());
			Stop();//I2C停止
	 }
	
}

/*
常用TWI操作(主模式写和主模式读)
*/
void i2c_write(uchar Wdata,uchar RomAddress)
 {
	charData=Wdata;//I2C总线写一个字节
	charAddr=RomAddress;//返回0:写成功
	charState=EE_WRITE;//返回非0:写失败
	Start();//I2C启动(TWI中断启动)
	while(charState!=EE_WRITE_OK);
	delay_ms(10);
 }
uchar i2c_read(uchar RomAddress)
 {
	charAddr=RomAddress;
	charState=EE_READ;
	Start();//I2C启动
	while(charState!=EE_READ_OK);
	return charData;
 }


int main (void)
{   uint8_t i;
    cli();
	  init_devices();
	  charState=EE_READ;
	  wdt_enable(WDTO_2S);
	  wdt_reset();
	  sei();
	  while(1)
	  {
	  	delay_ms(100);
	//  putchar(3);
	  i=i2c_read(0x00);
	 // putchar(i);
	 // putchar(0);
		if((flag0 & _BV(FLAG0_KEEP)) == 0x40) 
				{ 
					flag0 &= ~_BV(FLAG0_KEEP); 
					if((remote[0] + remote[1])==0xff)
      	   {
      	  	remote[0] = remote[0];
      	  	remote[1] = remote[1];
      	   }
      	  if((remote[2] + remote[3])==0xff)
      	   {
      		  remote[2] = remote[2];
      	  	remote[3] = remote[3];
      	  	remote[4] = 1;
      	    putchar(remote[0]);
      	    putchar(remote[1]);
      	    putchar(remote[2]);
      	    putchar(remote[3]);
					  putchar(remote[4]); 
				   }
				}
		if((flag0 & _BV(FLAG0_CODE)) == 0x80) 
				{
			   	flag0 &= ~_BV(FLAG0_CODE); 
				  if((remote[0] + remote[1])==0xff)
      	   {
      	  	remote[0] = remote[0];
      	  	remote[1] = remote[1];
      	   }
          
      	  if((remote[2] + remote[3])==0xff)
      	   {
      		  remote[2] = remote[2];
      	  	remote[3] = remote[3];
      	  	remote[4] = 0;
      	    putchar(remote[0]);
      	    putchar(remote[1]);
      	    putchar(remote[2]);
      	    putchar(remote[3]);
					  putchar(remote[4]);
      	   }
               	   
				}	
		 if(read_key()==1)
		 	  {
		 		putchar(1);
		 		twi_start();
		 		delay_ms(100);
		 		twi_writebyte(TWI_ADDRESS|TW_WRITE);
		 		delay_ms(100);
		 		for (i=0;i<10;i++)
		 		 {
		 		 	twi_writebyte(i);
		 		 	delay_ms(100);
		 		 }
		 		twi_stop();
		 		}	
		 if(read_key()==2)
		 	  {
		 	  putchar(2);
		 	  }
		 
	  }   
  	  
} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -