stm32f407 硬件I2C SGM58031

I2C

实习的第一个任务是调stm32f4的I2C接口,从机是SGM58031

SGM58031 I2C读写时序图

read word
SGM write

I2C程序


/***************************通信函数*******************************/


void I2C3_start(i2c_t i2c, uint8_t address, uint8_t direction)
{
	while(I2C_GetFlagStatus(i2c->base, I2C_FLAG_BUSY));
	
	//start signal
	I2C_GenerateSTART(i2c->base, ENABLE);
	while(!I2C_CheckEvent(i2c->base, I2C_EVENT_MASTER_MODE_SELECT));
	
	//7λµØÖ·
	I2C_Send7bitAddress(i2c->base, address, direction);
	if(direction == I2C_Direction_Transmitter)
	{
		while(!I2C_CheckEvent(i2c->base, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
	} 
	else if(direction == I2C_Direction_Receiver)
	{
		while(!I2C_CheckEvent(i2c->base, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
	}
}

I2C3_start()就代表时序图中的Frame1,包含2个操作。
①主机发出start信号
②往地址线写7位地址加1位读写位

uint8_t I2C_read_ack(i2c_t i2c)
{
	uint8_t data;
	// enable acknowledge of recieved data
	I2C_AcknowledgeConfig(i2c->base, ENABLE);
	// wait until one byte has been received
	while( !I2C_CheckEvent(i2c->base, I2C_EVENT_MASTER_BYTE_RECEIVED) );
	// read data from I2C data register and return data byte
	data = I2C_ReceiveData(i2c->base);
	return data;
}

I2C_read_ack()代表读时序中的Frame4
①接收1byte的数据
②数据接收完成后给发送机一个ACK信号,表示接收完成可以进行下一个数据传输

uint8_t I2C_read_nack(i2c_t i2c)
{
	uint8_t data;
	// disabe acknowledge of received data
	// nack also generates stop condition after last byte received
	// see reference manual for more info
	I2C_AcknowledgeConfig(i2c->base, DISABLE);
	I2C_GenerateSTOP(i2c->base, ENABLE);
	// wait until one byte has been received
	while( !I2C_CheckEvent(i2c->base, I2C_EVENT_MASTER_BYTE_RECEIVED) );
	// read data from I2C data register and return data byte
	data = I2C_ReceiveData(i2c->base);
	return data;
}

I2C_read_nack()读一个byte不返回ACK信号

void I2C3_write(i2c_t i2c, uint8_t data)
{
    I2C_SendData(i2c->base, data);
    // wait for I2C1 EV8_2 --> byte has been transmitted
    while(!I2C_CheckEvent(i2c->base, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}

I2C3_write()向总线写一个byte数据

void I2C_stop(i2c_t i2c)
{
	// Send I2C1 STOP Condition
	I2C_GenerateSTOP(i2c->base, ENABLE);
}

I2C_stop()对应上图中的stop by master,发出stop信号

uint16_t I2C_Read_Word(i2c_t i2c, uint8_t address, uint8_t Reg_addr)
{
		uint8_t high=0x00;
		uint8_t low=0x00;
		uint16_t Word=0x0000;
		
		I2C3_start(i2c,address,I2C_Direction_Transmitter);
		I2C3_write(i2c,Reg_addr);
		I2C_stop(i2c);
		
		I2C3_start(i2c,address,I2C_Direction_Receiver);
		high=I2C_read_ack(i2c);
		low=I2C_read_nack(i2c);
		Word=(high<<8)+low;
		//printf("%d \n",Word);
		return Word;
}

void I2C_Write_Word(i2c_t i2c, uint8_t address, uint8_t Reg_addr, uint16_t set_value)
{
		uint8_t high=0x00;
		uint8_t low=0x00;
		
		low=set_value&0x00ff;
		high=(set_value>>8)&0x00ff;
		
		I2C3_start(i2c,address,I2C_Direction_Transmitter);
		I2C3_write(i2c,Reg_addr);
		I2C3_write(i2c,high);
		I2C3_write(i2c,low);
		I2C_stop(i2c);
}

读写2bytes函数,由前面的通信函数组合起来,不容易出错

//封装
typedef struct i2c_device* i2c_t;

struct  i2c_device {
		I2C_TypeDef * base;
		uint32_t			CLK;
		void (*setup)(i2c_t);
};

///
/***************i2c3封装主要******************/
///

void __attribute__((weak)) target_i2c3_setup()
{
		pin_rcc_config();		//使能引脚时钟
		pin_AF_config();		//引脚复用
		I2C3_gpio_setup();	//I2C_gpio¹Ü½ÅÉèÖÃ
}

static void __i2c3_setup(i2c_t i2c)
{
    target_i2c3_setup();
}

struct i2c_device i2c3 = {
    I2C3,
	RCC_APB1Periph_I2C3,
    __i2c3_setup,
};

/
/*************硬件I2C初始化函数子函数*****************/
/

//使能引脚时钟
void pin_rcc_config()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
}

//使能硬件I2C时钟
void i2c3_rcc_config(i2c_t i2c)
{
	RCC_APB1PeriphClockCmd(i2c->CLK,ENABLE);
}

//管脚复用为I2C
void pin_AF_config()
{
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_I2C3);
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_I2C3);
}

//I2C_gpio管脚设置
void I2C3_gpio_setup()
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	//PC9 SDA PA8 SCL	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_Init(GPIOC, &GPIO_InitStructure);
}

//硬件I2C参数设置
void i2c_param_config(i2c_t i2c)
{
	I2C_InitTypeDef I2C_InitStructure;
	
	I2C_DeInit(i2c->base);
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	I2C_InitStructure.I2C_ClockSpeed = 10000;
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
	I2C_Init(i2c->base, &I2C_InitStructure);
}

///
/*************硬件I2C初始化****************/
///

void I2C3_Init(i2c_t i2c)
{
	i2c3_rcc_config(i2c);
	i2c->setup(i2c);
	i2c_param_config(i2c);
	I2C_Cmd(i2c->base,ENABLE);
}

封装以及硬件初始化函数

感受

搞清楚每个函数做了什么,对应着时序来写应该就不会出错

参考

i2c信号的ACK与NACK
I2C通信函数

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
SGM5347-8是一款4路可编程电源管理IC,可以用于电池管理、DC-DC转换器控制、LED背光控制等应用。它具有多个控制接口,包括I2C、SPI和GPIO控制接口。下面是一个使用STM32控制SGM5347-8的简单示例: 1. 连接硬件 将SGM5347-8的SDA和SCL引脚分别连接到STM32I2C1的对应引脚。同时,将SGM5347-8的CS引脚连接到STM32的一个GPIO引脚。 2. 配置STM32I2C总线 使用STM32的CubeMX工具配置I2C总线。选择I2C1,并启用I2C1的中断和DMA功能。 3. 初始化SGM5347-8 使用STM32I2C驱动程序发送I2C命令,初始化SGM5347-8。例如,使用以下命令配置SGM5347-8的第一个DC-DC转换器的输出电压为3.3V: ``` uint8_t data[3]; data[0] = 0x01; // 寄存器地址 data[1] = 0x80; // 输出使能,电压编码为01000,即输出3.3V data[2] = 0x00; HAL_I2C_Master_Transmit_DMA(&hi2c1, SGM5347_ADDR, data, 3); ``` 4. 控制SGM5347-8 使用GPIO控制SGM5347-8的CS引脚,选择要控制的寄存器,并使用I2C命令向其写入相应的配置值。例如,使用以下命令将SGM5347-8的第二个DC-DC转换器的输出电压编码为10101,即输出1.8V: ``` HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 选择寄存器 uint8_t data[3]; data[0] = 0x05; // 寄存器地址 data[1] = 0xA8; // 输出使能,电压编码为10101,即输出1.8V data[2] = 0x00; HAL_I2C_Master_Transmit_DMA(&hi2c1, SGM5347_ADDR, data, 3); // 发送I2C命令 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // 取消选择寄存器 ``` 以上是一个简单的示例,具体的控制方法还需要根据SGM5347-8的数据手册进行配置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值