STM32 驱动IP2366芯片,电池管理数据读取,降本增效
一、芯片及I2C初始化
英集芯IP2366,封装QFN40,集成AFC/FCP/PD2.0/PD3.0/PD3.1输入快充协议,可以通过Type-C口上的DPC/DMC/CC1/CC2向快充适配器申请快充电压,会自动调节充电电流大小,来适应不同负载能力的适配器。输入输出快充协议和同步升降压转换器的锂电池充放电管理芯片,充放电功率高达140W。
IP2366的高集成度与丰富功能,只需一个电感实现同步降升压功能,在应用时仅需极少的外围器件,有效减小整体方案的尺寸,降低BOM成本。

IP2366可以定制设置不同的电池类型、充满电压和充电电流,可以支持2/3/4/5/6串磷酸铁锂或锂电池充电。
IP2366的同步开关充放电系统,最大充电电流可达5A或100W充电输入,充电效率最高到96%,放电功率高达140W,可通过定制设置最大充放电功率。
IP2366内置IC温度、电池 NTC温度和输入电压控制检测环路,可以根据不同功率充电器,智能调节充电电流。
IP2366支持低功耗模式,进入低功耗模式后,待机电流降低到5μA。进入低功耗模式后,插入充电器可自动唤醒充电,放电需要按下EN键唤醒;
IP2366内置14bit ADC,可以精确测量充电输入电压和电流,电池电压和电流;可通过I2C获取充放电电压、充电电流等信息。
硬件可参考其手册标准原理图即可,可硬件电阻配置其充满电压、最大功率,简单便捷:


