cancel
Showing results for 
Search instead for 
Did you mean: 

I2C Library for PCA9685 won't work

Uwii
Associate

I'm creating an I2C library for PCA8596 to control servos using STM32F4 Discovery as master. I already checked the PCA using arduino, and it worked. It also compiled well and can be uploaded.

The problem is the SCL and SDA from the stm didn't generate any signal. My friend checked it, and said that the transmission stopped at the address. It confussed me, bcs i input the right address of PCA9685.

Please anyone can check and find out the mistakes i made on my library.

#define I2C2_TIMEOUT		0x3000
#define I2C_ACK_ENABLE         1
#define I2C_ACK_DISABLE        0
static __IO uint32_t TimingDelay = 0;
 
/*---------------------------
 *    I2C Initialization
 ---------------------------*/
void PCA_init_I2C (void)
{
	// Clock enable for I2Cx bus
	RCC_APB1PeriphClockCmd(RCC_PCA,ENABLE);
 
	//Clock enable for SCL and SDA pins
	RCC_AHB1PeriphClockCmd(PCA_RCC,ENABLE);
 
	// Configuration for Alternative Function in SCL and SDA pins
	GPIO_PinAFConfig(PCA_PORT,PS_SCL_PCA,AF_PCA);
	GPIO_PinAFConfig(PCA_PORT,PS_SDA_PCA,AF_PCA);
 
	//I2C pin init					SCL PIN		  SDA PIN
	GPIO_InitStructure.GPIO_Pin = PIN_SCL_PCA | PIN_SDA_PCA ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
	GPIO_Init(PCA_PORT, &GPIO_InitStructure);
 
//	I2C_DeInit(I2C2);
 
	//// Initialization of I2C_InitTypeDef
	I2C_InitStructure.I2C_Mode = I2Cx_MODE;
	I2C_InitStructure.I2C_DutyCycle = I2Cx_DUTY_CYCLE;
	I2C_InitStructure.I2C_OwnAddress1 = I2Cx_OWN_ADDRESS;
	I2C_InitStructure.I2C_Ack = I2Cx_ACK;
	I2C_InitStructure.I2C_ClockSpeed = 100000; //5kHz
	I2C_InitStructure.I2C_AcknowledgedAddress = I2Cx_ACKNOWLEDGED_ADDRESS;
	I2C_Init(I2C_PCA,&I2C_InitStructure);
	I2C_Cmd(I2C_PCA,ENABLE);
}
 
/*---------------------------
 * Primary Function of I2C
 ---------------------------*/
 
int16_t PCA_readByte_I2C(uint8_t reg)
{
	uint8_t received_data;
	uint32_t TimeOut = I2C2_TIMEOUT;
 
	//Generate I2C start pulse
	I2C_GenerateSTART(I2C2, ENABLE);
 
	//Wait till I2C is busy
	while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_SB)) {
			if (TimeOut != 0)
				TimeOut--;
		}
 
	//Ack disable
	I2C_AcknowledgeConfig(I2C2, DISABLE);
 
	//Send address with zero last bit
	I2C_Send7bitAddress(I2C2,(i2cadd<<1),I2C_Direction_Transmitter);
 
	//Wait till finished
	while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR)) {
			if (TimeOut != 0)
				TimeOut--;
		}
 
	//Read status register to clear ADDR flag
	I2C2->SR2;
 
	//Wait till I2C is not busy anymore
	while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) {
			if (TimeOut != 0)
				TimeOut--;
		}
 
	//Send I2C Register Address
	I2C_SendData(I2C2, reg);
 
	while ((!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF))){
			if (TimeOut != 0)
				TimeOut--;
		}
 
	I2C_AcknowledgeConfig(I2C2, ENABLE);
 
	//Generate I2C start pulse
	I2C_GenerateSTART(I2C2, ENABLE);
 
	//Wait till I2C is busy
	while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_SB)) {
			if (TimeOut != 0)
				TimeOut--;
		}
 
	//Send address with zero last bit
	I2C_Send7bitAddress(I2C2,(i2cadd<<1),I2C_Direction_Receiver);
 
	//Wait till finished
	while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR)) {
			if (TimeOut != 0)
				TimeOut--;
		}
 
	//Read status register to clear ADDR flag
	I2C2->SR2;
 
	while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE)){
			if (TimeOut != 0)
				TimeOut--;
		}
 
	// Stop Sequences
	I2C_GenerateSTOP(I2C2, ENABLE);
 
	received_data=I2C_ReceiveData(I2C2);
 
	//Ack enable
	I2C_AcknowledgeConfig(I2C2, ENABLE);
 
	return received_data;
}
 
