This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
你(们)好
我想使用 i2c 连接外部 EEPROM。 我更喜欢使用 Rm=1、并且我使用 ARDY 和 NACK 中断来控制传输。 我可以 选择器件、设置页地址 和发送 所有页字节(256)、但此时如果我通过在 CMDR 寄存器中设置 STP=1发送停止条件、我会收到仲裁失败中断和 NACK 中断? 我出什么问题了吗?
此致
以下是示例代码:
typedef 枚举
{
Wait_for_CMD、
select_device、
SEND_HI_ADDRESS、
SEND_LO_ADDRESS、
START_READ_DATA、
Read_data、
SEND_STOP、
完成、
Write_data、
WRITE_STOP、
start_write_pool、
Write_Pool、
DEVICE_NACK
} I2C_FSM_States;
typedef 枚举
{
I2C_NO_CMD、
I2C_WRITE_EEPROM、
I2C_READ_EEPROM
} I2C_COMMAND_VALUES;
typedef 结构
{
I2C_FSM_States 状态;
I2C_COMMAND_VALUES cmd;
易失性 bool 完成;
易失性 bool NACK;
uint32_t 地址;
int16_t n_Reads;
int16_t n_writes;
uint16_t SAR;
int16_t TRx_counter;
int16_t 重试;
} I2C_DATA_TAG;
I2C_DATA_TAG i2c;
/*====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
函数名称:
目的:
描述:
域:
精度:
注:
==================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================== *
中断空 i2c_int1a_isr (空)
{
//设置中断优先级:
volatile uint16_t TempPIEIER = PieCtrlRegs.PIEIER8.all;
uint16_t tmp;
IER |= M_INT8;
IER &= MINT8;
PieCtrlRegs.PIEIER8.ALL &= MG81;
PieCtrlRegs.PIEACX.ALL = 0xFFFF;
asm (" NOP");
EINT;
//在此处插入 ISR 代码...
tmp = I2caRegs.I2CISRC.ALL;
交换机(tmp & 0x3)
{
情况 I2C_NO_ISRC:
tmp = 0;
中断;
案例 I2C_ARB_ISRC:
tmp = 0;
中断;
I2C_Nack_ISRC 案例:
I2C.nack = true;
中断;
I2C_ARDY_ISRC 案例:
I2c.done = true;
中断;
I2C_RX_ISRC 案例:
tmp = 0;
中断;
I2C_TX_ISRC 案例:
tmp = 0;
中断;
I2C_SCD_ISRC 案例:
tmp = 0;
中断;
案例 I2C_AAS_ISRC:
tmp = 0;
中断;
}
//恢复保存的寄存器:
Dint;
PieCtrlRegs.PIEIER8.ALL = TempPIEIER;
}
/*====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
函数名称:
目的:
描述:
域:
精度:
注:
==================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================== *
void i2c_fSM (void)
{
交换机(i2c.state)
{
案例 WAIT_TO_CMD:
if (i2c.cmd!= I2C_NO_CMD)
{
// 准备 SAR
I2C.SAR =(i2c.address 和0x3FFFF)>> 16;
I2C.SAR = i2c.SAR << 1;
I2C.SAR =(i2c.SAR | DSC_Musk)>> 1;
// 下一状态
I2C.state = select_device;
}
中断;
案例 select_device:
//
I2C.DONE = false;
I2C.nack = false;
// 开始操作
I2caRegs.I2CMDR.bit.MST = 1;
I2caRegs.I2CMDR.bit.RM = 1;
I2caRegs.I2CMDR.bit.TRX = 1;
I2caRegs.I2CSAR = i2c.SAR;
I2caRegs.I2CMDR.bit.STT = 1;
// 下一状态
I2C.state = SEND_HI_ADDRESS;
中断;
案例 SEND_HI_ADDRESS:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
I2caRegs.I2CDXR =(i2c.address >> 8)& 0xFF;
// 下一状态
I2C.state = SEND_LO_ADDRESS;
}
}
中断;
案例 SEND_LO_ADDRESS:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
I2caRegs.I2CDXR = i2c.address & 0xFF;
交换机(i2c.cmd)
{
I2C_WRITE_EEPROM 案例:
I2C.TRx_COUNTER = 0;
// 下一状态
I2C.state = write_data;
中断;
I2C_READ_EEPROM 案例:
I2C.TRx_COUNTER = 0;
// 下一状态
I2C.state = start_read_data;
中断;
默认值:
中断;
}
}
}
中断;
案例 start_read_data:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
I2caRegs.I2CMDR.bit.TRX = 0;
I2caRegs.I2CMDR.bit.STT = 1;
// 下一状态
I2C.state = read_data;
}
}
中断;
案例 READ_DATA:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
READ_DATA[i2c.TRx_COUNTER++]= I2caRegs.I2CDRR;
if (i2c.TRx_counter =i2c.n_Readses)
{
// 下一状态
I2C.state = send_stop;
}
其他
{
// 下一状态
I2C.state = read_data;
}
}
}
中断;
案例 SEND_STOP:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
I2caRegs.I2CMDR.bit.STP= 1;
// 下一状态
I2C.state =完成;
}
}
中断;
案例完成:
如果(i2c.done)
{
I2C.DONE = false;
I2C.cmd = I2C_NO_CMD;
// 下一状态
I2C.state = WAIT_TO_CMD;
}
中断;
案例 WRITE_DATA:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
I2caRegs.I2CDXR = WRITE_DATA[i2c.TRx_COUNTER++];
if (i2c.TRx_counter =i2c.n_writes)
{
// 下一状态
I2C.state = WRITE_STOP;
}
其他
{
// 下一状态
I2C.state = write_data;
}
}
}
中断;
案例 WRITE_STOP:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
// 下一状态
I2C.state = device_nack;
}
其他
{
I2caRegs.I2CMDR.bit.STP= 1;
// 下一状态
I2C.state =完成;
}
}
中断;
案例 start_WRITE_POOL:
如果(i2c.done)
{
I2C.DONE = false;
I2C.nack = false;
I2C.RETRY = 0;
I2caRegs.I2CMDR.bit.MST = 1;
I2caRegs.I2CMDR.bit.RM = 1;
I2caRegs.I2CMDR.bit.TRX = 1;
I2caRegs.I2CSAR = i2c.SAR;
I2caRegs.I2CMDR.bit.STT = 1;
// 下一状态
I2C.state = write_pool;
}
中断;
案例 Write_Pool:
如果(i2c.done)
{
I2C.DONE = false;
if (i2c.nack)
{
I2C.RETRY ++;
I2caRegs.I2CMDR.bit.MST = 1;
I2caRegs.I2CMDR.bit.RM = 1;
I2caRegs.I2CMDR.bit.TRX = 1;
I2caRegs.I2CSAR = SAR;
I2caRegs.I2CMDR.bit.STT = 1;
// 下一状态
I2C.state = write_pool;
}
其他
{
I2caRegs.I2CMDR.bit.STP= 1;
// 下一状态
I2C.state =完成;
}
}
中断;
案例 DEVICE_NACK:
中断;
默认值:
中断;
}
}
大家好、Kevin
我使用另一种方法来使用 I2C 来解决问题... 但如果收到 NACK、我会遇到问题、似乎无法在收到 NACK 后恢复正确的通信。 那么、管理 NACK 的最佳方式是什么? 我应该复位 I2C 外设吗?
此致
尊敬的 Luca:
C2000ware 中的 I2C 示例可能会对您有所帮助。
目录:C:\ti\c2000Ware_1_00_02_00\device_support\F2833x\examples\i2c_eeprom
您可能需要与以下代码部分类似的内容:
// //中断源=寄存器访问就绪 //此中断用于确定何时设置 EEPROM 地址 //读取数据通信的部分已完成。 因为没有停止位 //命令,此标志告诉我们何时发送了消息而不是消息 // SCD 标志。 如果接收到 NACK、清除 NACK 位并执行命令 A //停止。 否则、请转到通信的读取数据部分。 // 否则、IF (IntSource = I2C_ARDY_ISRC) { if (I2caRegs.I2CSTR.bit.nack = 1) { I2caRegs.I2CMDR.bit.STP= 1; I2caRegs.I2CSTR.All = I2C_CLR_Nack_bit; } 否则(CurrentMsgPtr -> MsgStatus = I2C_MSGSTAT_SEND_NOSTOP_BUSY) { CurrentMsgPtr ->MsgStatus = I2C_MSGSTAT_RESTART; } }
如果在初始从器件寻址之后接收到 Nacks、则示例代码的另一部分会处理 Nacks。
希望这对您有所帮助、
Kevin