?? i2c state machine.c
字號:
#include "I2C State Machine.h"
//--------------------------------------------------------------------------//
// Variables for I2C state machine //
//--------------------------------------------------------------------------//
t_I2C_Main_States m_SM_State; // current state
t_I2C_Main_States m_SM_Next_State; // determines the following state
t_I2C_Message m_Current_Message; // message to be transferred
t_I2C_Transfer m_Current_Transfer; // one byte to be transferred
t_I2C_SM_Path m_Current_SM_Path; // used to determine SM_Next_State
bool m_ACK_Error; // status of last acknowledge cycle
//--------------------------------------------------------------------------//
// Function: I2C_Setup //
// //
// Access: Public //
// //
// Parameters: New_Message //
// New Message to be transmitted via I2C interface //
// //
// Return: None //
// //
// Description: This function is used to reset the internal state of the //
// state machine and to store the message passed as parameter //
// inside the SM. //
// After this function has been called, function //
// I2C_Advance_State() should be called repeatedly until it //
// returns TRUE (then the complete message has been //
// transferred or an error has occured). //
//--------------------------------------------------------------------------//
void I2C_Setup(t_I2C_Message *New_Message)
{
m_SM_State = I2C_IDLE;
m_SM_Next_State = I2C_IDLE;
m_Current_SM_Path = I2C_SM_Write_Path;
m_ACK_Error = false;
m_Current_Message = *New_Message;
I2C_Set_SDA_Output();
I2C_Set_SCL_Output();
}
//--------------------------------------------------------------------------//
// Function: Get_Error_Status //
// //
// Access: Public //
// //
// Parameters: None //
// //
// Return: None //
// false: No error occured in previous state machine cycle//
// true: Error occured in previous state machine cycle //
// //
// Description: This function should be called after a state machine cycle //
// is finished to determine if an error (missing ACK from the //
// Slave) has occured. //
//--------------------------------------------------------------------------//
bool I2C_Get_Error_Status(void)
{
return(m_ACK_Error);
}
//--------------------------------------------------------------------------//
// Function: Advance_State //
// //
// Access: Public //
// //
// Parameters: None //
// //
// Return: Status of operation //
// false: State machine cycle not finished //
// true: State machine cycle finished //
// //
// Description: This is called from the user and performs one state //
// transition in the I2C main state machine per call. //
// It needs to be called until it returns "true", then the SM //
// has finished one complete transfer (one message has been //
// sent/received). //
//--------------------------------------------------------------------------//
bool I2C_Advance_State(void)
{
bool Return_Value = false;
switch(m_SM_State)
{
// state IDLE
case I2C_IDLE:
// state transition IDLE -> START
m_SM_State = I2C_START;
m_Current_SM_Path = I2C_SM_Write_Path;
// set Device Address for next write
m_Current_Transfer.Byte = m_Current_Message.Dev_Addr & ~I2C_READ_WRITE_BIT;
m_Current_Transfer.Bit_Count = I2C_DEVICE_LENGTH;
break;
// state START
case I2C_START:
if(I2C_Execute_START())
{
// state transition START -> WRITE_DEV_ADDR
m_SM_State = I2C_WRITE_DEV_ADDR;
}
break;
// state WRITE_DEV_ADDR
case I2C_WRITE_DEV_ADDR:
if(I2C_Execute_WRITE())
{
// state transition WRITE_DEV_ADDR -> CHECK_ACK
m_SM_State = I2C_CHECK_ACK;
// determine if write or read cycle has to be performed
if(m_Current_SM_Path == I2C_SM_Write_Path)
{
// prepare state transition CHECK_ACK -> WRITE_REG_ADDR
m_SM_Next_State = I2C_WRITE_REG_ADDR;
// set Register Address for next write
m_Current_Transfer.Byte = m_Current_Message.Reg_Addr;
m_Current_Transfer.Bit_Count = I2C_REGISTER_LENGTH;
}
else
{
// prepare state transition CHECK_ACK -> READ_DATA
m_SM_Next_State = I2C_READ_DATA;
}
}
break;
// state WRITE_REG_ADDR
case I2C_WRITE_REG_ADDR:
if(I2C_Execute_WRITE())
{
// state transition WRITE_REG_ADDR -> CHECK_ACK
m_SM_State = I2C_CHECK_ACK;
// check if R/W bit is set; if it is set, then a read cycle is to be performed
if(m_Current_Message.Dev_Addr & I2C_READ_WRITE_BIT)
{
// prepare state transition CHECK_ACK -> START
m_SM_Next_State = I2C_START;
// next time around the SM take the "read path"
m_Current_SM_Path = I2C_SM_Read_Path;
// set Device Address for next write
m_Current_Transfer.Byte = m_Current_Message.Dev_Addr;
m_Current_Transfer.Bit_Count = I2C_DEVICE_LENGTH;
}
else
{
// prepare state transition CHECK_ACK -> WRITE_DATA
m_SM_Next_State = I2C_WRITE_DATA;
// set Data for next write
m_Current_Transfer.Byte = m_Current_Message.Data;
m_Current_Transfer.Bit_Count = I2C_DATA_LENGTH;
}
}
break;
// state WRITE_DATA
case I2C_WRITE_DATA:
if(I2C_Execute_WRITE())
{
// state transition WRITE_DATA -> CHECK_ACK
m_SM_State = I2C_CHECK_ACK;
// prepare state transition CHECK_ACK -> STOP
m_SM_Next_State = I2C_STOP;
}
break;
// state READ_DATA
case I2C_READ_DATA:
if(I2C_Execute_READ())
{
// state transition READ_DATA -> SEND_ACK
m_SM_State = I2C_SEND_ACK;
// set Acknowledge for next write
m_Current_Transfer.Byte = I2C_ACK_VALUE;
m_Current_Transfer.Bit_Count = I2C_ACK_LENGTH;
}
break;
// state CHECK_ACK
case I2C_CHECK_ACK:
if(I2C_Execute_CHECK_ACK())
{
// check if Slave acknowledges access
if(m_ACK_Error)
{
// state transition CHECK_ACK -> STOP (error occured)
m_SM_State = I2C_STOP;
}
else
{
// perform (earlier) prepared state transition
m_SM_State = m_SM_Next_State;
}
}
break;
// state SEND_ACK
case I2C_SEND_ACK:
if(I2C_Execute_WRITE())
{
// state transition SEND_ACK -> STOP
m_SM_State = I2C_STOP;
}
break;
// state STOP
case I2C_STOP:
if(I2C_Execute_STOP())
{
// state transition STOP -> IDLE
m_SM_State = I2C_IDLE;
Return_Value = true; // SM is finished
}
break;
}
return(Return_Value);
}
//--------------------------------------------------------------------------//
// Function: Execute_START //
// //
// Access: Private //
// //
// Parameters: None //
// //
// Return: Status of I2C Start condition //
// false: I2C Start condition not finished //
// true: I2C Start condition finished //
// //
// Description: This function is called from within the SPI main state //
// machine. //
// It executes a state machine that implements the I2C Stop //
// condition by setting SDA to 1 while SCL is 1. //
//--------------------------------------------------------------------------//
bool I2C_Execute_START(void)
{
bool Return_Value = false;
static t_I2C_Sub_States I2C_START_SM_State = I2C_SET_HIGH_SCL_SDA;
switch(I2C_START_SM_State)
{
// state SET_HIGH_SCL_SDA
case I2C_SET_HIGH_SCL_SDA:
// state transition SET_HIGH_SCL_SDA -> SET_LOW_SDA
I2C_START_SM_State = I2C_SET_LOW_SDA;
I2C_Set_High_SCL();
I2C_Set_High_SDA();
break;
// state SET_LOW_SDA
case I2C_SET_LOW_SDA:
// state transition SET_LOW_SDA -> SET_LOW_SCL
I2C_START_SM_State = I2C_SET_LOW_SCL;
I2C_Set_Low_SDA();
break;
// state SET_LOW_SCL
case I2C_SET_LOW_SCL:
// state transition SET_LOW_SCL -> SET_HIGH_SCL_SDA
I2C_START_SM_State = I2C_SET_HIGH_SCL_SDA;
I2C_Set_Low_SCL();
Return_Value = true; // SM is finished
break;
}
return(Return_Value);
}
//--------------------------------------------------------------------------//
// Function: Execute_STOP //
// //
// Access: Private //
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -