/** ########################################################################## ** Filename : ** Project : ** Module : ** Processor : ** Version : ** Compiler : ** Date/Time : ** Abstract : ** Contents : ** Note : ** ** (c) Copyright dmdz Co.,Ltd ** -------------------------------------------------------------------------- ** R E V I S I O N H I S T O R Y ** -------------------------------------------------------------------------- ** Date Ver Author Description ** -20230602- --V1.0-- --mingyea--- --修改-- ** #########################################################################*/ /*--------------------------------------------------------------------------- - I N C L U D E F I L E S ----------------------------------------------------------------------------*/ #include "common_cfg.h" #include "common_memory.h" #include "i2c.h" #include "nvic.h" #include "gpio_cfg.h" #include "i2c_simu.h" /*--------------------------------------------------------------------------- - D E F I N E S / M A C R O S ----------------------------------------------------------------------------*/ #define I2C_ADDR_TEST_MAX 4 /*--------------------------------------------------------------------------- - T Y P E D E F I N I T I O N S ----------------------------------------------------------------------------*/ typedef struct { u8 cmd; //写还是读; u8 state; u8 sub_state; u16 slave_addr; u8 slave_addr_len; u8 tx_count; u8 rx_count; u8 tx_len; u8 rx_len; u8 cmd_result; u8 result_temp; u8 result; u8 flag_nack; u16 timecount; u16 time_total; u8 *p_len; u8 *p_recv_data; u8 slave_addr_index; u8 slave_addr_tx[2]; //将地址,0表示高8位,1表示低8位 u8 tx_data[I2C_FRAME_MAX_SIZE]; u8 rx_data[I2C_FRAME_MAX_SIZE]; #ifdef I2C_DEBUG_EN u8 test_state; u8 test_len; volatile u8 test_addr; volatile u8 test_count; volatile u8 test_data[I2C_FRAME_MAX_SIZE]; volatile u8 test[80]; #else volatile u8 test_count; #endif }i2c_s; /*--------------------------------------------------------------------------- - S T A T I C V A R I A B L E S ----------------------------------------------------------------------------*/ static i2c_s g_i2c; /*--------------------------------------------------------------------------- * G L O B A L V A R I A B L E S ----------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- - C O N S T A N T S ----------------------------------------------------------------------------*/ const u8 g_addr_test[I2C_ADDR_TEST_MAX] = { #if 1 0x08, 0x08, 0x08, 0x08, #else 0x44, 0x45, 0x46, 0x47, #endif }; /*--------------------------------------------------------------------------- - F U N C T I O N P R O T O T Y P E ----------------------------------------------------------------------------*/ static void i2c_goto_stop_bit_state(void); static void i2c_calulate_addr(u8 cmd); static void i2c_rx_data_task(void); static void i2c_rx_data_start(void); static void i2c_tx_data_task(void); static void i2c_operate_result(u8 cmd); /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ void i2c_init(void) { common_memory_clear((u8*)&g_i2c,sizeof(g_i2c)); #ifdef I2C_DEBUG_EN g_i2c.test_addr=0u; #endif #ifdef I2C_MADE_BY_SIMU i2c_simu_init(); #else g_i2c.slave_addr = 0x00u; FL_I2C_MasterMode_Init(I2C, (FL_I2C_MasterMode_InitTypeDef*)&g_IICInitStructer); #ifdef I2C_INTERRUPT_EN /* NVIC中断配置 */ NVIC_ClearPendingIRQ(I2C_IRQn); NVIC_DisableIRQ(I2C_IRQn); NVIC_SetPriority(I2C_IRQn, NVIC_PRIORITY_I2C); NVIC_EnableIRQ(I2C_IRQn); #endif #endif } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ void i2c_re_init_para(void) { //gpio_i2c_recovery_init(); //gpio_i2c_init(); g_i2c.timecount = 0u; g_i2c.cmd = I2C_CMD_NULL; g_i2c.rx_count = 0u; g_i2c.tx_count = 0u; g_i2c.rx_len = 0u; g_i2c.tx_len = 0u; g_i2c.cmd_result = I2C_CMD_RESULT_INIT; g_i2c.result_temp = I2C_RESULT_INIT; g_i2c.result = I2C_RESULT_INIT; FL_I2C_Master_ClearFlag_TXComplete(I2C); FL_I2C_Master_ClearFlag_RXComplete(I2C); FL_I2C_Master_ClearFlag_NACK(I2C); FL_I2C_Master_ClearFlag_Timeout(I2C); FL_I2C_Master_DisableIT_NACK(I2C); FL_I2C_Master_DisableIT_TXComplete(I2C); FL_I2C_Master_DisableIT_RXComplete(I2C); FL_I2C_Master_DisableIT_Stop(I2C); FL_I2C_Master_DisableIT_Start(I2C); //FL_I2C_Master_EnableI2CRestart(I2C); #ifdef I2C_DEBUG_EN g_i2c.test[0]++; #endif } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ void i2c_task(void) { #ifdef I2C_MADE_BY_SIMU #else switch(g_i2c.state) { case I2C_STATE_IDLE: break; case I2C_STATE_START_BIT: #ifdef I2C_DEBUG_EN g_i2c.test[1]++; #endif g_i2c.timecount++; if(g_i2c.timecount>=g_i2c_time_total[I2C_TIME_TOTAL_ID_START_BIT]) { g_i2c.timecount=0u; i2c_re_init_para(); g_i2c.result = I2C_RESULT_FAILED_TIMEOUT; g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[2]++; #endif } break; case I2C_STATE_SEND_ADDR: #ifdef I2C_DEBUG_EN g_i2c.test[3]++; #endif g_i2c.timecount++; if(g_i2c.timecount>=g_i2c_time_total[I2C_TIME_TOTAL_ID_ADDR]) { g_i2c.timecount=0u; i2c_re_init_para(); g_i2c.result = I2C_RESULT_FAILED_TIMEOUT; g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[4]++; #endif } break; case I2C_STATE_WRITE: #ifdef I2C_DEBUG_EN g_i2c.test[5]++; #endif g_i2c.timecount++; if(g_i2c.timecount>=g_i2c_time_total[I2C_TIME_TOTAL_ID_WRITE]) { g_i2c.timecount=0u; i2c_re_init_para(); g_i2c.result = I2C_RESULT_FAILED_TIMEOUT; g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[6]++; #endif } break; case I2C_STATE_READ: #ifdef I2C_DEBUG_EN g_i2c.test[7]++; #endif g_i2c.timecount++; if(g_i2c.timecount>=g_i2c_time_total[I2C_TIME_TOTAL_ID_READ]) { g_i2c.timecount=0u; i2c_re_init_para(); g_i2c.result = I2C_RESULT_FAILED_TIMEOUT; g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[8]++; #endif } break; case I2C_STATE_STOP_BIT: #ifdef I2C_DEBUG_EN g_i2c.test[9]++; #endif g_i2c.timecount++; if(g_i2c.timecount>=g_i2c_time_total[I2C_TIME_TOTAL_ID_STOP_BIT]) { g_i2c.timecount=0u; i2c_re_init_para(); g_i2c.result = I2C_RESULT_FAILED_TIMEOUT; g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[10]++; #endif } break; default: break; } #endif } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ static void i2c_calulate_addr(u8 cmd) { if(g_i2c.slave_addr_len==I2C_ADDR_10BIT) { #ifdef I2C_DEBUG_EN g_i2c.test[11]++; #endif g_i2c.slave_addr_tx[0] = ((g_i2c.slave_addr & 0x300) >> 7) | 0XF0; if(cmd == I2C_CMD_READ) { g_i2c.slave_addr_tx[0] = g_i2c.slave_addr_tx[0] | 1u; #ifdef I2C_DEBUG_EN g_i2c.test[12]++; #endif } g_i2c.slave_addr_tx[1] = (g_i2c.slave_addr & 0xFF); g_i2c.slave_addr_index=0u; g_i2c.sub_state=0u; } else { #ifdef I2C_DEBUG_EN g_i2c.test[13]++; #endif g_i2c.slave_addr_tx[1] = (g_i2c.slave_addr << 1u); if(cmd == I2C_CMD_READ) { g_i2c.slave_addr_tx[1] = g_i2c.slave_addr_tx[1] | 1u; #ifdef I2C_DEBUG_EN g_i2c.test[14]++; #endif } g_i2c.slave_addr_index=1u; g_i2c.sub_state=1u; } } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ static void i2c_operate_result(u8 cmd) { i2c_len_type i; i2c_len_type l_len; if(cmd==I2C_CMD_READ) { *g_i2c.p_len = g_i2c.rx_count; if(g_i2c.rx_count>I2C_FRAME_MAX_SIZE) { l_len = I2C_FRAME_MAX_SIZE; } else { l_len=g_i2c.rx_count; } for(i = 0; i < l_len; i++) { g_i2c.p_recv_data[i] =g_i2c.rx_data[i]; } i2c_recv_block_successful_callback(); #ifdef I2C_DEBUG_EN g_i2c.test[15]++; #endif } else { *g_i2c.p_len = g_i2c.tx_count; i2c_send_block_successful_callback(); #ifdef I2C_DEBUG_EN g_i2c.test[16]++; #endif } } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ uint8_t i2c_send_block(u8 *p_buf, i2c_len_type len,i2c_len_type *p_real_len) { u8 i; u8 l_len; u8 status = I2C_CMD_RESULT_OK; #ifdef I2C_MADE_BY_SIMU *p_real_len=0u; i2c_simu_start(); i2c_simu_send_byte((g_i2c.slave_addr << 1)); if(i2c_simu_wait_ack()) { status = I2C_CMD_RESULT_FAILED; #ifdef I2C_DEBUG_EN g_i2c.test[18]++; #endif return status; } *p_real_len++; for(i = 0u; i < len; i++) { i2c_simu_send_byte(p_buf[i]); if(i2c_simu_wait_ack()) { status = I2C_CMD_RESULT_FAILED; #ifdef I2C_DEBUG_EN g_i2c.test[19]++; #endif return status; } *p_real_len++; } i2c_simu_stop(); i2c_recv_block_successful_callback(); #ifdef I2C_DEBUG_EN g_i2c.test[17]++; #endif //return status; #else #ifdef I2C_DEBUG_EN g_i2c.test[17]++; #endif //只有空闲时,才能 if(g_i2c.state == I2C_STATE_IDLE) { #ifdef I2C_DEBUG_EN g_i2c.test[18]++; #endif if(len0x7f) { g_i2c.slave_addr_len =I2C_ADDR_10BIT; } else { g_i2c.slave_addr_len =I2C_ADDR_7BIT; } } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : ----------------------------------------------------------------------------*/ static void i2c_goto_stop_bit_state(void) { //跳到 stop FL_I2C_Master_DisableIT_NACK(I2C); FL_I2C_Master_DisableIT_TXComplete(I2C); FL_I2C_Master_DisableIT_RXComplete(I2C); //发完--数据,接下来,发stop bit; g_i2c.timecount = 0u; g_i2c.sub_state = 0u; g_i2c.state = I2C_STATE_STOP_BIT; FL_I2C_Master_EnableI2CStop(I2C); FL_I2C_Master_EnableIT_Stop(I2C); #ifdef I2C_DEBUG_EN g_i2c.test[23]++; #endif } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description : I2C中断 ----------------------------------------------------------------------------*/ void I2C_IRQHandler(void) { u8 l_addr_id=0u; //start bit 成功 if( (FL_I2C_Master_IsEnabledIT_Start(I2C) == FL_ENABLE) && (FL_I2C_Master_IsActiveFlag_Start(I2C)==FL_SET) ) { #ifdef I2C_DEBUG_EN g_i2c.test[24]++; #endif /* -------------- disable read ---------- */ FL_I2C_Master_DisableRX(I2C); FL_I2C_Master_DisableIT_Start(I2C); FL_I2C_Master_DisableIT_Stop(I2C); g_i2c.timecount = 0u; if(g_i2c.state==I2C_STATE_START_BIT) { g_i2c.state = I2C_STATE_SEND_ADDR; #ifdef I2C_DEBUG_EN g_i2c.test[25]++; #endif } //开始传输地址-- FL_I2C_Master_WriteTXBuff(I2C, g_i2c.slave_addr_tx[g_i2c.slave_addr_index]); FL_I2C_Master_EnableIT_TXComplete(I2C); } if( (FL_I2C_Master_IsEnabledIT_TXComplete(I2C) == FL_ENABLE) && (FL_I2C_Master_IsActiveFlag_TXComplete(I2C) == FL_SET) ) { #ifdef I2C_DEBUG_EN g_i2c.test[26]++; #endif FL_I2C_Master_ClearFlag_TXComplete(I2C); g_i2c.timecount = 0u; //判斷,有沒有ack if(FL_I2C_Master_IsActiveFlag_NACK(I2C)==FL_SET) { g_i2c.result_temp=I2C_RESULT_FAILED_NACK; i2c_goto_stop_bit_state(); #ifdef I2C_DEBUG_EN g_i2c.test[27]++; #endif } else { #ifdef I2C_DEBUG_EN g_i2c.test[28]++; #endif } #if 1 if(g_i2c.state == I2C_STATE_SEND_ADDR) { #ifdef I2C_DEBUG_EN g_i2c.test[29]++; #endif if(g_i2c.sub_state==0u) //繼續發送低地址 { g_i2c.slave_addr_index=1; FL_I2C_Master_WriteTXBuff(I2C, g_i2c.slave_addr_tx[g_i2c.slave_addr_index]); FL_I2C_Master_EnableIT_TXComplete(I2C); g_i2c.sub_state=1u; #ifdef I2C_DEBUG_EN g_i2c.test[30]++; #endif } else //可以發送數據DATA { #ifdef I2C_DEBUG_EN g_i2c.test[31]++; #endif if(g_i2c.cmd == I2C_CMD_WRITE) { i2c_tx_data_task(); #ifdef I2C_DEBUG_EN g_i2c.test[32]++; #endif } else if(g_i2c.cmd == I2C_CMD_READ) { i2c_rx_data_start(); #ifdef I2C_DEBUG_EN g_i2c.test[33]++; #endif } } } else if (g_i2c.state == I2C_STATE_WRITE) { //开始发送数据内容 #ifdef I2C_DEBUG_EN g_i2c.test[34]++; #endif i2c_tx_data_task(); //FL_I2C_Master_EnableIT_TXComplete(I2C); } else { // } #endif } if( (FL_I2C_Master_IsEnabledIT_RXComplete(I2C) == FL_ENABLE) && (FL_I2C_Master_IsActiveFlag_RXComplete(I2C)==FL_SET) ) { #ifdef I2C_DEBUG_EN g_i2c.test[35]++; #endif g_i2c.timecount = 0u; //if (g_i2c.state == I2C_STATE_READ) FL_I2C_Master_ClearFlag_RXComplete(I2C); i2c_rx_data_task(); //if(l_nack==0u) { i2c_rx_data_start(); } } if( (FL_I2C_Master_IsEnabledIT_Stop(I2C) == FL_ENABLE) && (FL_I2C_Master_IsActiveFlag_Stop(I2C)==FL_SET) ) { g_i2c.timecount = 0u; FL_I2C_Master_DisableIT_NACK(I2C); FL_I2C_Master_DisableIT_TXComplete(I2C); #ifdef I2C_DEBUG_EN g_i2c.test[36]++; #endif if(g_i2c.result_temp == I2C_RESULT_FAILED_NACK) { g_i2c.result = I2C_RESULT_FAILED_NACK; g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[37]++; #endif } else if(g_i2c.result_temp == I2C_RESULT_OK) { g_i2c.result = I2C_RESULT_OK; i2c_operate_result(g_i2c.cmd); g_i2c.state = I2C_STATE_IDLE; #ifdef I2C_DEBUG_EN g_i2c.test[38]++; #endif } else { // } #ifdef I2C_DEBUG_EN g_i2c.test[39]++; #endif // } if( (FL_I2C_Master_IsEnabledIT_Timeout(I2C) == FL_ENABLE) && (FL_I2C_Master_IsActiveFlag_Timeout(I2C)==FL_SET) ) { #ifdef I2C_DEBUG_EN g_i2c.test[40]++; #endif FL_I2C_Master_ClearFlag_Timeout(I2C); FL_I2C_Master_ClearFlag_TXComplete(I2C); } if( (FL_I2C_Master_IsEnabledIT_WriteConflict(I2C) == FL_ENABLE) && (FL_I2C_Master_IsActiveFlag_WriteConflict(I2C)==FL_SET) ) { #ifdef I2C_DEBUG_EN g_i2c.test[41]++; #endif } #ifdef I2C_DEBUG_EN g_i2c.test[42]++; #endif } /*--------------------------------------------------------------------------- |Prototype : |Called by : |Preconditions : |Input parameters : |Output parameters : |Return value : |Description :發送數據 ----------------------------------------------------------------------------*/ static void i2c_tx_data_task(void) { u8 l_nack; u16 l_count =0u; g_i2c.state = I2C_STATE_WRITE; //if(g_i2c.mode == I2C_CMD_WRITE) { #ifdef I2C_DEBUG_EN g_i2c.test[43]++; #endif if(g_i2c.tx_count=I2C_ADDR_TEST_MAX) { g_i2c.test_addr=0u; g_i2c.test_state=2u; } else { g_i2c.test_state=0u; } } else { #ifdef I2C_DEBUG_EN g_i2c.test[69]++; #endif } #ifdef I2C_DEBUG_EN g_i2c.test[60]++; #endif break; case 2: g_i2c.cmd = I2C_CMD_NULL; i2c_re_init_para(); g_i2c.test_len=0u; g_i2c.test_data[0] =0x21; g_i2c.test_data[1] =0x21; for(i = 0; i < I2C_FRAME_MAX_SIZE; i++) { g_i2c.test_data[i] =0xcc; } g_i2c.result = I2C_RESULT_INIT; //i2c_sel_slave_addr(DEVICE_ADD); i2c_sel_slave_addr(g_addr_test[g_i2c.test_addr]); //uint8_t i2c_recv_block(uint16_t Device, uint8_t AddrLen, uint8_t *Buf, uint8_t Len) g_i2c.cmd_result = i2c_recv_block((u8*)&g_i2c.test_data[0], 6u ,&g_i2c.test_len); g_i2c.test_state=3u; #ifdef I2C_DEBUG_EN g_i2c.test[61]++; #endif break; case 3: //判断有没有发成功 if(g_i2c.result == I2C_RESULT_OK) { #ifdef I2C_DEBUG_EN g_i2c.test[62]++; #endif g_i2c.test_addr=0u; g_i2c.test_state=0u; } else if(g_i2c.result == I2C_RESULT_FAILED_TIMEOUT) { #ifdef I2C_DEBUG_EN g_i2c.test[63]++; #endif } else if(g_i2c.result == I2C_RESULT_FAILE_TOHER) { #ifdef I2C_DEBUG_EN g_i2c.test[64]++; #endif } else if(g_i2c.result == I2C_RESULT_FAILED_NACK) { #ifdef I2C_DEBUG_EN g_i2c.test[65]++; #endif g_i2c.test_addr++; if(g_i2c.test_addr>=I2C_ADDR_TEST_MAX) { g_i2c.test_addr=0u; g_i2c.test_state=2u; } else { g_i2c.test_state=2u; } } else { #ifdef I2C_DEBUG_EN g_i2c.test[66]++; #endif } #ifdef I2C_DEBUG_EN g_i2c.test[67]++; #endif break; default: break; } #endif #if 0 if(g_i2c.test_state==0) { } else { g_i2c.test_state=0u; g_i2c.rx_len=7u; common_memory_clear(&g_i2c.rx_data[0],20); l_result = i2c_recv_block(Device, AddrLen, &g_i2c.rx_data[0], g_i2c.rx_len); #ifdef I2C_DEBUG_EN g_i2c.test[1]++; #endif } #endif //return l_result; } /* END i2c.h. */