#include "i2c.h" #include "usart.h" #include "delay.h" #define I2C_BASE ((I2C_TypeDef*)i2cBase_Addr_List[i2c_dev->channelNo]) void i2c_hardware_enable(i2c_t *i2c_dev) { i2c_hardware_reset(i2c_dev); // Enables the i2c bus RCC->APB1ENR |= (1 << i2cBus_En_bitPos[i2c_dev->channelNo]); i2c_dev->hardwareState = i2c_hw_enabled; pinInit(pinA9); pinInit(pinA10); pinConfig(pinA9, alternate, openDrain, pullUp, fast);// I2C SCL pinConfig(pinA10, alternate, openDrain, pullUp, fast);// I2C CSA pinSetAlternate(pinA9, 4); pinSetAlternate(pinA10, 4); i2c_dev->hardwareState = i2c_hw_ready; } // Resets the I2C hardware using the reset registers, // This will init the device to it's defualt configuration established by STM void i2c_hardware_reset(i2c_t *i2c_dev) { RCC->APB1RSTR |= (1 << i2cBus_Rst_bitPos[i2c_dev->channelNo]); RCC->APB1RSTR &= ~(1 << i2cBus_Rst_bitPos[i2c_dev->channelNo]); i2c_dev->hardwareState = i2c_hw_reset; } //enables periferal void i2c_periferal_enable(i2c_t *i2c_dev) { I2C_BASE->CR1 |= I2C_CR1_PE; i2c_dev->periferalState = i2c_perif_enabled; //Wait untill periferal is ready for communication while(!i2c_is_perif_ready(i2c_dev)); i2c_dev->periferalState = i2c_perif_ready; } void i2c_periferal_disable(i2c_t *i2c_dev) { I2C_BASE->CR1 &= ~I2C_CR1_PE; i2c_dev->periferalState = i2c_perif_disabled; } void i2c_set_mode(i2c_t *i2c_dev, i2c_mode_t mode) { //This device will set himself automatically to master mode if(i2c_dev->mode == i2c_mode_master) { } else if(i2c_dev->mode == i2c_mode_slave) { // to be written. } } void i2c_set_address_lenght(i2c_t *i2c_dev, i2c_address_size_t size) { if(i2c_dev->mode == i2c_mode_master) { if(i2c_dev->addressSize == i2c_address_size_10b) { I2C_BASE->CR2 |= I2C_CR2_ADD10; // 10 Bit addressing I2C_BASE->CR2 &= ~I2C_CR2_HEAD10R; // 7 Bit header read turned on DEFAULT } else { I2C_BASE->CR2 &= ~I2C_CR2_ADD10; // 7 Bit addressing DEFAULT I2C_BASE->CR2 |= I2C_CR2_HEAD10R; // 7 Bit header read turned off DEFAULT } } else if(i2c_dev->mode == i2c_mode_slave) { // to be written. } } void i2c_set_clk_stretch(i2c_t *i2c_dev, i2c_clk_stretching_t stretching) { if(i2c_dev->stretching == i2c_clk_stretching_enable) { I2C_BASE->CR1 &=~ I2C_CR1_NOSTRETCH; } else if(i2c_dev->stretching == i2c_clk_stretching_disable) { I2C_BASE->CR1 |= I2C_CR1_NOSTRETCH; } } void i2c_set_clk_speed(i2c_t *i2c_dev, i2c_clk_speed_t speed) { switch(speed) { case i2c_clk_speed_standart: I2C_BASE->TIMINGR = 0x2000090E; break; case i2c_clk_speed_fast: break; case i2c_clk_speed_fastPlus: break; case i2c_clk_speed_hightSpeed: break; case i2c_clk_speed_ultraFast: break; default: break; } } void i2c_set_filter(i2c_t *i2c_dev, uint8_t enable) { if(enable) { //Anlalog filter is on I2C_BASE->CR1 &= ~I2C_CR1_ANFOFF; } else { //Anlalog filter is off I2C_BASE->CR1 |= I2C_CR1_ANFOFF; } } /************************************************************************************************** I2C Hardware functions ***************************************************************************************************/ void i2c_send_start(i2c_t *i2c_dev) { I2C_BASE->CR2 &=~ I2C_CR2_STOP; I2C_BASE->CR2 |= I2C_CR2_START; //Wait until the start condition in generated. //Bit 15BUSY: Bus busy //This flag indicates that a communication is in progress on the bus. It is set by hardware when a //START condition is detected. It is cleared by hardware when a Stop condition is detected, or //when PE=0. while(!(I2C_BASE->ISR & (I2C_ISR_BUSY))); i2c_dev->hardwareState = i2c_hw_sent_start; } void i2c_send_stop(i2c_t *i2c_dev) { // Send stop command I2C_BASE->CR2 |= I2C_CR2_STOP; I2C_BASE->CR2 &=~ I2C_CR2_START; i2c_dev->hardwareState = i2c_hw_sent_stop; } uint8_t i2c_is_perif_ready(i2c_t *i2c_dev) { if((I2C_BASE->ISR & (I2C_ISR_BUSY))!=I2C_ISR_BUSY) { i2c_dev->periferalState = i2c_perif_ready; return 1; } return 0; } void i2c_set_transfer_counter(i2c_t *i2c_dev, uint8_t count) { I2C_BASE->CR2 &= ~(0xFF << I2C_CR2_NBYTES_Pos); I2C_BASE->CR2 |= (count << I2C_CR2_NBYTES_Pos); } uint8_t i2c_get_transfer_counter(i2c_t *i2c_dev) { return (I2C_BASE->CR2 & I2C_CR2_NBYTES) >> I2C_CR2_NBYTES_Pos; } void i2c_init_write_command(i2c_t *i2c_dev) { I2C_BASE->CR2 &= ~I2C_CR2_RD_WRN; i2c_dev->hardwareState = i2c_hw_send_write; } void i2c_init_read_command(i2c_t *i2c_dev) { I2C_BASE->CR2 |= I2C_CR2_RD_WRN; i2c_dev->hardwareState =i2c_hw_send_read; } uint8_t i2c_send_address_for_write(i2c_t *i2c_dev, uint16_t *slaveAddress) { //Automatic end mode (master mode) disabled Enablede as default I2C_BASE->CR2 &= ~I2C_CR2_AUTOEND; // On This chip this shoudl be done before the start condition i2c_init_write_command(i2c_dev); // The Slave addrress is automatically place on the output buffer (must be done before the start condition) I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode // This device places the salve address automaticaly in the output buffer before sending the star condition i2c_send_start(i2c_dev); while(i2c_is_output_buffer_full(i2c_dev)); return 1; } uint8_t i2c_send_address_for_read(i2c_t *i2c_dev, uint16_t *slaveAddress) { // On This chip this shoudl be done before the start condition i2c_init_read_command(i2c_dev); // The Slave addrress is automatically place on the output buffer (must be done before the start condition) I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode // This device places the salve address automaticaly in the output buffer before sending the star condition i2c_send_start(i2c_dev); while(i2c_is_output_buffer_full(i2c_dev)); return 1; } uint8_t i2c_is_output_buffer_full(i2c_t *i2c_dev) { /* Bit 0 TXE: Transmit data register empty (transmitters) This bit is set by hardware when the I2C_TXDR register is empty. It is cleared when the next data to be sent is written in the I2C_TXDR register. This bit can be written to ‘1’ by software in order to flush the transmit data register I2C_TXDR. Note: This bit is set by hardware when PE=0. */ if(I2C_BASE->ISR & I2C_ISR_TXE) { i2c_dev->hardwareState = i2c_hw_out_buff_empty; return 0; } else { i2c_dev->hardwareState = i2c_hw_out_buff_full; return 1; } } uint8_t i2c_is_txis(i2c_t *i2c_dev) { if(I2C_BASE->ISR & I2C_ISR_TXIS) { i2c_dev->hardwareState = i2c_hw_out_buff_empty; return 0; } else { i2c_dev->hardwareState = i2c_hw_out_buff_full; return 1; } } void i2c_send_reg_address(i2c_t *i2c_dev, uint8_t *registerAddress) { I2C_BASE->TXDR = *registerAddress; i2c_dev->hardwareState = i2c_hw_out_buff_full; while(i2c_is_output_buffer_full(i2c_dev)); } void i2c_send_data(i2c_t *i2c_dev, uint8_t *data) { I2C_BASE->TXDR = *data; i2c_dev->hardwareState = i2c_hw_out_buff_full; while(i2c_is_output_buffer_full(i2c_dev)); } uint8_t i2c_is_transfer_complete(i2c_t *i2c_dev) { /* TC: Transfer Complete (master mode) This flag is set by hardware when RELOAD=0, AUTOEND=0 and NBYTES data have been transferred. It is cleared by software when START bit or STOP bit is set. Note: This bit is cleared by hardware when PE=0. */ if(I2C_BASE->ISR & I2C_ISR_TC) { return 1; } else { return 0; } } uint8_t i2c_is_input_buffer_full(i2c_t *i2c_dev) { if(I2C_BASE->ISR & I2C_ISR_RXNE) { i2c_dev->hardwareState = i2c_hw_in_buff_full; return 1; } else { i2c_dev->hardwareState = i2c_hw_in_buff_empty; return 0; } } void i2c_get_input_register(i2c_t *i2c_dev, uint8_t *data) { while(!i2c_is_input_buffer_full(i2c_dev)); *data = I2C_BASE->RXDR; while(!i2c_is_transfer_complete(i2c_dev)); } void i2c_send_nack(i2c_t *i2c_dev) { if(i2c_dev->mode == i2c_mode_master) { //IN master mode this ic geretes NACK's otomatically i2c_dev->hardwareState = i2c_hw_sent_nack; } else if(i2c_dev->mode == i2c_mode_slave) { // to be written. } } uint8_t i2c_check_nack(i2c_t *i2c_dev) { delayMs(2); return(I2C_BASE->ISR & I2C_ISR_NACKF); } void i2c_set_address(i2c_t *i2c_dev, uint16_t address){} void i2c_set_address_second(i2c_t *i2c_dev, uint16_t address){}