📄 twi.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 + -