2019-07-01 12:52 AM
Hi everyone I am trying to implement I2C Write and Read with DS3231. I am using stm32f051r8t6. I do not want to implement this using CUBE. Kindly help me in identifying the mistakes I have done. I am able to write and read but what I write does not affect the rtc registers to which I write a data. The data resets to its default value in the next read cycle. It wil be very helpful if anyone can point where I am making the mistake.
2019-07-01 12:56 AM
void I2C_config()
{
//Enabling the clock for PortB
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
//Clock enable for I2C1 peripheral
RCC->APB1ENR |= (RCC_APB1ENR_I2C1EN); //Clock enable for the I2C peripheral
//PF0 and PF1 to be configured as SCL and SDA respectively [I2C1 peripheral chosen]
//Configuring the GPIO pins to alternate function
GPIOB->MODER |= ((GPIO_MODER_MODER6_1) | (GPIO_MODER_MODER7_1));
GPIOB->MODER &= ~(GPIO_MODER_MODER7_0 | GPIO_MODER_MODER7_0);
//Configuring the GPIO pins assigned for I2C in open-drain
GPIOB->OTYPER |= (GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7);
//Configuring the speed of GPIO pins
GPIOB->OSPEEDR &= ~(GPIO_OSPEEDR_OSPEEDR6 | GPIO_OSPEEDR_OSPEEDR7);
//Configuring the alternate functions for the mapped GPIO pins [PB6 and PB7] ---> Alternate function 1 is Set for the pins --> AF1 is I2C for
GPIOB->AFR[0] |= (1<<24) | (1<<28);
I2C1->TIMINGR = (uint32_t)0x1042F013;//(uint32_t)0x00503D5A;//(uint32_t)0x0010020A; //I2C Timing register helps the controller set the fall and rise time from its peripheral to the slave device
I2C1->CR1 |= (I2C_CR1_PE) | (I2C_CR1_RXIE) | (I2C_CR1_TXIE); //I2C peripheral being enabled and Receive interrupt enabled
I2C1->ISR = 0b00000001;
NVIC_SetPriority(I2C1_IRQn,1);
NVIC_EnableIRQ(I2C1_IRQn);
trace_printf("\n I2C__Config done");
ISR_reg_val = I2C1->ISR;
trace_printf("\n %u", ISR_reg_val);
}
void I2C1_IRQHandler()
{
if((I2C1->ISR & I2C_ISR_RXNE) == I2C_ISR_RXNE)
{
recvd_byte = I2C1->RXDR;
I2C1->ICR |= I2C_ICR_NACKCF;
}
}
void I2C_Write_Reg()//uint32_t Device,uint32_t Register, uint32_t Data){
{
trace_printf("\n I am in Write");
//Reset CR2 Register
I2C1->CR2 = 0x00000000;
//Check to see if the bus is busy
while((I2C1->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
//Mentioning the rtc_slave addr in Write mode
I2C1->CR2 |= (I2C_CR2_SADD & EEPROM_W);
//Set CR2 for 2-Byte Transfer, for Device
I2C1->CR2 |= (1UL<<16); //| (EEPROM_W<<1);
//Start communication
I2C1->CR2 |= I2C_CR2_START;
//Check Tx empty before writing to it
if((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)){
I2C1->TXDR = reg_addr;
}
//Wait for TX Register to clear
while((I2C1->ISR & I2C_ISR_TXE) == 0);
//Check Tx empty before writing to it
if((I2C1->ISR & I2C_ISR_TXE) == I2C_ISR_TXE){
I2C1->TXDR = i2c_val;
}
//Wait for transfer to complete
while((I2C1->ISR & I2C_ISR_TC) == 0);
//Send Stop Condition
I2C1->CR2 |= I2C_CR2_STOP;
//Check to see if the bus is busy
while((I2C1->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
//Clear Stop bit flag
I2C1->ICR |= I2C_ICR_STOPCF;
trace_printf("\n Write done");
/*
//I2C1->CR1 |= (I2C_CR1_PE);
trace_printf("\n I am in Write");
//Reset CR2 Register
I2C1->CR2 = 0x00000000;
I2C1->ISR = 0x00000001;
//Check to see if the bus is busy
while((I2C1->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
//Mentioning the rtc_slave addr in Write mode
I2C1->CR2 |= (I2C_CR2_SADD & EEPROM_W);
//I2C1->CR2 |= (1<<4 | 1<<6 | 1<<7);
//Set CR2 for 1-Byte Transfer, for Device
I2C1->CR2 |= (1UL<<16);
//Start communication
I2C1->CR2 |= I2C_CR2_START;
trace_printf("\n I2C started");
//I2C1->CR2 &= ~(1<<0);// Clearing the 0th bit for a Write operation
//Wait for TXDR Register to become empty
while((I2C1->ISR & I2C_ISR_TXE) == 0);
trace_printf("\n TXDR empty");
//Check Tx empty before writing to it
if((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE)){
I2C1->TXDR = reg_addr;
}
trace_printf("\n reg addr given");
I2C1->ISR |= I2C_ISR_TXE;
trace_printf("\n Set TXE bit high to flush TXDR reg");
ISR_reg_val = I2C1->ISR;
trace_printf("\n %u",ISR_reg_val);
//Wait for transfer to complete
while((I2C1->ISR & I2C_ISR_TC) == 0);
trace_printf("\n Transfer complete");
//Set CR2 for 1-Byte Transfer, for Device
I2C1->CR2 |= (1UL<<16);
//Wait for TXDR Register to become empty
while((I2C1->ISR & I2C_ISR_TXE) == 0);
//Check Tx empty before writing to it
if((I2C1->ISR & I2C_ISR_TXE) == I2C_ISR_TXE){
I2C1->TXDR = i2c_val;
}
//while(!((I2C1->CR2 & I2C_CR2_NACK) == 0));
//trace_printf("\n ACK received : data");
//Wait for transfer to complete
while((I2C1->ISR & I2C_ISR_TC) == 0);
//Send Stop Condition
I2C1->CR2 |= I2C_CR2_STOP;
//Check to see if the bus is busy
while((I2C1->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
//Clear Stop bit flag
I2C1->ICR |= I2C_ICR_STOPCF;
trace_printf("\n Write done");
//I2C1->CR1 &= ~(I2C_CR1_PE);
*/
}
void I2C_data_Read()
{
trace_printf("\n\n Inside Read");
//Reset CR2 Register
I2C1->CR2 = 0x00000000;
//Reset CR2 Register
I2C1->ISR = 0x00000001;
ISR_reg_val = I2C1->ISR;
trace_printf("\n %u", ISR_reg_val);
//Check to see if the bus is busy
while((I2C1->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
//Mentioning the rtc_slave addr in Read mode
I2C1->CR2 |= (I2C_CR2_SADD & EEPROM_W);
//Set CR2 for 1-byte transfer for Device
I2C1->CR2 |=(1UL<<16);
//Start communication
I2C1->CR2 |= I2C_CR2_START;
//Checking TXDR Register to become empty
while((I2C1->ISR & I2C_ISR_TXE) == 0);
//Check Tx empty before writing to it
if((I2C1->ISR & I2C_ISR_TXE) == (I2C_ISR_TXE))
{
I2C1->TXDR = reg_addr;
}
trace_printf("\n reg specified to slave");
I2C1->ISR |= I2C_ISR_TXE;
trace_printf("\n TXDR reg is flushed");
//Wait for transfer to complete
while((I2C1->ISR & I2C_ISR_TC) == 0);
trace_printf("\n Transfer complete");
//Specifying the Slave address from which data is to be read
I2C1->CR2 |= (I2C_CR2_SADD & EEPROM_R);
//Set CR2 for 1-byte transfer, in read mode for Device
I2C1->CR2 |= (1UL<<16) | I2C_CR2_RD_WRN;
//Start communication
I2C1->CR2 |= I2C_CR2_START;
//Wait for transfer to complete
while((I2C1->ISR & I2C_ISR_TC) == 0);
//ISR_reg_val = I2C1->ISR;
//trace_printf("\n %u", ISR_reg_val);
//Send Stop Condition
I2C1->CR2 |= I2C_CR2_STOP;
//Check to see if the bus is busy
while((I2C1->ISR & I2C_ISR_BUSY) == I2C_ISR_BUSY);
//Clear Stop bit flag
I2C1->ICR |= I2C_ICR_STOPCF;
//return(I2C1_RX_Data);
I2C1->ICR |= I2C_ICR_NACKCF;
trace_printf("\n Receive wait over");
//return(recvd_byte);
}