2023-10-31 12:45 PM
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
}
Solved! Go to Solution.
2023-10-31 12:52 PM
It's a register, the act of writing it pushes values data into combinational logic and flip-flops internally. It's not designed to be used as a memory cell, or for you to RMW values into it
I2C1->DR |= data << 1 ; // to set PWM frequeency we set SLEEP bit 1 (PCA9685 datasheet page 24)
WHY???
Write the value I2C1->DR = data << 1
2023-10-31 12:52 PM
It's a register, the act of writing it pushes values data into combinational logic and flip-flops internally. It's not designed to be used as a memory cell, or for you to RMW values into it
I2C1->DR |= data << 1 ; // to set PWM frequeency we set SLEEP bit 1 (PCA9685 datasheet page 24)
WHY???
Write the value I2C1->DR = data << 1
2023-10-31 01:11 PM - edited 2023-10-31 01:21 PM
The problem is i used I2C1->DR |= .... It should be I2C1->DR = ....