ZHCACK6A june 2020 – may 2023 BQ25150 , BQ25155 , BQ25618 , BQ25619 , TS5A12301E , TS5A3157 , TS5A3159A , TS5A6542
/* --COPYRIGHT--,BSD
* Copyright (c) 2016, Texas Instruments Incorporated
* All rights reserved.
*
* 只要符合下列条件,便可再次分发和使用源代码和
* 二进制形式的以下内容,不管有无进行修改:
*
* * 在再次分发源代码时必须保留以上版权声明、
* 本条件清单以及下述免责声明。
*
* * 在以二进制形式进行再次分发时,必须复制
* 分发时提供的文件和/或其他材料中的以上
* 版权声明、本条件清单以及下述免责声明。
*
* * 除非事先得到特别的书面许可,否则请勿
* 使用米6体育平台手机版_好二三四 (TI) 公司和贡献者的名称
* 来支持和推广衍生自该软件的米6体育平台手机版_好二三四。
*
* 本软件由版权持有者和贡献者“按原样”
* 提供,且不承认任何明示或暗示的保证,
* 包括但不限于对适销性或在某特定用途
* 方面的适用性的隐含保证。在任何情况下,
* 对于任何因使用本软件而造成的直接、间接、附带、特殊,
* 惩罚性或结果性损害(包括但不限于:
* 替代性商品或服务的采购;使用、数据或利润的损失;
* 或者业务中断),无论这些损害是如何引起的,
* 在何种责任理论上,无论是出于合同、严格责任还是
* 侵权行为(包括疏忽或其他),版权所有者或贡献者
* 概不负责,即使已被提前告知出现这种损害的可能性。
* --/COPYRIGHT--*/
// ======== main.c ========
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#include "board_functions.h"
#include <stdlib.h>
#include <msp430.h>
#include "driverlib.h"
#include "StdI2C.h"
#include "BQ25150.h"
//#include "board_timer.h"
#include "USB_config/descriptors.h"
#include "USB_API/USB_Common/device.h"
#include "USB_API/USB_Common/usb.h" // USB-specific functions
#include "USB_API/USB_CDC_API/UsbCdc.h"
#include "USB_app/usbConstructs.h"
#include "OLED/Oled_SSD1306.h"
#include "StdPollI2C.h"
#include "hal.h"
// Function declarations
uint8_t retInString(char* string);
void initTimer(void);
void setTimer_A_Parameters(void);
// Global flags set by events
volatile uint8_t bCDCDataReceived_event = FALSE; // Indicates data has been rx'ed
// without an open rx operation
char str[50];
#define NUM_SAMPLES 8
#define clkspeed 3 // 24Mhz Clock Select
//#define clkspeed 1 // 8Mhz Clock Select
short samples[NUM_SAMPLES] ;
int sample_index = 0 ;
char str[50];
char cmdstring[5];
char cs2[3];
uint8_t response = 0;
//unsigned char buffer[10]={1,2,3,4,5,6,7,8,9,10};
volatile char wholeString[MAX_STR_LENGTH] = "";
volatile uint8_t modecounter = 0;
volatile uint8_t pluscounter = 0;
///Timer_A_initUpModeParam Timer_A_params = {0};
int i;
unsigned char* PRxData; // Pointer to RX data
unsigned char RXByteCtr;
volatile unsigned char RxBuffer[128]; // Allocate 128 byte of RAM
unsigned char* PTxData; // Pointer to TX data
unsigned char TXByteCtr;
const unsigned char TxData[] = // Table of data to transmit
{
0x11,
0x22,
0x33,
0x44,
0x55
};
volatile uint8_t Button_Released = 0;
unsigned int result;
const char* hexstring = "0xabcdef0";
int raddr;
int rdata;
char buf[5];
uint8_t uraddr;
uint8_t urdata;
uint16_t Err;
// Holds the outgoing string
char outString[MAX_STR_LENGTH] = "";
uint8_t connectedflag = 0;
uint8_t echoflag = 1;
int ubtncounter = 0;
uint8_t RegValueLSB = 0;
uint8_t RegValueMSB = 0;
uint8_t VbatMSB = 0;
uint8_t ADCCheck = 0;
uint32_t stobusf;
uint8_t ADCcount = 0;
uint8_t VinReadA = 0;
uint8_t VinReadB = 0;
uint8_t VinReadC = 0;
uint8_t VinLow = 0;
double vIn = 0;
char vBat[];
//uint8_t RegValueM = 0;
//uint8_t RegValueL = 0;
uint32_t stobuf;
uint32_t stobuf1;
double stobuf2;
uint8_t RegValues = 0;
//__delay_cycles(1000); 1000 = 100us
uint8_t rthex;
// Set/declare toggle delays
//uint16_t SlowToggle_Period = 20000 - 1;
//uint16_t FastToggle_Period = 1000 - 1;
/*
* ======== main ========
*/
void main(void)
{
WDT_A_hold(WDT_A_BASE); // Stop watchdog timer
// Minumum Vcore setting required for the USB API is PMM_CORE_LEVEL_2 .
PMM_setVCore(PMM_CORE_LEVEL_2);
USBHAL_initPorts(); // Config GPIOS for low-power (output low)
USBHAL_initClocks(8000000 * clkspeed); // Config clocks.MCLK=SMCLK=FLL=8MHz; ACLK=REFO=32kHz
//USBHAL_initClocks(24000000);
initTimer(); // Prepare timer for LED toggling
//USB_setup(TRUE, TRUE); // Init USB & events; if a host is present, connect
initI2C();
// ======== UART Setup ========
P3SEL = BIT3+BIT4; // P3.4,5 = USCI_A0 TXD/RXD
__delay_cycles(20000);
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 6; // 1MHz 9600 (see User's Guide)
UCA0BR1 = 0; // 1MHz 9600
UCA0MCTL = UCBRS_0 + UCBRF_13 + UCOS16; // Modln UCBRSx=0, UCBRFx=0,
// over sampling
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
// ======== GPIO Setup ========
//LED Setup
GPIO_setAsOutputPin(LED_1);
GPIO_setOutputLowOnPin(LED_1);
GPIO_setAsOutputPin(LED_2);
GPIO_setOutputLowOnPin(LED_2);
GPIO_setAsOutputPin(LED_3);
GPIO_setOutputLowOnPin(LED_3);
//GPIO Setup
GPIO_setAsInputPinWithPullUpResistor(BQ_INT);
GPIO_setAsInputPin(BQ_PG);
GPIO_setAsInputPinWithPullUpResistor(BQ_START);
GPIO_setAsOutputPin(BQ_CE);
GPIO_setOutputLowOnPin(BQ_CE);
GPIO_setAsOutputPin(BQ_LP);
GPIO_setOutputHighOnPin(BQ_LP);
GPIO_setAsOutputPin(BQ_G1);
GPIO_setOutputLowOnPin(BQ_G1);
GPIO_toggleOutputOnPin(LED_1);
waitms(500);
GPIO_toggleOutputOnPin(LED_1);
waitms(500);
GPIO_toggleOutputOnPin(LED_1);
waitms(500);
GPIO_toggleOutputOnPin(LED_1);
// ======== BQ25155 Register Setup ========
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_MASK0, 0x5E, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_MASK1, 0xBF, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_MASK2, 0xF1, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_MASK3, 0x77, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_VBAT_CTRL, 0x3C, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ICHG_CTRL, 0x50, &Err);//sets Ichg to 200mA, 0xA0 for 200mA, 0x50 for 100mA, 0x20 for 40mA
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_PCHRGCTRL, 0x02, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_TERMCTRL, 0x14, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_BUVLO, 0x00, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_CHARGERCTRL0, 0x92, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_CHARGERCTRL1, 0xC2, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ILIMCTRL, 0x06, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_MRCTRL, 0x2A, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ICCTRL0, 0x10, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ICCTRL1, 0x00, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ICCTRL2, 0x40, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCCTRL0, 0x40, &Err); //0x58 Sets ADC to continuous with 3ms conv., 0x40 sets to continuous with 24ms conv.
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCCTRL1, 0x00, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCALARM_COMP1_M, 0x23, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCALARM_COMP1_L, 0x20, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCALARM_COMP2_M, 0x38, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCALARM_COMP2_L, 0x90, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCALARM_COMP3_M, 0x00, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADCALARM_COMP3_L, 0x00, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_ADC_READ_EN, 0xFE, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_TS_FASTCHGCTRL, 0x34, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_TS_COLD, 0x7C, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_TS_COOL, 0x6D, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_TS_WARM, 0x38, &Err);
StdI2C_TX_Single(BQ25150_ADDR, BQ25150_TS_HOT, 0x28, &Err);
// ======== Ready while loop ========
//This while loop holds the program with the interrupts disabled.This allows synchronization with the case
//short BQ_START pin 3.7 to ground to exit loop
while(GPIO_getInputPinValue(BQ_START) == 1) //Wait on start condition before enabling interrupts
{
GPIO_toggleOutputOnPin(LED_2);
__delay_cycles(3000000);
GPIO_toggleOutputOnPin(LED_2);
__delay_cycles(3000000);
GPIO_toggleOutputOnPin(LED_2);
__delay_cycles(3000000);
GPIO_toggleOutputOnPin(LED_2);
__delay_cycles(24000000);
}
GPIO_setOutputLowOnPin(LED_2);
// ======== Interrupt Enables ========
__enable_interrupt(); // Enable interrupts globally
GPIO_enableInterrupt(BQ_INT);
GPIO_selectInterruptEdge(BQ_INT, GPIO_HIGH_TO_LOW_TRANSITION);
GPIO_clearInterrupt(BQ_INT);
// ======== Main while loop ========
//reads Vbat, waits for case to drive Vin low
while(1)
{
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_ADCDATA_VBAT_M, &VbatMSB, &Err); //Read Vbat
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_ADCDATA_VIN_M, &RegValueMSB, &Err); //Read Vin
GPIO_toggleOutputOnPin(LED_1);
__delay_cycles(12000000);
}
}
/*
* ======== TIMER1_A0_ISR ========
*/
#if defined(__TI_COMPILER_VERSION__) || (__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
#elif defined(__GNUC__) && (__MSP430__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) TIMER0_A0_ISR (void)
#else
#error Compiler not found!
#endif
{
// wake on CCR0 count match
TA0CCTL0 = 0;
__bic_SR_register_on_exit(LPM0_bits|GIE);
}
// ======== BQ25155 Interrupt ========
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(PORT1_VECTOR)))
#endif
void Port_1(void)
{
switch(__even_in_range(P1IV,0x03))
{
case P1IV_P1IFG3:
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_STAT0, &RegValueMSB, &Err); //Read STAT0 REG
RegValueMSB &= 0x01; // Check if VIN_PGOOD_STAT is asserted
if(RegValueMSB == 0x00){ //if VIN_PGOOD_STAT is not asserted check to see if Vin has been driven low
// __delay_cycles(6000000);
//
// StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_ADCDATA_VIN_M, &RegValueMSB, &Err); //Read Vin
// stobuf = RegValueMSB;
// stobuf1 = stobuf * 6;
// vIn = (double)stobuf1 / 256;
ADCcount = 0;
VinLow = 0;
VinReadA = 5;
VinReadB = 5;
VinReadC = 5;
while(ADCcount < 85 && VinLow == 0){
__delay_cycles(120000);
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_ADCDATA_VIN_M, &RegValueMSB, &Err); //Read Vin
stobuf = RegValueMSB;
stobuf1 = stobuf * 6;
vIn = (double)stobuf1 / 256;
VinReadC = VinReadB;
VinReadB = VinReadA;
VinReadA = vIn;
ADCcount++;
if(VinReadA < 3 && VinReadB < 3 && VinReadC < 3){
VinLow = 1;
VinReadA = 0;
VinReadB = 0;
VinReadC = 0;
vIn = 0;
}
}
if(VinLow == 1){//if Vin is <3V begin communication process
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_STAT0, &RegValueMSB, &Err); //Read STAT0 REG
RegValueMSB &= 0x20; // Check if CHARGE_DONE_STAT is asserted
// RegValueMSB = 0x20; //uncomment to assert charge complete bit for testing
if(RegValueMSB){ // if CHARGE_DONE_STAT is asserted transmit 0xD5, 0xD5 = Vbat = 5v, this is chosen as the arbitrary charge complete bit for simplicity
GPIO_setOutputHighOnPin(BQ_G1); // Enter Comms Mode
__delay_cycles(4000);
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = 0xD5; // TX -> 0xD5 = 5V, out of charge range
__delay_cycles(4000);
GPIO_toggleOutputOnPin(LED_3);
GPIO_setOutputLowOnPin(BQ_G1); //Enter Power Mode
GPIO_toggleOutputOnPin(LED_2);
__delay_cycles(4000000);
GPIO_toggleOutputOnPin(LED_2);
__delay_cycles(4000000);
GPIO_setOutputHighOnPin(LED_2);
}
else{
stobuf = VbatMSB;
stobuf1 = stobuf * 6;
stobuf2 = (double)stobuf1 / 256; //stobuf2 = double of Vbat
GPIO_setOutputHighOnPin(BQ_G1); // Enter Comms Mode
__delay_cycles(4000);
while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = VbatMSB; // TX -> vBat MSB
__delay_cycles(4000);
GPIO_toggleOutputOnPin(LED_3);
GPIO_setOutputLowOnPin(BQ_G1); //Enter Power Mode
}
}
}
//Clear all interrupt flags
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_FLAG0, &RegValues, &Err);
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_FLAG1, &RegValues, &Err);
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_FLAG2, &RegValues, &Err);
StdI2C_P_RX_Single(BQ25150_ADDR, BQ25150_FLAG3, &RegValues, &Err);
GPIO_clearInterrupt(BQ_INT);
break;
default:
break;
}
}
//Released_Version_5_10_00_17