int16_t PCA_writeByte_I2C(uint8_t reg,uint8_t value)
{
	uint32_t TimeOut = I2C2_TIMEOUT;
 
		//Generate I2C start pulse
		I2C_GenerateSTART(I2C2, ENABLE);
 
		//Wait till I2C is busy
		while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_SB)) {
				if (TimeOut != 0)
					TimeOut--;
			}
 
		//Send slave address write
		I2C_Send7bitAddress(I2C2,(i2cadd<<1),I2C_Direction_Transmitter);
 
		//Wait till finished
		while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR)) {
				if (TimeOut != 0)
					TimeOut--;
			}
 
		//Read status register to clear ADDR flag
		I2C2->SR2;
 
		while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) {
				if(TimeOut != 0)
					TimeOut--;
			}
 
		// Value Send
		I2C_SendData(I2C2, reg);
 
		while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) {
				if(TimeOut != 0)
					TimeOut--;
			}
 
		// Value Send
		I2C_SendData(I2C2, value);
 
		//Wait till transmitter not empty
		while ((!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF))) {
				if (TimeOut != 0) {
					TimeOut--;
			}
		}
 
		//Generate stop
		I2C_GenerateSTOP(I2C2, ENABLE);
 
	return 0;
}
 
int16_t PCA_writeMultiByte_I2C(uint8_t reg, uint8_t jumlahdata)
{
	int a, value[jumlahdata];
	uint32_t TimeOut = I2C2_TIMEOUT;
 
		//Generate I2C start pulse
		I2C_GenerateSTART(I2C2, ENABLE);
 
		//Wait till I2C is busy
		while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_SB)) {
				if (TimeOut != 0)
					TimeOut--;
			}
 
		//Send slave address write
		I2C_Send7bitAddress(I2C2,(i2cadd<<1),I2C_Direction_Transmitter);
 
		//Wait till finished
		while (!I2C_GetFlagStatus(I2C2, I2C_FLAG_ADDR)) {
				if (TimeOut != 0)
					TimeOut--;
			}
 
		//Read status register to clear ADDR flag
		I2C2->SR2;
 
		while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) {
				if(TimeOut != 0)
					TimeOut--;
			}
 
		// Value Send
		I2C_SendData(I2C2, reg);
 
		for(a=0;a<jumlahdata;a++){
			while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) {
				if(TimeOut != 0)
					TimeOut--;
			}
 
			// Value Send
			I2C_SendData(I2C2, (value[a] & 0xFF));
 
			while(!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) {
				if(TimeOut != 0)
					TimeOut--;
			}
 
			// Value Send
			I2C_SendData(I2C2, (value[a] >> 8));
		}
 
		//Wait till transmitter not empty
		while ((!I2C_GetFlagStatus(I2C2, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(I2C2, I2C_FLAG_BTF))) {
				if (TimeOut != 0) {
					TimeOut--;
			}
		}
 
		//Generate stop
		I2C_GenerateSTOP(I2C2, ENABLE);
 
	return 0;
}

and this my lib.h

#define i2cadd 0x40 //PCA Address
#define OSC_FREQ 25000000L
 
