#include "eeprom.h" #include "board_cfg.h" #include "gd32e23x.h" #include "common.h" #include "systick.h" #define ACK 1 #define NACK 0 #define IIC_WP_PIN GPIO_PIN_15 #define IIC_DATA_IO GPIOF #define IIC_SDA_PIN GPIO_PIN_0 #define IIC_SCL_PIN GPIO_PIN_1 #define PAGE_SZIE_32 (32) #define PAGE_SIZE_16 (16) #define IIC_READ_SDA() gpio_input_bit_get(IIC_DATA_IO, IIC_SDA_PIN) #define IIC_SCL_SET gpio_bit_set(IIC_DATA_IO, IIC_SCL_PIN) #define IIC_SCL_CLR gpio_bit_reset(IIC_DATA_IO, IIC_SCL_PIN) #define IIC_SDA_SET gpio_bit_set(IIC_DATA_IO, IIC_SDA_PIN) #define IIC_SDA_CLR gpio_bit_reset(IIC_DATA_IO, IIC_SDA_PIN) #define AT24C01 127 #define AT24C02 255 #define AT24C04 511 #define AT24C08 1023 #define AT24C16 2047 #define AT24C32 4095 #define AT24C64 8191 #define AT24C128 16383 #define AT24C256 32767 #define USER_DEFINE_EEPROM_TYPE AT24C64 #define PAGE_SIZE PAGE_SZIE_32 static void iic_init(void); static void iic_start_signal(void); static void iic_stop_signal(void); static void iic_send_byte(uint8_t data); static uint8_t iic_read_byte(uint8_t ack); static uint8_t iic_wait_ack(void); static void iic_send_ack(void); static void iic_send_nack(void); static uint8_t eeprom_read_1_byte(uint16_t addr); static void eeprom_write_1_byte(uint16_t addr,uint8_t data); static void eeprom_write(uint16_t w_addr,uint8_t *data,uint16_t lenth); static void eeprom_read(uint16_t r_addr,uint8_t *data,uint16_t lenth); static void check_threshold(uint8_t in_out,uint8_t channel); static uint8_t eeprom_page_read(uint16_t addr,uint8_t *data,uint16_t lenth); static uint8_t eeprom_write_page(uint16_t addr,uint8_t *data,uint16_t chuank); static void eeprom_auto_page_write(uint16_t addr,uint8_t *data,uint16_t lenth); static void eeprom_auto_page_read(uint16_t addr,uint8_t *data,uint16_t lenth); static inline void iic_set_sda_input() { gpio_mode_set(IIC_DATA_IO, GPIO_MODE_INPUT, GPIO_PUPD_NONE, IIC_SDA_PIN); } static inline void iic_set_sda_output() { gpio_mode_set(IIC_DATA_IO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, IIC_SDA_PIN); gpio_output_options_set(IIC_DATA_IO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, IIC_SDA_PIN); } void eeprom_init(void) { board_t *board = get_board(); iic_init(); board->read_eeprom = eeprom_read; board->write_eeprom = eeprom_write; board->check_threshold = check_threshold; board->read_eeprom_page = eeprom_auto_page_read; board->write_eeprom_page = eeprom_auto_page_write; } static void iic_init(void) { rcu_periph_clock_enable(RCU_GPIOC); gpio_mode_set(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_15); gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15); /* WP */ gpio_bit_reset(GPIOC, GPIO_PIN_15); rcu_periph_clock_enable(RCU_GPIOF); gpio_mode_set(IIC_DATA_IO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_0); gpio_output_options_set(IIC_DATA_IO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, IIC_SDA_PIN); /* SDA */ gpio_mode_set(IIC_DATA_IO, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_1); /* SCL */ gpio_output_options_set(IIC_DATA_IO, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, IIC_SCL_PIN); } /***************************************************************************************** * start data transport signal * 1 2 3 4 * __________ * SCL : __/ \_____ * ________ * SDA : \___________ ******************************************************************************************/ static void iic_start_signal(void) { iic_set_sda_output(); IIC_SDA_SET; IIC_SCL_SET; DelayNus(4); IIC_SDA_CLR; DelayNus(4); IIC_SCL_CLR; } /***************************************************************************************** * stop data transport signal * 1 2 3 4 * _______________ * SCL : ______/ * __ ____________ * SDA : \______/ * ^ * | * ******************************************************************************************/ static void iic_stop_signal(void) { iic_set_sda_output(); IIC_SCL_CLR; IIC_SDA_CLR; DelayNus(4); IIC_SCL_SET; DelayNus(4); IIC_SDA_SET; DelayNus(4); } /***************************************************************************************** * iic send 1 byte * 1 2 3 4 * ______ * SCL: ________/ \______ * ______________________ * SDA: \\\___________________ * ******************************************************************************************/ static void iic_send_byte(uint8_t data) { iic_set_sda_output(); IIC_SCL_CLR; uint8_t t; for(t = 0; t < 8; t++){ if((data & 0x80) >> 7) { IIC_SDA_SET; }else { IIC_SDA_CLR; } data <<= 1; DelayNus(2); IIC_SCL_SET; DelayNus(2); IIC_SCL_CLR; DelayNus(2); } } /***************************************************************************************** * read 1 byte * 1 2 3 4 * ______ * SCL: ______/ \___ * ____________________ * SDA: \\\\______________\\\ * ******************************************************************************************/ static uint8_t iic_read_byte(uint8_t ack) { uint8_t i; uint8_t receive = 0; iic_set_sda_input(); for(i = 0; i < 8; i++ ){ IIC_SCL_CLR; DelayNus(2); IIC_SCL_SET; receive <<= 1; if(IIC_READ_SDA()) { receive ++; } DelayNus(1); } if(NACK == ack) { iic_send_nack(); }else{ iic_send_ack(); } return receive; } /***************************************************************************************** * wait ack signal * _______|____ * SCL: | \_________ * _______| * SDA: \_____________ * ******************************************************************************************/ static uint8_t iic_wait_ack(void) { uint8_t err_time = 0; iic_set_sda_input(); IIC_SCL_SET; DelayNus(1); while(IIC_READ_SDA()) { err_time++; if(err_time >250) { iic_stop_signal(); return 1; } } IIC_SCL_CLR; return 0; } /***************************************************************************************** * send ack signal * 1 2 3 4 * ______ * SCL: ________/ \______ * __ * SDA: \___________________ ******************************************************************************************/ static void iic_send_ack(void) { IIC_SCL_CLR; iic_set_sda_output(); IIC_SDA_CLR; DelayNus(2); IIC_SCL_SET; DelayNus(2); IIC_SCL_CLR; } /***************************************************************************************** * send nack signal * 1 2 3 4 * ______ * SCL: ________/ \______ * ______________________ * SDA: __/ ******************************************************************************************/ static void iic_send_nack(void) { IIC_SCL_CLR; iic_set_sda_output(); IIC_SDA_SET; DelayNus(2); IIC_SCL_SET; DelayNus(2); IIC_SCL_CLR; } static uint8_t eeprom_read_1_byte(uint16_t addr) { uint8_t temp =0; iic_start_signal(); if(USER_DEFINE_EEPROM_TYPE > AT24C16) { iic_send_byte(0XA0); iic_wait_ack(); iic_send_byte(addr >> 8); }else { iic_send_byte(0XA0 + ((addr / 256) << 1)); } iic_wait_ack(); iic_send_byte(addr % 256); iic_wait_ack(); iic_start_signal(); iic_send_byte(0XA1); iic_wait_ack(); temp = iic_read_byte(0); iic_stop_signal(); return temp; } static void eeprom_write_1_byte(uint16_t addr,uint8_t data) { iic_start_signal(); if(USER_DEFINE_EEPROM_TYPE > AT24C16) { iic_send_byte(0XA0); iic_wait_ack(); iic_send_byte(addr >> 8); }else { iic_send_byte(0XA0 + ((addr / 256) << 1)); } iic_wait_ack(); iic_send_byte(addr % 256); iic_wait_ack(); iic_send_byte(data); iic_wait_ack(); iic_stop_signal(); DelayNms(7); } static void eeprom_write(uint16_t w_addr,uint8_t *data,uint16_t lenth) { while(lenth) { eeprom_write_1_byte(w_addr,*data); w_addr++; data++; lenth--; } } static void eeprom_read(uint16_t r_addr,uint8_t *data,uint16_t lenth) { while(lenth) { *data = eeprom_read_1_byte(r_addr); data++; r_addr++; lenth--; } } static void check_threshold(uint8_t in_out,uint8_t channel) { if(in_out == THRESHOLD_IN) { #if (AC_3_3 || AC_3_4) board_t *board = get_board(); if(board->md_data.rw_data.i_V_max > Default_Voltage_Max) board->md_data.rw_data.i_V_max = 0; if(board->md_data.rw_data.i_V_min > Default_Voltage_Max) board->md_data.rw_data.i_V_min = 0; if(board->md_data.rw_data.i_I_max > Default_Current_Max) board->md_data.rw_data.i_I_max = 0; if(board->md_data.rw_data.i_P_max > Default_Power_Max) board->md_data.rw_data.i_P_max = 0; if(board->md_data.rw_data.i_C_max > Default_Consum_Max) board->md_data.rw_data.i_C_max = 0; if(board->md_data.rw_data.i_V_max <= THRESHOULD_JUDGMENT) UNSET_VOLTAGE_MAX_EN(board->in_wanning_en[channel]); else SET_VOLTAGE_MAX_EN(board->in_wanning_en[channel]); if(board->md_data.rw_data.i_V_min <= THRESHOULD_JUDGMENT) UNSET_VOLTAGE_MIN_EN(board->in_wanning_en[channel]); else SET_VOLTAGE_MIN_EN(board->in_wanning_en[channel]); if(board->md_data.rw_data.i_I_max <= THRESHOULD_JUDGMENT) UNSET_CURRENT_MAX_EN(board->in_wanning_en[channel]); else SET_CURRENT_MAX_EN(board->in_wanning_en[channel]); if(board->md_data.rw_data.i_P_max <= THRESHOULD_JUDGMENT) UNSET_POWER_MAX_EN(board->in_wanning_en[channel]); else SET_POWER_MAX_EN(board->in_wanning_en[channel]); if(board->md_data.rw_data.i_C_max <= THRESHOULD_JUDGMENT) UNSET_CONSUMER_MAX_EN(board->in_wanning_en[channel]); else SET_CONSUMER_MAX_EN(board->in_wanning_en[channel]); #endif }else if(in_out == THRESHOLD_OUT) { board_t *board = get_board(); if(channel < RelaySlaveChaNum) { if(board->md_data.rw_data.o_V_max[channel] > Default_Voltage_Max) board->md_data.rw_data.o_V_max[channel] = 0; if(board->md_data.rw_data.o_V_min[channel] > Default_Voltage_Max) board->md_data.rw_data.o_V_min[channel] = 0; if(board->md_data.rw_data.o_I_max[channel] > Default_Current_Max) board->md_data.rw_data.o_I_max[channel] = 0; if(board->md_data.rw_data.o_P_max[channel] > Default_Power_Max) board->md_data.rw_data.o_P_max[channel] = 0; if(board->md_data.rw_data.o_C_max[channel] > Default_Consum_Max) board->md_data.rw_data.o_C_max[channel] = 0; if(board->md_data.rw_data.o_V_max[channel] <= THRESHOULD_JUDGMENT) UNSET_VOLTAGE_MAX_EN(board->out_wanning_en[channel]); else SET_VOLTAGE_MAX_EN(board->out_wanning_en[channel]); if(board->md_data.rw_data.o_V_min[channel] <= THRESHOULD_JUDGMENT) UNSET_VOLTAGE_MIN_EN(board->out_wanning_en[channel]); else SET_VOLTAGE_MIN_EN(board->out_wanning_en[channel]); if(board->md_data.rw_data.o_I_max[channel] <= THRESHOULD_JUDGMENT) UNSET_CURRENT_MAX_EN(board->out_wanning_en[channel]); else SET_CURRENT_MAX_EN(board->out_wanning_en[channel]); if(board->md_data.rw_data.o_P_max[channel] <= THRESHOULD_JUDGMENT) UNSET_POWER_MAX_EN(board->out_wanning_en[channel]); else SET_POWER_MAX_EN(board->out_wanning_en[channel]); if(board->md_data.rw_data.o_C_max[channel] <= THRESHOULD_JUDGMENT) UNSET_CONSUMER_MAX_EN(board->out_wanning_en[channel]); else SET_CONSUMER_MAX_EN(board->out_wanning_en[channel]); } } } static uint8_t eeprom_page_read(uint16_t addr,uint8_t *data,uint16_t lenth) { if(lenth == 0 || lenth > PAGE_SIZE || ((addr % PAGE_SIZE) + lenth > PAGE_SIZE)) { return 1; } iic_start_signal(); if(USER_DEFINE_EEPROM_TYPE > AT24C16) { iic_send_byte(0XA0); if(iic_wait_ack()) goto failed; iic_send_byte(addr >> 8); }else { iic_send_byte(0XA0 + ((addr / 256) << 1)); } if(iic_wait_ack()) goto failed; iic_send_byte(addr % 256); if(iic_wait_ack()) goto failed; iic_start_signal(); iic_send_byte(0XA1); if(iic_wait_ack()) goto failed; for(int i = 0; i < lenth;i++) { if(i == lenth -1) { data[i] = iic_read_byte(0); }else { data[i] = iic_read_byte(1); } } iic_stop_signal(); return 0; failed: iic_stop_signal(); return 1; } static uint8_t eeprom_write_page(uint16_t addr,uint8_t *data,uint16_t chuank) { if(chuank == 0 || chuank > PAGE_SIZE || ((addr % PAGE_SIZE) + chuank > PAGE_SIZE)) { return 1; } iic_start_signal(); if(USER_DEFINE_EEPROM_TYPE > AT24C16) { iic_send_byte(0XA0); if(iic_wait_ack()) goto failed; iic_send_byte(addr >> 8); }else { iic_send_byte(0XA0 + ((addr / 256) << 1)); } if(iic_wait_ack()) goto failed; iic_send_byte(addr % 256); if(iic_wait_ack()) goto failed; for(uint16_t i = 0; i < chuank;i++) { iic_send_byte(data[i]); if(iic_wait_ack()) goto failed; } iic_stop_signal(); DelayNms(7); return 0; failed: iic_stop_signal(); return 1; } static void eeprom_auto_page_write(uint16_t addr,uint8_t *data,uint16_t lenth) { uint16_t remaining = lenth; uint8_t *p = data; uint8_t count = 5; while(remaining > 0) { uint8_t chunk = PAGE_SIZE - (addr % PAGE_SIZE); if(chunk > remaining) chunk = remaining; do{ if(!eeprom_write_page(addr, p,chunk)) { break; } }while(count--); addr += chunk; p += chunk; remaining -= chunk; } } static void eeprom_auto_page_read(uint16_t addr,uint8_t *data,uint16_t lenth) { uint16_t remaining = lenth; uint8_t *p = data; uint8_t count = 5; while(remaining > 0) { uint8_t chunk = PAGE_SIZE - (addr % PAGE_SIZE); if(chunk > remaining) chunk = remaining; do{ if(!eeprom_page_read(addr, p, chunk)) { break; } }while(count--); addr += chunk; p += chunk; remaining -= chunk; } }