|
使用MEGA328的硬件TWI中断模式读取240C2(内部0x02 里面的数据应该是0xd0),发现TWI流程正确。(所有返回状态正确)但是最后读取TWDR的时候却一直是0,SDA SCL都有上拉电阻 ,在线等
/**************************************
** 函数名称:IIC_Init(void) **********
** 功能:总线初始化(主机模式)*******
** 输入值:无 **************
** 返回值:无 ***************
**************************************/
void IIC_Init(void)
{
DDRC&=~((1<<PC4)&(1<<PC5));
PORTC|= (1<<PC4)|(1<<PC5);
TWAR = 0x00; //设置为主机模式
TWCR = (1<<TWEA)|(1<<TWEN)|(1<<TWIE); //主机模式,使能TWI 使能中断
TWBR = 0x10; //设置分频因子初值64(f = 8M/(16+2*64))
TWSR = 0x00; //不分频
}
/****************************************************
** 函数名称:IIC_Write_Byte *******************
** 功能:总线写函数 *******************
** 输入值:IIC_Addr、REG_Address、REG_data *********
** 返回值:无 *******************
****************************************************/
void IIC_Write_Byte(unsigned char IIC_Addr,unsigned char REG_Address,unsigned char REG_data)
{
SLA_RW_flg = 0 ; //写命令
IIC_Device_Addr = IIC_Addr; //写入操纵器件地址(写)
RW_Addr = REG_Address; //写入操纵地址(写)
RW_Data = REG_data; //写入数据内容(写)
IIC_START(); //启动发送命令
}
/****************************************************
** 函数名称:IIC_Read_Byte *******************
** 功能:总线读函数 *******************
** 输入值:IIC_Addr、REG_Address *******************
** 返回值:无 *******************
****************************************************/
unsigned char IIC_Read_BYTE(unsigned char IIC_Addr,unsigned int REG_Address)
{
Recive_Over_flg = 0 ; //请接受完成标志位,等待IIC读取完成
RW_Data = 0 ; //清接受数据缓存器
SLA_RW_flg = 1 ; //读命令
IIC_Device_Addr = IIC_Addr; //写入操纵器件地址(读)
RW_Addr = REG_Address; //写入操纵地址(读)
IIC_START(); //启动发送命令
while(Recive_Over_flg);
return RW_Data ; //返回读取数据
}
/****************************************************
** 函数名称:IIC_ISR *******************
** 功能:IIC中断函数 *******************
** 输入值:无 *******************
** 返回值:无 *******************
****************************************************/
#pragma interrupt_handler IIC_ISR:25
void IIC_ISR(void)
{
unsigned char IIC_State = 0; //定义IIC状态变量,用于读取状态寄存器与预定的状态比较
IIC_State = (TWSR & 0xF8); //取出IIC状态变量
//接收模式
if(SLA_RW_flg == 1)
{
switch(IIC_State) //判断IIC当前状态
{
case START_08: //start已经发送,接下来发送SLA+W
TWDR = IIC_Device_Addr ; //导入将要操纵的IIC元器件的地址
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE); //发送IIC器件地址,置位中断标志位
break;
case RE_START_10: //重复START已发送
TWDR = IIC_Device_Addr+1 ; //SLA+R
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE);//发送 地址+读
break;
case MT_SLA_ACK_18: //SLA+W 已发送;接收到 ACK
TWDR = RW_Addr; //写入要读寄存器的高8位地址
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWIE);//发送数据(数据内容是:读器件地址)
break;
case MT_SLA_NACK_20: //SLA+W 已发送接收到 NACK
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);//发送停止信号并使能中断
break;
case MT_DATA_ACK_28: //数据(要读寄存器首地址)已经发送,接收到ACK
IIC_START(); //再发送起始信号
break;
case MR_SLA_ACK_40: //SLA+R 已发送接收到ACK
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE);
break;
case MR_SLA_NACK_48: //SLA+R 已发送接收到NACK
Recive_Over_flg = 1 ;
IIC_STOP();
break;
case MR_DATA_ACK_50: //数据已经收到,应答
Recive_Over_flg = 1 ;
IIC_STOP();
break;
case MR_DATA_NACK_58:
RW_Data = TWDR; //读出地址中的数据
Recive_Over_flg = 1 ;
IIC_STOP();
break;
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|