/*
官方例程GD32F10x
GD32F103\GD32F1系列固件库\GD32F10x_Firmware_Library_V2.2.3 \GD32F10x_Firmware_Library_V2.2.3\Examples\I2C\I2C_EEPROM_dma
当BUFFER_SIZE是1的时候,eeprom_buffer_read_dma_timeout处理里面number_of_byte容易变0xfff
eeprom_buffer_read_dma_timeout(i2c_buffer_read, EEP_FIRST_PAGE, BUFFER_SIZE);
导致 while(!dma_flag_get(I2C_DMA, DMA_RX_CH, DMA_FLAG_FTF));一直卡在这
*/
uint8_t i2c_24c02_test(void)
{
uint16_t i;
uint8_t i2c_buffer_write[BUFFER_SIZE];
uint8_t i2c_buffer_read[BUFFER_SIZE];
printf("\r\nAT24C02 writing...\r\n");
/* initialize i2c_buffer_write */
for(i = 0; i < BUFFER_SIZE; i++) {
i2c_buffer_write[i] = i;
printf("0x%02X ", i2c_buffer_write[i]);
if(15 == i % 16) {
printf("\r\n");
}
}
/* EEPROM data write */
eeprom_buffer_write_dma_timeout(i2c_buffer_write, EEP_FIRST_PAGE, BUFFER_SIZE);
printf("AT24C02 reading...\r\n");
/* EEPROM data read */
eeprom_buffer_read_dma_timeout(i2c_buffer_read, EEP_FIRST_PAGE, BUFFER_SIZE);
/* compare the read buffer and write buffer */
for(i = 0; i < BUFFER_SIZE; i++) {
if(i2c_buffer_read[i] != i2c_buffer_write[i]) {
printf("0x%02X ", i2c_buffer_read[i]);
printf("Err:data read and write aren't matching.\n\r");
return I2C_FAIL;
}
printf("0x%02X ", i2c_buffer_read[i]);
if(15 == i % 16) {
printf("\r\n");
}
}
printf("I2C-AT24C02 test passed!\n\r");
return I2C_OK;
}
uint8_t eeprom_buffer_read_dma_timeout(uint8_t *p_buffer, uint8_t read_address, uint16_t number_of_byte)
{
dma_parameter_struct dma_init_struct;
uint8_t state = I2C_START;
uint8_t read_cycle = 0;
uint16_t timeout = 0;
uint8_t i2c_timeout_flag = 0;
/* enable acknowledge */
i2c_ack_config(I2CX, I2C_ACK_ENABLE);
while(!(i2c_timeout_flag)) {
switch(state) {
case I2C_START:
if(RESET == read_cycle) {
/* disable I2CX */
i2c_disable(I2CX);
/* enable I2CX */
i2c_enable(I2CX);
/* enable acknowledge */
i2c_ack_config(I2CX, I2C_ACK_ENABLE);
/* 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) {
/* send the start signal */
i2c_start_on_bus(I2CX);
timeout = 0;
state = I2C_SEND_ADDRESS;
} else {
i2c_bus_reset();
timeout = 0;
state = I2C_START;
printf("i2c bus is busy in READ!\n");
}
} else {
i2c_start_on_bus(I2CX);
timeout = 0;
state = I2C_SEND_ADDRESS;
}
break;
case I2C_SEND_ADDRESS:
/* i2c master sends START signal successfully */
while((! i2c_flag_get(I2CX, I2C_FLAG_SBSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
if(RESET == read_cycle) {
i2c_master_addressing(I2CX, eeprom_address, I2C_TRANSMITTER);
state = I2C_CLEAR_ADDRESS_FLAG;
} else {
i2c_master_addressing(I2CX, eeprom_address, I2C_RECEIVER);
state = I2C_CLEAR_ADDRESS_FLAG;
}
timeout = 0;
} else {
timeout = 0;
state = I2C_START;
read_cycle = 0;
printf("i2c master sends start signal timeout in READ!\n");
}
break;
case I2C_CLEAR_ADDRESS_FLAG:
/* address flag set means i2c slave sends ACK */
while((!i2c_flag_get(I2CX, I2C_FLAG_ADDSEND)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
i2c_flag_clear(I2CX, I2C_FLAG_ADDSEND);
timeout = 0;
state = I2C_TRANSMIT_DATA;
} else {
timeout = 0;
state = I2C_START;
read_cycle = 0;
printf("i2c master clears address flag timeout in READ!\n");
}
break;
case I2C_TRANSMIT_DATA:
if(RESET == read_cycle) {
/* 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;
} else {
timeout = 0;
state = I2C_START;
read_cycle = 0;
printf("i2c master wait data buffer is empty timeout in READ!\n");
}
/* wait until BTC bit is set */
while((!i2c_flag_get(I2CX, I2C_FLAG_BTC)) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_START;
read_cycle++;
} else {
timeout = 0;
state = I2C_START;
read_cycle = 0;
printf("i2c master sends EEPROM's internal address timeout in READ!\n");
}
} else {
/* one byte master reception procedure (polling) */
if(number_of_byte < 2) {
/* disable acknowledge */
i2c_ack_config(I2CX, I2C_ACK_DISABLE);
/* clear ADDSEND register by reading I2C_STAT0 then I2C_STAT1 register (I2C_STAT0 has already been read) */
i2c_flag_get(I2CX, I2C_FLAG_ADDSEND);
/* send a stop condition to I2C bus*/
i2c_stop_on_bus(I2CX);
/* wait for the byte to be received */
while(!i2c_flag_get(I2CX, I2C_FLAG_RBNE));
/* read the byte received from the EEPROM */
*p_buffer = i2c_data_receive(I2CX);
/* decrement the read bytes counter */
number_of_byte--;
timeout = 0;
state = I2C_STOP;
} else { /* more than one byte master reception procedure (DMA) */
dma_deinit(I2C_DMA, DMA_RX_CH);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t)p_buffer;
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct.number = number_of_byte;
dma_init_struct.periph_addr = (uint32_t)&I2C_DATA(I2CX);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(I2C_DMA, DMA_RX_CH, &dma_init_struct);
i2c_dma_last_transfer_config(I2CX, I2C_DMALST_ON);
/* enable I2CX DMA */
i2c_dma_config(I2CX, I2C_DMA_ON);
/* enable DMA0 channel5 */
dma_channel_enable(I2C_DMA, DMA_RX_CH);
/* wait until BTC bit is set */
while(!dma_flag_get(I2C_DMA, DMA_RX_CH, DMA_FLAG_FTF));
state = I2C_STOP;
}
}
break;
case I2C_STOP:
/* send a stop condition to I2C bus */
i2c_stop_on_bus(I2CX);
/* i2c master sends STOP signal successfully */
while((I2C_CTL0(I2CX) & I2C_CTL0_STOP) && (timeout < I2C_TIME_OUT)) {
timeout++;
}
if(timeout < I2C_TIME_OUT) {
timeout = 0;
state = I2C_END;
i2c_timeout_flag = I2C_OK;
} else {
timeout = 0;
state = I2C_START;
read_cycle = 0;
printf("i2c master sends stop signal timeout in READ!\n");
}
break;
default:
state = I2C_START;
read_cycle = 0;
i2c_timeout_flag = I2C_OK;
timeout = 0;
printf("i2c master sends start signal in READ.\n");
break;
}
}
return I2C_END;
}
while(!dma_flag_get(I2C_DMA, DMA_RX_CH, DMA_FLAG_FTF));IIC的DMA卡住
最新推荐文章于 2024-05-17 15:49:03 发布