We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I'm using stm32f103c8 and PCA9685 devices. I'm trying to send data to PCA9685 via I2C bus. I send data using I2C_DR register. But when i write a data to I2C_DR register it sticks to it. After the data is send thee I2C_DR register should be cleared but it wont happen in my code. I have no idea why this is happening. This is what i see in logic analyzer.
#include "stm32f10x.h" void I2C_Write_Single(int device_address, int mem_address, int data); void I2C_Restart(int device_address, int data); uint32_t temp = 0; int main(){ /*********STEPS FOLLOWED********* 1. Enable the I2C Clock and GPIO Clock 2. Configure I2C Pins for alternate funtion 3. Reset I2C 4. Program the peripherald input clock in I2C_CR2 Register in order to generate correct timing 5. configure the clock control register 6. Configure the rise time register 7. Program the I2C_CR1 register to enable the peripheral */ I2C1->CR1 |= (1<<15); I2C1->CR1 &=~ (1<<15); //GPIO Port B neabled RCC->APB2ENR |= (1<<3); //I2C enabled RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; //timer enable TIM2 (general timer) RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM2 config TIM4->PSC |= 0; TIM4->ARR |= 71; TIM4->CR1 |= TIM_CR1_URS; TIM4->DIER |= TIM_DIER_UIE; TIM4->EGR |= TIM_EGR_UG; NVIC_EnableIRQ(TIM4_IRQn); //Mode register set for 50MHz (B7 and B6) GPIOB->CRL |= (1<<25) | (1<<24); GPIOB->CRL |= (1<<29) | (1<<28); //GPIO B7 and B6 pin registers (alternate function open drain) GPIOB->CRL |= (1<<27) | (1<<26); GPIOB->CRL |= GPIO_CRL_CNF7_1 | (1<<30); //Peripherald frequency (APB1) 36MHz (its written in datasheet) I2C1->CR2 |= 36 ; //I2C clock control register /* to calculate CCR (Clock Control Register) CCR= [((I2C_Period)/2)/(APB1_Period)] I2C preiod is 400KHz(from user manual page 781) Ti2c= 1/100K = 10us APB1 Period = 1/36 = 27.7 ns CCR = [(5000ns)/(27.7ns)]= 180 */ I2C1->CCR |= 180; I2C1->TRISE |= 37 ; // TRise = CR2+1 (from datasheet page 783) I2C1->CR1 |= I2C_CR1_ACK; I2C1->CR1 |= I2C_CR1_PE; I2C_Restart(0x00, 0x06); I2C_Write_Single( 0x80, 0x00, 0x08); //SLEEP bit gets cleared so we can get PWM signal I2C_Write_Single( 0x40, 0x00, 1<<6); //EXTERNAL CLOCK bit gets cleared so we can get PWM signal I2C_Write_Single( 0x40, 0xFE, 0XB0); // PRE_SCALE registers set to 0xB0 that way PWM Frequency will be 50 MHz (PCA9685 Datasheet page 9) // PWM delay %0 so LED0_ON_L and LED0_ON_H registers set to 0 I2C_Write_Single( 0x40, 0x06, 0X01); I2C_Write_Single( 0x40, 0x07, 0X99); // 1.5ms PWM will be given (1,5/20)*4096=307 LED0_OFF_H= 3 (decimal) LED0_OFF_H= 07 (decimal) I2C_Write_Single( 0x41, 0x09, 0X08); I2C_Write_Single( 0x41, 0x08, 0X00); return 0; } void I2C_Write_Single(int device_address, int mem_address, int data) { I2C1->CR1 |= I2C_CR1_START; //generate start condition while (!(I2C1->SR1 & I2C_SR1_SB)); // we check the SB flag if start bit didnt sent master device will stay in this loop I2C1->DR |= device_address ; // device adrees is 0x00 while (!(I2C1->SR1 & I2C_SR1_ADDR)); // we check ADDR flag. Once there is address mach dvice will exit the loop temp = I2C1->SR1 | I2C1->SR2; // we need to cleear ADDR bit after we checked the flags. To reset SR1 and SR2 registers we just read them while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->DR |= mem_address ; // MODE1 register (PCA9685 datasheet page 9) while (!(I2C1->SR1 & I2C_SR1_BTF));//wait for transmit while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->DR |= data << 1 ; // to set PWM frequeency we set SLEEP bit 1 (PCA9685 datasheet page 24) while (!(I2C1->SR1 & I2C_SR1_BTF));//wait for transmit I2C1->CR1 |= I2C_CR1_STOP; //generate stop condition } void I2C_Restart(int device_address, int data){ I2C1->CR1 |= I2C_CR1_START; //generate start condition while (!(I2C1->SR1 & I2C_SR1_SB)); // we check the SB flag if start bit didnt sent master device will stay in this loop I2C1->DR |= device_address; // device adrees is 0x00 while (!(I2C1->SR1 & I2C_SR1_ADDR)); // we check ADDR flag. Once there is address mach dvice will exit the loop temp = I2C1->SR1 | I2C1->SR2; // we need to cleear ADDR bit after we checked the flags. To reset SR1 and SR2 registers we just read them while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->DR |= data; // MODE1 register (PCA9685 datasheet page 9) while (!(I2C1->SR1 & I2C_SR1_BTF));//wait for transmit while (!(I2C1->SR1 & I2C_SR1_TXE)); // wait for the byte transfer I2C1->CR1 |= I2C_CR1_STOP; //generate stop condition }
the solution is not using I2C1->DR |=... instead it should be I2C1-> Dr =