[Zhaoyi GD32H759I-EVAL] i2c read/write at24c02 test
[Copy Link]
The at24c02 read/write test is performed through the i2c routine on the official website.
1、 Hardware
1.1. i2c hardware circuit diagram
I2C1 uses ports PH4 and PB11
1.2 Mapping of PH4 and PB11 in the Data Book
1.3. at24c02 memory parameters
storage structure
The total storage space of at24c02 is 2048bits=2048/8=256 bytes. There are 32 pages inside, and each page has 8 bytes.
2、 Program part
2.1. i2c pin configuration
void gpio_config(void) { /* enable I2C_SCL_PIN clock */ rcu_periph_clock_enable(RCU_GPIO_I2C_SCL); /* enable I2C_SDA_PIN clock */ rcu_periph_clock_enable(RCU_GPIO_I2C_SDA); /* enable I2C clock */ rcu_periph_clock_enable(RCU_I2C); /* connect I2C_SCL_PIN to I2C_SCL */ gpio_af_set(I2C_SCL_PORT, I2C_GPIO_AF, I2C_SCL_PIN); /* connect I2C_SDA_PIN to I2C_SDA */ gpio_af_set(I2C_SDA_PORT, I2C_GPIO_AF, I2C_SDA_PIN); /* configure GPIO pins of I2C */ gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN); gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_60MHZ, I2C_SCL_PIN); gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN); gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_60MHZ, I2C_SDA_PIN); }
2.2 i2c Clock Configuration
void i2c_config(void) { /* configure the I2C1 clock source selection */ rcu_i2c_clock_config(IDX_I2C1, RCU_I2CSRC_IRC64MDIV); /* configure I2C timing */ i2c_timing_config(I2CX, 0x0, 0x6, 0); i2c_master_clock_config(I2CX, 0x26, 0x73); /* enable I2C */ i2c_enable(I2CX); }
2.3. at24c02 Write Function
void eeprom_buffer_write(uint8_t *p_buffer, uint8_t write_address, uint16_t number_of_byte) { uint8_t number_of_page = 0, number_of_single = 0, address = 0, count = 0; address = write_address % I2C_PAGE_SIZE; count = I2C_PAGE_SIZE - address; number_of_page = number_of_byte / I2C_PAGE_SIZE; number_of_single = number_of_byte % I2C_PAGE_SIZE; /* if write_address is I2C_PAGE_SIZE aligned */ if(0 == address) { while(number_of_page--) { eeprom_page_write(p_buffer, write_address, I2C_PAGE_SIZE); delay_1ms(6); write_address += I2C_PAGE_SIZE; p_buffer += I2C_PAGE_SIZE; } if(0 != number_of_single) { eeprom_page_write(p_buffer, write_address, number_of_single); delay_1ms(6); } } else { /* if write_address is not I2C_PAGE_SIZE aligned */ if(number_of_byte < count) { eeprom_page_write(p_buffer, write_address, number_of_byte); delay_1ms(6); } else { number_of_byte -= count; number_of_page = number_of_byte / I2C_PAGE_SIZE; number_of_single = number_of_byte % I2C_PAGE_SIZE; if(0 != count) { eeprom_page_write(p_buffer, write_address, count); delay_1ms(6); write_address += count; p_buffer += count; } /* write page */ while(number_of_page--) { eeprom_page_write(p_buffer, write_address, I2C_PAGE_SIZE); delay_1ms(6); write_address += I2C_PAGE_SIZE; p_buffer += I2C_PAGE_SIZE; } /* write single */ if(0 != number_of_single) { eeprom_page_write(p_buffer, write_address, number_of_single); delay_1ms(6); } } } }
2.4. at24c02 Read Function
void eeprom_buffer_read(uint8_t *p_buffer, uint8_t read_address, uint16_t number_of_byte) { uint32_t nbytes_reload = 0; i2c_process_enum state = I2C_START; uint32_t timeout = 0; uint8_t end_flag = 0; uint8_t restart_flag = 0; uint8_t first_reload_flag = 1; uint8_t last_reload_flag = 0; while(! end_flag) { switch(state) { case I2C_START: if(0 == restart_flag) { /* clear I2C_TDATA register */ I2C_STAT(I2CX) |= I2C_STAT_TBE; /* configure slave address */ i2c_master_addressing(I2CX, eeprom_address, I2C_MASTER_TRANSMIT); /* configure number of bytes to be transferred */ i2c_transfer_byte_number_config(I2CX, 1); /* disable I2C automatic end mode in master mode */ i2c_automatic_end_disable(I2CX); /* i2c master sends start signal only when the bus is idle */ while(i2c_flag_get(I2CX, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) { timeout++; } if(timeout < I2C_TIME_OUT) { i2c_start_on_bus(I2CX); timeout = 0; state = I2C_SEND_ADDRESS; } else { /* timeout, bus reset */ i2c_bus_reset(); timeout = 0; state = I2C_START; printf("i2c bus is busy in read!\n"); } } else { /* restart */ i2c_start_on_bus(I2CX); restart_flag = 0; state = I2C_TRANSMIT_DATA; } break; case I2C_SEND_ADDRESS: /* wait until the transmit data buffer is empty */ while((!i2c_flag_get(I2CX, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { timeout++; } if(timeout < I2C_TIME_OUT) { /* send the EEPROM's internal address to write to : only one byte address */ i2c_data_transmit(I2CX, read_address); timeout = 0; state = I2C_RESTART; } else { timeout = 0; state = I2C_START; printf("i2c master sends data timeout in read!\n"); } break; case I2C_RESTART: /* wait until the transmit data buffer is empty */ while((!i2c_flag_get(I2CX, I2C_FLAG_TC)) && (timeout < I2C_TIME_OUT)) { timeout++; } if(timeout < I2C_TIME_OUT) { /* configure the EEPROM's internal address to write to : only one byte address */ i2c_master_addressing(I2CX, eeprom_address, I2C_MASTER_RECEIVE); /* enable I2C reload mode */ i2c_reload_enable(I2CX); /* configure number of bytes to be transferred */ timeout = 0; state = I2C_RELOAD; restart_flag = 1; } else { timeout = 0; state = I2C_START; printf("i2c master sends EEPROM's internal address timeout in read!\n"); } break; case I2C_RELOAD: if(number_of_byte > MAX_RELOAD_SIZE) { number_of_byte = number_of_byte - MAX_RELOAD_SIZE; nbytes_reload = MAX_RELOAD_SIZE; } else { nbytes_reload = number_of_byte; last_reload_flag = 1; } if(1 == first_reload_flag) { /* configure number of bytes to be transferred */ i2c_transfer_byte_number_config(I2CX, nbytes_reload); if(1 == last_reload_flag) { last_reload_flag = 0; /* disable I2C reload mode */ if(number_of_byte <= MAX_RELOAD_SIZE) { i2c_reload_disable(I2CX); /* enable I2C automatic end mode in master mode */ i2c_automatic_end_enable(I2CX); } } first_reload_flag = 0; state = I2C_START; } else { /* wait for TCR flag */ while((!i2c_flag_get(I2CX, I2C_FLAG_TCR)) && (timeout < I2C_TIME_OUT)) { timeout++; } if(timeout < I2C_TIME_OUT) { /* configure number of bytes to be transferred */ i2c_transfer_byte_number_config(I2CX, nbytes_reload); /* disable I2C reload mode */ if(number_of_byte <= MAX_RELOAD_SIZE) { i2c_reload_disable(I2CX); /* enable I2C automatic end mode in master mode */ i2c_automatic_end_enable(I2CX); } timeout = 0; state = I2C_TRANSMIT_DATA; } else { timeout = 0; state = I2C_START; printf("i2c master reload data timeout in read!\n"); } } break; case I2C_TRANSMIT_DATA: /* wait until TI bit is set */ while((!i2c_flag_get(I2CX, I2C_FLAG_TBE)) && (timeout < I2C_TIME_OUT)) { timeout++; } if(timeout < I2C_TIME_OUT) { while(nbytes_reload) { delay_1ms(2); /* wait until the RBNE bit is set and clear it */ if(i2c_flag_get(I2CX, I2C_FLAG_RBNE)) { /* read a byte from the EEPROM */ *p_buffer = i2c_data_receive(I2CX); /* point to the next location where the byte read will be saved */ p_buffer++; /* decrement the read bytes counter */ nbytes_reload--; } } timeout = 0; /* check if the reload mode is enabled or not */ if(I2C_CTL1(I2CX) & I2C_CTL1_RELOAD) { timeout = 0; state = I2C_RELOAD; } else { timeout = 0; state = I2C_STOP; } } else { /* wait TI timeout */ timeout = 0; state = I2C_START; printf("i2c master read data timeout in read!\n"); } break; case I2C_STOP: /* wait until the stop condition is finished */ while((!i2c_flag_get(I2CX, I2C_FLAG_STPDET)) && (timeout < I2C_TIME_OUT)) { timeout++; } if(timeout < I2C_TIME_OUT) { /* clear STPDET flag */ i2c_flag_clear(I2CX, I2C_FLAG_STPDET); timeout = 0; state = I2C_END; end_flag = 1; } else { timeout = 0; state = I2C_START; printf("i2c master sends stop signal timeout in read!\n"); } break; default: /* default status */ state = I2C_START; end_flag = 1; timeout = 0; printf("i2c master sends start signal in read!\n"); break; } } }
2.5、main.c
#include "main.h" void cache_enable(void); char txbuf[]=" https://bbs.eeworld.com.cn/GD32H759I-EVAL "; char rxbuf[]; int main(void) { uint8_t x=0; uint32_t sd=0; uint32_t yd=0; cache_enable(); systick_config(); init_usart(115200); init_led(); gpio_config(); i2c_config(); i2c_eeprom_init(); exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0); init_lcd(); LCDDisplayDir(LCD_SCREEN_HORIZONTAL); LCDClear(LCD_COLOR_WHITE); eeprom_buffer_write(txbuf, 0x00, sizeof(txbuf)); LCDShowString(10, 20, 400,16, LCD_FONT_16, LCD_TEXT_TRANS, LCD_COLOR_RED, NULL, "at24c02 write data:"); LCDShowString(10, 40, 400,16, LCD_FONT_16, LCD_TEXT_TRANS, LCD_COLOR_RED, NULL, txbuf); eeprom_buffer_read(rxbuf, 0x00, sizeof(txbuf)); LCDShowString(10, 80, 400,16, LCD_FONT_16, LCD_TEXT_TRANS, LCD_COLOR_BLUE, NULL, "at24c02 read data:"); LCDShowString(10, 100, 400,16, LCD_FONT_16, LCD_TEXT_TRANS, LCD_COLOR_BLUE, NULL, rxbuf); while(1) { delay_1ms(100); } } void cache_enable(void) { /* enable i-cache */ SCB_EnableICache(); /* enable d-cache */ SCB_EnableDCache(); }
3、 Operation results
After downloading the program and running the development board, the content of writing and reading at24c02 will be displayed on the display screen.
4、 Attachment
i2c.c
(4.6 KB, download times: 0)
i2c.h
(2.38 KB, number of downloads: 0)
|