#include "hal_sy6970.h" #define READ_SDA4 GPIO_ReadInputPins(GPIO_PORT_A,GPIO_PIN_12) #define IIC_SDA4(n) (n?GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_12):GPIO_ResetPins(GPIO_PORT_A, GPIO_PIN_12)) #define IIC_SCL4(n) (n?GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_11):GPIO_ResetPins(GPIO_PORT_A, GPIO_PIN_11)) #define sy6970_speed 5 //需要示波器调1us的时间 static void delay_us(uint16_t time) { uint16_t i; for(i=time;i>0;i--) { __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); } } static void iic4_init(void) { stc_gpio_init_t pstcGpioInit1; GPIO_StructInit(&pstcGpioInit1); pstcGpioInit1.u16PinDir = PIN_DIR_OUT; pstcGpioInit1.u16PinState = PIN_STAT_RST; GPIO_Init(GPIO_PORT_A, GPIO_PIN_11,&pstcGpioInit1); GPIO_Init(GPIO_PORT_A, GPIO_PIN_12,&pstcGpioInit1); GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_11); GPIO_SetPins(GPIO_PORT_A, GPIO_PIN_12); } void sy6970_init(void) { iic4_init(); } static void SDA_IN4(void) { stc_gpio_init_t pstcGpioInit3;//iic的引脚 pstcGpioInit3.u16PinDir = PIN_DIR_IN; //pstcGpioInit3.u16PinInputType = PIN_PU_ON; GPIO_Init(GPIO_PORT_A, GPIO_PIN_12,&pstcGpioInit3); } static void SDA_OUT4(void) { stc_gpio_init_t pstcGpioInit3; pstcGpioInit3.u16PinDir = PIN_DIR_OUT; pstcGpioInit3.u16PinOutputType=PIN_OUT_TYPE_NMOS; GPIO_Init(GPIO_PORT_A, GPIO_PIN_12,&pstcGpioInit3); } static void iic_start(void) { SDA_OUT4(); IIC_SDA4(1); IIC_SCL4(1); delay_us(sy6970_speed); IIC_SDA4(0); delay_us(sy6970_speed); IIC_SCL4(0); } static void iic_stop(void) { SDA_OUT4(); IIC_SCL4(0); IIC_SDA4(0); delay_us(sy6970_speed); IIC_SCL4(1); IIC_SDA4(1); delay_us(sy6970_speed); } static void iic_ack(void) { SDA_OUT4(); IIC_SCL4(0); IIC_SDA4(0); delay_us(sy6970_speed); IIC_SCL4(1); delay_us(sy6970_speed); IIC_SCL4(0); } static void iic_nack(void) { SDA_OUT4(); IIC_SCL4(0); IIC_SDA4(1); delay_us(sy6970_speed); IIC_SCL4(1); delay_us(sy6970_speed); IIC_SCL4(0); } static uint8_t iic_wait_ack(void) { uint16_t t =200; SDA_OUT4(); IIC_SDA4(1);delay_us(1); IIC_SCL4(1);delay_us(1); SDA_IN4(); while(READ_SDA4) { t--; if(t==0) { iic_stop(); return 1; } delay_us(1); } IIC_SCL4(0); return 0; } static void iic_send_byte(uint8_t byte) { uint8_t bit_cnt; SDA_OUT4(); IIC_SCL4(0); for(bit_cnt=0;bit_cnt<8;bit_cnt++) { if(byte&0x80) IIC_SDA4(1); else IIC_SDA4(0); byte<<=1; delay_us(sy6970_speed); IIC_SCL4(1); delay_us(sy6970_speed); IIC_SCL4(0); } } static uint8_t iic_recive_byte(unsigned char ack) { uint8_t retc = 0; uint8_t bit_cnt; SDA_IN4(); delay_us(1); for(bit_cnt=0;bit_cnt<8;bit_cnt++) { IIC_SCL4(0); delay_us(sy6970_speed); IIC_SCL4(1); retc=retc<<1; if(READ_SDA4) retc++; delay_us(sy6970_speed); } return(retc); } static void sy6970_write_byte(uint8_t dev_addr,uint8_t RAddr, uint8_t WData) { iic_start(); iic_send_byte(dev_addr); iic_wait_ack(); iic_send_byte(RAddr); iic_wait_ack(); iic_send_byte(WData); iic_wait_ack(); iic_stop(); } static void sy6970_read_byte(uint8_t dev_addr,uint8_t RAddr, uint8_t *RData) { iic_start(); iic_send_byte(dev_addr); iic_wait_ack(); iic_send_byte(RAddr); iic_wait_ack(); iic_start(); iic_send_byte(dev_addr|0x01); iic_wait_ack(); *RData = iic_recive_byte(0); iic_stop(); } _Bool sy6970_write_bytes ( unsigned char SlaveAddr, unsigned char RegAddr, unsigned char *Buf, unsigned char Num ) { iic_start(); //起始信号 //发送设备地址(写) iic_send_byte ( SlaveAddr ); //等待应答 iic_wait_ack(); //发送寄存器地址 iic_send_byte ( RegAddr ) ; //等待应答 iic_wait_ack(); while ( Num-- ) //循环写入数据 { //发送数据 iic_send_byte ( *Buf ); //等待应答 iic_wait_ack(); Buf++; //数据指针偏移到下一个 delay_us(10); } iic_stop(); //停止信号 return 0; } _Bool sy6970_read_bytes ( unsigned char SlaveAddr, unsigned char RegAddr, unsigned char *Buf, unsigned char Num ) { iic_start(); //起始信号 //发送设备地址(写) iic_send_byte ( SlaveAddr ); //等待应答 iic_wait_ack(); //发送寄存器地址 iic_send_byte ( RegAddr ); //等待应答 iic_wait_ack(); iic_start(); //重启信号 //发送设备地址(读) iic_send_byte ( SlaveAddr + 1 ); //等待应答 iic_wait_ack(); while ( Num-- ) { //偏移到下一个数据存储地址 if ( Num == 0 ) { *Buf = iic_recive_byte ( 0 ); //最后一个数据需要回NOACK } else { *Buf = iic_recive_byte ( 1 ); //回应ACK } Buf++; } iic_stop(); return 0; } #if 0 /**********************************************SY6970 操作函数****************************************************/ /* * 设置sy6970输入电流的大小 * * set_val 需要操作的从机设备 Fast Charge Current Limit: ICHG=[ICHG]*64mA Range:0mA(0000000)-5056mA(1001111) 0000000=0mA(Disable Charge) 0000001=64mA … 0100000=2048mA(Default) … 1001111~1111111=5056mA * * 返回值:void * */ void sy6970_set_input_current_limit(uint8_t set_val) { set_val&= 0x7F; sy6970_write_byte(SY6970_ADDR,0x04,set_val); } /* * 设置sy6970输入电压的大小 * * set_val 需要操作的从机设备 Charge Voltage Limit: VREG=3.840V+[VREG]*16mV Range:3.840V-4.608V(110000) 000000=3.840V 000001=3.856V … 010111=4.208V(Default) … 110000~111111=4.608V * * 返回值:void * */ void sy6970_set_input_voltage_limit(uint8_t set_val) { set_val&= 0xFC; sy6970_write_byte(SY6970_ADDR,0x06,set_val); } /*充电使能*/ void sy6970_charge_enable(void) { uint8_t set_val = 0x00; set_val&= 0x01<<4; sy6970_write_byte(SY6970_ADDR,0x03,set_val); } /*充电不使能*/ void sy6970_charge_disable(void) { uint8_t set_val = 0x00; set_val&= 0x00<<4; sy6970_write_byte(SY6970_ADDR,0x03,set_val); } /*充电状态查询 返回值: 00-Not Charging 01-Pre-charge (VBAT >=3; status &=0x03; return status; } uint8_t statusx = 0; #endif #include "FreeRTOS.h" #include "task.h" uint16 batt_voltage = 0, sys_voltage = 0; uint8 charge_status = 0; uint8 charge_ctl = 0; REG_SYS_CONFIG reg[0X15]; REG_SYS_CONFIG regRead; uint8 ntc_error = 0, bus_state = 0, current_limit = 0; uint16 charge_voltage = 0, charge_current = 0, inutcharg = 0, charge_current_read = 0; uint8 charge_flag = 0; /**********************************************SY6970 操作函数****************************************************/ /* * 设置sy6970输入电流的大小 * * set_val 需要操作的从机设备 Fast Charge Current Limit: ICHG=[ICHG]*64mA Range:0mA(0000000)-5056mA(1001111) 0000000=0mA(Disable Charge) 0000001=64mA … 0100000=2048mA(Default) … 1001111~1111111=5056mA * * 返回值:void * */ void sy6970_set_input_current_limit(uint8_t set_val) { set_val&= 0x7F; sy6970_write_byte(SY6970_ADDR,0x04,set_val); } /* * 设置sy6970输入电压的大小 * * set_val 需要操作的从机设备 Charge Voltage Limit: VREG=3.840V+[VREG]*16mV Range:3.840V-4.608V(110000) 000000=3.840V 000001=3.856V … 010111=4.208V(Default) … 110000~111111=4.608V * * 返回值:void * */ void sy6970_set_input_voltage_limit(uint8_t set_val) { set_val &= 0xFC; sy6970_write_byte(SY6970_ADDR,0x06,set_val); } /*充电使能*/ void sy6970_set_reg03_charge(void) { REG_SYS_CONFIG bat_config = {0}; bat_config.reg03_config.bat_load_en = 0; bat_config.reg03_config.wd_rst = 1; bat_config.reg03_config.otg_config = 0; bat_config.reg03_config.chg_config = 1; bat_config.reg03_config.sys_min = 5; sy6970_write_byte(SY6970_ADDR,0x03, bat_config.data_uint8); } /*获取 */ REG_SYS_CONFIG sy6970_get_reg_config(uint8_t cmd) { REG_SYS_CONFIG bat_read = {0}; sy6970_read_byte(SY6970_ADDR, cmd, &bat_read.data_uint8); return bat_read; } /*获取REG02配置*/ REG_SYS_CONFIG sy6970_get_reg02_config(void) { REG_SYS_CONFIG bat_read = {0}; sy6970_read_byte(SY6970_ADDR,0x02, &bat_read.data_uint8); return bat_read; } /*获取充电配置*/ REG_SYS_CONFIG sy6970_get_reg03_config(void) { REG_SYS_CONFIG bat_read = {0}; sy6970_read_byte(SY6970_ADDR,0x03, &bat_read.data_uint8); return bat_read; } /*配置reg0D*/ void sy6970_reg0d_vindpm_config(void) { REG_SYS_CONFIG bat_config = {0}; bat_config.reg0D_config.VINDPM_MODE = 1; bat_config.reg0D_config.VINDPM = 100; sy6970_write_byte(SY6970_ADDR,0x0D, bat_config.data_uint8); } /*获取reg0D配置*/ REG_SYS_CONFIG sy6970_get_reg0d_vindpm_config(void) { REG_SYS_CONFIG bat_read = {0}; sy6970_read_byte(SY6970_ADDR,0x0D, &bat_read.data_uint8); return bat_read; } /* * * 获取reg11数据 * 包括 * bus状态 * BUSV * */ REG_SYS_CONFIG sy6970_get_reg11_bus_status(void) { REG_SYS_CONFIG bat_status = {0}; sy6970_read_byte(SY6970_ADDR, 0x11, &(bat_status.data_uint8)); return bat_status; } /*充电不使能*/ void sy6970_reg03_charge_disable(void) { REG_SYS_CONFIG bat_status = {0}; //bat_status.reg03_config. //sy6970_read_byte(SY6970_ADDR, 0x11, &(bat_status.data)); //return bat_status; } /* */ REG_SYS_CONFIG sy6970_get_reg0b_charge_status(void) { REG_SYS_CONFIG bat_read = {0}; sy6970_read_byte(SY6970_ADDR,0x0b, &bat_read.data_uint8); return bat_read; } /* * 电池电压查询 返回值: 电池电压 单位mv */ uint16_t sy6970_get_batv(void) { uint8_t data = 0; sy6970_read_byte(SY6970_ADDR,0x0E,&data); return 2304 + 20 * (data & 0X7F); } uint16_t sy6970_set_reg(uint8 cmd, uint16 cmd_data) { REG_SYS_CONFIG bat_config = {0}; switch(cmd) { case 0X00: bat_config.re00_config.EN_HIZ = 0; bat_config.re00_config.EN_ILIM = 1; bat_config.re00_config.IINLIM = (cmd_data - 100) / 50; break; case 0X02: bat_config.reg02_config.conv_start = 1; bat_config.reg02_config.conv_rate = 0; bat_config.reg02_config.boost_freq = 0; bat_config.reg02_config.aicl_en = 1; bat_config.reg02_config.hvdcp_en = 1; bat_config.reg02_config.hv_type = 1; bat_config.reg02_config.force_dpdm = 0; bat_config.reg02_config.auto_dpdm_en = 0; break; case 0X03: switch(cmd_data) { case 0X00: bat_config.reg03_config.bat_load_en = 0; bat_config.reg03_config.wd_rst = 0; bat_config.reg03_config.otg_config = 0; bat_config.reg03_config.chg_config = 0; bat_config.reg03_config.sys_min = 5; break; case 0X01: bat_config.reg03_config.bat_load_en = 0; bat_config.reg03_config.wd_rst = 0; bat_config.reg03_config.otg_config = 0; bat_config.reg03_config.chg_config = 1; bat_config.reg03_config.sys_min = 5; break; default: return 1; } break; case 0X04://充电电流设置 cmd_data = cmd_data/64; bat_config.reg04_config.EN_PUMPX = 0; bat_config.reg04_config.ICHG = cmd_data; break; case 0X06: if(cmd_data < 3804) return 0; else {} cmd_data = (cmd_data - 4208) >= 0 ? (cmd_data - 3840)/16 : 23; //bat_config. bat_config.reg06_config.VREG = cmd_data; bat_config.reg06_config.BATLOWV = 1; bat_config.reg06_config.VRECHG = 0; break; default: return 1; } sy6970_write_byte(SY6970_ADDR, cmd ,bat_config.data_uint8); return 0; } /* * system电压查询 返回值: system电压 单位mv */ uint16_t sy6970_get_sysv(void) { uint8_t data = 0; sy6970_read_byte(SY6970_ADDR,0x0F,&data); return 2304 + 20 * (data & 0X7F); } void sy6970_task(void *argv) { /*Buck Mode: 000-Normal 010-NTC Warm 011-NTC Cool 101-NTC Cold 110-NTC Hot Boost Mode: 000-NTC Normal 101-NTC Cold 110-NTC Hot*/ //charge_status = sy6970_charge_status();// value_v = data * 0.02 + 2.304; charge_current = 1024; charge_voltage = 4208; inutcharg = 1000; sy6970_set_reg(REG_ADC_START_CTR, 0); sy6970_set_reg(REG_INPUT_CURRENT_CTR, inutcharg); sy6970_set_reg(REG_CURRENT_CHARGE_CTR, charge_current); sy6970_set_reg(REG_VOLTAGE_CHARGE_CTR, charge_voltage); //sy6970_set_reg(REG_ADC_START_CTR, inutcharg); while(1) { regRead = sy6970_get_reg_config(REG_VOLTAGE_READ); batt_voltage = regRead.reg0e_batt_info.BATV * 20 + 2304; regRead = sy6970_get_reg_config(REG_SYS_VOLTAGE_READ); sys_voltage = regRead.reg0f_sysv_info.SYSV * 20 + 2304; regRead = sy6970_get_reg_config(REG_CHARGE_STATUS_READ); charge_status = regRead.reg0b_onre_status.charg_stat; regRead = sy6970_get_reg_config(REG_NTC_STATUS_READ); ntc_error = regRead.reg0c_tem_info.NTC_FAULT; regRead = sy6970_get_reg_config(REG_CHARGE_CURRENT_READ); charge_current_read = regRead.reg12_charge_info.ICHGR * 50; regRead = sy6970_get_reg_config(REG_CURRENT_STATUS_READ); current_limit = regRead.reg13_current_input_info.CurrentInputLimit; if(batt_voltage > 4224 && 1 == charge_flag) { sy6970_set_reg(REG_CHARGE_CTR, DISABLE); charge_flag = 0; } else if(batt_voltage < 4000 && 0 == charge_flag) { sy6970_set_reg(REG_CHARGE_CTR, ENABLE); charge_flag = 1; } else{;} sy6970_set_reg(REG_ADC_START_CTR, 0); vTaskDelay(pdMS_TO_TICKS(1000)); //3.872 ** xian 3884 for(uint8 i = 0; i <= 0X14; i++) { reg[i] = sy6970_get_reg_config(i); } // // batt_voltage = reg[0X0E].reg0e_batt_info.BATV * 20 + 2304; // sys_voltage = reg[0X0F].reg0f_sysv_info.SYSV * 20 + 2304; // charge_status = reg[0X0B].reg0b_onre_status.charg_stat; // bus_state = reg[0X11].r11_bus_info.bus_gd; // bus_v = reg[0X11].reg11_bus_info.busv * 100 + 2600; // charge_current = reg[0X12].reg12_charge_info.ICHGR; // ntc_error = reg[0X0C].reg0c_tem_info.NTC_FAULT; } }