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

📄 twi.c

📁 一个关于AVR单片机的例程
💻 C
字号:
// 作者:古欣
// AVR与虚拟仪器 http://www.avrvi.com
// TWI.C 

#include "config.h"

volatile uint8 main_tmp=0;
//extern volatile uint8 main_tmp=0;

//TWI master initialize
// bit rate:100
void twi_master_init(void)
{
 TWCR= 0x00; //disable twi
 TWBR= 0x64; //set bit rate
 TWSR= 0x00; //set prescale
 TWAR= 0x00; //set slave address
 TWCR= 0x04; //enable twi
}

//TWI slave initialize
// bit rate:100
void twi_slave_init(uint8 add)
{
 TWCR= 0x00; //disable twi
 TWBR= 0x64; //set bit rate
 TWSR= 0x00; //set prescale
 TWAR= add; //set slave address 从机地址为 0x01
 TWCR= (1<<TWEN)|(1<<TWEA)|(1<<TWIE); //enable twi
 //TWEN必须置位以使能TWI接口。TWEA也要置位以使主机寻址到自己(从机地址或广播) 时返回确认信息ACK
}

//总线上起动开始条件
void i2c_start(void)
{
	TWCR= (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
   	while (!(TWCR & (1<<TWINT))); //等待START 信号成功发送
}

//把一个字节数据输入器件, 返回TWI状态
//发送地址和数据都可以使用本函数
uint8 i2c_write(uint8 data)
{
	TWDR = data; 
   	TWCR = (1<<TWINT)|(1<<TWEN); 
   	while (!(TWCR & (1<<TWINT)));
   	_NOP();
   	return(TWSR&0b11111000); //TWSR高五位为I2C工作状态。
}

//从器件读出一个字节
uint8 i2c_read(void)
{
   	TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN); 
   	while (!(TWCR & (1<<TWINT)));
   	return(TWDR);
}

//总线上起动停止条件 
void i2c_stop(void) 
{ 
   TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN); 
}

//操作步骤: 启动,发送地址,发送数据,关闭总线
void i2c_maste_transt(uint8 addr, uint8 data)
{
 i2c_start();
 if(i2c_write(addr)==TW_MT_SLA_ACK) //发送地址成功并收到ACK
 {
  i2c_write(data);
 }
 i2c_stop();
}

#if TWI_MOD==0 //从机模式
#pragma interrupt_handler twi_isr:18
void twi_isr(void)
{
 //twi event
 switch (TWSR&0xF8)
 {
 //从接收
 case TW_SR_SLA_ACK:
 case TW_SR_ARB_LOST_SLA_ACK:
 case TW_SR_GCALL_ACK:
 case TW_SR_ARB_LOST_GCALL_ACK:
 	  Twi_Ack();  //返回ACK
	  break;
 case TW_SR_DATA_ACK:
 case TW_SR_DATA_NACK:
 	  main_tmp = TWDR;
  	  PORTA = ~ TWDR; //接收数据并显示
 	  Twi_Ack();  //返回ACK
	  break;
 case TW_SR_GCALL_DATA_ACK:
 case TW_SR_GCALL_DATA_NACK:	
 	  Twi_Ack();  //返回ACK
	  break;
 case TW_SR_STOP:
 	  Twi_Ack(); 
	  break;
 //从发送*****************************
 
   case TW_ST_SLA_ACK:               // 0xA8: 自己的SLA+R 已经被接收,ACK 已返回 
   case TW_ST_ARB_LOST_SLA_ACK:// 0xB0: SLA+R/W 作为主机的仲裁失败;自己的SLA+R 已经被接收,ACK 已返回 
      // 被选中为从读出 (数据将从传回主机) 
	  TWDR=main_tmp;  //发送全局变量中值
	  Twi_Ack(); 		
	  break;    
  case TW_ST_DATA_ACK:            // 0xB8: TWDR 里数据已经发送,接收到ACK 
      //发送数据位 
	 TWDR=main_tmp;
     break;    
   case TW_ST_DATA_NACK:            // 0xC0: TWDR 里数据已经发送接收到NOT ACK 
   case TW_ST_LAST_DATA:            // 0xC8: TWDR 的一字节数据已经发送(TWAE = “0”);接收到ACK 
      // 全部完成 
      // 从方式开放 
      Twi_NoAcK(); 
	  twi_slave_init(0x50);        //重新回到初始化状态,等待接收模式的到来
      break; 
   case TW_NO_INFO:                 // 0xF8: 没有相关的状态信息;TWINT = “0” 
      // 无操作 
	  break; 
   case TW_BUS_ERROR:               // 0x00: 由于非法的START 或STOP 引起的总线错误 
      // 内部硬件复位,释放总线 
      TWCR=TWCR&TWCR_CMD_MASK|(1<<TWINT)|(1<<TWSTO)|(1<<TWEA); 
     break;  
 	 default:
	 break;
 }
}

#endif

⌨️ 快捷键说明

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