软件则只需简单软件I2C即可读取寄存器各数据,做好电量显示等充放电管理。
二、程序源码
ip2366.c
#include "ip2366.h"
#include "main.h"
stIP2366Data IP2366Data;
uint8_t temp_ip[5];
// IP_SCL PB0
// IP_SDA PB1
//IP_IIC
void IP2366_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = IP_SCL_PIN | IP_SDA_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(IP_GPIO_PORT, &GPIO_InitStructure);
IP_SDA_HIGH();
IP_SCL_HIGH();
}
void delay_us_i2c(void)
{
uint8_t i;
/*
下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。
CPU主频72MHz时,在内部Flash运行, MDK工程不优化
循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
IAR工程编译效率高,不能设置为7
*/
for (i = 0; i < 21; i++);
}
void delay_50us_i2c(void)
{
uint8_t i;
/*
下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。
CPU主频72MHz时,在内部Flash运行, MDK工程不优化
循环次数为10时,SCL频率 = 205KHz
循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us
循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us
IAR工程编译效率高,不能设置为7
*/
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
for (i = 0; i < 10; i++);
}
/*************************************************
void I2C_Start(void)
*************************************************/
void IIC2_Start(void)
{
IP_SDA_HIGH();
delay_us_i2c();
IP_SCL_HIGH();
delay_us_i2c();
IP_SDA_LOW();
delay_us_i2c();
IP_SCL_LOW();
delay_us_i2c();
}
/************************************************
void Stop_I2c(void)
*************************************************/
void IIC2_Stop(void)
{
IP_SDA_LOW();
delay_us_i2c();
IP_SCL_HIGH();
delay_us_i2c();
IP_SDA_HIGH();
}
/**************************************************
void Send_Byte(unsigned char send)
***************************************************/
void IIC2_Send_Byte(uint8_t _ucByte)
{
uint8_t i;
IP_SDA_OUT();
/* 先发送字节的高位bit7 */
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
IP_SDA_HIGH();
}
else
{
IP_SDA_LOW();
}
delay_us_i2c();
IP_SCL_HIGH();
delay_us_i2c();
IP_SCL_LOW();
if (i == 7)
{
IP_SDA_HIGH(); // 释放总线
}
_ucByte <<= 1; /* 左移一个bit */
delay_us_i2c();
}
}
/**************************************************************
unsigned char Receive_Byte(void)
***************************************************************/
unsigned char IIC2_Read_Byte(void)
{
uint8_t i;
uint8_t value;
IP_SDA_IN();
/* 读到第1个bit为数据的bit7 */
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
IP_SCL_HIGH();
delay_us_i2c();
if (READ_IP_SDA !=0)
{
value++;
}
IP_SCL_LOW();
delay_us_i2c();
}
IP_SDA_OUT();
return value;
}
/***********************************************************************************
void Ack_I2c(void) 器件发送应答信号 ack=0非应答 ack=1应答
************************************************************************************/
void IIC2_Wait_Ack(void)
{
IP_SDA_LOW();
IP_SCL_HIGH();
delay_us_i2c();
IP_SCL_LOW();
delay_us_i2c();
IP_SDA_HIGH();
}
void IIC2_Wait_NoAck(void)
{
IP_SDA_HIGH();
IP_SCL_HIGH();
delay_us_i2c();
IP_SCL_LOW();
delay_us_i2c();
}
uint8_t IP2366_ReadOneByte(uint16_t ReadAddr)
{
uint8_t temp=0;
IIC2_Start();
IIC2_Send_Byte(IP2366_ADR_WRITE_);
IIC2_Wait_Ack();
delay_50us_i2c();
IIC2_Send_Byte(ReadAddr); //发送读地址
IIC2_Wait_Ack();
delay_50us_i2c();
IIC2_Start();
IIC2_Send_Byte(IP2366_ADR_READ_);
IIC2_Wait_Ack();
delay_50us_i2c();
temp=IIC2_Read_Byte();
IIC2_Wait_NoAck();
IIC2_Stop(); //产生一个停止条件
return temp;
}
void IP2366_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite)
{
IIC2_Start();
IIC2_Send_Byte(IP2366_ADR_WRITE_);
IIC2_Wait_Ack();
IIC2_Send_Byte(WriteAddr); //发送地址
IIC2_Wait_Ack();
IIC2_Send_Byte(DataToWrite); //发送字节
IIC2_Wait_Ack();
IIC2_Stop();//产生一个停止条件
delay_us_i2c();
}
unsigned int IP2366_Get_IpData(void)
{
uint8_t flag=1;
switch (IP2366Data.IP_Step)
{
case 0:
IP2366Data.S_Bat_StateCtrl_0 = IP2366_ReadOneByte(IP2366_STATE_CTL0_);
IP2366Data.IP_Step = 1;
break;
case 1:
IP2366Data.S_Bat_StateCtrl_1 = IP2366_ReadOneByte(IP2366_STATE_CTL1_);
IP2366Data.IP_Step = 2;
break;
case 2:
IP2366Data.S_Bat_StateCtrl_2 = IP2366_ReadOneByte(IP2366_STATE_CTL2_);
IP2366Data.IP_Step = 3;
break;
case 3:
IP2366Data.V_Bat_Data0 = IP2366_ReadOneByte(IP2366_BATVADC_DAT0);
IP2366Data.IP_Step = 4;
break;
case 4:
IP2366Data.V_Bat_Data1 = IP2366_ReadOneByte(IP2366_BATVADC_DAT1);
IP2366Data.IP_Step = 5;
break;
case 5:
IP2366Data.V_Sys_Data0 = IP2366_ReadOneByte(IP2366_VSYSVADC_L);
IP2366Data.IP_Step = 6;
break;
case 6:
IP2366Data.V_Sys_Data1 = IP2366_ReadOneByte(IP2366_VSYSVADC_H);
IP2366Data.IP_Step = 7;
break;
case 7:
IP2366Data.I_Bat_Data0 = IP2366_ReadOneByte(IP2366_IBATIADC_L);
IP2366Data.IP_Step = 8;
break;
case 8:
IP2366Data.I_Bat_Data1 = IP2366_ReadOneByte(IP2366_IBATIADC_H);
IP2366Data.IP_Step = 9;
break;
case 9:
IP2366Data.P_Sys_PowData0 = IP2366_ReadOneByte(IP2366_VSYS_POW_L);
IP2366Data.IP_Step = 10;
break;
case 10:
IP2366Data.P_Sys_PowData1 = IP2366_ReadOneByte(IP2366_VSYS_POW_H);
IP2366Data.IP_Step = 0;
break;
// case 11:
// IP2366Data.S_TypeC = IP2366_ReadOneByte(IP2366_TYPEC_STATE0);
// IP2366Data.IP_Step = 12;
// break;
// case 12:
// IP2366Data.V_GPIO0_Data0 = IP2366_ReadOneByte(IP2366_VGPIO0_NTC_L);
// IP2366Data.IP_Step = 13;
// break;
// case 13:
// IP2366Data.V_GPIO0_Data1 = IP2366_ReadOneByte(IP2366_VGPIO0_NTC_H);
// IP2366Data.IP_Step = 14;
// break;
// case 14:
// IP2366Data.T_TimeNode1 = IP2366_ReadOneByte(IP2366_TIMENODE1);
// IP2366Data.IP_Step = 15;
// break;
// case 15:
// IP2366Data.T_TimeNode2 = IP2366_ReadOneByte(IP2366_TIMENODE2);
// IP2366Data.IP_Step = 16;
// break;
// case 16:
// IP2366Data.T_TimeNode3 = IP2366_ReadOneByte(IP2366_TIMENODE3);
// IP2366Data.IP_Step = 17;
// break;
// case 17:
// IP2366Data.T_TimeNode4 = IP2366_ReadOneByte(IP2366_TIMENODE4);
// IP2366Data.IP_Step = 18;
// break;
// case 18:
// IP2366Data.T_TimeNode5 = IP2366_ReadOneByte(IP2366_TIMENODE5);
// IP2366Data.IP_Step = 0;
// break;
default:
IP2366Data.IP_Step = 0;
break;
}
ip2366.h
#ifndef _IP_2366_h
#define _IP_2366_h
#include "main.h"
#define IP_GPIO_PORT GPIOB
#define IP_SCL_PIN GPIO_Pin_6//GPIO_Pin_0 /* 连接到SCL时钟线的GPIO */
#define IP_SDA_PIN GPIO_Pin_7//GPIO_Pin_1 /* 连接到SDA数据线的GPIO */
#define IP_SCL_HIGH() GPIO_SetBits(IP_GPIO_PORT, IP_SCL_PIN) /* SCL = 1 */
#define IP_SCL_LOW() GPIO_ResetBits(IP_GPIO_PORT, IP_SCL_PIN) /* SCL = 0 */
#define IP_SDA_HIGH() GPIO_SetBits(IP_GPIO_PORT, IP_SDA_PIN) /* SDA = 1 */
#define IP_SDA_LOW() GPIO_ResetBits(IP_GPIO_PORT, IP_SDA_PIN) /* SDA = 0 */
#define READ_IP_SDA GPIO_ReadInputDataBit(IP_GPIO_PORT, IP_SDA_PIN) /* 读SDA口线状态 */
#define IP_SDA_IN() {GPIOB->CRL &= 0X0FFFFFFF;GPIOB->CRL |= (u32)8<<28;} //PB7输入模式
#define IP_SDA_OUT() {GPIOB->CRL &= 0X0FFFFFFF;GPIOB->CRL |= (u32)3<<28;} //PB7输出模式
#define IP2366_ADR_WRITE_ 0xEA
#define IP2366_ADR_READ_ 0xEB
#define IP2366_ADDR_ 0xEA
#define IP2366_STATE_CTL0_ 0x31 // 充电状态控制寄存器
#define IP2366_STATE_CTL1_ 0x32 // 充电状态控制寄存器
#define IP2366_STATE_CTL2_ 0x33 // 输入 PD 状态控制寄存器
#define IP2366_ADR_WRITE 0xEA
#define IP2366_ADR_READ 0xEB
#define IP2366_ADDR 0xEA
#define IP2366_SYS_CTL0 0x00 // charge 使能寄存器
#define IP2366_SYS_CTL1 0x01 // 串联节数设置、电池类型、电流设置模式
#define IP2366_SYS_CTL2 0x02 // VSET 充满电压设定
#define IP2366_SYS_CTL3 0x03 // ISET 充电功率或电流设置
#define IP2366_SYS_CTL6 0x06 // 涓流充电电流设置
#define IP2366_SYS_CTL8 0x08 // 停充电流和再充电阈值设置
#define IP2366_SYS_CTL9 0x09 // 待机使能和低电电压设置
#define IP2366_SYS_CTL10 0x0A // 电池低电电压设置
#define IP2366_SYS_CTL11 0x0B // 输出使能寄存器
#define IP2366_TYPEC_CTL8 0x22 // TYPE-C 模式控制寄存器
#define IP2366_TYPEC_CTL9 0x23 // 输出 PDO 电流设置寄存器
#define IP2366_TYPEC_CTL10 0x24 // 5VPDO 电流设置寄存器
#define IP2366_TYPEC_CTL11 0x25 // 9VPDO 电流设置寄存器
#define IP2366_TYPEC_CTL12 0x26 // 12VPDO 电流设置寄存器
#define IP2366_TYPEC_CTL13 0x27 // 15VPDO 电流设置寄存器
#define IP2366_TYPEC_CTL14 0x28 // 20VPDO 电流设置寄存器
#define IP2366_TYPEC_CTL23 0x29 // PPS1 PDO 电流设置寄存器
#define IP2366_TYPEC_CTL24 0x2A // PPS2 PDO 电流设置寄存器
#define IP2366_TYPEC_CTL17 0x2B // 输出 PDO 设置寄存器
#define IP2366_STATE_CTL0 0x31 // 充电状态控制寄存器
#define IP2366_STATE_CTL1 0x32 // 充电状态控制寄存器
#define IP2366_STATE_CTL2 0x33 // 输入 PD 状态控制寄存器
#define IP2366_TYPEC_STATE0 0x34 // 系统状态指示寄存器
#define IP2366_MOS_STATE 0x35 // 输入 MOS 状态指示寄存器
#define IP2366_STATE_CTL3 0x38 // 系统过流指示寄存器
#define IP2366_BATVADC_DAT0 0x50 // VBAT 电压
#define IP2366_BATVADC_DAT1 0x51 // VBAT 电压
#define IP2366_VSYSVADC_L 0x52 // VSYS 电压
#define IP2366_VSYSVADC_H 0x53 // VSYS 电压
#define IP2366_IVBUS_IADC 0x54 // 充电输入电流
#define IP2366_TIMENODE1 0x69 // 时间戳寄存器第一位
#define IP2366_TIMENODE2 0x6A // 时间戳寄存器第二位
#define IP2366_TIMENODE3 0x6B // 时间戳寄存器第三位
#define IP2366_TIMENODE4 0x6C // 时间戳寄存器第四位
#define IP2366_TIMENODE5 0x6D // 时间戳寄存器第五位
#define IP2366_IBATIADC_L 0x6E // 电芯端电流
#define IP2366_IBATIADC_H 0x6F // 电芯端电流
#define IP2366_ISYS_IADC 0x70 // IVSYS 端电流
#define IP2366_VSYS_POW_L 0x74 // VSYS 端功率
#define IP2366_VSYS_POW_H 0x75 // VSYS 端功率
#define IP2366_INTC_IADC 0x77 // NTC 输出电流寄存器
#define IP2366_VGPIO0_NTC_L 0x78 // NTC端电压
#define IP2366_VGPIO0_NTC_H 0x79 // NTC端电压
#define IP2366_VGPIO1_ISET 0x7A // 电流设置
#define IP2366_VGPIO2_VSET 0x7C // 单节电压设置
#define IP2366_VGPIO3_FCAP 0x7E // 电池容量设置
#define IP2366_VGPIO4_BATNUM 0x80 // 电池节数设置
//IO方向设置
//#define IP_SDA_IN() {GPIOB->CRL &= 0XFFFFFF0F;GPIOB->CRL |= (u32)8<<4;} //PB1输入模式
//#define IP_SDA_OUT() {GPIOB->CRL &= 0XFFFFFF0F;GPIOB->CRL |= (u32)3<<4;} //PB1输入模式
typedef struct
{
u8 IP_Step; //读取步骤
u8 S_Bat_StateCtrl_0; //0x31
u8 S_Bat_StateCtrl_1; //0x32
u8 S_Bat_StateCtrl_2; //0x33
u8 V_Bat_Data0; //0x50,mV
u8 V_Bat_Data1; //0x51,mV
u8 V_Sys_Data0; //0x52,mV
u8 V_Sys_Data1; //0x53,mV
u8 T_TimeNode1; //0x69
u8 T_TimeNode2; //0x6A
u8 T_TimeNode3; //0x6B
u8 T_TimeNode4; //0x6C
u8 T_TimeNode5; //0x6D
u8 I_Bat_Data0; //0x6E,mA
u8 I_Bat_Data1; //0x6F,mA
u8 P_Sys_PowData0; //0x74,10mW
u8 P_Sys_PowData1; //0x75,mW
u8 V_GPIO0_Data0; //0x78,mV
u8 V_GPIO0_Data1; //0x79,mV
u32 S_Bat; //state
u16 V_Bat; //mV
u16 V_Sys; //mV
u16 I_Bat; //mA
u16 P_Sys; //mW
u8 S_TypeC; //state
u16 V_Gpio; //mV
}stIP2366Data;
extern stIP2366Data IP2366Data;
extern uint8_t IP2366_ReadOneByte(uint16_t ReadAddr);
extern void IP2366_WriteOneByte(uint16_t WriteAddr,uint8_t DataToWrite);
extern unsigned int IP2366_Get_IpData(void);
extern void IP2366_Init(void);
#endif
main.c
#include "main.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
u32 SysTick_Cnt = 0;
u16 Timer10ms_Cnt = 0;
u8 IP2366_Step = 0;
s32 Pressure_Value[80];
u32 VBATValue = 0;
u32 IP2366_STATE_CTL0_VALUE = 0;
u32 IP2366_BATVADC_DAT0_VALUE = 0;
u32 IP2366_BATVADC_DAT1_VALUE = 0;
u8 IP2366_InitOk_Flag = 0;
u8 Charger_NoLoad_Flag = 0;
u8 Charger_State = BAT_NoCharger;
u8 timer_ADC_IOV_HIGH_CNT = 0;
u8 timer_ADC_IOV_LOW_CNT = 0;
float Depth_Sum;
MachInfoDrv MachInfo;
struct Mag mag_info;
void SysTick_Configuration(void);
void RTC_Configuration(void);
void EXTI_Configuration(void);
int main(void)
{
SysTick_Configuration(); //SysTick 10ms
vUsart1_Debug_Init(); //
GPIO_EXTI_Config();
Gpio_Init();
ADC1_Init();
TIM3_NVIC_Init(9, 7199); //cycle 1ms Button detection
TIM4_NVIC_Init(2499, 7199); //cycle 250ms LED blinking control
IP2366_Init();
SysTick_Cnt = 1;
Timer10ms_Cnt = 1;
printf("\r\n power on ... \r\n");
while(1)
{
if((Timer10ms_Cnt%5) == 0) //100ms
{
if(IP2366_InitOk_Flag)
{
IP2366_Get_IpData();
}
IP2366Data.S_Bat = IP2366Data.S_Bat_StateCtrl_0 + (0x0000FF00&(IP2366Data.S_Bat_StateCtrl_1<<8)) + (0x00FF0000&(IP2366Data.S_Bat_StateCtrl_2<<16));
IP2366Data.V_Bat = IP2366Data.V_Bat_Data0 + (0xFF00&(IP2366Data.V_Bat_Data1<<8));
IP2366Data.V_Sys = IP2366Data.V_Sys_Data0 + (0xFF00&(IP2366Data.V_Sys_Data1<<8));
IP2366Data.I_Bat = IP2366Data.I_Bat_Data0 + (0xFF00&(IP2366Data.I_Bat_Data1<<8));
IP2366Data.P_Sys = (IP2366Data.P_Sys_PowData0 + (0xFF00&(IP2366Data.P_Sys_PowData1<<8)))*10;
IP2366Data.V_Gpio = IP2366Data.V_GPIO0_Data0 + (0xFF00&(IP2366Data.V_GPIO0_Data1<<8));
}
if(Timer10ms_Cnt >= 20) //20*10ms
{
Timer10ms_Cnt = 0;
VBATValue = GetVBATValue();
if(IP2366_INT_HIGH) // IP2366 唤醒成功,可正常访问
{
IP2366_InitOk_Flag = 1;
}
}
if(LED_Cnt >= 50) //500ms亮 500ms灭
{
LED_Cnt = 0;
Battery_Display(IP2366Data.V_Bat,BAT_Charging,IP2366Data.S_Bat);
}
if(Charger_NoLoad_Cnt >= 100) //100*10ms 1s
{
Charger_NoLoad_Cnt = 0;
printf("Adc= %dmv S_Bat= 0x%3x V_Bat= %dmV V_Sys= %dmV I_Bat= %dmA P_Sys= %dmW ",VBATValue,IP2366Data.S_Bat,IP2366Data.V_Bat,IP2366Data.V_Sys,IP2366Data.I_Bat,IP2366Data.P_Sys);
// printf("Adc= %dmv S_Bat= 0x%3x S_TypeC= 0x%x V_Bat= %dmV V_Sys= %dmV I_Bat= %dmA P_Sys= %dmW V_Gpio= %dmV T_TN_1-5=0x%x 0x%x 0x%x 0x%x 0x%x ",VBATValue,IP2366Data.S_Bat,IP2366Data.S_TypeC,IP2366Data.V_Bat,IP2366Data.V_Sys,IP2366Data.I_Bat,IP2366Data.P_Sys,IP2366Data.V_Gpio,IP2366Data.T_TimeNode1,IP2366Data.T_TimeNode2,IP2366Data.T_TimeNode3,IP2366Data.T_TimeNode4,IP2366Data.T_TimeNode5);
}
/*
if((timer_ADC_IOV_LOW_CNT + timer_ADC_IOV_HIGH_CNT) >= 35) //35*200 7s
{
if((timer_ADC_IOV_LOW_CNT >= 3) && (timer_ADC_IOV_HIGH_CNT >= 3))
{
Charger_State = BAT_NoCharger;
}else {
Charger_State = BAT_Charging;
}
timer_ADC_IOV_LOW_CNT = 0;
timer_ADC_IOV_HIGH_CNT = 0;
}
*/
}
}
/**
* @brief Configures the SysTick to generate an interrupt each 500 ms.
* @param None
* @retval None
*/
void SysTick_Configuration(void)
{
/* SysTick interrupt each 10 ms with SysTick Clock equal to (HCLK/8) */
if (SysTick_Config((SystemCoreClock/8) / 100)) //(SystemCoreClock/8)=1s
{
/* Capture error */
while (1);
}
/* Select AHB clock(HCLK) divided by 8 as SysTick clock source */
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
/* Set SysTick Preemption Priority to 1 */
NVIC_SetPriority(SysTick_IRQn, 0x04);
}
/**
* @brief Configures RTC clock source and prescaler.
* @param None
* @retval None
*/
void RTC_Configuration(void)
{
/* Check if the StandBy flag is set */
if(PWR_GetFlagStatus(PWR_FLAG_SB) != RESET) //
{/* System resumed from STANDBY mode */
/* Clear StandBy flag */
PWR_ClearFlag(PWR_FLAG_SB);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* No need to configure the RTC as the RTC configuration(clock source, enable,
prescaler,...) is kept after wake-up from STANDBY */
}
else
{/* StandBy flag is not set */
/* RTC clock source configuration ----------------------------------------*/
/* Reset Backup Domain */
BKP_DeInit();
/* Enable LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
}
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* RTC configuration -----------------------------------------------------*/
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Set the RTC time base to 1s */
RTC_SetPrescaler(40000);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Enable the RTC Alarm interrupt */
RTC_ITConfig(RTC_IT_ALR, ENABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
}
}
/**
* @brief Configures EXTI Lines.
* @param None
* @retval None
*/
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Configure EXTI Line17(RTC Alarm) to generate an interrupt on rising edge */
EXTI_ClearITPendingBit(EXTI_Line17);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* 2 bits for Preemption Priority and 2 bits for Sub Priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
三、注意IP2366的I2C时序有些特殊,需要做特定的延时处理才能正常读取到寄存器数据

1、读取操作时各个位置增加50us延时

2、I2C频率设在100-200k合适;
3、结束读取后增加nack信号,防止读不出下一个数据。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)