#define I2C_PCA			I2C2  //Selected I2C peripheral
#define RCC_PCA			RCC_APB1Periph_I2C2 //Bus where the peripheral is connected
#define AF_PCA          GPIO_AF_I2C2    //Alternate function for GPIO pins
//Bus for GPIO Port of SCL-SDA
#define PCA_RCC   		RCC_AHB1Periph_GPIOB
#define PCA_PORT    	GPIOB
//for SCL pin
#define PIN_SCL_PCA     GPIO_Pin_10
#define PS_SCL_PCA      GPIO_PinSource10
//for SDA pin
#define PIN_SDA_PCA		GPIO_Pin_11
#define PS_SDA_PCA      GPIO_PinSource11
 
#define I2Cx_ACKNOWLEDGED_ADDRESS	I2C_AcknowledgedAddress_7bit
#define I2Cx_MODE					I2C_Mode_I2C
#define I2Cx_OWN_ADDRESS			0x00
#define I2Cx_ACK					I2C_Ack_Disable
#define I2Cx_DUTY_CYCLE				I2C_DutyCycle_2
 
/*
 * REGISTERS OF PCA
 */
#define MODE1 0x00
#define MODE1_ALLCALL_BIT 0
#define MODE1_ALLCALL_MASK ~(1 << MODE1_ALLCALL_BIT)
#define MODE1_SUB3_BIT 1
#define MODE1_SUB3_MASK ~(1 << MODE1_SUB3_BIT)
#define MODE1_SUB2_BIT 2
#define MODE1_SUB2_MASK ~(1 << MODE1_SUB2_BIT)
#define MODE1_SUB1_BIT 3
#define MODE1_SUB1_MASK ~(1 << MODE1_SUB1_BIT)
#define MODE1_SLEEP_BIT 4
#define MODE1_SLEEP_MASK ~(1 << MODE1_SLEEP_BIT)
#define MODE1_AI_BIT 5
#define MODE1_AI_MASK ~(1 << MODE1_AI_BIT)
#define MODE1_EXTCLK_BIT 6
#define MODE1_EXTCLK_MASK ~(1 << MODE1_EXTCLK_BIT)
#define MODE1_RESTART_BIT 7
#define MODE1_RESTART_MASK ~(1 << MODE1_RESTART_BIT)
 
#define MODE2 0x01
#define MODE2_OUTNE_BIT 0
#define MODE2_OUTNE_MASK ~(3 << MODE2_OUTNE_BIT)
#define MODE2_OUTDRV_BIT 2
#define MODE2_OUTDRV_MASK ~(1 << MODE2_OUTDRV_BIT)
#define MODE2_OCH_BIT 3
#define MODE2_OCH_MASK ~(1 << MODE2_OCH_BIT)
#define MODE2_INVRT_BIT 4
#define MODE2_INVRT_MASK ~(1 << MODE2_INVRT_BIT)
#define OCH_ACK 1
#define OCH_STOP 0
#define OUTDRV_TOTEM_POLE 1
#define OUTDRV_OPEN_DRAIN 1
#define OUTNE_LOW 0
#define OUTNE_HIGH 1
#define OUTNE_HIGH_IMPEDANCE 2
 
#define SUBADR1 0x02
#define SUBADR2 0x03
#define SUBADR3 0x04
#define ALLCALLADR 0x05
#define LED0_ON_L 0x06
#define LED0_ON_H 0x07
#define LED0_OFF_L 0x08
#define LED0_OFF_H 0x09
#define ALL_LED_ON_L 0xFA
#define ALL_LED_ON_H 0xFB
#define ALL_LED_OFF_L 0xFC
#define ALL_LED_OFF_H 0xFD
#define PRE_SCALE 0xFE
 
#define false 0
#define true 1
static __IO uint32_t TimingDelay;
 
//Functions
 
void PCA_init();
 
void PCA_init_I2C ();
int16_t PCA_readByte_I2C(uint8_t reg);
int16_t PCA_writeByte_I2C(uint8_t reg, uint8_t value);
int16_t PCA_readMultiByte_I2C(uint8_t reg, uint8_t jumlahdata);

0 REPLIES 0