📄 twi.c
字号:
#include <header.h>
#include <TWI.h>
unsigned char TWI_sen_dat[10];
unsigned char TWI_rev_dat[10];
unsigned char TWI_com_addr;
unsigned char TWI_set_len;
unsigned char TWI_send_len;
unsigned char TWI_rev_len;
unsigned char TWI_sended=0;
unsigned char TWI_reved=0;
unsigned char TWI_sending_str=0;
void TWI_int()
{
TWBR=0x00; //比特率寄存器SCLfre=CPUCLK/(16+2*TWBR*4E(TWPS)),与ADS1100用2
TWSR=0x00; //Bits1.0-TWPS:TWI预分频位1,4,16,64
//TWDR=0x00; //TWI数据寄存器,在第一次中断发生之前用户不能够初始化数据寄存器。1读
TWAR=0x02; //TWI(从机)地址寄存器,Bit0–TWGCE: 使能TWI广播识别
TWCR=(1<<TWEA)|(1<<TWEN); //控制寄存器
/*
TWINT中断标志(清零必须通过软件写"1"来完成,只要这一位被清零,TWI立即开始工作。)
TWEA使能应答,
TWSTA: START状态标志(成为总线上的主机,发送START之后软件必须清零TWSTA),
TWSTO: STOP状态标志(在主机模式下,在总线上产生STOP状态,自动清零。在从机模式下,置位TWSTO 可以使接口从错误状态恢复到未被寻址的状态.),
TWWC: TWI写碰撞标志
TWEN: TWI使能
TWIE: 使能TWI中断
*/
}
void TWI_close()
{
TWCR=0;
}
void TWI_my_addr(unsigned char addr)
{
TWAR=addr; //TWI(从机)地址寄存器,Bit0–TWGCE: 使能TWI广播识别
}
void TWI_set(unsigned char status_sel,unsigned char speed_sel)
{
if(status_sel<2)TWCR|=(1<<TWSTA);
else TWCR|=(1<<TWSTO);
TWSR=(TWSR&0xfc)|(speed_sel&0x03); //Bits1.0-TWPS:TWI预分频位1,4,16,64
}
void TWI_send_dat(unsigned char *dat,unsigned char lng) //发送数据
{
memcpy(TWI_sen_dat, dat, lng);
TWI_send_len=lng;
}
void TWI_inr()
{
switch(TWSR&0xf8)
{
case 0x00://由于非法的START或STOP引起的总线错误
break;
case 0x08://start已发送
if(TWI_sending_str){TWCR&=(~(1<<TWSTA));TWI_sending_str=0;return;}
TWI_sended=0;
TWDR=TWI_com_addr;
TWCR=(TWCR|(1<<TWINT)|(1<<TWEN))&~(1<<TWSTA);
break;
case 0x10://重复start已发送
TWI_sended=0;
TWDR=TWI_com_addr;
TWCR=(TWCR|(1<<TWINT)|(1<<TWEN))&~(1<<TWSTA);
break;
case 0x18://SLA+W已发送,接收到ACK
if(TWI_sended<TWI_send_len)
{
TWDR=TWI_sen_dat[TWI_sended++];
TWCR|=(1<<TWINT)|(1<<TWEN);
}
else
{
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
TWI_sended=1;
}
break;
case 0x20://SLA+W已发送,接收到NOT ACK
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
break;
case 0x28://数据已发送,接收到ACK
if(TWI_sended<TWI_send_len)
{
TWDR=TWI_sen_dat[TWI_sended++];
TWCR|=(1<<TWINT)|(1<<TWEN);
}
else
{
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
TWI_sended=1;
}
break;
case 0x30://数据已发送,接收到NOT ACK
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
break;
case 0x38://SLA或数据的仲裁失败
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
break;
case 0x40://SLA+R已发送,接收到ACK
if(TWI_reved<TWI_rev_len)
{
TWDR=TWI_rev_dat[TWI_reved++];
TWCR|=(1<<TWINT)|(1<<TWEN);
}
else
{
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
TWI_reved=1;
}
break;
case 0x48://SLA+R已发送,接收到NOT ACK
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
break;
case 0x50://接收到数据,ACK已返回
if(TWI_reved<TWI_rev_len)
{
TWDR=TWI_rev_dat[TWI_reved++];
TWCR|=(1<<TWINT)|(1<<TWEN);
}
else
{
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
TWI_reved=1;
}
break;
case 0x58://接收到数据,NOT ACK已返回
TWCR|=(1<<TWINT)|(1<<TWEN)|(1<<TWSTA);
break;
case 0x60://自己的SLA+W已经被接收ACK已返回
case 0x68://SLA+R/W作为主机的仲裁失败;自己的SLA+W已经被接收ACK已返回
case 0x70://接收到广播地址ACK已返回
case 0x78://SLA+R/W作为主机的仲裁失败;接收到广播地址ACK 已返回
case 0x80://以前以自己的SLA+W被寻址;数据已经被接收ACK已返回
case 0x88://以前以自己的SLA+W被寻址;数据已经被接收NOT ACK已返回
case 0x90://以前以广播方式被寻址;数据已经被接收ACK已返回
case 0x98://以前以广播方式被寻址;数据已经被接收NOT ACK已返回
case 0xA0://在以从机工作时接收到STOP或重复START
case 0xA8://自己的SLA+R 已经被接收ACK已返回
case 0xB0://SLA+R/W作为主机的仲裁失败;自己的SLA+R已经被接收ACK已返回
case 0xB8://TWDR里数据已经发送接收到ACK
case 0xC0://TWDR里数据已经发送接收到NOT ACK
case 0xC8://TWDR的一字节数据已经发送(TWAE="0");接收到ACK
case 0xF0://没有相关的状态信息;TWINT="0"
default:;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -