feat: KT mBMS 펌웨어 3종(HW1/2/3) 및 통합 빌드 환경 초기 커밋 (V4.0.0.1)
This commit is contained in:
803
APP_R3323/App/Hardware/ADBMS1818.c
Normal file
803
APP_R3323/App/Hardware/ADBMS1818.c
Normal file
@@ -0,0 +1,803 @@
|
||||
/*! ADBMS1818: Multicell Battery Monitors
|
||||
*
|
||||
*@verbatim
|
||||
*The ADBMS1818 is multi-cell battery stack monitor that measures up to 18 series
|
||||
*connected battery cells with a total measurement error of less than 2.2mV.
|
||||
*The cell measurement range of 0V to 5V makes the ADBMS1818 suitable for most
|
||||
*battery chemistries. All 18 cell voltages can be captured in 290uS, and lower
|
||||
*data acquisition rates can be selected for high noise reduction.
|
||||
*Using the ADBMS1818, multiple devices are connected in a daisy-chain with one
|
||||
*host processor connection for all devices, permitting simultaneous cell monitoring
|
||||
*of long, high voltage battery strings.
|
||||
*@endverbatim
|
||||
*
|
||||
* https://www.analog.com/en/products/ADBMS1818.html /TBD
|
||||
* https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/EVAL-ADBMS1818.html /TBD
|
||||
*
|
||||
*********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
//! @ingroup BMS
|
||||
//! @{
|
||||
//! @defgroup ADBMS1818 ADBMS1818: Multicell Battery Monitor
|
||||
//! @}
|
||||
|
||||
/*! @file
|
||||
@ingroup ADBMS1818
|
||||
Library for ADBMS1818 Multicell Battery Monitor
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include "ADBMS181x.h"
|
||||
#include "ADBMS1818.h"
|
||||
|
||||
/* Helper function to initialize register limits. */
|
||||
void ADBMS1818_init_reg_limits(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
for(uint8_t cic=0; cic<total_ic; cic++)
|
||||
{
|
||||
ic[cic].ic_reg.cell_channels = 18;
|
||||
ic[cic].ic_reg.stat_channels = 4;
|
||||
ic[cic].ic_reg.aux_channels = 9;
|
||||
ic[cic].ic_reg.num_cv_reg = 6;
|
||||
ic[cic].ic_reg.num_gpio_reg = 4;
|
||||
ic[cic].ic_reg.num_stat_reg = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This command will write the configuration registers of the ADBMS1818s
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void ADBMS1818_wrcfg(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
ADBMS181x_wrcfg(total_ic,ic);
|
||||
}
|
||||
|
||||
/*
|
||||
This command will write the configuration b registers of the ADBMS1818s
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void ADBMS1818_wrcfgb(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
ADBMS181x_wrcfgb(total_ic,ic);
|
||||
}
|
||||
|
||||
/* Reads configuration registers of a ADBMS1818 daisy chain */
|
||||
int8_t ADBMS1818_rdcfg(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = ADBMS181x_rdcfg(total_ic,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
/* Reads configuration b registers of a ADBMS1818 daisy chain */
|
||||
int8_t ADBMS1818_rdcfgb(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = ADBMS181x_rdcfgb(total_ic,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
/* Starts cell voltage conversion */
|
||||
void ADBMS1818_adcv(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP, //Discharge Permit
|
||||
uint8_t CH //Cell Channels to be measured
|
||||
)
|
||||
{
|
||||
ADBMS181x_adcv(MD,DCP,CH);
|
||||
}
|
||||
|
||||
/* Start a GPIO and Vref2 Conversion */
|
||||
void ADBMS1818_adax(uint8_t MD, //ADC Mode
|
||||
uint8_t CHG //GPIO Channels to be measured)
|
||||
)
|
||||
{
|
||||
ADBMS181x_adax(MD,CHG);
|
||||
}
|
||||
|
||||
/* Start a Status ADC Conversion */
|
||||
void ADBMS1818_adstat(uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //Stat Channels to be measured
|
||||
)
|
||||
{
|
||||
ADBMS181x_adstat(MD,CHST);
|
||||
}
|
||||
|
||||
/* Starts cell voltage and GPIO 1&2 conversion */
|
||||
void ADBMS1818_adcvax(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
ADBMS181x_adcvax(MD,DCP);
|
||||
}
|
||||
|
||||
/* Starts cell voltage and SOC conversion */
|
||||
void ADBMS1818_adcvsc( uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
ADBMS181x_adcvsc(MD,DCP);
|
||||
}
|
||||
|
||||
/* Reads and parses the ADBMS1818 cell voltage registers */
|
||||
uint8_t ADBMS1818_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t total_ic, // The number of ICs in the system
|
||||
cell_asic *ic // Array of the parsed cell codes
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = ADBMS181x_rdcv(reg,total_ic,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
/*
|
||||
The function is used
|
||||
to read the parsed GPIO codes of the ADBMS1818. This function will send the requested
|
||||
read commands parse the data and store the gpio voltages in aux_codes variable
|
||||
*/
|
||||
int8_t ADBMS1818_rdaux(uint8_t reg, //Determines which GPIO voltage register is read back.
|
||||
uint8_t total_ic,//The number of ICs in the system
|
||||
cell_asic *ic//A two dimensional array of the gpio voltage codes.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
ADBMS181x_rdaux(reg,total_ic,ic);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
/*
|
||||
Reads and parses the ADBMS1818 stat registers.
|
||||
The function is used
|
||||
to read the parsed stat codes of the ADBMS1818. This function will send the requested
|
||||
read commands parse the data and store the stat voltages in stat_codes variable
|
||||
*/
|
||||
int8_t ADBMS1818_rdstat(uint8_t reg, //Determines which Stat register is read back.
|
||||
uint8_t total_ic,//The number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array of the stat codes.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = ADBMS181x_rdstat(reg,total_ic,ic);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
/* Sends the poll ADC command */
|
||||
uint8_t ADBMS1818_pladc()
|
||||
{
|
||||
return(ADBMS181x_pladc());
|
||||
}
|
||||
|
||||
/* This function will block operation until the ADC has finished it's conversion */
|
||||
uint32_t ADBMS1818_pollAdc()
|
||||
{
|
||||
return(ADBMS181x_pollAdc());
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the cell voltage registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void ADBMS1818_clrcell()
|
||||
{
|
||||
ADBMS181x_clrcell();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Auxiliary registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void ADBMS1818_clraux()
|
||||
{
|
||||
ADBMS181x_clraux();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Stat registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void ADBMS1818_clrstat()
|
||||
{
|
||||
ADBMS181x_clrstat();
|
||||
}
|
||||
|
||||
/* Starts the Mux Decoder diagnostic self test */
|
||||
void ADBMS1818_diagn()
|
||||
{
|
||||
ADBMS181x_diagn();
|
||||
}
|
||||
|
||||
/* Starts cell voltage self test conversion */
|
||||
void ADBMS1818_cvst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
ADBMS181x_cvst(MD,ST);
|
||||
}
|
||||
|
||||
/* Start an Auxiliary Register Self Test Conversion */
|
||||
void ADBMS1818_axst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
ADBMS181x_axst(MD,ST);
|
||||
}
|
||||
|
||||
/* Start a Status Register Self Test Conversion */
|
||||
void ADBMS1818_statst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
ADBMS181x_statst(MD,ST);
|
||||
}
|
||||
|
||||
/* Starts cell voltage overlap conversion */
|
||||
void ADBMS1818_adol(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
ADBMS181x_adol(MD,DCP);
|
||||
}
|
||||
|
||||
/* Start an GPIO Redundancy test */
|
||||
void ADBMS1818_adaxd(uint8_t MD, //ADC Mode
|
||||
uint8_t CHG //GPIO Channels to be measured
|
||||
)
|
||||
{
|
||||
ADBMS181x_adaxd(MD,CHG);
|
||||
}
|
||||
|
||||
/* Start a Status register redundancy test Conversion */
|
||||
void ADBMS1818_adstatd(uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //Stat Channels to be measured
|
||||
)
|
||||
{
|
||||
ADBMS181x_adstatd(MD,CHST);
|
||||
}
|
||||
|
||||
/* Runs the Digital Filter Self Test */
|
||||
int16_t ADBMS1818_run_cell_adc_st(uint8_t adc_reg, // Type of register
|
||||
uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic, // A two dimensional array that will store the data
|
||||
uint8_t md, //ADC Mode
|
||||
bool adcopt // The adcopt bit in the configuration register
|
||||
)
|
||||
{
|
||||
int16_t error = 0;
|
||||
error = ADBMS181x_run_cell_adc_st(adc_reg,total_ic,ic,md,adcopt);
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* Runs the ADC overlap test for the IC */
|
||||
uint16_t ADBMS1818_run_adc_overlap(uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
uint16_t error = 0;
|
||||
int32_t measure_delta =0;
|
||||
int16_t failure_pos_limit = 20;
|
||||
int16_t failure_neg_limit = -20;
|
||||
uint32_t conv_time=0;
|
||||
wakeup_idle(total_ic);
|
||||
ADBMS181x_adol(MD_7KHZ_3KHZ,DCP_DISABLED);
|
||||
conv_time = ADBMS181x_pollAdc();
|
||||
|
||||
wakeup_idle(total_ic);
|
||||
error = ADBMS181x_rdcv(0, total_ic,ic);
|
||||
for (int cic = 0; cic<total_ic; cic++)
|
||||
{
|
||||
|
||||
|
||||
measure_delta = (int32_t)ic[cic].cells.c_codes[6]-(int32_t)ic[cic].cells.c_codes[7];
|
||||
if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit))
|
||||
{
|
||||
error = error | (1<<(cic-1));
|
||||
}
|
||||
measure_delta = (int32_t)ic[cic].cells.c_codes[12]-(int32_t)ic[cic].cells.c_codes[13];
|
||||
if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit))
|
||||
{
|
||||
error = error | (1<<(cic-1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Keeping here, Unused variables to retain Lib API as is */
|
||||
(void)conv_time;
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* Runs the redundancy self test */
|
||||
int16_t ADBMS1818_run_adc_redundancy_st(uint8_t adc_mode, //ADC Mode
|
||||
uint8_t adc_reg, // Type of register
|
||||
uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
int16_t error = 0;
|
||||
ADBMS181x_run_adc_redundancy_st(adc_mode,adc_reg,total_ic,ic);
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* Start an open wire Conversion */
|
||||
void ADBMS1818_adow(uint8_t MD, //ADC Mode
|
||||
uint8_t PUP, //Pull up/Pull down current
|
||||
uint8_t CH, //Sets which Cell channels are converted
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
ADBMS181x_adow(MD,PUP,CH,DCP);
|
||||
}
|
||||
|
||||
/* Start GPIOs open wire ADC conversion */
|
||||
void ADBMS1818_axow(uint8_t MD, //ADC Mode
|
||||
uint8_t PUP //Pull up/Pull down current
|
||||
)
|
||||
{
|
||||
ADBMS181x_axow(MD, PUP);
|
||||
}
|
||||
|
||||
/* Runs the data sheet algorithm for open wire for single cell detection */
|
||||
void ADBMS1818_run_openwire_single(uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_run_openwire_single(total_ic, ic);
|
||||
}
|
||||
|
||||
/* Runs the data sheet algorithm for open wire for multiple cell and two consecutive cells detection */
|
||||
void ADBMS1818_run_openwire_multi(uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_run_openwire_multi( total_ic, ic);
|
||||
}
|
||||
|
||||
/* Runs open wire for GPIOs */
|
||||
void ADBMS1818_run_gpio_openwire(uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_run_gpio_openwire(total_ic, ic);
|
||||
}
|
||||
|
||||
/* Helper function to set discharge bit in CFG register */
|
||||
void ADBMS1818_set_discharge(int Cell, // Cell to be discharged
|
||||
uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
for (int i=0; i<total_ic; i++)
|
||||
{
|
||||
if (Cell==0)
|
||||
{
|
||||
ic[i].configb.tx_data[1] = ic[i].configb.tx_data[1] |(0x04);
|
||||
}
|
||||
else if (Cell<9)
|
||||
{
|
||||
ic[i].config.tx_data[4] = ic[i].config.tx_data[4] | (1<<(Cell-1));
|
||||
}
|
||||
else if (Cell < 13)
|
||||
{
|
||||
ic[i].config.tx_data[5] = ic[i].config.tx_data[5] | (1<<(Cell-9));
|
||||
}
|
||||
else if (Cell<17)
|
||||
{
|
||||
ic[i].configb.tx_data[0] = ic[i].configb.tx_data[0] | (1<<(Cell-9));
|
||||
}
|
||||
else if (Cell<19)
|
||||
{
|
||||
ic[i].configb.tx_data[1] = ic[i].configb.tx_data[1] | (1<<(Cell-17));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clears all of the DCC bits in the configuration registers */
|
||||
void ADBMS1818_clear_discharge(uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_clear_discharge(total_ic,ic);
|
||||
}
|
||||
|
||||
/* Writes the pwm registers of a ADBMS1818 daisy chain */
|
||||
void ADBMS1818_wrpwm(uint8_t total_ic, // Number of ICs in the system
|
||||
uint8_t pwmReg, // PWM Register A or B
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
ADBMS181x_wrpwm(total_ic,pwmReg,ic);
|
||||
}
|
||||
|
||||
/* Reads pwm registers of a ADBMS1818 daisy chain */
|
||||
int8_t ADBMS1818_rdpwm(uint8_t total_ic, //Number of ICs in the system
|
||||
uint8_t pwmReg, // PWM Register A or B
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error =0;
|
||||
pec_error = ADBMS181x_rdpwm(total_ic,pwmReg,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
/* Writes data in S control register the ADBMS1818 connected in a daisy chain stack */
|
||||
void ADBMS1818_wrsctrl(uint8_t total_ic, // number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg, // SCTRL Register A or B
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_wrsctrl(total_ic, sctrl_reg, ic);
|
||||
}
|
||||
|
||||
/* Reads sctrl registers of a ADBMS1818 daisy chain */
|
||||
int8_t ADBMS1818_rdsctrl(uint8_t total_ic, // number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg, // SCTRL Register A or B
|
||||
cell_asic *ic //< a two dimensional array that the function stores the read data
|
||||
)
|
||||
{
|
||||
return ADBMS181x_rdsctrl( total_ic, sctrl_reg,ic );
|
||||
}
|
||||
|
||||
/*
|
||||
Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
*/
|
||||
void ADBMS1818_stsctrl()
|
||||
{
|
||||
ADBMS181x_stsctrl();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Sctrl registers and initializes
|
||||
all values to 0. The register will read back hexadecimal 0x00
|
||||
after the command is sent.
|
||||
*/
|
||||
void ADBMS1818_clrsctrl()
|
||||
{
|
||||
ADBMS181x_clrsctrl();
|
||||
}
|
||||
|
||||
/* Write the 6813 PWM/Sctrl Register B */
|
||||
void ADBMS1818_wrpsb(uint8_t total_ic, // Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
uint8_t write_buffer[256];
|
||||
uint8_t c_ic = 0;
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x1C;
|
||||
for(uint8_t current_ic = 0; current_ic<total_ic;current_ic++)
|
||||
{
|
||||
/*
|
||||
* isospi_reverse
|
||||
* if true then taking current_ic as c_ic from ,
|
||||
* but in other functions it seems to be different
|
||||
* where if false they are taking current_ic as c_ic
|
||||
* so changing to it false to be in sync with other code
|
||||
*/
|
||||
//if(ic->isospi_reverse == true){c_ic = current_ic;}
|
||||
if(ic->isospi_reverse == false){c_ic = current_ic;}
|
||||
else{c_ic = total_ic - current_ic - 1;}
|
||||
|
||||
write_buffer[ (current_ic*6) + 0] = ic[c_ic].pwmb.tx_data[0];
|
||||
write_buffer[ (current_ic*6) + 1] = ic[c_ic].pwmb.tx_data[1];
|
||||
write_buffer[ (current_ic*6) + 2]= ic[c_ic].pwmb.tx_data[2];
|
||||
write_buffer[ (current_ic*6) + 3] = ic[c_ic].sctrlb.tx_data[3];
|
||||
write_buffer[ (current_ic*6) + 4] = ic[c_ic].sctrlb.tx_data[4];
|
||||
write_buffer[ (current_ic*6) + 5]= ic[c_ic].sctrlb.tx_data[5];
|
||||
#if 0
|
||||
write_buffer[0] = ic[c_ic].pwmb.tx_data[0];
|
||||
write_buffer[1] = ic[c_ic].pwmb.tx_data[1];
|
||||
write_buffer[2]= ic[c_ic].pwmb.tx_data[2];
|
||||
write_buffer[3] = ic[c_ic].sctrlb.tx_data[3];
|
||||
write_buffer[4] = ic[c_ic].sctrlb.tx_data[4];
|
||||
write_buffer[5]= ic[c_ic].sctrlb.tx_data[5];
|
||||
#endif
|
||||
}
|
||||
write_68(total_ic, cmd, write_buffer);
|
||||
}
|
||||
|
||||
/* Reading the 6813 PWM/Sctrl Register B */
|
||||
uint8_t ADBMS1818_rdpsb(uint8_t total_ic, //< number of ICs in the daisy chain
|
||||
cell_asic *ic //< a two dimensional array that the function stores the read data
|
||||
)
|
||||
{
|
||||
uint8_t cmd[4];
|
||||
uint8_t read_buffer[256];
|
||||
int8_t pec_error = 0;
|
||||
uint16_t data_pec;
|
||||
uint16_t calc_pec;
|
||||
uint8_t c_ic = 0;
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x1E;
|
||||
pec_error = read_68(total_ic, cmd, read_buffer);
|
||||
|
||||
for(uint8_t current_ic =0; current_ic<total_ic; current_ic++)
|
||||
{
|
||||
if(ic->isospi_reverse == false){c_ic = current_ic;}
|
||||
else{c_ic = total_ic - current_ic - 1;}
|
||||
for(int byte=0; byte<3;byte++)
|
||||
{
|
||||
ic[c_ic].pwmb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
|
||||
for(int byte=3; byte<6;byte++)
|
||||
{
|
||||
ic[c_ic].sctrlb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
|
||||
for(int byte=6; byte<8;byte++)
|
||||
{
|
||||
ic[c_ic].pwmb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
ic[c_ic].sctrlb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
|
||||
calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
|
||||
data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
|
||||
if(calc_pec != data_pec )
|
||||
{
|
||||
ic[c_ic].pwmb.rx_pec_match = 1;
|
||||
ic[c_ic].sctrlb.rx_pec_match = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ic[c_ic].pwmb.rx_pec_match = 0;
|
||||
ic[c_ic].sctrlb.rx_pec_match = 0;
|
||||
|
||||
}
|
||||
}
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
/* Writes the COMM registers of a ADBMS1818 daisy chain */
|
||||
void ADBMS1818_wrcomm(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the comm data that will be written
|
||||
)
|
||||
{
|
||||
ADBMS181x_wrcomm(total_ic,ic);
|
||||
}
|
||||
|
||||
/* Reads COMM registers of a ADBMS1818 daisy chain */
|
||||
int8_t ADBMS1818_rdcomm(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
ADBMS181x_rdcomm(total_ic, ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
/* Shifts data in COMM register out over ADBMS1818 SPI/I2C port */
|
||||
void ADBMS1818_stcomm(uint8_t len) //Length of data to be transmitted
|
||||
{
|
||||
ADBMS181x_stcomm(len);
|
||||
}
|
||||
|
||||
/* Mutes the ADBMS1818 discharge transistors */
|
||||
void ADBMS1818_mute()
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x28;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
/* Clears the ADBMS1818 Mute Discharge */
|
||||
void ADBMS1818_unmute()
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x29;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
/* Helper function that increments PEC counters */
|
||||
void ADBMS1818_check_pec(uint8_t total_ic,//Number of ICs in the system
|
||||
uint8_t reg, // Type of register
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_check_pec(total_ic,reg,ic);
|
||||
}
|
||||
|
||||
/* Helper Function to reset PEC counters */
|
||||
void ADBMS1818_reset_crc_count(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic // A two dimensional array that will store the data
|
||||
)
|
||||
{
|
||||
ADBMS181x_reset_crc_count(total_ic,ic);
|
||||
}
|
||||
|
||||
/* Helper function to initialize CFG variables */
|
||||
void ADBMS1818_init_cfg(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
ADBMS181x_init_cfg(total_ic,ic);
|
||||
}
|
||||
|
||||
/* Helper function to set CFGR variable */
|
||||
void ADBMS1818_set_cfgr(uint8_t nIC, cell_asic *ic, bool refon, bool adcopt, bool gpio[5],bool dcc[12],bool dcto[4], uint16_t uv, uint16_t ov)
|
||||
{
|
||||
ADBMS181x_set_cfgr_refon (nIC, ic, refon);
|
||||
ADBMS181x_set_cfgr_adcopt(nIC, ic, adcopt);
|
||||
ADBMS181x_set_cfgr_gpio (nIC, ic, gpio);
|
||||
ADBMS181x_set_cfgr_dis (nIC, ic, dcc);
|
||||
ADBMS181x_set_cfgr_dcto (nIC, ic, dcto);
|
||||
ADBMS181x_set_cfgr_uv (nIC, ic, uv);
|
||||
ADBMS181x_set_cfgr_ov (nIC, ic, ov);
|
||||
}
|
||||
|
||||
/* Helper function to set the REFON bit */
|
||||
void ADBMS1818_set_cfgr_refon(uint8_t nIC, cell_asic *ic, bool refon)
|
||||
{
|
||||
ADBMS181x_set_cfgr_refon(nIC,ic,refon);
|
||||
}
|
||||
|
||||
/* Helper function to set the adcopt bit */
|
||||
void ADBMS1818_set_cfgr_adcopt(uint8_t nIC, cell_asic *ic, bool adcopt)
|
||||
{
|
||||
ADBMS181x_set_cfgr_adcopt(nIC,ic,adcopt);
|
||||
}
|
||||
|
||||
/* Helper function to set GPIO bits */
|
||||
void ADBMS1818_set_cfgr_gpio(uint8_t nIC, cell_asic *ic,bool gpio[5])
|
||||
{
|
||||
ADBMS181x_set_cfgr_gpio(nIC,ic,gpio);
|
||||
}
|
||||
|
||||
/* Helper function to control discharge */
|
||||
void ADBMS1818_set_cfgr_dis(uint8_t nIC, cell_asic *ic,bool dcc[12])
|
||||
{
|
||||
ADBMS181x_set_cfgr_dis(nIC,ic,dcc);
|
||||
}
|
||||
|
||||
/* Helper Function to set uv value in CFG register */
|
||||
void ADBMS1818_set_cfgr_uv(uint8_t nIC, cell_asic *ic,uint16_t uv)
|
||||
{
|
||||
ADBMS181x_set_cfgr_uv(nIC, ic, uv);
|
||||
}
|
||||
|
||||
/* Helper Function to set dcto value in CFG register */
|
||||
void ADBMS1818_set_cfgr_dcto(uint8_t nIC, cell_asic *ic,bool dcto[4])
|
||||
{
|
||||
ADBMS181x_set_cfgr_dcto(nIC, ic, dcto);
|
||||
}
|
||||
|
||||
/* Helper function to set OV value in CFG register */
|
||||
void ADBMS1818_set_cfgr_ov(uint8_t nIC, cell_asic *ic,uint16_t ov)
|
||||
{
|
||||
ADBMS181x_set_cfgr_ov( nIC, ic, ov);
|
||||
}
|
||||
|
||||
/* Helper Function to initialize the CFGRB data structures */
|
||||
void ADBMS1818_init_cfgb(uint8_t total_ic,cell_asic *ic)
|
||||
{
|
||||
for (uint8_t current_ic = 0; current_ic<total_ic;current_ic++)
|
||||
{
|
||||
for(int j =0; j<6;j++)
|
||||
{
|
||||
ic[current_ic].configb.tx_data[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper Function to set the configuration register B */
|
||||
void ADBMS1818_set_cfgrb(uint8_t nIC, cell_asic *ic,bool fdrf,bool dtmen,bool ps[2],bool gpiobits[4],bool dccbits[7])
|
||||
{
|
||||
ADBMS1818_set_cfgrb_fdrf (nIC, ic, fdrf);
|
||||
ADBMS1818_set_cfgrb_dtmen (nIC, ic, dtmen);
|
||||
ADBMS1818_set_cfgrb_ps (nIC, ic, ps);
|
||||
ADBMS1818_set_cfgrb_gpio_b(nIC, ic, gpiobits);
|
||||
ADBMS1818_set_cfgrb_dcc_b (nIC, ic, dccbits);
|
||||
}
|
||||
|
||||
/* Helper function to set the FDRF bit */
|
||||
void ADBMS1818_set_cfgrb_fdrf(uint8_t nIC, cell_asic *ic, bool fdrf)
|
||||
{
|
||||
if(fdrf) ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|0x40;
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&0xBF;
|
||||
}
|
||||
|
||||
/* Helper function to set the DTMEN bit */
|
||||
void ADBMS1818_set_cfgrb_dtmen(uint8_t nIC, cell_asic *ic, bool dtmen)
|
||||
{
|
||||
if(dtmen) ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|0x08;
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&0xF7;
|
||||
}
|
||||
|
||||
/* Helper function to set the PATH SELECT bit */
|
||||
void ADBMS1818_set_cfgrb_ps(uint8_t nIC, cell_asic *ic, bool ps[])
|
||||
{
|
||||
for(int i =0;i<2;i++)
|
||||
{
|
||||
if(ps[i])ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|(0x01<<(i+4));
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&(~(0x01<<(i+4)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function to set the gpio bits in configb b register */
|
||||
void ADBMS1818_set_cfgrb_gpio_b(uint8_t nIC, cell_asic *ic, bool gpiobits[])
|
||||
{
|
||||
for(int i =0;i<4;i++)
|
||||
{
|
||||
if(gpiobits[i])ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0]|(0x01<<i);
|
||||
else ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0]&(~(0x01<<i));
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function to set the dcc bits in configb b register */
|
||||
void ADBMS1818_set_cfgrb_dcc_b(uint8_t nIC, cell_asic *ic, bool dccbits[])
|
||||
{
|
||||
for(int i =0;i<7;i++)
|
||||
{
|
||||
if(i==0)
|
||||
{
|
||||
if(dccbits[i])ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|0x04;
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&0xFB;
|
||||
}
|
||||
if(i>0 && i<5)
|
||||
{
|
||||
if(dccbits[i])ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0]|(0x01<<(i+3));
|
||||
else ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0]&(~(0x01<<(i+3)));
|
||||
}
|
||||
if(i>4 && i<7)
|
||||
{
|
||||
if(dccbits[i])ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|(0x01<<(i-5));
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&(~(0x01<<(i-5)));
|
||||
}
|
||||
}
|
||||
}
|
||||
637
APP_R3323/App/Hardware/ADBMS1818.h
Normal file
637
APP_R3323/App/Hardware/ADBMS1818.h
Normal file
@@ -0,0 +1,637 @@
|
||||
/*! ADBMS1818: Multicell Battery Monitors
|
||||
*
|
||||
*@verbatim
|
||||
*The ADBMS1818 is multi-cell battery stack monitor that measures up to 18 series
|
||||
*connected battery cells with a total measurement error of less than 2.2mV.
|
||||
*The cell measurement range of 0V to 5V makes the ADBMS1818 suitable for most
|
||||
*battery chemistries. All 18 cell voltages can be captured in 290uS, and lower
|
||||
*data acquisition rates can be selected for high noise reduction.
|
||||
*Using the ADBMS1818, multiple devices are connected in a daisy-chain with one
|
||||
*host processor connection for all devices, permitting simultaneous cell monitoring
|
||||
*of long, high voltage battery strings.
|
||||
*@endverbatim
|
||||
*
|
||||
* https://www.analog.com/en/products/ADBMS1818.html /TBD
|
||||
* https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/EVAL-ADBMS1818.html /TBD
|
||||
*
|
||||
*********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/*! @file
|
||||
@ingroup ADBMS1818
|
||||
Header for ADBMS1818 Multicell Battery Monitor
|
||||
*/
|
||||
|
||||
#ifndef ADBMS1818_H
|
||||
#define ADBMS1818_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "ADBMS181x.h"
|
||||
|
||||
#define CELL 1
|
||||
#define AUX 2
|
||||
#define STAT 3
|
||||
|
||||
/*!
|
||||
Helper function to initialize register limits
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_init_reg_limits(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS1818 configuration register A
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_wrcfg(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS1818 configuration register B
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_wrcfgb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads configuration register A of a ADBMS1818 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS1818_rdcfg(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read configuration data
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads configuration register B of a ADBMS1818 daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS1818_rdcfgb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read configuration data
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adcv(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP, //!< Controls if Discharge is permitted during conversion
|
||||
uint8_t CH //!< Sets which Cell channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a GPIO and Vref2 Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adax(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a Status ADC Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adstat( uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHST //!< Sets which Stat channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage and GPIO 1 & 2 conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adcvax(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and Sum of cells conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adcvsc(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads and parses the ADBMS1818 cell voltage registers.
|
||||
@return uint8_t, pec_error PEC Status.
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
uint8_t ADBMS1818_rdcv(uint8_t reg, //!< Controls which cell voltage register is read back.
|
||||
uint8_t total_ic, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic //!< Array of the parsed cell codes from lowest to highest.
|
||||
);
|
||||
|
||||
/*! Reads and parses the ADBMS1818 auxiliary registers.
|
||||
@return int8_t, pec_error PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t ADBMS1818_rdaux(uint8_t reg, //!< Controls which GPIO voltage register is read back
|
||||
uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array of the parsed gpio voltage codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads and parses the ADBMS1818 stat registers.
|
||||
@return int8_t, pec_error PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t ADBMS1818_rdstat(uint8_t reg, //!< Determines which Stat register is read back.
|
||||
uint8_t total_ic,//!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Sends the poll ADC command
|
||||
@returns 1 byte read back after a pladc command. If the byte is not 0xFF ADC conversion has completed
|
||||
*/
|
||||
uint8_t ADBMS1818_pladc(void);
|
||||
|
||||
/*!
|
||||
This function will block operation until the ADC has finished it's conversion
|
||||
@returns uint32_t, counter The approximate time it took for the ADC function to complete.
|
||||
*/
|
||||
uint32_t ADBMS1818_pollAdc(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS1818 cell voltage registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_clrcell(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS1818 Auxiliary registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_clraux(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS1818 Stat registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_clrstat(void);
|
||||
|
||||
/*!
|
||||
Starts the Mux Decoder diagnostic self test
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_diagn(void);
|
||||
|
||||
/*!
|
||||
Starts cell voltage self test conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_cvst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Self Test Mode
|
||||
);
|
||||
|
||||
/*!
|
||||
Start an Auxiliary Register Self Test Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_axst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a Status Register Self Test Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_statst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage overlap conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adol(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*!
|
||||
Start an GPIO Redundancy test
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adaxd(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a Status register redundancy test Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adstatd(uint8_t MD, //!< ADC Mode
|
||||
uint8_t CHST //!< Sets which Status channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs the ADC Self Tests
|
||||
@return int16_t, error Number of errors detected.
|
||||
*/
|
||||
int16_t ADBMS1818_run_cell_adc_st(uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t md, //!< ADC Mode
|
||||
bool adcopt //!< The adcopt bit in the configuration register
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function that runs the ADC Overlap test
|
||||
@return uint16_t, error
|
||||
0: Pass
|
||||
-1: False, Error detected
|
||||
*/
|
||||
uint16_t ADBMS1818_run_adc_overlap(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs the ADC Digital Redundancy commands and checks output for errors
|
||||
@return int16_t, error Number of errors detected.
|
||||
*/
|
||||
int16_t ADBMS1818_run_adc_redundancy_st(uint8_t adc_mode, //!< ADC Mode
|
||||
uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Start an open wire Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_adow(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t PUP,//!< Pull up/Pull down current
|
||||
uint8_t CH, //!< Sets which Cell channels are converted
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*!
|
||||
Start GPIOs open wire ADC conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_axow(uint8_t MD, //!< ADC Mode
|
||||
uint8_t PUP //!< Pull up/Pull down current
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs the data sheet algorithm for open wire for single cell detection
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_run_openwire_single(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs open wire for multiple cell and two consecutive cells detection
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_run_openwire_multi(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Runs open wire for GPIOs
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_run_gpio_openwire(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function to Set DCC bits in the CFGR Registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_discharge(int Cell, //!< The cell to be discharged
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function to clear DCC bits in the CFGR Registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_clear_discharge(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS1818 PWM register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_wrpwm(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
uint8_t pwmReg, //!< PWM Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads pwm registers of a ADBMS1818 daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS1818_rdpwm(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
uint8_t pwmReg, //!< PWM Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS1818 Sctrl register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_wrsctrl(uint8_t nIC, //!< Number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,//! SCTRL Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads sctrl registers of a ADBMS1818 daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS1818_rdsctrl(uint8_t nIC, //!< Number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,//!< SCTRL Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_stsctrl(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS1818 Sctrl registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_clrsctrl(void);
|
||||
|
||||
/*!
|
||||
Write the 6813 PWM/Sctrl Register B
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_wrpsb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Reading pwm/s control register B
|
||||
@return uint8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
uint8_t ADBMS1818_rdpsb(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read data
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS1818 COMM register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_wrcomm(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array of the comm data that will be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads comm registers of a ADBMS1818 daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS1818_rdcomm(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< Two dimensional array that the function stores the read comm data.
|
||||
);
|
||||
|
||||
/*!
|
||||
Issues a stcomm command and clocks data out of the COMM register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_stcomm(uint8_t len //!< Length of data to be transmitted
|
||||
);
|
||||
|
||||
/*!
|
||||
Mutes the ADBMS1818 discharge transistors
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_mute(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS1818 Mute Discharge
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_unmute(void);
|
||||
|
||||
/*!
|
||||
Helper Function that counts overall PEC errors and register/IC PEC errors
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_check_pec(uint8_t total_ic, //!< Number of ICs in the system
|
||||
uint8_t reg, //!< Type of register
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function that resets the PEC error counters
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_reset_crc_count(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function to initialize the CFGR data structures
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_init_cfg(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set appropriate bits in CFGR register based on bit function
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon, //!< The REFON bit
|
||||
bool adcopt, //!< The ADCOPT bit
|
||||
bool gpio[5], //!< The GPIO bits
|
||||
bool dcc[12], //!< The DCC bits
|
||||
bool dcto[4], //!< The Dcto bits
|
||||
uint16_t uv, //!< The UV value
|
||||
uint16_t ov //!< The OV value
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the REFON bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_refon(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon //!< The REFON bit
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the ADCOPT bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_adcopt(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool adcopt //!< The ADCOPT bit
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the GPIO bits HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_gpio(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool gpio[] //!< The GPIO bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the DCC bits HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_dis(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool dcc[] //!< The DCC bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set UV field in CFGRA register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_uv(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t uv //!< The UV value
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set DCTO field in CFGRA register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_dcto(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool dcto[4] //!< The Dcto bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set OV field in CFGRA register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgr_ov(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t ov //!< The OV value
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function to initialize the CFGR B data structures
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_init_cfgb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set appropriate bits in CFGR register based on bit function
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgrb(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool fdrf, //!< The FDRF bit
|
||||
bool dtmen, //!< The DTMEN bit
|
||||
bool ps[2], //!< Path selection bits
|
||||
bool gpiobits[4], //!< The GPIO bits
|
||||
bool dccbits[7] //!< The DCC bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the FDRF bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgrb_fdrf(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool fdrf //!< The FDRF bit
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the DTMEN bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgrb_dtmen(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool dtmen //!< The DTMEN bit
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the Path Select bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgrb_ps(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool ps[] //!< Path selection bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the GPIO bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgrb_gpio_b(uint8_t nIC, //!< The number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool gpiobits[] //!< The GPIO bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the DCC bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS1818_set_cfgrb_dcc_b(uint8_t nIC, //!< The number of ICs in The daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store The data
|
||||
bool dccbits[] //!< The DCC bits
|
||||
);
|
||||
|
||||
#endif
|
||||
2316
APP_R3323/App/Hardware/ADBMS181x.c
Normal file
2316
APP_R3323/App/Hardware/ADBMS181x.c
Normal file
File diff suppressed because it is too large
Load Diff
768
APP_R3323/App/Hardware/ADBMS181x.h
Normal file
768
APP_R3323/App/Hardware/ADBMS181x.h
Normal file
@@ -0,0 +1,768 @@
|
||||
/*! General BMS Library
|
||||
*******************************************************************************
|
||||
* @file ADBMS181x.h
|
||||
* @author BMS (bms.support@analog.com)
|
||||
|
||||
********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/*! @file
|
||||
Library for ADBMS181x Multi-cell Battery Monitor
|
||||
*/
|
||||
|
||||
#ifndef ADBMS181x_h
|
||||
#define ADBMS181x_h
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <stdint.h>
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
#ifndef bool
|
||||
#define bool uint8_t
|
||||
#endif
|
||||
|
||||
#define IC_ADBMS1818
|
||||
|
||||
#define MD_422HZ_1KHZ 0
|
||||
#define MD_27KHZ_14KHZ 1
|
||||
#define MD_7KHZ_3KHZ 2
|
||||
#define MD_26HZ_2KHZ 3
|
||||
|
||||
#define ADC_OPT_ENABLED 1
|
||||
#define ADC_OPT_DISABLED 0
|
||||
|
||||
#define CELL_CH_ALL 0
|
||||
#define CELL_CH_1and7 1
|
||||
#define CELL_CH_2and8 2
|
||||
#define CELL_CH_3and9 3
|
||||
#define CELL_CH_4and10 4
|
||||
#define CELL_CH_5and11 5
|
||||
#define CELL_CH_6and12 6
|
||||
|
||||
#define SELFTEST_1 1
|
||||
#define SELFTEST_2 2
|
||||
|
||||
#define AUX_CH_ALL 0
|
||||
#define AUX_CH_GPIO1 1
|
||||
#define AUX_CH_GPIO2 2
|
||||
#define AUX_CH_GPIO3 3
|
||||
#define AUX_CH_GPIO4 4
|
||||
#define AUX_CH_GPIO5 5
|
||||
#define AUX_CH_VREF2 6
|
||||
|
||||
#define STAT_CH_ALL 0
|
||||
#define STAT_CH_SOC 1
|
||||
#define STAT_CH_ITEMP 2
|
||||
#define STAT_CH_VREGA 3
|
||||
#define STAT_CH_VREGD 4
|
||||
|
||||
#define REG_ALL 0
|
||||
#define REG_1 1
|
||||
#define REG_2 2
|
||||
#define REG_3 3
|
||||
#define REG_4 4
|
||||
#define REG_5 5
|
||||
#define REG_6 6
|
||||
|
||||
#define DCP_DISABLED 0
|
||||
#define DCP_ENABLED 1
|
||||
|
||||
#define PULL_UP_CURRENT 1
|
||||
#define PULL_DOWN_CURRENT 0
|
||||
|
||||
#define NUM_RX_BYT 8
|
||||
#define CELL 1
|
||||
#define AUX 2
|
||||
#define STAT 3
|
||||
#define CFGR 0
|
||||
#define CFGRB 4
|
||||
|
||||
#define CS_PIN_HIGH SPI1_NSS_HIGH
|
||||
#define CS_PIN_LOW SPI1_NSS_LOW
|
||||
|
||||
/*! Cell Voltage data structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t c_codes[18]; //!< Cell Voltage Codes
|
||||
uint8_t pec_match[6]; //!< If a PEC error was detected during most recent read cmd
|
||||
} cv;
|
||||
|
||||
/*! AUX Reg Voltage Data structure */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t a_codes[12]; //!< Aux Voltage Codes
|
||||
uint8_t pec_match[4]; //!< If a PEC error was detected during most recent read cmd
|
||||
} ax;
|
||||
|
||||
/*! Status Reg data structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t stat_codes[4]; //!< Status codes.
|
||||
uint8_t flags[3]; //!< Byte array that contains the uv/ov flag data
|
||||
uint8_t mux_fail[1]; //!< Mux self test status flag
|
||||
uint8_t thsd[1]; //!< Thermal shutdown status
|
||||
uint8_t pec_match[2]; //!< If a PEC error was detected during most recent read cmd
|
||||
} st;
|
||||
|
||||
/*! IC register structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t tx_data[6]; //!< Stores data to be transmitted
|
||||
uint8_t rx_data[8]; //!< Stores received data
|
||||
uint8_t rx_pec_match; //!< If a PEC error was detected during most recent read cmd
|
||||
} ic_register;
|
||||
|
||||
/*! PEC error counter structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pec_count; //!< Overall PEC error count
|
||||
uint16_t cfgr_pec; //!< Configuration register data PEC error count
|
||||
uint16_t cell_pec[6]; //!< Cell voltage register data PEC error count
|
||||
uint16_t aux_pec[4]; //!< Aux register data PEC error count
|
||||
uint16_t stat_pec[2]; //!< Status register data PEC error count
|
||||
} pec_counter;
|
||||
|
||||
/*! Register configuration structure */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cell_channels; //!< Number of Cell channels
|
||||
uint8_t stat_channels; //!< Number of Stat channels
|
||||
uint8_t aux_channels; //!< Number of Aux channels
|
||||
uint8_t num_cv_reg; //!< Number of Cell voltage register
|
||||
uint8_t num_gpio_reg; //!< Number of Aux register
|
||||
uint8_t num_stat_reg; //!< Number of Status register
|
||||
} register_cfg;
|
||||
|
||||
/*! Cell variable structure */
|
||||
typedef struct
|
||||
{
|
||||
ic_register config;
|
||||
ic_register configb;
|
||||
cv cells;
|
||||
ax aux;
|
||||
st stat;
|
||||
ic_register com;
|
||||
ic_register pwm;
|
||||
ic_register pwmb;
|
||||
ic_register sctrl;
|
||||
ic_register sctrlb;
|
||||
uint8_t sid[6];
|
||||
bool isospi_reverse;
|
||||
pec_counter crc_count;
|
||||
register_cfg ic_reg;
|
||||
long system_open_wire;
|
||||
} cell_asic;
|
||||
|
||||
/*!
|
||||
Wake isoSPI up from IDlE state and enters the READY state
|
||||
@return void
|
||||
*/
|
||||
void wakeup_idle(uint8_t total_ic);//!< Number of ICs in the daisy chain
|
||||
|
||||
/*!
|
||||
Wake the ADBMS181x from the sleep state
|
||||
@return void
|
||||
*/
|
||||
void wakeup_sleep(uint8_t total_ic); //!< Number of ICs in the daisy chain
|
||||
|
||||
/*!
|
||||
Sends a command to the BMS IC. This code will calculate the PEC code for the transmitted command
|
||||
@return void
|
||||
*/
|
||||
void cmd_68(uint8_t tx_cmd[2]); //!< 2 byte array containing the BMS command to be sent
|
||||
|
||||
/*!
|
||||
Writes an array of data to the daisy chain
|
||||
@return void
|
||||
*/
|
||||
void write_68(uint8_t total_ic , //!< Number of ICs in the daisy chain
|
||||
uint8_t tx_cmd[2], //!< 2 byte array containing the BMS command to be sent
|
||||
uint8_t data[] //!< Array containing the data to be written to the BMS ICs
|
||||
);
|
||||
|
||||
/*!
|
||||
Issues a command onto the daisy chain and reads back 6*total_ic data in the rx_data array
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t read_68( uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
uint8_t tx_cmd[2], //!< 2 byte array containing the BMS command to be sent
|
||||
uint8_t *rx_data); //!< Array that the read back data will be stored in.
|
||||
|
||||
/*!
|
||||
Calculates and returns the CRC15
|
||||
@returns The calculated pec15 as an unsigned int
|
||||
*/
|
||||
uint16_t pec15_calc(uint8_t len, //!< The length of the data array being passed to the function
|
||||
uint8_t *data //!< The array of data that the PEC will be generated from
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS181x CFGRA register
|
||||
This command will write the configuration registers of the ADBMS181xs connected in a daisy chain stack.
|
||||
The configuration is written in descending order so the last device's configuration is written first.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_wrcfg(uint8_t total_ic, //!< The number of ICs being written to
|
||||
cell_asic *ic //!< A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS181x CFGRB register
|
||||
This command will write the configuration registers of the ADBMS181xs connected in a daisy chain stack.
|
||||
The configuration is written in descending order so the last device's configuration is written first.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_wrcfgb(uint8_t total_ic, //!< The number of ICs being written to
|
||||
cell_asic *ic //!< A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads the ADBMS181x CFGRA register
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS181x_rdcfg(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read configuration data.
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads the ADBMS181x CFGRB register
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS181x_rdcfgb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read configuration data.
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage conversion
|
||||
Starts ADC conversions of the ADBMS181x Cpin inputs.
|
||||
The type of ADC conversion executed can be changed by setting the following parameters:
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adcv(uint8_t MD, //!< ADC conversion Mode
|
||||
uint8_t DCP, //!< Controls if Discharge is permitted during conversion
|
||||
uint8_t CH //!< Sets which Cell channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a GPIO and Vref2 Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adax( uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a Status ADC Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adstat(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHST //!< Sets which Stat channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage and GPIO 1&2 conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adcvax( uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage and SOC conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adcvsc(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads and parses the ADBMS181x cell voltage registers.
|
||||
The function is used to read the cell codes of the ADBMS181x.
|
||||
This function will send the requested read commands parse the data and store the cell voltages in the cell_asic structure.
|
||||
@return uint8_t, PEC Status.
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
uint8_t ADBMS181x_rdcv(uint8_t reg, //!< Controls which cell voltage register is read back.
|
||||
uint8_t total_ic, //!< The number of ICs in the system
|
||||
cell_asic *ic //!< Array of the parsed cell codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads and parses the ADBMS181x auxiliary registers.
|
||||
The function is used to read the parsed GPIO codes of the ADBMS181x.
|
||||
This function will send the requested read commands parse the data and store the gpio voltages in the cell_asic structure.
|
||||
@return int8_t, PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t ADBMS181x_rdaux(uint8_t reg, //!< Determines which GPIO voltage register is read back.
|
||||
uint8_t total_ic,//!< the number of ICs in the system
|
||||
cell_asic *ic//!< Array of the parsed aux codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads and parses the ADBMS181x stat registers.
|
||||
The function is used to read the parsed status codes of the ADBMS181x.
|
||||
This function will send the requested read commands parse the data and store the status voltages in the cell_asic structure
|
||||
@return int8_t, PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t ADBMS181x_rdstat(uint8_t reg, //!< Determines which Stat register is read back.
|
||||
uint8_t total_ic,//!< The number of ICs in the system
|
||||
cell_asic *ic//!< Array of the parsed stat codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads the raw cell voltage register data
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_rdcv_reg(uint8_t reg, //!< Determines which cell voltage register is read back
|
||||
uint8_t total_ic, //!< The number of ICs in the
|
||||
uint8_t *data //!< An array of the unparsed cell codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Read the raw data from the ADBMS181x auxiliary register
|
||||
The function reads a single GPIO voltage register and stores the read data in the *data point as a byte array.
|
||||
This function is rarely used outside of the ADBMS181x_rdaux() command.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_rdaux_reg( uint8_t reg, //!< Determines which GPIO voltage register is read back
|
||||
uint8_t total_ic, //!< The number of ICs in the system
|
||||
uint8_t *data //!< Array of the unparsed auxiliary codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Read the raw data from the ADBMS181x stat register
|
||||
The function reads a single Status register and stores the read data in the *data point as a byte array.
|
||||
This function is rarely used outside of the ADBMS181x_rdstat() command.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_rdstat_reg(uint8_t reg, //!< Determines which stat register is read back
|
||||
uint8_t total_ic, //!< The number of ICs in the system
|
||||
uint8_t *data //!< Array of the unparsed stat codes
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that parses voltage measurement registers
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t parse_cells(uint8_t current_ic, //!< Current IC
|
||||
uint8_t cell_reg, //!< Type of register
|
||||
uint8_t cell_data[], //!< Unparsed data
|
||||
uint16_t *cell_codes, //!< Parsed data
|
||||
uint8_t *ic_pec //!< PEC error
|
||||
);
|
||||
|
||||
/*!
|
||||
Sends the poll ADC command
|
||||
@returns uint8_t adc_state 1 byte read back after a pladc command. If the byte is not 0xFF ADC conversion has completed
|
||||
*/
|
||||
uint8_t ADBMS181x_pladc(void);
|
||||
|
||||
/*!
|
||||
This function will block operation until the ADC has finished it's conversion
|
||||
@returns uint32_t counter The approximate time it took for the ADC function to complete.
|
||||
*/
|
||||
uint32_t ADBMS181x_pollAdc(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS181x Cell voltage registers
|
||||
The command clears the cell voltage registers and initializes all values to 1.
|
||||
The register will read back hexadecimal 0xFF after the command is sent.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_clrcell(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS181x Auxiliary registers
|
||||
The command clears the Auxiliary registers and initializes all values to 1.
|
||||
The register will read back hexadecimal 0xFF after the command is sent.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_clraux(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS181x Stat registers
|
||||
The command clears the Stat registers and initializes all values to 1.
|
||||
The register will read back hexadecimal 0xFF after the command is sent.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_clrstat(void);
|
||||
|
||||
/*!
|
||||
Starts the Mux Decoder diagnostic self test
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1ms to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_diagn(void);
|
||||
|
||||
/*!
|
||||
Starts cell voltage self test conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_cvst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*!
|
||||
Start an Auxiliary Register Self Test Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_axst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a Status Register Self Test Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_statst( uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*!
|
||||
Starts cell voltage overlap conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adol(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*!
|
||||
Start an GPIO Redundancy test
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adaxd(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Start a Status register redundancy test Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adstatd(uint8_t MD, //!< ADC Mode
|
||||
uint8_t CHST //!< Sets which Status channels are converted
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs the ADC Self Tests
|
||||
@return int16_t, error Number of errors detected.
|
||||
*/
|
||||
int16_t ADBMS181x_run_cell_adc_st(uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t md, //!< ADC Mode
|
||||
bool adcopt //!< ADCOPT bit in the configuration register
|
||||
);
|
||||
|
||||
/*!
|
||||
Self Test Helper Function
|
||||
@return uint16_t test_pattern returns the register data pattern for a given ADC MD and Self test
|
||||
*/
|
||||
uint16_t ADBMS181x_st_lookup( uint8_t MD, //!< ADC Mode
|
||||
uint8_t ST, //!< Self Test
|
||||
bool adcopt //!< ADCOPT bit in the configuration register
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function that runs the ADC Overlap test
|
||||
@return uint16_t, error
|
||||
0: Pass
|
||||
-1: False, Error detected
|
||||
*/
|
||||
uint16_t ADBMS181x_run_adc_overlap(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs the ADC Digital Redundancy commands and checks output for errors
|
||||
@return int16_t, error Number of errors detected.
|
||||
*/
|
||||
int16_t ADBMS181x_run_adc_redundancy_st(uint8_t adc_mode, //!< ADC Mode
|
||||
uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Start an open wire Conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_adow(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t PUP, //!< Pull up/Pull down current
|
||||
uint8_t CH, //!< Channels
|
||||
uint8_t DCP//!< Discharge Permit
|
||||
);
|
||||
|
||||
/*!
|
||||
Start GPIOs open wire ADC conversion
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_axow(uint8_t MD, //!< ADC Mode
|
||||
uint8_t PUP //!<Pull up/Pull down current
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs the data sheet algorithm for open wire for single cell detection
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_run_openwire_single(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function that runs open wire for multiple cell and two consecutive cells detection
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_run_openwire_multi(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Runs open wire for GPIOs
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_run_gpio_openwire(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function to clear DCC bits in the CFGR Registers
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_clear_discharge(uint8_t total_ic,//!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS181x PWM register
|
||||
This command will write the pwm registers of the ADBMS181x connected in a daisy chain stack.
|
||||
The pwm is written in descending order so the last device's pwm is written first.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_wrpwm(uint8_t total_ic, //!< The number of ICs being written to
|
||||
uint8_t pwmReg, //!< The PWM Register to be written
|
||||
cell_asic *ic //!< A two dimensional array that will store the data to be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads pwm registers of a ADBMS181x daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS181x_rdpwm(uint8_t total_ic, //!< Number of ICs in the system
|
||||
uint8_t pwmReg, //!< The PWM Register to be written A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the read data
|
||||
);
|
||||
|
||||
/*!
|
||||
Write the ADBMS181x Sctrl register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_wrsctrl(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg, //!< The Sctrl Register to be written A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data to be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads sctrl registers of a ADBMS181x daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS181x_rdsctrl(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg, //!< The Sctrl Register to be written A or B
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read data
|
||||
);
|
||||
|
||||
/*!
|
||||
Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_stsctrl(void);
|
||||
|
||||
/*!
|
||||
Clears the ADBMS181x SCTRL registers
|
||||
The command clears the SCTRL registers and initializes all values to 0.
|
||||
The register will read back hexadecimal 0x00 after the command is sent.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_clrsctrl(void);
|
||||
|
||||
/*!
|
||||
Write the ADBMS181x COMM register
|
||||
This command will write the comm registers of the ADBMS181x connected in a daisy chain stack.
|
||||
The comm is written in descending order so the last device's configuration is written first.
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_wrcomm(uint8_t total_ic, //!< The number of ICs being written to
|
||||
cell_asic *ic //!< A two dimensional array that will store the data to be written
|
||||
);
|
||||
|
||||
/*!
|
||||
Reads comm registers of a ADBMS181x daisy chain
|
||||
@return int8_t, pec_error PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t ADBMS181x_rdcomm(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that the function stores the read data
|
||||
);
|
||||
|
||||
/*!
|
||||
Issues a stcomm command and clocks data out of the COMM register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_stcomm(uint8_t len //!< Length of data to be transmitted
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function that counts overall PEC errors and register/IC PEC errors
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_check_pec(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
uint8_t reg, //!< Type of register
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function that resets the PEC error counters
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_reset_crc_count(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper Function to initialize the CFGR data structures
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_init_cfg(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set appropriate bits in CFGR register based on bit function
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon, //!< The REFON bit
|
||||
bool adcopt, //!< The ADCOPT bit
|
||||
bool gpio[5],//!< The GPIO bits
|
||||
bool dcc[12],//!< The DCC bits
|
||||
bool dcto[4],//!< The Dcto bits
|
||||
uint16_t uv, //!< The UV value
|
||||
uint16_t ov //!< The OV value
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the REFON bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_refon(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon //!< The REFON bit
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the ADCOPT bit HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_adcopt(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool adcopt //!< The ADCOPT bit
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the GPIO bits HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_gpio(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool gpio[] //!< The GPIO bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to turn the DCC bits HIGH or LOW
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_dis(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool dcc[] //!< The DCC bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to control discharge time value
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_dcto(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool dcto[] //!< The Dcto bits
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set uv field in CFGRA register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_uv(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t uv //!< The UV value
|
||||
);
|
||||
|
||||
/*!
|
||||
Helper function to set ov field in CFGRA register
|
||||
@return void
|
||||
*/
|
||||
void ADBMS181x_set_cfgr_ov(uint8_t nIC, //!< Current IC
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t ov //!< The OV value
|
||||
);
|
||||
|
||||
#endif
|
||||
496
APP_R3323/App/Hardware/adc.c
Normal file
496
APP_R3323/App/Hardware/adc.c
Normal file
@@ -0,0 +1,496 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file adc.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of adc control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include <includes.h>
|
||||
#include "adc.h"
|
||||
#include "delay.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/*
|
||||
* If you remap the mapping between the channel and the pin with the function
|
||||
* ADC_ChannelRemap, define ADC_CH_REMAP as non-zero, otherwise define as 0.
|
||||
*/
|
||||
#define ADC_CH_REMAP (0u)
|
||||
|
||||
/* ADC clock selection definition. */
|
||||
#define ADC_CLK_PCLK (1u)
|
||||
#define ADC_CLK_MPLLQ (2u)
|
||||
#define ADC_CLK_UPLLR (3u)
|
||||
|
||||
/* ADC1 channel definition for this example. */
|
||||
#define ADC1_SA_NORMAL_CHANNEL (ADC1_CH0 | ADC1_CH1 | ADC1_CH2 | ADC1_CH3 | ADC1_CH4 | ADC1_CH5 | ADC1_CH6 | ADC1_CH7)
|
||||
#define ADC1_SA_CHANNEL (ADC1_SA_NORMAL_CHANNEL)
|
||||
#define ADC1_SA_CHANNEL_COUNT (8u)
|
||||
|
||||
#define ADC1_CHANNEL (ADC1_SA_CHANNEL)
|
||||
|
||||
/* ADC1 channel sampling time. ADC1_CH0 ADC1_CH1 ADC1_CH2 ADC1_CH3 ADC1_CH4 ADC1_CH5 ADC1_CH6 ADC1_CH7 */
|
||||
#define ADC1_SA_CHANNEL_SAMPLE_TIME { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
|
||||
|
||||
/* ADC2 channel definition for this example. */
|
||||
#define ADC2_SA_NORMAL_CHANNEL (ADC2_CH6 | ADC2_CH7)
|
||||
#define ADC2_SA_CHANNEL (ADC2_SA_NORMAL_CHANNEL)
|
||||
#define ADC2_SA_CHANNEL_COUNT (2u)
|
||||
|
||||
/* ADC2 channel sampling time. ADC2_CH6(AD_10), ADC2_CH7(AD_11) */
|
||||
#define ADC2_SA_CHANNEL_SAMPLE_TIME { 0x30, 0x30 }
|
||||
|
||||
#define ADC2_CHANNEL (ADC2_SA_CHANNEL)
|
||||
|
||||
/* DMA definition for ADC1. */
|
||||
#define ADC1_SA_DMA_UNIT (M4_DMA1)
|
||||
#define ADC1_SA_DMA_CH (DmaCh0)
|
||||
#define ADC1_SA_DMA_PWC (PWC_FCG0_PERIPH_DMA1)
|
||||
#define ADC1_SA_DMA_TRGSRC (EVT_ADC1_EOCA)
|
||||
#define ADC1_SA_DMA_IRQ_NUM (INT_DMA1_TC0)
|
||||
#define ADC1_SA_DMA_INT_CB (Dma1Btc0_IrqHandler)
|
||||
#define ADC1_DMA_IRQ_NVIC_NUM (Int030_IRQn)
|
||||
|
||||
/* DMA definition for ADC2. */
|
||||
#define ADC2_SA_DMA_UNIT (M4_DMA1)
|
||||
#define ADC2_SA_DMA_CH (DmaCh2)
|
||||
#define ADC2_SA_DMA_PWC (PWC_FCG0_PERIPH_DMA1)
|
||||
#define ADC2_SA_DMA_TRGSRC (EVT_ADC2_EOCA)
|
||||
#define ADC2_SA_DMA_IRQ_NUM (INT_DMA1_TC2)
|
||||
#define ADC2_SA_DMA_INT_CB (Dma1Btc2_IrqHandler)
|
||||
#define ADC2_DMA_IRQ_NVIC_NUM (Int031_IRQn)
|
||||
|
||||
#define ADC1_SA_DMA_BUFFER_MAX (1024 / ADC1_SA_CHANNEL_COUNT)
|
||||
#define ADC2_SA_DMA_BUFFER_MAX (1024 / ADC2_SA_CHANNEL_COUNT)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
// DMA Buffer
|
||||
uint16_t Adc1DmaSaBuff[ADC1_SA_DMA_BUFFER_MAX][ADC1_SA_CHANNEL_COUNT];
|
||||
uint16_t Adc2DmaSaBuff[ADC2_SA_DMA_BUFFER_MAX][ADC2_SA_CHANNEL_COUNT];
|
||||
|
||||
uint8_t m_u8Adc1DmaIrqFlag = 0u;
|
||||
uint8_t m_u8Adc2DmaIrqFlag = 0u;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void AdcConfig(void);
|
||||
void AdcInitConfig(void);
|
||||
void AdcChannelConfig(void);
|
||||
void AdcTriggerConfig(void);
|
||||
|
||||
void DmaConfig(void);
|
||||
void DmaIrqConfig(void);
|
||||
void DmaIrqRegister(stc_irq_regi_conf_t *pstcCfg, uint32_t u32Priority);
|
||||
|
||||
void AdcSetChannelPinMode(const M4_ADC_TypeDef *ADCx,
|
||||
uint32_t u32Channel,
|
||||
en_pin_mode_t enMode);
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief ADC configuration, including clock configuration, initial configuration,
|
||||
** channel configuration and trigger source configuration.
|
||||
**
|
||||
** \param None.
|
||||
**
|
||||
** \retval None.
|
||||
**
|
||||
******************************************************************************/
|
||||
void AdcConfig(void)
|
||||
{
|
||||
// stc_port_init_t stcPortInit;
|
||||
|
||||
// /* configuration structure initialization */
|
||||
// MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
// stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
// stcPortInit.enExInt = Disable;
|
||||
// stcPortInit.enPullUp = Disable;
|
||||
|
||||
// /* Test Port/Pin initialization */
|
||||
// PORT_Init(PortE, Pin00, &stcPortInit);
|
||||
|
||||
AdcInitConfig();
|
||||
AdcChannelConfig();
|
||||
AdcTriggerConfig();
|
||||
|
||||
memset(Adc1DmaSaBuff, 0xAA, sizeof(Adc1DmaSaBuff));
|
||||
memset(Adc2DmaSaBuff, 0xBB, sizeof(Adc2DmaSaBuff));
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief ADC initial configuration.
|
||||
**
|
||||
******************************************************************************/
|
||||
void AdcInitConfig(void)
|
||||
{
|
||||
stc_adc_init_t stcAdcInit;
|
||||
|
||||
MEM_ZERO_STRUCT(stcAdcInit);
|
||||
|
||||
stcAdcInit.enResolution = AdcResolution_12Bit;
|
||||
stcAdcInit.enDataAlign = AdcDataAlign_Right;
|
||||
stcAdcInit.enAutoClear = AdcClren_Enable;
|
||||
stcAdcInit.enScanMode = AdcMode_SAContinuous;
|
||||
stcAdcInit.enRschsel = AdcRschsel_Restart;
|
||||
/* 1. Enable ADC1. */
|
||||
PWC_Fcg3PeriphClockCmd(PWC_FCG3_PERIPH_ADC1, Enable);
|
||||
/* 2. Initialize ADC1. */
|
||||
ADC_Init(M4_ADC1, &stcAdcInit);
|
||||
|
||||
/* 1. Enable ADC2. */
|
||||
PWC_Fcg3PeriphClockCmd(PWC_FCG3_PERIPH_ADC2, Enable);
|
||||
/* 2. Initialize ADC2. */
|
||||
ADC_Init(M4_ADC2, &stcAdcInit);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief ADC channel configuration.
|
||||
**
|
||||
******************************************************************************/
|
||||
void AdcChannelConfig(void)
|
||||
{
|
||||
uint8_t au8Adc1SaSampTime[ADC1_SA_CHANNEL_COUNT] = ADC1_SA_CHANNEL_SAMPLE_TIME;
|
||||
uint8_t au8Adc2SaSampTime[ADC2_SA_CHANNEL_COUNT] = ADC2_SA_CHANNEL_SAMPLE_TIME;
|
||||
stc_adc_ch_cfg_t stcChCfg;
|
||||
|
||||
MEM_ZERO_STRUCT(stcChCfg);
|
||||
|
||||
/**************************** Add ADC1 channels ****************************/
|
||||
/* 1. Set the ADC pin to analog mode. */
|
||||
AdcSetChannelPinMode(M4_ADC1, ADC1_CHANNEL, Pin_Mode_Ana);
|
||||
|
||||
stcChCfg.u32Channel = ADC1_SA_CHANNEL;
|
||||
stcChCfg.u8Sequence = ADC_SEQ_A;
|
||||
stcChCfg.pu8SampTime = au8Adc1SaSampTime;
|
||||
/* 2. Add ADC channel. */
|
||||
ADC_AddAdcChannel(M4_ADC1, &stcChCfg);
|
||||
|
||||
/**************************** Add ADC2 channels ****************************/
|
||||
/* 1. Set the ADC pin to analog mode. */
|
||||
AdcSetChannelPinMode(M4_ADC2, ADC2_CHANNEL, Pin_Mode_Ana);
|
||||
|
||||
stcChCfg.u32Channel = ADC2_SA_CHANNEL;
|
||||
stcChCfg.u8Sequence = ADC_SEQ_A;
|
||||
stcChCfg.pu8SampTime = au8Adc2SaSampTime;
|
||||
/* 2. Add ADC channel. */
|
||||
ADC_AddAdcChannel(M4_ADC2, &stcChCfg);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief ADC trigger source configuration.
|
||||
**
|
||||
******************************************************************************/
|
||||
void AdcTriggerConfig(void)
|
||||
{
|
||||
stc_adc_trg_cfg_t stcTrgCfg;
|
||||
|
||||
MEM_ZERO_STRUCT(stcTrgCfg);
|
||||
/*
|
||||
* If select an event(@ref en_event_src_t) to trigger ADC,
|
||||
* AOS must be enabled first.
|
||||
*/
|
||||
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS, Enable);
|
||||
|
||||
/* Trigger ADC1 sequence A. */
|
||||
stcTrgCfg.u8Sequence = ADC_SEQ_A;
|
||||
stcTrgCfg.enTrgSel = AdcTrgsel_TRGX0;
|
||||
stcTrgCfg.enInTrg0 = EVT_ADC1_EOCA;
|
||||
ADC_ConfigTriggerSrc(M4_ADC1, &stcTrgCfg);
|
||||
// ADC_TriggerSrcCmd(M4_ADC1, ADC_SEQ_A, Enable);
|
||||
/* ADC1 sequence A will be started by software. */
|
||||
ADC_TriggerSrcCmd(M4_ADC1, ADC_SEQ_A, Disable);
|
||||
|
||||
/* Trigger ADC2 sequence A. */
|
||||
stcTrgCfg.u8Sequence = ADC_SEQ_A;
|
||||
stcTrgCfg.enTrgSel = AdcTrgsel_TRGX0;
|
||||
stcTrgCfg.enInTrg0 = EVT_ADC2_EOCA;
|
||||
ADC_ConfigTriggerSrc(M4_ADC2, &stcTrgCfg);
|
||||
/* ADC2 sequence A will be started by software. */
|
||||
ADC_TriggerSrcCmd(M4_ADC2, ADC_SEQ_A, Disable);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief DMA configuration for ADC1 and ADC2, including initial configuration
|
||||
** and interrupt configuration.
|
||||
**
|
||||
******************************************************************************/
|
||||
void DmaConfig(void)
|
||||
{
|
||||
DmaInitConfig();
|
||||
DmaIrqConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief DMA initial configuration.
|
||||
**
|
||||
******************************************************************************/
|
||||
void DmaInitConfig(void)
|
||||
{
|
||||
stc_dma_config_t stcDmaCfg;
|
||||
|
||||
MEM_ZERO_STRUCT(stcDmaCfg);
|
||||
|
||||
stcDmaCfg.u16BlockSize = ADC1_SA_CHANNEL_COUNT;
|
||||
stcDmaCfg.u16TransferCnt = ADC1_SA_DMA_BUFFER_MAX * ADC1_SA_CHANNEL_COUNT;
|
||||
stcDmaCfg.u32SrcAddr = (uint32_t)(&M4_ADC1->DR0);
|
||||
stcDmaCfg.u32DesAddr = (uint32_t)(&Adc1DmaSaBuff[0][0]);
|
||||
stcDmaCfg.u16DesRptSize = ADC1_SA_DMA_BUFFER_MAX * ADC1_SA_CHANNEL_COUNT;
|
||||
stcDmaCfg.u16SrcRptSize = ADC1_SA_CHANNEL_COUNT;
|
||||
stcDmaCfg.u32DmaLlp = 0u;
|
||||
stcDmaCfg.stcSrcNseqCfg.u16Cnt = 0u;
|
||||
stcDmaCfg.stcSrcNseqCfg.u32Offset = 0u;
|
||||
stcDmaCfg.stcDesNseqCfg.u16Cnt = 0u;
|
||||
stcDmaCfg.stcDesNseqCfg.u32Offset = 0u;
|
||||
stcDmaCfg.stcDmaChCfg.enSrcInc = AddressIncrease;
|
||||
stcDmaCfg.stcDmaChCfg.enDesInc = AddressIncrease;
|
||||
stcDmaCfg.stcDmaChCfg.enSrcRptEn = Enable;
|
||||
stcDmaCfg.stcDmaChCfg.enDesRptEn = Enable;
|
||||
stcDmaCfg.stcDmaChCfg.enSrcNseqEn = Disable;
|
||||
stcDmaCfg.stcDmaChCfg.enDesNseqEn = Disable;
|
||||
stcDmaCfg.stcDmaChCfg.enTrnWidth = Dma16Bit;
|
||||
stcDmaCfg.stcDmaChCfg.enLlpEn = Disable;
|
||||
/* Enable DMA interrupt. */
|
||||
stcDmaCfg.stcDmaChCfg.enIntEn = Enable;
|
||||
|
||||
PWC_Fcg0PeriphClockCmd(ADC1_SA_DMA_PWC, Enable);
|
||||
DMA_InitChannel(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, &stcDmaCfg);
|
||||
DMA_Cmd(ADC1_SA_DMA_UNIT, Enable);
|
||||
DMA_ChannelCmd(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, Enable);
|
||||
DMA_ClearIrqFlag(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, TrnCpltIrq);
|
||||
/* AOS must be enabled to use DMA */
|
||||
/* AOS enabled at first. */
|
||||
/* If you have enabled AOS before, then the following statement is not needed. */
|
||||
PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_AOS, Enable);
|
||||
DMA_SetTriggerSrc(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, ADC1_SA_DMA_TRGSRC);
|
||||
|
||||
// DMA ADC2 SA
|
||||
stcDmaCfg.u16BlockSize = ADC2_SA_CHANNEL_COUNT;
|
||||
stcDmaCfg.u16TransferCnt = ADC2_SA_DMA_BUFFER_MAX * ADC2_SA_CHANNEL_COUNT; //
|
||||
stcDmaCfg.u32SrcAddr = (uint32_t)(&M4_ADC2->DR6);
|
||||
stcDmaCfg.u32DesAddr = (uint32_t)(&Adc2DmaSaBuff[0][0]);
|
||||
stcDmaCfg.u16DesRptSize = ADC2_SA_DMA_BUFFER_MAX * ADC2_SA_CHANNEL_COUNT;
|
||||
stcDmaCfg.u16SrcRptSize = ADC2_SA_CHANNEL_COUNT;
|
||||
PWC_Fcg0PeriphClockCmd(ADC2_SA_DMA_PWC, Enable);
|
||||
DMA_InitChannel(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, &stcDmaCfg);
|
||||
DMA_Cmd(ADC2_SA_DMA_UNIT, Enable);
|
||||
DMA_ChannelCmd(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, Enable);
|
||||
DMA_ClearIrqFlag(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, TrnCpltIrq);
|
||||
DMA_SetTriggerSrc(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, ADC2_SA_DMA_TRGSRC);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief DMA initial configuration.
|
||||
**
|
||||
******************************************************************************/
|
||||
void DmaReloadConfig(uint8_t nAdc)
|
||||
{
|
||||
if (nAdc == 0) {
|
||||
DMA_SetBlockSize(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, ADC1_SA_CHANNEL_COUNT);
|
||||
DMA_SetTransferCnt(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, ADC1_SA_DMA_BUFFER_MAX * ADC1_SA_CHANNEL_COUNT);
|
||||
|
||||
DMA_Cmd(ADC1_SA_DMA_UNIT, Enable);
|
||||
DMA_ChannelCmd(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, Enable);
|
||||
} else {
|
||||
DMA_SetBlockSize(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, ADC2_SA_CHANNEL_COUNT);
|
||||
DMA_SetTransferCnt(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, ADC2_SA_DMA_BUFFER_MAX * ADC2_SA_CHANNEL_COUNT);
|
||||
|
||||
DMA_Cmd(ADC2_SA_DMA_UNIT, Enable);
|
||||
DMA_ChannelCmd(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, Enable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief DMA interrupt configuration.
|
||||
**
|
||||
** \note DMA NVIC number: [Int030_IRQn, Int031_IRQn]
|
||||
**
|
||||
******************************************************************************/
|
||||
void DmaIrqConfig(void)
|
||||
{
|
||||
stc_irq_regi_conf_t stcAdcIrqCfg;
|
||||
|
||||
stcAdcIrqCfg.enIntSrc = ADC1_SA_DMA_IRQ_NUM;
|
||||
stcAdcIrqCfg.enIRQn = ADC1_DMA_IRQ_NVIC_NUM;
|
||||
stcAdcIrqCfg.pfnCallback = &ADC1_SA_DMA_INT_CB;
|
||||
DmaIrqRegister(&stcAdcIrqCfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
|
||||
stcAdcIrqCfg.enIntSrc = ADC2_SA_DMA_IRQ_NUM;
|
||||
stcAdcIrqCfg.enIRQn = ADC2_DMA_IRQ_NVIC_NUM;
|
||||
stcAdcIrqCfg.pfnCallback = &ADC2_SA_DMA_INT_CB;
|
||||
DmaIrqRegister(&stcAdcIrqCfg, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief DMA IRQ register function.
|
||||
**
|
||||
******************************************************************************/
|
||||
void DmaIrqRegister(stc_irq_regi_conf_t *pstcCfg, uint32_t u32Priority)
|
||||
{
|
||||
int16_t s16Vnum = pstcCfg->enIRQn;
|
||||
|
||||
if ((s16Vnum == ADC1_DMA_IRQ_NVIC_NUM) || (s16Vnum == ADC2_DMA_IRQ_NVIC_NUM)) {
|
||||
if (Ok != enIrqRegistration(pstcCfg)) return;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
NVIC_ClearPendingIRQ(pstcCfg->enIRQn);
|
||||
NVIC_SetPriority(pstcCfg->enIRQn, u32Priority);
|
||||
NVIC_EnableIRQ(pstcCfg->enIRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief Config the pin which is mapping the channel to analog or digit mode.
|
||||
**
|
||||
******************************************************************************/
|
||||
void AdcSetChannelPinMode(const M4_ADC_TypeDef *ADCx,
|
||||
uint32_t u32Channel,
|
||||
en_pin_mode_t enMode)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
stcPortInit.enPinMode = enMode;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
if (M4_ADC1 == ADCx) {
|
||||
PORT_Init(PortA, Pin00, &stcPortInit);
|
||||
PORT_Init(PortA, Pin01, &stcPortInit);
|
||||
PORT_Init(PortA, Pin02, &stcPortInit);
|
||||
PORT_Init(PortA, Pin03, &stcPortInit);
|
||||
PORT_Init(PortA, Pin04, &stcPortInit);
|
||||
PORT_Init(PortA, Pin05, &stcPortInit);
|
||||
PORT_Init(PortA, Pin06, &stcPortInit);
|
||||
PORT_Init(PortA, Pin07, &stcPortInit);
|
||||
} else if (M4_ADC2 == ADCx) {
|
||||
PORT_Init(PortC, Pin00, &stcPortInit);
|
||||
PORT_Init(PortC, Pin01, &stcPortInit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief DMA IRQ callbacks.
|
||||
**
|
||||
******************************************************************************/
|
||||
void Dma1Btc0_IrqHandler(void)
|
||||
{
|
||||
DMA_ClearIrqFlag(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, BlkTrnCpltIrq);
|
||||
DMA_ClearIrqFlag(ADC1_SA_DMA_UNIT, ADC1_SA_DMA_CH, TrnCpltIrq);
|
||||
|
||||
m_u8Adc1DmaIrqFlag = true;
|
||||
|
||||
// PORT_ResetBits(PortE, Pin00);
|
||||
|
||||
NVIC_ClearPendingIRQ(ADC1_DMA_IRQ_NVIC_NUM);
|
||||
}
|
||||
|
||||
void Dma1Btc2_IrqHandler(void)
|
||||
{
|
||||
DMA_ClearIrqFlag(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, BlkTrnCpltIrq);
|
||||
DMA_ClearIrqFlag(ADC2_SA_DMA_UNIT, ADC2_SA_DMA_CH, TrnCpltIrq);
|
||||
|
||||
m_u8Adc2DmaIrqFlag = true;
|
||||
|
||||
// PORT_ResetBits(PortE, Pin00);
|
||||
|
||||
NVIC_ClearPendingIRQ(ADC2_DMA_IRQ_NVIC_NUM);
|
||||
}
|
||||
|
||||
uint8_t GetAdcIrgFlag(uint8_t nAdc)
|
||||
{
|
||||
uint8_t result = false;
|
||||
|
||||
if (nAdc == 0) {
|
||||
result = m_u8Adc1DmaIrqFlag;
|
||||
m_u8Adc1DmaIrqFlag = false;
|
||||
} else {
|
||||
result = m_u8Adc2DmaIrqFlag;
|
||||
m_u8Adc2DmaIrqFlag = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t AvgAdc1DmaValue(uint16_t ch)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
|
||||
for (int i = 0; i < ADC1_SA_DMA_BUFFER_MAX; i++)
|
||||
sum += Adc1DmaSaBuff[i][ch];
|
||||
|
||||
return (uint16_t)(sum / ADC1_SA_DMA_BUFFER_MAX);
|
||||
}
|
||||
|
||||
//VI(Voltage and Current) port Initialize
|
||||
void ADC_Port_Init(void)
|
||||
{
|
||||
/* Config ADCs. */
|
||||
AdcConfig();
|
||||
|
||||
/* Config DMA. */
|
||||
DmaConfig();
|
||||
}
|
||||
|
||||
uint16_t AvgAdc2DmaValue(uint16_t ch)
|
||||
{
|
||||
__IO uint32_t sum = 0;
|
||||
|
||||
for (int i = 0; i < ADC2_SA_DMA_BUFFER_MAX; i++) {
|
||||
sum += Adc2DmaSaBuff[i][ch];
|
||||
}
|
||||
return (uint32_t)(sum / ADC2_SA_DMA_BUFFER_MAX);
|
||||
}
|
||||
|
||||
uint32_t CheckAdc2DmaValue(uint16_t ch)
|
||||
{
|
||||
__IO uint32_t sum = 0;
|
||||
|
||||
for (int i = 0; i < ADC2_SA_DMA_BUFFER_MAX; i++) {
|
||||
if (sum < Adc2DmaSaBuff[i][ch])
|
||||
sum = Adc2DmaSaBuff[i][ch];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
#ifdef CONSOLE_DEBUG
|
||||
void DisplayAdc2DmaBufferValue(uint8_t ch)
|
||||
{
|
||||
for (int i = 0; i < ADC2_SA_DMA_BUFFER_MAX; i++) {
|
||||
printf("(%3d), %04X\r\n", i, Adc2DmaSaBuff[i][ch]);
|
||||
|
||||
delay_os_ms(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
58
APP_R3323/App/Hardware/adc.h
Normal file
58
APP_R3323/App/Hardware/adc.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file adc.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of adc control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _ADC_H
|
||||
#define _ADC_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
#define ADC_VBASE 3300 // 3.3V
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void DmaInitConfig(void);
|
||||
void DmaReloadConfig(uint8_t nAdc);
|
||||
|
||||
void ADC_Port_Init(void);
|
||||
|
||||
uint8_t GetAdcIrgFlag(uint8_t nAdc);
|
||||
|
||||
/****** ADC1 for Temperature **************************************************/
|
||||
uint16_t AvgAdc1DmaValue(uint16_t ch);
|
||||
uint16_t GetAdc1DmaBufferValue(uint16_t ch, uint16_t no);
|
||||
void DisplayAdc1DmaBufferValue(void);
|
||||
|
||||
/****** ADC2 for VI ***********************************************************/
|
||||
uint16_t AvgAdc2DmaValue(uint16_t ch);
|
||||
uint16_t GetAdc2DmaBufferValue(uint16_t ch, uint16_t no);
|
||||
void DisplayAdc2DmaBufferValue(uint8_t ch);
|
||||
|
||||
uint32_t CheckAdc2DmaValue(uint16_t ch);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
62
APP_R3323/App/Hardware/buck.c
Normal file
62
APP_R3323/App/Hardware/buck.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file buck.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of buck control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "buck.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Buck on/off Port/Pin definition */
|
||||
#define BUCK_ONOFF_PORT (PortA)
|
||||
#define BUCK_ONOFF_PIN (Pin11)
|
||||
|
||||
// Relay port definitions
|
||||
#define BUCK_ON PORT_ResetBits(BUCK_ONOFF_PORT, BUCK_ONOFF_PIN);
|
||||
#define BUCK_OFF PORT_SetBits(BUCK_ONOFF_PORT, BUCK_ONOFF_PIN);
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
// Relay IO Initialize
|
||||
void Buck_ctrl_Init(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enPinOType = Pin_OType_Od;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* Relay Control Port/Pin initialization */
|
||||
PORT_Init(BUCK_ONOFF_PORT, BUCK_ONOFF_PIN, &stcPortInit);
|
||||
|
||||
BUCK_ON;
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
39
APP_R3323/App/Hardware/buck.h
Normal file
39
APP_R3323/App/Hardware/buck.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file buck.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of buck control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _BUCK_H
|
||||
#define _BUCK_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void Buck_ctrl_Init(void); // Initialize
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
65
APP_R3323/App/Hardware/buzzer.c
Normal file
65
APP_R3323/App/Hardware/buzzer.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file buzzer.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of buzzer control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "buzzer.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Define port and pin for device address */
|
||||
#define BUZZER_PORT (PortE)
|
||||
#define BUZZER_PIN (Pin02)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
//Relay IO Initialize
|
||||
void Buzzer_Init(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* LED Port/Pin initialization */
|
||||
PORT_Init(BUZZER_PORT, BUZZER_PIN, &stcPortInit);
|
||||
|
||||
PORT_ResetBits(BUZZER_PORT, BUZZER_PIN);
|
||||
}
|
||||
|
||||
void Buzzer(uint8_t onoff)
|
||||
{
|
||||
if (onoff) PORT_SetBits(BUZZER_PORT, BUZZER_PIN);
|
||||
else PORT_ResetBits(BUZZER_PORT, BUZZER_PIN);
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
43
APP_R3323/App/Hardware/buzzer.h
Normal file
43
APP_R3323/App/Hardware/buzzer.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file buzzer.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of buzzer control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _BUZZER_H
|
||||
#define _BUZZER_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void Buzzer_Init(void); //Initialize
|
||||
void Buzzer(uint8_t onoff);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
239
APP_R3323/App/Hardware/can.c
Normal file
239
APP_R3323/App/Hardware/can.c
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file can.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of CAN communication functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "can.h"
|
||||
#include "string.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* CAN channel definition */
|
||||
/* CAN baudrate definition */
|
||||
#define CAN_BAUDRATE (250000ul)
|
||||
|
||||
/* CAN RX Port/Pin definition */
|
||||
#define CAN_RX_PORT (PortE)
|
||||
#define CAN_RX_PIN (Pin01)
|
||||
#define CAN_RX_FUNC (Func_Can1_Rx)
|
||||
|
||||
/* CAN TX Port/Pin definition */
|
||||
#define CAN_TX_PORT (PortE)
|
||||
#define CAN_TX_PIN (Pin00)
|
||||
#define CAN_TX_FUNC (Func_Can1_Tx)
|
||||
|
||||
#define TX_BUFFER_SIZE 10
|
||||
#define RX_BUFFER_SIZE 320
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
volatile uint16_t RxInPos, RxOutPos;
|
||||
volatile uint32_t RxOverflowCount;
|
||||
uint16_t TxInPos, TxOutPos;
|
||||
stc_can_rxframe_t RxBuf[RX_BUFFER_SIZE];
|
||||
stc_can_txframe_t TxBuf[TX_BUFFER_SIZE];
|
||||
} CAN_Info;
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
CAN_Info Can;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void CAN_RxIrqCallBack(void);
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
// Initializes CAN Port
|
||||
void can_init(uint32_t CAN_Baud_Rate)
|
||||
{
|
||||
stc_can_init_config_t stcCanInitCfg;
|
||||
stc_can_filter_t stcFilter;
|
||||
stc_irq_regi_conf_t stcIrqRegiConf;
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
MEM_ZERO_STRUCT(stcCanInitCfg);
|
||||
MEM_ZERO_STRUCT(stcFilter);
|
||||
MEM_ZERO_STRUCT(stcIrqRegiConf);
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
MEM_ZERO_STRUCT(Can);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Enable;
|
||||
|
||||
/* SPI Port/Pin initialization */
|
||||
PORT_Init(CAN_TX_PORT, CAN_TX_PIN, &stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
|
||||
PORT_Init(CAN_RX_PORT, CAN_RX_PIN, &stcPortInit);
|
||||
|
||||
// PORT_Init(PortB, Pin03, &stcPortInit);
|
||||
PORT_Init(PortB, Pin04, &stcPortInit);
|
||||
|
||||
//<<Enable can peripheral clock and buffer(ram)
|
||||
PWC_RamOpMdConfig(HighSpeedMd);
|
||||
PWC_RamPwrdownCmd(PWC_RAMPWRDOWN_CAN, Enable);
|
||||
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable);
|
||||
|
||||
//<<CAN GPIO config
|
||||
PORT_SetFunc(CAN_RX_PORT, CAN_RX_PIN, CAN_RX_FUNC, Disable);
|
||||
PORT_SetFunc(CAN_TX_PORT, CAN_TX_PIN, CAN_TX_FUNC, Disable);
|
||||
|
||||
//<<Can bit time config
|
||||
// stcCanInitCfg.stcCanBt.PRESC = 4u-1u;//???,??????????
|
||||
switch(CAN_Baud_Rate) {
|
||||
case 1000: // 1000K
|
||||
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
|
||||
break;
|
||||
case 500: // 500K
|
||||
stcCanInitCfg.stcCanBt.PRESC = 4u-1u;
|
||||
break;
|
||||
case 250: // 125K
|
||||
stcCanInitCfg.stcCanBt.PRESC = 8u-1u;
|
||||
break;
|
||||
case 125: // 100K
|
||||
stcCanInitCfg.stcCanBt.PRESC = 16u-1u;
|
||||
break;
|
||||
default:
|
||||
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
|
||||
break;
|
||||
}
|
||||
|
||||
// stcCanInitCfg.stcCanBt.PRESC = 1u-1u;
|
||||
stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u;
|
||||
stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u;
|
||||
stcCanInitCfg.stcCanBt.SJW = 3u-1u;
|
||||
|
||||
stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
|
||||
stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;
|
||||
|
||||
stcCanInitCfg.enCanRxBufAll = CanRxNormal;
|
||||
stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
|
||||
stcCanInitCfg.enCanSAck = CanSelfAckDisable; //CanSelfAckEnable;
|
||||
stcCanInitCfg.enCanSTBMode = CanSTBFifoMode;
|
||||
|
||||
CAN_Init(&stcCanInitCfg);
|
||||
|
||||
//<<Can filter config
|
||||
stcFilter.enAcfFormat = CanAllFrames;
|
||||
stcFilter.enFilterSel = CanFilterSel1;
|
||||
stcFilter.u32CODE = 0x00000000u;
|
||||
stcFilter.u32MASK = 0x1FFFFFFFu;
|
||||
CAN_FilterConfig(&stcFilter, Enable);
|
||||
|
||||
//<<Can Irq Enable
|
||||
CAN_IrqCmd(CanRxIrqEn, Enable);
|
||||
CAN_IrqCmd(CanTxPrimaryIrqEn, Enable);
|
||||
|
||||
stcIrqRegiConf.enIRQn = Int005_IRQn;
|
||||
stcIrqRegiConf.enIntSrc = INT_CAN_INT;
|
||||
stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack;
|
||||
enIrqRegistration(&stcIrqRegiConf);
|
||||
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
|
||||
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
|
||||
}
|
||||
|
||||
void CAN_RxIrqCallBack(void)
|
||||
{
|
||||
if (true == CAN_IrqFlgGet(CanRxIrqFlg)) {
|
||||
CAN_IrqFlgClr(CanRxIrqFlg);
|
||||
|
||||
stc_can_rxframe_t received;
|
||||
uint16_t next = (uint16_t)((Can.RxInPos + 1U) % RX_BUFFER_SIZE);
|
||||
/* Always drain the hardware receive slot, even when the software queue is full. */
|
||||
CAN_Receive(&received);
|
||||
if (next == Can.RxOutPos) {
|
||||
Can.RxOverflowCount++;
|
||||
} else {
|
||||
memcpy(&Can.RxBuf[Can.RxInPos], &received, sizeof(received));
|
||||
__DMB();
|
||||
Can.RxInPos = next;
|
||||
}
|
||||
|
||||
// CAN_IrqCmd(CanRxIrqEn, Disable);
|
||||
}
|
||||
if (true == CAN_IrqFlgGet(CanTxPrimaryIrqFlg)) {
|
||||
CAN_IrqFlgClr(CanTxPrimaryIrqFlg);
|
||||
// CAN_IrqCmd(CanRxIrqEn, Enable);
|
||||
}
|
||||
if (true == CAN_IrqFlgGet(CanBusErrorIrqFlg)) {
|
||||
CAN_IrqFlgClr(CanBusErrorIrqFlg);
|
||||
}
|
||||
if (true == CAN_IrqFlgGet(CanArbiLostIrqFlg)) {
|
||||
CAN_IrqFlgClr(CanArbiLostIrqFlg);
|
||||
}
|
||||
NVIC_ClearPendingIRQ(Int005_IRQn);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : uint8_t CAN_GetPacket(CanRxMsg *packet)
|
||||
* Description : Send 1 packet data to CAN Port transmit buffer
|
||||
* Parameters : none
|
||||
* Return : Transmission result (0: buffer empty, 1: buffer has data)
|
||||
*******************************************************************************/
|
||||
uint8_t CAN_GetPacket(stc_can_rxframe_t *packet)
|
||||
{
|
||||
if (Can.RxInPos != Can.RxOutPos) {
|
||||
memcpy(packet, &Can.RxBuf[Can.RxOutPos], sizeof(stc_can_rxframe_t));
|
||||
__DMB();
|
||||
Can.RxOutPos = (uint16_t)((Can.RxOutPos + 1U) % RX_BUFFER_SIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CAN_SendPacket(stc_can_txframe_t *packet)
|
||||
{
|
||||
uint32_t timeout = 50000;
|
||||
while ((M4_CAN->TCMD_f.TPE != 0) && (--timeout > 0)) {
|
||||
__NOP();
|
||||
}
|
||||
if (timeout == 0) {
|
||||
M4_CAN->TCMD |= CanPTBTxAbortCmd;
|
||||
}
|
||||
|
||||
CAN_SetFrame(packet);
|
||||
en_can_tx_buf_status_t txSts = CAN_TransmitCmd(CanPTBTxCmd);
|
||||
switch (txSts) {
|
||||
case CanTxBufEmpty: // = 0, ///< TTEN=0 or TTTBM=0: STB is empty
|
||||
// printf("CanTxBufEmpty \r\n");
|
||||
break; ///< TTEN=1 and TTTBM=1: PTB and STB are empty
|
||||
case CanTxBufnotHalfFull: // = 1, ///< TTEN=0 or TTTBM=0: STB is less than or equal to half full
|
||||
// printf("CanTxBufnotHalfFull \r\n");
|
||||
break; ///< TTEN=1 and TTTBM=1: PTB and STB are not empty and not full
|
||||
case CanTxBufHalfFull: // = 2, ///< TTEN=0 or TTTBM=0: STB is more than half full
|
||||
// printf("CanTxBufHalfFull \r\n");
|
||||
break; ///< TTEN=1 and TTTBM=1: None
|
||||
case CanTxBufFull: // = 3, ///< TTEN=0 or TTTBM=0: STB is full
|
||||
// printf("CanTxBufFull \r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// CAN_IrqCmd(CanRxIrqEn, Enable);
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
39
APP_R3323/App/Hardware/can.h
Normal file
39
APP_R3323/App/Hardware/can.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file can.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the CAN communication functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __CAN_H
|
||||
#define __CAN_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void can_init(uint32_t CAN_Baud_Rate);
|
||||
uint8_t CAN_GetPacket(stc_can_rxframe_t *packet);
|
||||
void CAN_SendPacket(stc_can_txframe_t *packet);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
126
APP_R3323/App/Hardware/delay.c
Normal file
126
APP_R3323/App/Hardware/delay.c
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file delay.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the code of the delay functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "delay.h"
|
||||
#include "includes.h" //ucos use
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define SYS_CLOCK 200
|
||||
#define SYSTICK_LOAD 200000
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private prototype functions -----------------------------------------------*/
|
||||
|
||||
// OS is called the delay function delay
|
||||
// ticks:Delay number of beats
|
||||
void delay_ostimedly(uint32_t ticks)
|
||||
{
|
||||
#ifdef CPU_CFG_CRITICAL_METHOD
|
||||
OS_ERR err;
|
||||
OSTimeDly(ticks,OS_OPT_TIME_PERIODIC, &err);//UCOSIII delay adoption cycle mode
|
||||
#else
|
||||
OSTimeDly(ticks); //UCOSII delay
|
||||
#endif
|
||||
}
|
||||
|
||||
void delay_us1(uint32_t us)
|
||||
{
|
||||
uint32_t udelay = us * 10;
|
||||
|
||||
for (int i = 0; i < udelay; i++)
|
||||
{
|
||||
i = i;
|
||||
}
|
||||
}
|
||||
|
||||
void delay_us(uint32_t us)
|
||||
{
|
||||
uint32_t usec = us * SYS_CLOCK;
|
||||
uint32_t temp = CPU_REG_NVIC_ST_CURRENT;
|
||||
uint32_t comp = temp + usec;
|
||||
|
||||
if (temp < usec)
|
||||
{
|
||||
comp = SYSTICK_LOAD - (usec - temp); // 200 - 100 = 100, 200000 - 100 = 199900, 200000 + 100
|
||||
while ((comp < temp) || (temp < usec))
|
||||
{
|
||||
temp = CPU_REG_NVIC_ST_CURRENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
comp = temp - usec;
|
||||
while (comp < temp)
|
||||
{
|
||||
temp = CPU_REG_NVIC_ST_CURRENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delay_ns1(uint32_t ns)
|
||||
{
|
||||
uint32_t nsec = ns / 1;
|
||||
uint32_t temp = CPU_REG_NVIC_ST_CURRENT;
|
||||
uint32_t comp = temp + nsec;
|
||||
|
||||
if (temp < nsec)
|
||||
{
|
||||
comp = SYSTICK_LOAD - (nsec - temp); // 200 - 100 = 100, 200000 - 100 = 199900, 200000 + 100
|
||||
while ((comp < temp) || (temp < nsec))
|
||||
{
|
||||
temp = CPU_REG_NVIC_ST_CURRENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
comp = temp - nsec;
|
||||
while (comp < temp)
|
||||
{
|
||||
temp = CPU_REG_NVIC_ST_CURRENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void delay_ns(uint32_t ns)
|
||||
{
|
||||
for (uint32_t i = 0; i < ns; i++)
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
}
|
||||
|
||||
void delay_os_ms(uint32_t ms)
|
||||
{
|
||||
OS_ERR err;
|
||||
|
||||
OSTimeDlyHMSM(0, 0, (ms / 1000), (ms % 1000),
|
||||
OS_OPT_TIME_HMSM_STRICT,
|
||||
&err);
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
71
APP_R3323/App/Hardware/delay.h
Normal file
71
APP_R3323/App/Hardware/delay.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file delay.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the delay functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __DELAY_H
|
||||
#define __DELAY_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void delay_init(uint32_t SYSCLK);
|
||||
void delay_ms(uint32_t nms);
|
||||
void delay_us(uint32_t us);
|
||||
void delay_ns(uint32_t ns);
|
||||
|
||||
void delay_os_ms(uint32_t ms);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
86
APP_R3323/App/Hardware/dev_addr.c
Normal file
86
APP_R3323/App/Hardware/dev_addr.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dev_addr.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of device address functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "dev_addr.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Define port and pin for device address */
|
||||
#define DEV_ADDR_0_PORT (PortB)
|
||||
#define DEV_ADDR_0_PIN (Pin10)
|
||||
|
||||
#define DEV_ADDR_1_PORT (PortE)
|
||||
#define DEV_ADDR_1_PIN (Pin15)
|
||||
|
||||
#define DEV_ADDR_2_PORT (PortE)
|
||||
#define DEV_ADDR_2_PIN (Pin14)
|
||||
|
||||
#define DEV_ADDR_3_PORT (PortE)
|
||||
#define DEV_ADDR_3_PIN (Pin13)
|
||||
|
||||
//#define DEV_ADDR_4_PORT (PortE)
|
||||
//#define DEV_ADDR_4_PIN (Pin01)
|
||||
|
||||
//#define DEV_ADDR_5_PORT (PortE)
|
||||
//#define DEV_ADDR_5_PIN (Pin01)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
//Relay IO Initialize
|
||||
void DevAddrInit(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Enable;
|
||||
|
||||
/* LED Port/Pin initialization */
|
||||
PORT_Init(DEV_ADDR_0_PORT, DEV_ADDR_0_PIN, &stcPortInit);
|
||||
PORT_Init(DEV_ADDR_1_PORT, DEV_ADDR_1_PIN, &stcPortInit);
|
||||
PORT_Init(DEV_ADDR_2_PORT, DEV_ADDR_2_PIN, &stcPortInit);
|
||||
PORT_Init(DEV_ADDR_3_PORT, DEV_ADDR_3_PIN, &stcPortInit);
|
||||
}
|
||||
|
||||
uint8_t GetDevAddr(void)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
result |= (!PORT_GetBit(DEV_ADDR_0_PORT, DEV_ADDR_0_PIN) << 3);
|
||||
result |= (!PORT_GetBit(DEV_ADDR_1_PORT, DEV_ADDR_1_PIN) << 2);
|
||||
result |= (!PORT_GetBit(DEV_ADDR_2_PORT, DEV_ADDR_2_PIN) << 1);
|
||||
result |= (!PORT_GetBit(DEV_ADDR_3_PORT, DEV_ADDR_3_PIN) << 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
47
APP_R3323/App/Hardware/dev_addr.h
Normal file
47
APP_R3323/App/Hardware/dev_addr.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file dev_addr.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of device address functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _DEV_ADDR_H
|
||||
#define _DEV_ADDR_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
//Relay port definitions
|
||||
|
||||
void DevAddrInit(void); // Initialize
|
||||
void DevAddrDeInit(void); // DeInitialize
|
||||
|
||||
uint8_t GetDevAddr(void);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
253
APP_R3323/App/Hardware/flash_if.c
Normal file
253
APP_R3323/App/Hardware/flash_if.c
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file flash_if.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the flash memory functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "flash_if.h"
|
||||
#include "stdio.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
FW_INFO fwinfo;
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Unlocks Flash for write access
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void FLASH_If_Init(void)
|
||||
{
|
||||
/* Unlock EFM. */
|
||||
EFM_Unlock();
|
||||
|
||||
/* Enable flash. */
|
||||
EFM_FlashCmd(Enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function does an erase of all user flash area
|
||||
* @param StartSector: start of user flash area
|
||||
* @retval 0: user flash area successfully erased
|
||||
* 1: error occurred
|
||||
*/
|
||||
uint32_t FLASH_If_Erase(uint32_t StartSector, uint32_t uSize)
|
||||
{
|
||||
uint32_t UserStartSector, UserEndSector, i = 0;
|
||||
|
||||
/* Unlock EFM. */
|
||||
EFM_Unlock();
|
||||
|
||||
/* Enable flash. */
|
||||
EFM_FlashCmd(Enable);
|
||||
/* Wait flash ready. */
|
||||
while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/* Get the sector where start the user flash area */
|
||||
UserStartSector = StartSector;
|
||||
UserEndSector = (StartSector + uSize);
|
||||
|
||||
for(i = UserStartSector; i <= UserEndSector; i += SECTOR_SIZE)
|
||||
{
|
||||
/* Reload IWDG counter */
|
||||
WDT_RefreshCounter();
|
||||
|
||||
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
||||
be done by word */
|
||||
if (EFM_SectorErase(i) != Ok)
|
||||
{
|
||||
/* Error occurred while page erase */
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock EFM. */
|
||||
EFM_Lock();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function does an erase of all user flash area
|
||||
* @param StartSector: start of user flash area
|
||||
* @retval 0: user flash area successfully erased
|
||||
* 1: error occurred
|
||||
*/
|
||||
uint32_t FLASH_If_SingleSectorErase(uint32_t SectorAddr)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
|
||||
/* Unlock EFM. */
|
||||
EFM_Unlock();
|
||||
|
||||
/* Enable flash. */
|
||||
EFM_FlashCmd(Enable);
|
||||
/* Wait flash ready. */
|
||||
while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/* Reload IWDG counter */
|
||||
WDT_RefreshCounter();
|
||||
|
||||
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
||||
be done by word */
|
||||
if (EFM_SectorErase(SectorAddr) != Ok)
|
||||
{
|
||||
/* Error occurred while page erase */
|
||||
result = (1);
|
||||
}
|
||||
|
||||
/* Lock EFM. */
|
||||
EFM_Lock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function writes a data buffer in flash (data are 32-bit aligned).
|
||||
* @note After writing data buffer, the flash content is checked.
|
||||
* @param FlashAddress: start address for writing data buffer
|
||||
* @param Data: pointer on data buffer
|
||||
* @param DataLength: length of data buffer (unit is 32-bit word)
|
||||
* @retval 0: Data successfully written to Flash memory
|
||||
* 1: Error occurred while writing data in Flash memory
|
||||
* 2: Written Data in flash memory is different from expected one
|
||||
*/
|
||||
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data, uint32_t DataLength)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t result = 0;
|
||||
|
||||
/* Unlock EFM. */
|
||||
EFM_Unlock();
|
||||
|
||||
/* Enable flash. */
|
||||
EFM_FlashCmd(Enable);
|
||||
/* Wait flash ready. */
|
||||
while(Set != EFM_GetFlagStatus(EFM_FLAG_RDY))
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
for (i = 0; (i < DataLength) && (*FlashAddress <= (mBMS_FW_DN_END_ADDRESS - 4)); i++)
|
||||
{
|
||||
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
|
||||
be done by word */
|
||||
if (EFM_SingleProgram(*FlashAddress, *(uint32_t *)(Data + i)) == Ok)
|
||||
{
|
||||
/* Check the written value */
|
||||
if (*(uint32_t*)*FlashAddress != *(uint32_t *)(Data + i))
|
||||
{
|
||||
/* Flash content doesn't match SRAM content */
|
||||
result = 2;
|
||||
break;
|
||||
}
|
||||
/* Increment FLASH destination address */
|
||||
*FlashAddress += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Error occurred while writing data in Flash memory */
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Lock EFM. */
|
||||
EFM_Lock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
///**
|
||||
// * @brief Returns the write protection status of user flash area.
|
||||
// * @param None
|
||||
// * @retval 0: No write protected sectors inside the user flash area
|
||||
// * 1: Some sectors inside the user flash area are write protected
|
||||
// */
|
||||
//uint16_t FLASH_If_GetWriteProtectionStatus(void)
|
||||
//{
|
||||
// uint32_t UserStartSector = FLASH_Sector_1;
|
||||
|
||||
// /* Get the sector where start the user flash area */
|
||||
// UserStartSector = GetSector(APPLICATION_ADDRESS);
|
||||
|
||||
// /* Check if there are write protected sectors inside the user flash area */
|
||||
// if ((FLASH_OB_GetWRP() >> (UserStartSector/8)) == (0xFFF >> (UserStartSector/8)))
|
||||
// { /* No write protected sectors inside the user flash area */
|
||||
// return 1;
|
||||
// }
|
||||
// else
|
||||
// { /* Some sectors inside the user flash area are write protected */
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
///**
|
||||
// * @brief Disables the write protection of user flash area.
|
||||
// * @param None
|
||||
// * @retval 1: Write Protection successfully disabled
|
||||
// * 2: Error: Flash write unprotection failed
|
||||
// */
|
||||
//uint32_t FLASH_If_DisableWriteProtection(void)
|
||||
//{
|
||||
// __IO uint32_t UserStartSector = FLASH_Sector_1, UserWrpSectors = OB_WRP_Sector_1;
|
||||
|
||||
// /* Get the sector where start the user flash area */
|
||||
// UserStartSector = GetSector(APPLICATION_ADDRESS);
|
||||
|
||||
// /* Mark all sectors inside the user flash area as non protected */
|
||||
// UserWrpSectors = 0xFFF-((1 << (UserStartSector/8))-1);
|
||||
//
|
||||
// /* Unlock the Option Bytes */
|
||||
// FLASH_OB_Unlock();
|
||||
|
||||
// /* Disable the write protection for all sectors inside the user flash area */
|
||||
// FLASH_OB_WRPConfig(UserWrpSectors, DISABLE);
|
||||
|
||||
// /* Start the Option Bytes programming process. */
|
||||
// if (FLASH_OB_Launch() != FLASH_COMPLETE)
|
||||
// {
|
||||
// /* Error: Flash write unprotection failed */
|
||||
// return (2);
|
||||
// }
|
||||
|
||||
// /* Write Protection successfully disabled */
|
||||
// return (1);
|
||||
//}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
103
APP_R3323/App/Hardware/flash_if.h
Normal file
103
APP_R3323/App/Hardware/flash_if.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file flash_if.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the flash memory functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __FLASH_IF_H
|
||||
#define __FLASH_IF_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t AppFileSize;
|
||||
uint8_t BootVer[4];
|
||||
uint8_t AppVer[4];
|
||||
uint8_t FileName[30];
|
||||
uint8_t BootUpdate;
|
||||
uint8_t AppUpdate;
|
||||
} FW_INFO;
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Base address of the Flash sectors */
|
||||
#define SECTOR_SIZE 8192 // 0X2000
|
||||
|
||||
#define ADDR_FLASH_SECTOR_00 ((uint32_t)0x00000000) /* Base @ of Sector 0, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_01 ((uint32_t)0x00002000) /* Base @ of Sector 1, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_02 ((uint32_t)0x00004000) /* Base @ of Sector 2, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_03 ((uint32_t)0x00006000) /* Base @ of Sector 3, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_04 ((uint32_t)0x00008000) /* Base @ of Sector 4, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_05 ((uint32_t)0x0000A000) /* Base @ of Sector 5, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_06 ((uint32_t)0x0000C000) /* Base @ of Sector 6, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_07 ((uint32_t)0x0000E000) /* Base @ of Sector 7, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_08 ((uint32_t)0x00010000) /* Base @ of Sector 8, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_09 ((uint32_t)0x00012000) /* Base @ of Sector 9, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x00014000) /* Base @ of Sector 10, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x00016000) /* Base @ of Sector 11, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x00018000) /* Base @ of Sector 12, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x0001A000) /* Base @ of Sector 13, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x0001C000) /* Base @ of Sector 14, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0001E000) /* Base @ of Sector 15, 8 Kbyte */
|
||||
|
||||
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x00020000) /* Base @ of Sector 16, 8 Kbyte */
|
||||
#define ADDR_FLASH_SECTOR_32 ((uint32_t)0x00040000) /* Base @ of Sector 32, 8 Kbyte */
|
||||
|
||||
#define ADDR_FLASH_SECTOR_48 ((uint32_t)0x00060000) /* Base @ of Sector 1, 16 Kbyte */
|
||||
|
||||
/* Define the address from where user application will be loaded.
|
||||
Note: the 1st sector 0x00000000-0x00020000 is reserved for the IAP code */
|
||||
#define mBMS_FW_RN_ADDRESS ADDR_FLASH_SECTOR_16
|
||||
|
||||
#define mBMS_FW_DN_ADDRESS ADDR_FLASH_SECTOR_48
|
||||
|
||||
/* End of the Flash address */
|
||||
#define mBMS_FW_DN_END_ADDRESS ((uint32_t)0x00080000)
|
||||
/* Define the user application size */
|
||||
#define mBMS_FW_FLASH_SIZE (mBMS_FW_DN_END_ADDRESS - mBMS_FW_DN_ADDRESS)
|
||||
#define mBMS_FW_PACKET_SIZE 0x800 // 2048
|
||||
|
||||
#define mBMS_SOC_BASE_ADDR ADDR_FLASH_SECTOR_11
|
||||
|
||||
#define mBMS_PARAM_BASE_ADDR ADDR_FLASH_SECTOR_12
|
||||
#define mBMS_INV_BASE_ADDR ADDR_FLASH_SECTOR_13
|
||||
#define mBMS_CALIB_BASE_ADDR ADDR_FLASH_SECTOR_14
|
||||
#define mBMS_FW_INFO_BASE_ADDR ADDR_FLASH_SECTOR_15
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
void FLASH_If_Init(void);
|
||||
uint32_t FLASH_If_Erase(uint32_t StartSector, uint32_t uSize);
|
||||
uint32_t FLASH_If_SingleSectorErase(uint32_t SectorAddr);
|
||||
|
||||
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data, uint32_t DataLength);
|
||||
uint16_t FLASH_If_GetWriteProtectionStatus(void);
|
||||
uint32_t FLASH_If_DisableWriteProtection(void);
|
||||
|
||||
extern FW_INFO fwinfo;
|
||||
|
||||
#endif /* __FLASH_IF_H */
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
217
APP_R3323/App/Hardware/i2c.c
Normal file
217
APP_R3323/App/Hardware/i2c.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file i2c.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of i2c functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "i2c.h"
|
||||
#include "delay.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Define I2C unit used for the example */
|
||||
#define I2C_UNIT (M4_I2C1)
|
||||
|
||||
/* Define BQ Series device address */
|
||||
#define BQ_ADDRESS (0x50u)
|
||||
#define BQ_ADR_LEN (1u)
|
||||
|
||||
/* Define port and pin for SDA and SCL */
|
||||
#define I2C_SCL_PORT (PortD)
|
||||
#define I2C_SCL_PIN (Pin01)
|
||||
|
||||
#define I2C_SDA_PORT (PortD)
|
||||
#define I2C_SDA_PIN (Pin00)
|
||||
|
||||
#define I2C_GPIO_SCL_FUNC (Func_I2c1_Scl)
|
||||
#define I2C_GPIO_SDA_FUNC (Func_I2c1_Sda)
|
||||
|
||||
#define I2C_FCG_USE (PWC_FCG1_PERIPH_I2C1)
|
||||
|
||||
#define TIMEOUT (0x40000ul)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C memory write
|
||||
**
|
||||
** \param u8DevAddr The slave address
|
||||
** \param u8Addr The register address
|
||||
** \param pu8Data Pointer to the data buffer
|
||||
** \param u32Size Data size
|
||||
** \param u32TimeOut Time out count
|
||||
** \retval en_result_t Enumeration value:
|
||||
** - Ok: Success
|
||||
** - Error: Receive NACK
|
||||
** - ErrorTimeout: Time out
|
||||
******************************************************************************/
|
||||
en_result_t I2C_Reg_Write(uint16_t u8DevAddr, uint8_t u8RegAddr, uint8_t *pu8Data, uint32_t u32Size, uint32_t u32TimeOut)
|
||||
{
|
||||
en_result_t enRet;
|
||||
|
||||
I2C_Cmd(I2C_UNIT, Enable);
|
||||
|
||||
I2C_SoftwareResetCmd(I2C_UNIT, Enable);
|
||||
I2C_SoftwareResetCmd(I2C_UNIT, Disable);
|
||||
enRet = I2C_Start(I2C_UNIT, u32TimeOut);
|
||||
if (Ok == enRet)
|
||||
{
|
||||
enRet = I2C_TransAddr(I2C_UNIT, u8DevAddr, I2CDirTrans, u32TimeOut);
|
||||
|
||||
if (Ok == enRet)
|
||||
{
|
||||
enRet = I2C_TransData(I2C_UNIT, (uint8_t *)&u8RegAddr, BQ_ADR_LEN, u32TimeOut);
|
||||
if (Ok == enRet)
|
||||
{
|
||||
enRet = I2C_TransData(I2C_UNIT, pu8Data, u32Size, u32TimeOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
I2C_Stop(I2C_UNIT, u32TimeOut);
|
||||
I2C_Cmd(I2C_UNIT, Disable);
|
||||
|
||||
return enRet;
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief I2C memory read
|
||||
**
|
||||
** \param u8DevAddr The slave address
|
||||
** \param u8Addr The register address
|
||||
** \param pu8Data Pointer to the data buffer
|
||||
** \param u32Size Data size
|
||||
** \param u32TimeOut Time out count
|
||||
** \retval en_result_t Enumeration value:
|
||||
** - Ok: Success
|
||||
** - ErrorTimeout: Time out
|
||||
******************************************************************************/
|
||||
en_result_t I2C_Reg_Read(uint8_t u8DevAddr, uint8_t u8RegAddr, uint8_t *pu8Data, uint32_t u32Size, uint32_t u32TimeOut)
|
||||
{
|
||||
en_result_t enRet;
|
||||
|
||||
I2C_Cmd(I2C_UNIT, Enable);
|
||||
|
||||
I2C_SoftwareResetCmd(I2C_UNIT, Enable);
|
||||
I2C_SoftwareResetCmd(I2C_UNIT, Disable);
|
||||
enRet = I2C_Start(I2C_UNIT, u32TimeOut);
|
||||
if (Ok == enRet)
|
||||
{
|
||||
enRet = I2C_TransAddr(I2C_UNIT, (uint8_t)u8DevAddr, I2CDirTrans, u32TimeOut);
|
||||
|
||||
if (Ok == enRet)
|
||||
{
|
||||
enRet = I2C_TransData(I2C_UNIT, (uint8_t *)&u8RegAddr, BQ_ADR_LEN, u32TimeOut);
|
||||
if(Ok == enRet)
|
||||
{
|
||||
enRet = I2C_Restart(I2C_UNIT, u32TimeOut);
|
||||
if (Ok == enRet)
|
||||
{
|
||||
if (1ul == u32Size)
|
||||
{
|
||||
I2C_AckConfig(I2C_UNIT, I2c_NACK);
|
||||
}
|
||||
|
||||
enRet = I2C_TransAddr(I2C_UNIT, (uint8_t)u8DevAddr, I2CDirReceive, u32TimeOut);
|
||||
if (Ok == enRet)
|
||||
{
|
||||
enRet = I2C_MasterDataReceiveAndStop(I2C_UNIT, pu8Data, u32Size, u32TimeOut);
|
||||
}
|
||||
|
||||
I2C_AckConfig(I2C_UNIT, I2c_ACK);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Ok != enRet)
|
||||
{
|
||||
I2C_Stop(I2C_UNIT, u32TimeOut);
|
||||
}
|
||||
|
||||
I2C_Cmd(I2C_UNIT, Disable);
|
||||
return enRet;
|
||||
}
|
||||
|
||||
/**
|
||||
******************************************************************************
|
||||
** \brief Initialize the I2C peripheral for e2prom
|
||||
** \param None
|
||||
** \retval en_result_t Enumeration value:
|
||||
** - Ok: Success
|
||||
** - ErrorTimeout: Time out
|
||||
******************************************************************************/
|
||||
static en_result_t E2_Initialize(void)
|
||||
{
|
||||
stc_i2c_init_t stcI2cInit;
|
||||
en_result_t enRet;
|
||||
float32_t fErr;
|
||||
|
||||
I2C_DeInit(I2C_UNIT);
|
||||
|
||||
/* Initialize I2C port*/
|
||||
PORT_SetFunc(I2C_SCL_PORT, I2C_SCL_PIN, I2C_GPIO_SCL_FUNC, Disable);
|
||||
PORT_SetFunc(I2C_SDA_PORT, I2C_SDA_PIN, I2C_GPIO_SDA_FUNC, Disable);
|
||||
|
||||
/* Enable I2C Peripheral*/
|
||||
PWC_Fcg1PeriphClockCmd(I2C_FCG_USE, Enable);
|
||||
|
||||
MEM_ZERO_STRUCT(stcI2cInit);
|
||||
stcI2cInit.u32ClockDiv = I2C_CLK_DIV8;
|
||||
stcI2cInit.u32Baudrate = 100000ul;
|
||||
stcI2cInit.u32SclTime = 0ul;
|
||||
|
||||
enRet = I2C_Init(I2C_UNIT, &stcI2cInit, &fErr);
|
||||
|
||||
I2C_BusWaitCmd(I2C_UNIT, Enable);
|
||||
|
||||
return enRet;
|
||||
}
|
||||
|
||||
void I2c_Config(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* SPI Port/Pin initialization */
|
||||
PORT_Init(I2C_SCL_PORT, I2C_SCL_PIN, &stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
|
||||
PORT_Init(I2C_SDA_PORT, I2C_SDA_PIN, &stcPortInit);
|
||||
|
||||
E2_Initialize();
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
46
APP_R3323/App/Hardware/i2c.h
Normal file
46
APP_R3323/App/Hardware/i2c.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file i2c.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the spi communication.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __I2C_H
|
||||
#define __I2C_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void I2c_Config(void);
|
||||
|
||||
en_result_t I2C_Reg_Write(uint16_t u8DevAddr, uint8_t u8RegAddr, uint8_t *pu8Data, uint32_t u32Size, uint32_t u32TimeOut);
|
||||
en_result_t I2C_Reg_Read(uint8_t u8DevAddr, uint8_t u8RegAddr, uint8_t *pu8Data, uint32_t u32Size, uint32_t u32TimeOut);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
45
APP_R3323/App/Hardware/iwdg.c
Normal file
45
APP_R3323/App/Hardware/iwdg.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file iwdg.c
|
||||
* @author AMG Energy Solution Application Team
|
||||
* @version V1.0.0
|
||||
* @date 25-January-2022
|
||||
* @brief Watchdog Service Routines.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "iwdg.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* WDT count cycle definition */
|
||||
#define WDT_COUNT_CYCLE (16384u)
|
||||
|
||||
/* Reset source definition */
|
||||
#define RESET_WDT_TRIGGER (0u)
|
||||
#define RESET_OTHER_TRIGGER (1u)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
//Initialize watch-dog
|
||||
void IWDG_Init(void)
|
||||
{
|
||||
stc_wdt_init_t stcWdtInit;
|
||||
|
||||
/* configure structure initialization */
|
||||
MEM_ZERO_STRUCT(stcWdtInit);
|
||||
|
||||
stcWdtInit.enClkDiv = WdtPclk3Div8192;
|
||||
stcWdtInit.enCountCycle = WdtCountCycle16384;
|
||||
stcWdtInit.enRefreshRange = WdtRefresh100Pct; //WdtRefresh0To25Pct;
|
||||
stcWdtInit.enSleepModeCountEn = Disable;
|
||||
stcWdtInit.enRequestType = WdtTriggerResetRequest;
|
||||
WDT_Init(&stcWdtInit);
|
||||
|
||||
/* First refresh to start WDT */
|
||||
WDT_RefreshCounter();
|
||||
}
|
||||
19
APP_R3323/App/Hardware/iwdg.h
Normal file
19
APP_R3323/App/Hardware/iwdg.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef _IWDG_H
|
||||
#define _IWDG_H
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F407 Development Board
|
||||
//Independent watch-dog driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date created: 2015/9/1
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2014-2024
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
void IWDG_Init(void); //Initialize
|
||||
|
||||
#endif
|
||||
161
APP_R3323/App/Hardware/led.c
Normal file
161
APP_R3323/App/Hardware/led.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file led.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the code of the led control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "led.h"
|
||||
#include "delay.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
//LED port definitions
|
||||
/* LED RUN(GREEN) Port/Pin definition */
|
||||
#define LED_BD_PORT (PortB)
|
||||
#define LED_BD_PIN (Pin08)
|
||||
|
||||
/* LED RUN(GREEN) Port/Pin definition */
|
||||
#define LED_G_PORT (PortE)
|
||||
#define LED_G_PIN (Pin08)
|
||||
|
||||
/* LED ALARM (RED) Port/Pin definition */
|
||||
#define LED_R_PORT (PortE)
|
||||
#define LED_R_PIN (Pin07)
|
||||
|
||||
/* LED SOC Port/Pin definition */
|
||||
#define LED_SOC_3_PORT (PortE)
|
||||
#define LED_SOC_3_PIN (Pin09)
|
||||
|
||||
#define LED_SOC_2_PORT (PortE)
|
||||
#define LED_SOC_2_PIN (Pin10)
|
||||
|
||||
#define LED_SOC_1_PORT (PortE)
|
||||
#define LED_SOC_1_PIN (Pin11)
|
||||
|
||||
#define LED_SOC_0_PORT (PortE)
|
||||
#define LED_SOC_0_PIN (Pin12)
|
||||
|
||||
/* LED0~3 toggle definition */
|
||||
#define LED_G_TOGGLE() (PORT_Toggle(LED_G_PORT, LED_G_PIN))
|
||||
#define LED_R_TOGGLE() (PORT_Toggle(LED_R_PORT, LED_R_PIN))
|
||||
#define LED_S0C_0_TOGGLE() (PORT_Toggle(LED_SOC_0_PIN, LED_SOC_0_PIN))
|
||||
#define LED_S0C_1_TOGGLE() (PORT_Toggle(LED_SOC_1_PIN, LED_SOC_1_PIN))
|
||||
#define LED_S0C_2_TOGGLE() (PORT_Toggle(LED_SOC_2_PIN, LED_SOC_2_PIN))
|
||||
#define LED_S0C_3_TOGGLE() (PORT_Toggle(LED_SOC_3_PIN, LED_SOC_3_PIN))
|
||||
|
||||
#define DLY_MS (200ul)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
// LED class IO
|
||||
void LED_Init(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* LED Port/Pin initialization */
|
||||
PORT_Init(LED_BD_PORT, LED_BD_PIN, &stcPortInit);
|
||||
|
||||
PORT_Init(LED_G_PORT, LED_G_PIN, &stcPortInit);
|
||||
PORT_Init(LED_R_PORT, LED_R_PIN, &stcPortInit);
|
||||
|
||||
PORT_Init(LED_SOC_0_PORT, LED_SOC_0_PIN, &stcPortInit);
|
||||
PORT_Init(LED_SOC_1_PORT, LED_SOC_1_PIN, &stcPortInit);
|
||||
PORT_Init(LED_SOC_2_PORT, LED_SOC_2_PIN, &stcPortInit);
|
||||
PORT_Init(LED_SOC_3_PORT, LED_SOC_3_PIN, &stcPortInit);
|
||||
}
|
||||
|
||||
void LED_SelfTest(void)
|
||||
{
|
||||
LED_Off(LED_ALL);
|
||||
delay_os_ms(DLY_MS);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
LED_On((LED_CONTROL)i);
|
||||
if (i > 0) LED_Off((LED_CONTROL)(i - 1));
|
||||
delay_os_ms(DLY_MS);
|
||||
}
|
||||
|
||||
LED_Off(LED_ALL);
|
||||
delay_os_ms(DLY_MS);
|
||||
|
||||
LED_On(LED_G);
|
||||
}
|
||||
|
||||
void LED_On(LED_CONTROL flag)
|
||||
{
|
||||
switch (flag) {
|
||||
case (LED_CONTROL)0: PORT_SetBits(LED_G_PORT, LED_G_PIN); break;
|
||||
case (LED_CONTROL)1: PORT_SetBits(LED_R_PORT, LED_R_PIN); break;
|
||||
case (LED_CONTROL)2: PORT_SetBits(LED_SOC_0_PORT, LED_SOC_0_PIN); break;
|
||||
case (LED_CONTROL)3: PORT_SetBits(LED_SOC_1_PORT, LED_SOC_1_PIN); break;
|
||||
case (LED_CONTROL)4: PORT_SetBits(LED_SOC_2_PORT, LED_SOC_2_PIN); break;
|
||||
case (LED_CONTROL)5: PORT_SetBits(LED_SOC_3_PORT, LED_SOC_3_PIN); break;
|
||||
case (LED_CONTROL)6: PORT_ResetBits(LED_BD_PORT, LED_BD_PIN); break;
|
||||
case (LED_CONTROL)7:
|
||||
PORT_SetBits(LED_G_PORT, LED_G_PIN);
|
||||
PORT_SetBits(LED_R_PORT, LED_R_PIN);
|
||||
PORT_SetBits(LED_SOC_0_PORT, LED_SOC_0_PIN);
|
||||
PORT_SetBits(LED_SOC_1_PORT, LED_SOC_1_PIN);
|
||||
PORT_SetBits(LED_SOC_2_PORT, LED_SOC_2_PIN);
|
||||
PORT_SetBits(LED_SOC_3_PORT, LED_SOC_3_PIN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LED_Off(LED_CONTROL flag)
|
||||
{
|
||||
switch (flag) {
|
||||
case (LED_CONTROL)0: PORT_ResetBits(LED_G_PORT, LED_G_PIN); break;
|
||||
case (LED_CONTROL)1: PORT_ResetBits(LED_R_PORT, LED_R_PIN); break;
|
||||
case (LED_CONTROL)2: PORT_ResetBits(LED_SOC_0_PORT, LED_SOC_0_PIN); break;
|
||||
case (LED_CONTROL)3: PORT_ResetBits(LED_SOC_1_PORT, LED_SOC_1_PIN); break;
|
||||
case (LED_CONTROL)4: PORT_ResetBits(LED_SOC_2_PORT, LED_SOC_2_PIN); break;
|
||||
case (LED_CONTROL)5: PORT_ResetBits(LED_SOC_3_PORT, LED_SOC_3_PIN); break;
|
||||
case (LED_CONTROL)6: PORT_SetBits(LED_BD_PORT, LED_BD_PIN); break;
|
||||
case (LED_CONTROL)7:
|
||||
PORT_ResetBits(LED_G_PORT, LED_G_PIN);
|
||||
PORT_ResetBits(LED_R_PORT, LED_R_PIN);
|
||||
PORT_ResetBits(LED_SOC_0_PORT, LED_SOC_0_PIN);
|
||||
PORT_ResetBits(LED_SOC_1_PORT, LED_SOC_1_PIN);
|
||||
PORT_ResetBits(LED_SOC_2_PORT, LED_SOC_2_PIN);
|
||||
PORT_ResetBits(LED_SOC_3_PORT, LED_SOC_3_PIN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BD_LED_Toggle(void)
|
||||
{
|
||||
PORT_Toggle(LED_BD_PORT, LED_BD_PIN);
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
58
APP_R3323/App/Hardware/led.h
Normal file
58
APP_R3323/App/Hardware/led.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file led.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the led control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _LED_H
|
||||
#define _LED_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
typedef enum {
|
||||
LED_G = 0, /* 0: GREEN LED */
|
||||
LED_R, /* 1: RED LED */
|
||||
LED_SOC_0, /* 2: SOC 0 LED */
|
||||
LED_SOC_1, /* 3: SOC 1 LED */
|
||||
LED_SOC_2, /* 4: SOC 2 LED */
|
||||
LED_SOC_3, /* 5: SOC 3 LED */
|
||||
LED_BD, /* 6: Board LED */
|
||||
LED_ALL /* 7: All LED */
|
||||
} LED_CONTROL;
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void LED_Init(void); //Initialize
|
||||
void LED_SelfTest(void);
|
||||
void LED_On(LED_CONTROL flag);
|
||||
void LED_Off(LED_CONTROL flag);
|
||||
|
||||
void BD_LED_Toggle(void);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
948
APP_R3323/App/Hardware/ltc6813.c
Normal file
948
APP_R3323/App/Hardware/ltc6813.c
Normal file
@@ -0,0 +1,948 @@
|
||||
/*! LTC6813: Multicell Battery Monitors
|
||||
*
|
||||
*@verbatim
|
||||
*The LTC6813 is multicell battery stack monitor that measures up to 18 series
|
||||
*connected battery cells with a total measurement error of less than 2.2mV.
|
||||
*The cell measurement range of 0V to 5V makes the LTC6813 suitable for most
|
||||
*battery chemistries. All 18 cell voltages can be captured in 290uS, and lower
|
||||
*data acquisition rates can be selected for high noise reduction.
|
||||
*Using the LTC6813-1, multiple devices are connected in a daisy-chain with one
|
||||
*host processor connection for all devices, permitting simultaneous cell monitoring
|
||||
*of long, high voltage battery strings.
|
||||
*@endverbatim
|
||||
*
|
||||
* https://www.analog.com/en/products/ltc6813-1.html
|
||||
* https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/dc2350a-b.html
|
||||
*
|
||||
*********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
//! @ingroup BMS
|
||||
//! @{
|
||||
//! @defgroup LTC6813-1 LTC6813-1: Multicell Battery Monitor
|
||||
//! @}
|
||||
|
||||
/*! @file
|
||||
@ingroup LTC6813-1
|
||||
Library for LTC6813-1 Multicell Battery Monitor
|
||||
*/
|
||||
|
||||
#include <includes.h>
|
||||
#include "stdint.h"
|
||||
#include "spi.h"
|
||||
#include "LTC681x.h"
|
||||
#include "LTC6813.h"
|
||||
#include "delay.h"
|
||||
|
||||
//Helper function to initialize register limits.
|
||||
void LTC6813_init_reg_limits(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
for (uint8_t cic = 0; cic < total_ic; cic++)
|
||||
{
|
||||
ic[cic].ic_reg.cell_channels = 18;
|
||||
ic[cic].ic_reg.stat_channels = 4;
|
||||
ic[cic].ic_reg.aux_channels = 9;
|
||||
ic[cic].ic_reg.num_cv_reg = 6;
|
||||
ic[cic].ic_reg.num_gpio_reg = 4;
|
||||
ic[cic].ic_reg.num_stat_reg = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function to initialize CFG variables.
|
||||
void LTC6813_init_cfg(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
bool REFON = true;
|
||||
bool ADCOPT = false;
|
||||
uint8_t gpioBits = 0x1F; // {true, true, true, true, true};
|
||||
uint16_t dccBits = 0;
|
||||
|
||||
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++)
|
||||
{
|
||||
for (int j =0; j < 6; j++)
|
||||
{
|
||||
ic[current_ic].config.tx_data[j] = 0;
|
||||
ic[current_ic].configb.tx_data[j] = 0;
|
||||
}
|
||||
LTC6813_set_cfgr(current_ic , ic, REFON, ADCOPT, gpioBits, dccBits, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function to set CFGR variable
|
||||
void LTC6813_set_cfgr(uint8_t nIC, cell_asic *ic, bool refon, bool adcopt, uint8_t gpio, uint16_t dcc, uint8_t dcto, uint16_t uv, uint16_t ov)
|
||||
{
|
||||
LTC6813_set_cfgr_refon (nIC, ic, refon );
|
||||
LTC6813_set_cfgr_adcopt(nIC, ic, adcopt);
|
||||
LTC6813_set_cfgr_gpio (nIC, ic, gpio );
|
||||
LTC6813_set_cfgr_dis (nIC, ic, dcc );
|
||||
LTC6813_set_cfgr_dcto (nIC, ic, dcto );
|
||||
LTC6813_set_cfgr_uv (nIC, ic, uv );
|
||||
LTC6813_set_cfgr_ov (nIC, ic, ov );
|
||||
}
|
||||
|
||||
//Helper function to set the REFON bit
|
||||
void LTC6813_set_cfgr_refon(uint8_t nIC, cell_asic *ic, bool refon)
|
||||
{
|
||||
if (refon) ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0] | 0x04;
|
||||
else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0] & 0xFB;
|
||||
}
|
||||
|
||||
//Helper function to set the adcopt bit
|
||||
void LTC6813_set_cfgr_adcopt(uint8_t nIC, cell_asic *ic, bool adcopt)
|
||||
{
|
||||
if (adcopt) ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0] | 0x01;
|
||||
else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0] & 0xFE;
|
||||
}
|
||||
|
||||
//Helper function to set GPIO bits
|
||||
void LTC6813_set_cfgr_gpio(uint8_t nIC, cell_asic *ic, uint8_t gpio)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if ((gpio >> i) & 0x01) ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0] | ( 0x01 << (i + 3));
|
||||
else ic[nIC].config.tx_data[0] = ic[nIC].config.tx_data[0] & (~(0x01 << (i + 3)));
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function to control discharge
|
||||
void LTC6813_set_cfgr_dis(uint8_t nIC, cell_asic *ic, uint16_t dcc)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if ((dcc >> i) & 0x0001) ic[nIC].config.tx_data[4] = ic[nIC].config.tx_data[4] | (0x01 << i);
|
||||
else ic[nIC].config.tx_data[4] = ic[nIC].config.tx_data[4] & (~(0x01 << i));
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((dcc >> (8 + i)) & 0x0001) ic[nIC].config.tx_data[5] = ic[nIC].config.tx_data[5] | (0x01 << i);
|
||||
else ic[nIC].config.tx_data[5] = ic[nIC].config.tx_data[5] & (~(0x01 << i));
|
||||
}
|
||||
}
|
||||
|
||||
//Helper Function to set dcto value in CFG register
|
||||
void LTC6813_set_cfgr_dcto(uint8_t nIC, cell_asic *ic, uint8_t dcto)
|
||||
{
|
||||
ic[nIC].config.tx_data[5] &= 0x0F;
|
||||
ic[nIC].config.tx_data[5] |= (uint8_t)((dcto << 4) & 0xF0);
|
||||
}
|
||||
|
||||
//Helper Function to set uv value in CFG register
|
||||
void LTC6813_set_cfgr_uv(uint8_t nIC, cell_asic *ic,uint16_t uv)
|
||||
{
|
||||
ic[nIC].config.tx_data[1] = (uint8_t)((uv >> 0) & 0xFF);
|
||||
ic[nIC].config.tx_data[2] &= 0xF0;
|
||||
ic[nIC].config.tx_data[2] |= (uint8_t)((uv >> 8) & 0x0F);
|
||||
}
|
||||
|
||||
//Helper function to set OV value in CFG register
|
||||
void LTC6813_set_cfgr_ov(uint8_t nIC, cell_asic *ic, uint16_t ov)
|
||||
{
|
||||
ic[nIC].config.tx_data[2] &= 0x0F;
|
||||
ic[nIC].config.tx_data[2] |= (uint8_t)((ov << 4) & 0xF0);
|
||||
ic[nIC].config.tx_data[3] = (uint8_t)((ov >> 4) & 0xFF);
|
||||
}
|
||||
|
||||
/***************************** CFGRB *********************************/
|
||||
|
||||
//Helper Function to initialize the CFGRB data structures
|
||||
void LTC6813_init_cfgb(uint8_t total_ic,cell_asic *ic)
|
||||
{
|
||||
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++)
|
||||
{
|
||||
for(int j = 0; j < 6; j++)
|
||||
{
|
||||
ic[current_ic].configb.tx_data[j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Helper Function to set the configuration register B
|
||||
void LTC6813_set_cfgrb(uint8_t nIC, cell_asic *ic, bool fdrf, bool dtmen, bool ps[2], uint8_t gpiobits, uint16_t dccbits)
|
||||
{
|
||||
LTC6813_set_cfgrb_fdrf (nIC, ic, fdrf);
|
||||
LTC6813_set_cfgrb_dtmen (nIC, ic, dtmen);
|
||||
LTC6813_set_cfgrb_ps (nIC, ic, ps);
|
||||
LTC6813_set_cfgrb_gpio_b(nIC, ic, gpiobits);
|
||||
LTC6813_set_cfgrb_dcc_b (nIC, ic, dccbits);
|
||||
}
|
||||
|
||||
//Helper function to set the FDRF bit
|
||||
void LTC6813_set_cfgrb_fdrf(uint8_t nIC, cell_asic *ic, bool fdrf)
|
||||
{
|
||||
if(fdrf) ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|0x40;
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&0xBF;
|
||||
}
|
||||
|
||||
//Helper function to set the DTMEN bit
|
||||
void LTC6813_set_cfgrb_dtmen(uint8_t nIC, cell_asic *ic, bool dtmen)
|
||||
{
|
||||
if(dtmen) ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|0x08;
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&0xF7;
|
||||
}
|
||||
|
||||
//Helper function to set the PATH SELECT bit
|
||||
void LTC6813_set_cfgrb_ps(uint8_t nIC, cell_asic *ic, bool ps[])
|
||||
{
|
||||
for(int i =0;i<2;i++)
|
||||
{
|
||||
if(ps[i])ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]|(0x01<<(i+4));
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1]&(~(0x01<<(i+4)));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to set the gpio bits in configb b register
|
||||
void LTC6813_set_cfgrb_gpio_b(uint8_t nIC, cell_asic *ic, uint8_t gpiobits)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((gpiobits >> 1) & 0x01) ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0] | ( 0x01 << i);
|
||||
else ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0] & (~(0x01 << i));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to set the dcc bits in configb b register
|
||||
void LTC6813_set_cfgrb_dcc_b(uint8_t nIC, cell_asic *ic, uint16_t dccbits)
|
||||
{
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (i < 4)
|
||||
{
|
||||
// DCC 13, 14, 15, 16
|
||||
if ((dccbits >> i) & 0x0001) ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0] | (0x01 << (i + 4));
|
||||
else ic[nIC].configb.tx_data[0] = ic[nIC].configb.tx_data[0] & (~(0x01 << (i + 4)));
|
||||
}
|
||||
if (i >= 4 && i < 6)
|
||||
{
|
||||
if ((dccbits >> i) & 0x0001) ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1] | (0x01 << (i - 4));
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1] & (~(0x01 << (i - 4)));
|
||||
}
|
||||
if (i == 6)
|
||||
{
|
||||
if ((dccbits >> i) & 0x0001) ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1] | 0x04;
|
||||
else ic[nIC].configb.tx_data[1] = ic[nIC].configb.tx_data[1] & (~0x04); //0xFB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This command will write the configuration registers of the LTC6813-1s
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void LTC6813_wrcfg(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
LTC681x_wrcfg(total_ic,ic);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This command will write the configuration b registers of the LTC6813-1s
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void LTC6813_wrcfgb(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
LTC681x_wrcfgb(total_ic, ic);
|
||||
}
|
||||
|
||||
|
||||
// Reads configuration registers of a LTC6813 daisy chain
|
||||
int8_t LTC6813_rdcfg(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
uint8_t cmd[2] = {0x00, 0x02};
|
||||
uint8_t read_buffer[10];
|
||||
int8_t pec_error = 0;
|
||||
uint16_t data_pec;
|
||||
uint16_t calc_pec;
|
||||
uint8_t c_ic = 0;
|
||||
|
||||
pec_error = read_68(total_ic, cmd, read_buffer);
|
||||
|
||||
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++)
|
||||
{
|
||||
if (ic->isospi_reverse == false)
|
||||
{
|
||||
c_ic = current_ic;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ic = total_ic - current_ic - 1;
|
||||
}
|
||||
|
||||
for (int byte = 0; byte < 8; byte++)
|
||||
{
|
||||
ic[c_ic].config.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
|
||||
data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
|
||||
if (calc_pec != data_pec )
|
||||
{
|
||||
ic[c_ic].config.rx_pec_match = 1;
|
||||
}
|
||||
else ic[c_ic].config.rx_pec_match = 0;
|
||||
}
|
||||
LTC681x_check_pec(total_ic,CFGR,ic);
|
||||
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Reads configuration b registers of a LTC6813 daisy chain
|
||||
int8_t LTC6813_rdcfgb(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
uint8_t cmd[2]= {0x00 , 0x26};
|
||||
uint8_t read_buffer[256];
|
||||
int8_t pec_error = 0;
|
||||
uint16_t data_pec;
|
||||
uint16_t calc_pec;
|
||||
uint8_t c_ic = 0;
|
||||
|
||||
pec_error = read_68(total_ic, cmd, read_buffer);
|
||||
|
||||
for (uint8_t current_ic = 0; current_ic < total_ic; current_ic++)
|
||||
{
|
||||
if (ic->isospi_reverse == false)
|
||||
{
|
||||
c_ic = current_ic;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ic = total_ic - current_ic - 1;
|
||||
}
|
||||
|
||||
for (int byte = 0; byte < 8; byte++)
|
||||
{
|
||||
ic[c_ic].configb.rx_data[byte] = read_buffer[byte + (8 * current_ic)];
|
||||
}
|
||||
calc_pec = pec15_calc(6, &read_buffer[8 * current_ic]);
|
||||
data_pec = read_buffer[7 + (8 * current_ic)] | (read_buffer[6 + (8 * current_ic)] << 8);
|
||||
if (calc_pec != data_pec )
|
||||
{
|
||||
ic[c_ic].configb.rx_pec_match = 1;
|
||||
}
|
||||
else ic[c_ic].configb.rx_pec_match = 0;
|
||||
}
|
||||
LTC681x_check_pec(total_ic,CFGR,ic);
|
||||
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
|
||||
//Starts cell voltage conversion
|
||||
void LTC6813_adcv(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP, //Discharge Permit
|
||||
uint8_t CH //Cell Channels to be measured
|
||||
)
|
||||
{
|
||||
uint8_t cmd[4];
|
||||
uint8_t md_bits;
|
||||
|
||||
md_bits = (MD & 0x02) >> 1;
|
||||
cmd[0] = md_bits + 0x02;
|
||||
md_bits = (MD & 0x01) << 7;
|
||||
cmd[1] = md_bits + 0x60 + (DCP << 4) + CH;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
// Reads and parses the LTC6813 cell voltage registers.
|
||||
uint8_t LTC6813_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t total_ic, // the number of ICs in the system
|
||||
cell_asic *ic // Array of the parsed cell codes
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = LTC681x_rdcv(reg,total_ic,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Start a GPIO and Vref2 Conversion
|
||||
void LTC6813_adax(uint8_t MD, //ADC Mode
|
||||
uint8_t CHG //GPIO Channels to be measured)
|
||||
)
|
||||
{
|
||||
uint8_t cmd[4];
|
||||
uint8_t md_bits;
|
||||
|
||||
md_bits = (MD & 0x02) >> 1;
|
||||
cmd[0] = md_bits + 0x04;
|
||||
md_bits = (MD & 0x01) << 7;
|
||||
cmd[1] = md_bits + 0x60 + CHG ;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
The function is used
|
||||
to read the parsed GPIO codes of the LTC6813. This function will send the requested
|
||||
read commands parse the data and store the gpio voltages in aux_codes variable
|
||||
*/
|
||||
int8_t LTC6813_rdaux(uint8_t reg, //Determines which GPIO voltage register is read back.
|
||||
uint8_t total_ic,//the number of ICs in the system
|
||||
cell_asic *ic//A two dimensional array of the gpio voltage codes.
|
||||
)
|
||||
{
|
||||
uint8_t *data;
|
||||
int8_t pec_error = 0;
|
||||
uint8_t c_ic =0;
|
||||
data = (uint8_t *) malloc((NUM_RX_BYT * total_ic) * sizeof(uint8_t));
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
for (uint8_t gpio_reg = 1; gpio_reg < ic[0].ic_reg.num_gpio_reg + 1; gpio_reg++) //executes once for each of the LTC6813 aux voltage registers
|
||||
{
|
||||
LTC681x_rdaux_reg(gpio_reg, total_ic, data); //Reads the raw auxiliary register data into the data[] array
|
||||
for (int current_ic = 0; current_ic < total_ic; current_ic++)
|
||||
{
|
||||
if (ic->isospi_reverse == false)
|
||||
{
|
||||
c_ic = current_ic;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ic = total_ic - current_ic - 1;
|
||||
}
|
||||
pec_error = parse_auxs(current_ic, gpio_reg, data,
|
||||
&ic[c_ic].aux.a_codes[0],
|
||||
&ic[c_ic].aux.pec_match[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LTC681x_rdaux_reg(reg, total_ic, data);
|
||||
|
||||
for (int current_ic = 0; current_ic<total_ic; current_ic++)
|
||||
{
|
||||
if (ic->isospi_reverse == false)
|
||||
{
|
||||
c_ic = current_ic;
|
||||
}
|
||||
else
|
||||
{
|
||||
c_ic = total_ic - current_ic - 1;
|
||||
}
|
||||
pec_error = parse_cells(current_ic,reg, data,
|
||||
&ic[c_ic].aux.a_codes[0],
|
||||
&ic[c_ic].aux.pec_match[0]);
|
||||
}
|
||||
|
||||
}
|
||||
LTC681x_check_pec(total_ic,AUX,ic);
|
||||
free(data);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
//Start a Status ADC Conversion
|
||||
void LTC6813_adstat(uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //GPIO Channels to be measured
|
||||
)
|
||||
{
|
||||
LTC681x_adstat(MD,CHST);
|
||||
}
|
||||
|
||||
/*
|
||||
Reads and parses the LTC6813 stat registers.
|
||||
The function is used
|
||||
to read the parsed stat codes of the LTC6813. This function will send the requested
|
||||
read commands parse the data and store the stat voltages in stat_codes variable
|
||||
*/
|
||||
int8_t LTC6813_rdstat(uint8_t reg, //Determines which Stat register is read back.
|
||||
uint8_t total_ic,//the number of ICs in the system
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
pec_error = LTC681x_rdstat(reg,total_ic,ic);
|
||||
return (pec_error);
|
||||
}
|
||||
|
||||
// Starts cell voltage and GPIO 1&2 conversion
|
||||
void LTC6813_adcvax(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
// LTC681x_adcvax(MD,DCP);
|
||||
}
|
||||
|
||||
//Starts cell voltage and SOC conversion
|
||||
void LTC6813_adcvsc( uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
// LTC681x_adcvsc(MD,DCP);
|
||||
}
|
||||
|
||||
//Starts the Mux Decoder diagnostic self test
|
||||
void LTC6813_diagn()
|
||||
{
|
||||
LTC681x_diagn();
|
||||
}
|
||||
|
||||
//Starts cell voltage self test conversion
|
||||
void LTC6813_cvst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
LTC681x_cvst(MD,ST);
|
||||
}
|
||||
|
||||
//Start an Auxiliary Register Self Test Conversion
|
||||
void LTC6813_axst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
LTC681x_axst(MD,ST);
|
||||
}
|
||||
|
||||
//Start a Status Register Self Test Conversion
|
||||
void LTC6813_statst(uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
)
|
||||
{
|
||||
LTC681x_statst(MD,ST);
|
||||
}
|
||||
|
||||
// Runs the Digital Filter Self Test
|
||||
int16_t LTC6813_run_cell_adc_st(uint8_t adc_reg,uint8_t total_ic, cell_asic *ic,uint8_t md,bool adcopt)
|
||||
{
|
||||
int16_t error = 0;
|
||||
// error = LTC681x_run_cell_adc_st(adc_reg,total_ic,ic,md,adcopt);
|
||||
return(error);
|
||||
}
|
||||
|
||||
//Starts cell voltage overlap conversion
|
||||
void LTC6813_adol(uint8_t MD, //ADC Mode
|
||||
uint8_t DCP //Discharge Permit
|
||||
)
|
||||
{
|
||||
LTC681x_adol(MD,DCP);
|
||||
}
|
||||
|
||||
// Runs the ADC overlap test for the IC
|
||||
uint16_t LTC6813_run_adc_overlap(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
uint16_t error = 0;
|
||||
int32_t measure_delta =0;
|
||||
int16_t failure_pos_limit = 20;
|
||||
int16_t failure_neg_limit = -20;
|
||||
uint32_t conv_time=0;
|
||||
wakeup_idle(total_ic);
|
||||
LTC681x_adol(MD_7KHZ_3KHZ, DCP_DISABLED);
|
||||
conv_time = LTC6813_pollAdc();
|
||||
conv_time = conv_time;
|
||||
|
||||
wakeup_idle(total_ic);
|
||||
error = LTC681x_rdcv(0, total_ic,ic);
|
||||
for (int cic = 0; cic<total_ic; cic++)
|
||||
{
|
||||
|
||||
|
||||
measure_delta = (int32_t)ic[cic].cells.c_codes[6]-(int32_t)ic[cic].cells.c_codes[7];
|
||||
if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit))
|
||||
{
|
||||
error = error | (1<<(cic-1));
|
||||
}
|
||||
measure_delta = (int32_t)ic[cic].cells.c_codes[12]-(int32_t)ic[cic].cells.c_codes[13];
|
||||
if ((measure_delta>failure_pos_limit) || (measure_delta<failure_neg_limit))
|
||||
{
|
||||
error = error | (1<<(cic-1));
|
||||
}
|
||||
}
|
||||
return(error);
|
||||
}
|
||||
|
||||
//Start GPIOs open wire ADC conversion
|
||||
void LTC6813_axow(uint8_t MD, //ADC Mode
|
||||
uint8_t PUP //Discharge Permit
|
||||
)
|
||||
{
|
||||
// LTC681x_axow(MD, PUP);
|
||||
}
|
||||
|
||||
// Start an open wire Conversion
|
||||
void LTC6813_adow(uint8_t MD,uint8_t PUP,uint8_t CH,uint8_t DCP)
|
||||
{
|
||||
// LTC681x_adow(MD,PUP,CH,DCP);
|
||||
}
|
||||
|
||||
//Runs open wire for GPIOs
|
||||
void LTC6813_run_gpio_openwire(uint8_t total_ic,
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
// LTC681x_run_gpio_openwire(total_ic, ic);
|
||||
}
|
||||
|
||||
//Runs the data sheet algorithm for open wire for single cell detection
|
||||
void LTC6813_run_openwire_single(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
// LTC681x_run_openwire_single(total_ic, ic);
|
||||
}
|
||||
|
||||
//Runs the data sheet algorithm for open wire for multiple cell and two consecutive cells detection
|
||||
void LTC6813_run_openwire_multi(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
// LTC681x_run_openwire_multi( total_ic, ic);
|
||||
}
|
||||
|
||||
//Start an GPIO Redundancy test
|
||||
void LTC6813_adaxd(uint8_t MD, //ADC Mode
|
||||
uint8_t CHG //GPIO Channels to be measured)
|
||||
)
|
||||
{
|
||||
LTC681x_adaxd(MD,CHG);
|
||||
}
|
||||
|
||||
// Start a Status register redundancy test Conversion
|
||||
void LTC6813_adstatd(uint8_t MD, //ADC Mode
|
||||
uint8_t CHST //GPIO Channels to be measured
|
||||
)
|
||||
{
|
||||
LTC681x_adstatd(MD,CHST);
|
||||
}
|
||||
|
||||
//Runs the redundancy self test
|
||||
int16_t LTC6813_run_adc_redundancy_st(uint8_t adc_mode, uint8_t adc_reg, uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
int16_t error = 0;
|
||||
LTC681x_run_adc_redundancy_st(adc_mode,adc_reg,total_ic,ic);
|
||||
return(error);
|
||||
}
|
||||
|
||||
//Sends the poll ADC command
|
||||
uint8_t LTC6813_pladc()
|
||||
{
|
||||
// return(LTC681x_pladc());
|
||||
return(0);
|
||||
}
|
||||
|
||||
//This function will block operation until the ADC has finished it's conversion
|
||||
uint32_t LTC6813_pollAdc()
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
uint8_t finished = 0;
|
||||
uint8_t current_time = 0;
|
||||
uint8_t cmd[4];
|
||||
uint16_t cmd_pec;
|
||||
|
||||
cmd[0] = 0x07;
|
||||
cmd[1] = 0x14;
|
||||
cmd_pec = pec15_calc(2, cmd);
|
||||
cmd[2] = (uint8_t)(cmd_pec >> 8);
|
||||
cmd[3] = (uint8_t)(cmd_pec);
|
||||
|
||||
CS_PIN_LOW();
|
||||
spi_write_array(4,cmd);
|
||||
|
||||
while ((counter < 200000) && (finished == 0))
|
||||
{
|
||||
current_time = spi_read_byte(0xff);
|
||||
if (current_time > 0)
|
||||
finished = 1;
|
||||
else
|
||||
counter = counter + 10;
|
||||
|
||||
delay_os_ms(1);
|
||||
}
|
||||
CS_PIN_HIGH();
|
||||
|
||||
return(counter);
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the cell voltage registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clrcell()
|
||||
{
|
||||
LTC681x_clrcell();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Auxiliary registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clraux()
|
||||
{
|
||||
LTC681x_clraux();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Stat registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clrstat()
|
||||
{
|
||||
LTC681x_clrstat();
|
||||
}
|
||||
|
||||
//Writes the pwm registers of a LTC6813 daisy chain
|
||||
void LTC6813_wrpwm(uint8_t total_ic,
|
||||
uint8_t pwmReg, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the configuration data that will be written
|
||||
)
|
||||
{
|
||||
// LTC681x_wrpwm(total_ic,pwmReg,ic);
|
||||
}
|
||||
|
||||
//Reads pwm registers of a LTC6813 daisy chain
|
||||
int8_t LTC6813_rdpwm(uint8_t total_ic, //Number of ICs in the system
|
||||
uint8_t pwmReg,
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error =0;
|
||||
// pec_error = LTC681x_rdpwm(total_ic,pwmReg,ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Writes data in S control register the ltc6813-1 connected in a daisy chain stack.
|
||||
void LTC6813_wrsctrl(uint8_t total_ic, //< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,
|
||||
cell_asic *ic
|
||||
)
|
||||
{
|
||||
// LTC681x_wrsctrl(total_ic, sctrl_reg, ic);
|
||||
}
|
||||
|
||||
// Reads sctrl registers of a ltc6812 daisy chain
|
||||
int8_t LTC6813_rdsctrl(uint8_t total_ic, //< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,
|
||||
cell_asic *ic //< a two dimensional array that the function stores the read pwm data
|
||||
)
|
||||
{
|
||||
// LTC681x_rdsctrl( total_ic, sctrl_reg,ic );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
*/
|
||||
void LTC6813_stsctrl()
|
||||
{
|
||||
// LTC681x_stsctrl();
|
||||
}
|
||||
|
||||
/*
|
||||
The command clears the Sctrl registers and initializes
|
||||
all values to 0. The register will read back hexadecimal 0x00
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC6813_clrsctrl()
|
||||
{
|
||||
// LTC681x_clrsctrl();
|
||||
}
|
||||
|
||||
//Writes the COMM registers of a LTC6813 daisy chain
|
||||
void LTC6813_wrcomm(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic *ic //A two dimensional array of the comm data that will be written
|
||||
)
|
||||
{
|
||||
// LTC681x_wrcomm(total_ic,ic);
|
||||
}
|
||||
|
||||
// Reads COMM registers of a LTC6813 daisy chain
|
||||
int8_t LTC6813_rdcomm(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic *ic //A two dimensional array that the function stores the read configuration data.
|
||||
)
|
||||
{
|
||||
int8_t pec_error = 0;
|
||||
// LTC681x_rdcomm(total_ic, ic);
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
// Shifts data in COMM register out over LTC6813 SPI/I2C port
|
||||
void LTC6813_stcomm()
|
||||
{
|
||||
// LTC681x_stcomm();
|
||||
}
|
||||
|
||||
//Helper function to set discharge bit in CFG register
|
||||
void LTC6813_set_discharge(int Cell, uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
for (int i=0; i<total_ic; i++)
|
||||
{
|
||||
if (Cell==0)
|
||||
{
|
||||
ic[i].configb.tx_data[1] = ic[i].configb.tx_data[1] |(0x04);
|
||||
}
|
||||
else if (Cell<9)
|
||||
{
|
||||
ic[i].config.tx_data[4] = ic[i].config.tx_data[4] | (1<<(Cell-1));
|
||||
}
|
||||
else if (Cell < 13)
|
||||
{
|
||||
ic[i].config.tx_data[5] = ic[i].config.tx_data[5] | (1<<(Cell-9));
|
||||
}
|
||||
else if (Cell<17)
|
||||
{
|
||||
ic[i].configb.tx_data[0] = ic[i].configb.tx_data[0] | (1<<(Cell-9));
|
||||
}
|
||||
else if (Cell<19)
|
||||
{
|
||||
ic[i].configb.tx_data[1] = ic[i].configb.tx_data[1] | (1<<(Cell-17));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Clears all of the DCC bits in the configuration registers
|
||||
void LTC6813_clear_discharge(uint8_t total_ic,
|
||||
cell_asic *ic)
|
||||
{
|
||||
// LTC681x_clear_discharge(total_ic,ic);
|
||||
|
||||
}
|
||||
|
||||
//Helper function that increments PEC counters
|
||||
void LTC6813_check_pec(uint8_t total_ic,uint8_t reg, cell_asic *ic)
|
||||
{
|
||||
LTC681x_check_pec(total_ic,reg,ic);
|
||||
}
|
||||
|
||||
//Helper Function to reset PEC counters
|
||||
void LTC6813_reset_crc_count(uint8_t total_ic, cell_asic *ic)
|
||||
{
|
||||
LTC681x_reset_crc_count(total_ic,ic);
|
||||
}
|
||||
|
||||
// Write the 6813 PWM/S ctrl Register B
|
||||
void LTC6813_wrpsb(uint8_t total_ic,cell_asic *ic)
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
uint8_t write_buffer[256];
|
||||
uint8_t c_ic = 0;
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x1C;
|
||||
for(uint8_t current_ic = 0; current_ic<total_ic;current_ic++)
|
||||
{
|
||||
if(ic->isospi_reverse == true){c_ic = current_ic;}
|
||||
else{c_ic = total_ic - current_ic - 1;}
|
||||
|
||||
write_buffer[0] = ic[c_ic].pwmb.tx_data[0];
|
||||
write_buffer[1] = ic[c_ic].pwmb.tx_data[1];
|
||||
write_buffer[2]= ic[c_ic].pwmb.tx_data[2];
|
||||
write_buffer[3] = ic[c_ic].sctrlb.tx_data[3];
|
||||
write_buffer[4] = ic[c_ic].sctrlb.tx_data[4];
|
||||
write_buffer[5]= ic[c_ic].sctrlb.tx_data[5];
|
||||
}
|
||||
write_68(total_ic, cmd, write_buffer);
|
||||
}
|
||||
|
||||
//Reading pwm/s control register b
|
||||
uint8_t LTC6813_rdpsb(uint8_t total_ic, //< number of ICs in the daisy chain
|
||||
cell_asic *ic //< a two dimensional array that the function stores the read pwm data
|
||||
)
|
||||
{
|
||||
uint8_t cmd[4];
|
||||
uint8_t read_buffer[256];
|
||||
int8_t pec_error = 0;
|
||||
uint16_t data_pec;
|
||||
uint16_t calc_pec;
|
||||
uint8_t c_ic = 0;
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x1E;
|
||||
pec_error = read_68(total_ic, cmd, read_buffer);
|
||||
|
||||
for(uint8_t current_ic =0; current_ic<total_ic; current_ic++)
|
||||
{
|
||||
if(ic->isospi_reverse == false){c_ic = current_ic;}
|
||||
else{c_ic = total_ic - current_ic - 1;}
|
||||
for(int byte=0; byte<3;byte++)
|
||||
{
|
||||
ic[c_ic].pwmb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
|
||||
for(int byte=3; byte<6;byte++)
|
||||
{
|
||||
ic[c_ic].sctrlb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
|
||||
for(int byte=6; byte<8;byte++)
|
||||
{
|
||||
ic[c_ic].pwmb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
ic[c_ic].sctrlb.rx_data[byte] = read_buffer[byte+(8*current_ic)];
|
||||
}
|
||||
|
||||
calc_pec = pec15_calc(6,&read_buffer[8*current_ic]);
|
||||
data_pec = read_buffer[7+(8*current_ic)] | (read_buffer[6+(8*current_ic)]<<8);
|
||||
if(calc_pec != data_pec )
|
||||
{
|
||||
ic[c_ic].pwmb.rx_pec_match = 1;
|
||||
ic[c_ic].sctrlb.rx_pec_match = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ic[c_ic].pwmb.rx_pec_match = 0;
|
||||
ic[c_ic].sctrlb.rx_pec_match = 0;
|
||||
|
||||
}
|
||||
}
|
||||
return(pec_error);
|
||||
}
|
||||
|
||||
//Mutes the LTC6813 discharge transistors
|
||||
void LTC6813_mute()
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x28;
|
||||
|
||||
cmd_68(cmd);
|
||||
}
|
||||
|
||||
//Clears the LTC6813 Mute Discharge
|
||||
void LTC6813_unmute()
|
||||
{
|
||||
uint8_t cmd[2];
|
||||
|
||||
cmd[0] = 0x00;
|
||||
cmd[1] = 0x29;
|
||||
cmd_68(cmd);
|
||||
}
|
||||
516
APP_R3323/App/Hardware/ltc6813.h
Normal file
516
APP_R3323/App/Hardware/ltc6813.h
Normal file
@@ -0,0 +1,516 @@
|
||||
/*! LTC6813: Multicell Battery Monitors
|
||||
*
|
||||
*@verbatim
|
||||
*The LTC6813 is multicell battery stack monitor that measures up to 18 series
|
||||
*connected battery cells with a total measurement error of less than 2.2mV.
|
||||
*The cell measurement range of 0V to 5V makes the LTC6813 suitable for most
|
||||
*battery chemistries. All 18 cell voltages can be captured in 290uS, and lower
|
||||
*data acquisition rates can be selected for high noise reduction.
|
||||
*Using the LTC6813-1, multiple devices are connected in a daisy-chain with one
|
||||
*host processor connection for all devices, permitting simultaneous cell monitoring
|
||||
*of long, high voltage battery strings.
|
||||
*@endverbatim
|
||||
*
|
||||
* https://www.analog.com/en/products/ltc6813-1.html
|
||||
* https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/dc2350a-b.html
|
||||
*
|
||||
*********************************************************************************
|
||||
* Copyright 2019(c) Analog Devices, Inc.
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* - Neither the name of Analog Devices, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* - The use of this software may or may not infringe the patent rights
|
||||
* of one or more patent holders. This license does not release you
|
||||
* from the requirement that you obtain separate licenses from these
|
||||
* patent holders to use this software.
|
||||
* - Use of the software either in source or binary form, must be run
|
||||
* on or directly connected to an Analog Devices Inc. component.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************/
|
||||
|
||||
/*! @file
|
||||
@ingroup LTC6813-1
|
||||
Header for LTC6813-1 Multicell Battery Monitor
|
||||
*/
|
||||
|
||||
#ifndef LTC6813_H
|
||||
#define LTC6813_H
|
||||
|
||||
#include "stdint.h"
|
||||
#include "LTC681x.h"
|
||||
|
||||
#define CELL 1
|
||||
#define AUX 2
|
||||
#define STAT 3
|
||||
|
||||
/*! Helper function to initialize register limits */
|
||||
//!@return void
|
||||
void LTC6813_init_reg_limits(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function to initialize the CFGR data structures*/
|
||||
//!@return void
|
||||
void LTC6813_init_cfg(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function to set appropriate bits in CFGR register based on bit function*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon, //!< the REFON bit
|
||||
bool adcopt, //!< the ADCOPT bit
|
||||
uint8_t gpio, //!< the GPIO bits
|
||||
uint16_t dcc, //!< the DCC bits
|
||||
uint8_t dcto, //!< the Dcto bits
|
||||
uint16_t uv, //!< the UV value
|
||||
uint16_t ov //!< the OV value
|
||||
);
|
||||
|
||||
/*! Helper function to turn the refon bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_refon(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool refon //!< the REFON bit
|
||||
);
|
||||
|
||||
/*! Helper function to turn the ADCOPT bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_adcopt(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool adcopt //!< the ADCOPT bit
|
||||
);
|
||||
|
||||
/*! Helper function to turn the GPIO bits HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_gpio(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t gpio //!< the GPIO bits
|
||||
);
|
||||
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_dis(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t dcc //!< the DCC bits
|
||||
);
|
||||
|
||||
/*! Helper function to set uv field in CFGRA register*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_uv(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t uv //!< the UV value
|
||||
);
|
||||
|
||||
/*! Helper function to set DCTO field in CFGRA register*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_dcto(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t dcto //!< the Dcto bits
|
||||
);
|
||||
|
||||
/*! Helper function to set ov field in CFGRA register*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgr_ov(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t ov //!< the OV value
|
||||
);
|
||||
|
||||
/*! Helper Function to initialize the CFGR B data structures*/
|
||||
//!@return void
|
||||
void LTC6813_init_cfgb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function to set appropriate bits in CFGR register based on bit function*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgrb(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool fdrf, //!< the FDRF bit
|
||||
bool dtmen, //!< the DTMEN bit
|
||||
bool ps[2], //!< Path selection bits
|
||||
uint8_t gpiobits, //!< the GPIO bits
|
||||
uint16_t dccbits //!< the DCC bits - 7bits
|
||||
);
|
||||
|
||||
/*! Helper function to turn the fdrf bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgrb_fdrf(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool fdrf //!< the FDRF bit
|
||||
);
|
||||
|
||||
/*! Helper function to turn the DTMEN bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgrb_dtmen(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool dtmen //!< the DTMEN bit
|
||||
);
|
||||
|
||||
/*! Helper function to turn the Path Select bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgrb_ps(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
bool ps[] //!< Path selection bits
|
||||
);
|
||||
|
||||
/*! Helper function to turn the GPIO bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgrb_gpio_b(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t gpiobits //!< the GPIO bits
|
||||
);
|
||||
|
||||
/*! Helper function to turn the dcc bit HIGH or LOW*/
|
||||
//!@return void
|
||||
void LTC6813_set_cfgrb_dcc_b(uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint16_t dccbits //!< the DCC bits - 7bits
|
||||
);
|
||||
|
||||
/*! Write the LTC6813 configuration register A*/
|
||||
//!@return void
|
||||
void LTC6813_wrcfg(uint8_t nIC, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*! Write the LTC6813 configuration register B*/
|
||||
//!@return void
|
||||
void LTC6813_wrcfgb(uint8_t nIC, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*! Reads configuration register A of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC */
|
||||
int8_t LTC6813_rdcfg(uint8_t nIC, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array that the function stores the read configuration data
|
||||
);
|
||||
|
||||
/*! Reads configuration register B of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC */
|
||||
int8_t LTC6813_rdcfgb(uint8_t nIC, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< a two dimensional array that the function stores the read configuration data
|
||||
);
|
||||
|
||||
/*! Starts cell voltage conversion */
|
||||
//!@return void
|
||||
void LTC6813_adcv(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP, //!< Controls if Discharge is permitted during conversion
|
||||
uint8_t CH //!< Sets which Cell channels are converted
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC6813 cell voltage registers.
|
||||
@return uint8_t, PEC Status.
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
uint8_t LTC6813_rdcv(uint8_t reg, //!< controls which cell voltage register is read back.
|
||||
uint8_t total_ic, //!< the number of ICs in the daisy chain(-1 only)
|
||||
cell_asic *ic //!< array of the parsed cell codes from lowest to highest.
|
||||
);
|
||||
|
||||
/*! Start a GPIO and Vref2 Conversion */
|
||||
//!@return void
|
||||
void LTC6813_adax(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC6813 auxiliary registers.
|
||||
@return int8_t, PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t LTC6813_rdaux(uint8_t reg, //!< controls which GPIO voltage register is read back
|
||||
uint8_t nIC, //!< the number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array of the parsed gpio voltage codes
|
||||
);
|
||||
|
||||
/*! Start a Status ADC Conversion */
|
||||
//!@return void
|
||||
void LTC6813_adstat( uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHST //!< Sets which Stat channels are converted
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC6813 stat registers.
|
||||
@return int8_t, PEC Status
|
||||
0: No PEC error detected
|
||||
-1: PEC error detected, retry read
|
||||
*/
|
||||
int8_t LTC6813_rdstat(uint8_t reg, //!< Determines which Stat register is read back.
|
||||
uint8_t total_ic,//!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and GPIO 1&2 conversion */
|
||||
//!@return void
|
||||
void LTC6813_adcvax(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and SOC conversion */
|
||||
//!@return void
|
||||
void LTC6813_adcvsc(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
/*! Starts the Mux Decoder diagnostic self test
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
*/
|
||||
//!@return void
|
||||
void LTC6813_diagn(void);
|
||||
|
||||
/*! Starts cell voltage self test conversion */
|
||||
//!@return void
|
||||
void LTC6813_cvst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Self Test Mode
|
||||
);
|
||||
|
||||
/*! Start an Auxiliary Register Self Test Conversion */
|
||||
//!@return void
|
||||
void LTC6813_axst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*! Start a Status Register Self Test Conversion */
|
||||
//!@return void
|
||||
void LTC6813_statst(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
/*! Helper function that runs the ADC Self Tests*/
|
||||
//!@return int16_t, error
|
||||
//! Number of errors detected.
|
||||
int16_t LTC6813_run_cell_adc_st(uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic, //!< A two dimensional array that will store the data
|
||||
uint8_t md, //!< ADC Mode
|
||||
bool adcopt //!< the adcopt bit in the configuration register
|
||||
);
|
||||
|
||||
/*! Starts cell voltage overlap conversion */
|
||||
//!@return void
|
||||
void LTC6813_adol(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*! Helper Function that runs the ADC Overlap test*/
|
||||
//!@return uint16_t, error
|
||||
//! 0: Pass
|
||||
//!-1: False, Error detected
|
||||
uint16_t LTC6813_run_adc_overlap(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Start an open wire Conversion
|
||||
*/
|
||||
//!@return void
|
||||
void LTC6813_adow(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t PUP,//!< Controls if Discharge is permitted during
|
||||
uint8_t CH, //!< Sets which Cell channels are converted
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*! start GPIOs open wire ADC conversion */
|
||||
//!@return void
|
||||
void LTC6813_axow(uint8_t MD, //!< ADC Mode
|
||||
uint8_t PUP //!< Discharge Permit
|
||||
);
|
||||
|
||||
/*! Runs open wire for GPIOs*/
|
||||
//!@return void
|
||||
void LTC6813_run_gpio_openwire(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function that runs the data sheet algorithm for open wire for single cell detection*/
|
||||
//!@return void
|
||||
void LTC6813_run_openwire_single(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper function that runs open wire for multiple cell and two consecutive cells detection*/
|
||||
//!@return void
|
||||
void LTC6813_run_openwire_multi(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Start an GPIO Redundancy test */
|
||||
//!@return void
|
||||
void LTC6813_adaxd(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Start a Status register redundancy test Conversion */
|
||||
//!@return void
|
||||
void LTC6813_adstatd(uint8_t MD, //!< ADC Mode
|
||||
uint8_t CHST //!< Sets which Status channels are converted
|
||||
);
|
||||
|
||||
/*! Helper function that runs the ADC Digital Redundancy commands and checks output for errors*/
|
||||
//!@return int16_t, error
|
||||
int16_t LTC6813_run_adc_redundancy_st(uint8_t adc_mode, //!< ADC Mode
|
||||
uint8_t adc_reg, //!< Type of register
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
//! Sends the poll ADC command
|
||||
//! @returns 1 byte read back after a pladc command. If the byte is not 0xFF ADC conversion has completed
|
||||
uint8_t LTC6813_pladc(void);
|
||||
|
||||
//! This function will block operation until the ADC has finished it's conversion
|
||||
//! @returns the approximate time it took for the ADC function to complete.
|
||||
uint32_t LTC6813_pollAdc(void);
|
||||
|
||||
/*! Clears the LTC6813 cell voltage registers */
|
||||
//!@return void
|
||||
void LTC6813_clrcell(void);
|
||||
|
||||
/*! Clears the LTC6813 Auxiliary registers */
|
||||
//!@return void
|
||||
void LTC6813_clraux(void);
|
||||
|
||||
/*! Clears the LTC6813 Stat registers */
|
||||
//!@return void
|
||||
void LTC6813_clrstat(void);
|
||||
|
||||
/*! Write the LTC6813 PWM register */
|
||||
//!@return void
|
||||
void LTC6813_wrpwm(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t pwmReg, //!< PWM Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Reads pwm registers of a LTC6813 daisy chain */
|
||||
//!@return int8_t, PEC Status.
|
||||
//! 0: Data read back has matching PEC
|
||||
//! -1: Data read back has incorrect PEC
|
||||
int8_t LTC6813_rdpwm(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t pwmReg, //! PWM Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Write the LTC6813 Sctrl register */
|
||||
//!@return void
|
||||
void LTC6813_wrsctrl(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,//! SCTRL Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Reads sctrl registers of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t LTC6813_rdsctrl(uint8_t nIC, //!< number of ICs in the daisy chain
|
||||
uint8_t sctrl_reg,//! SCTRL Register A or B
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Start Sctrl data communication
|
||||
This command will start the sctrl pulse communication over the spins
|
||||
*/
|
||||
//!@return void
|
||||
void LTC6813_stsctrl(void);
|
||||
|
||||
/*! Clears the LTC6813 Sctrl registers */
|
||||
//!@return void
|
||||
void LTC6813_clrsctrl(void);
|
||||
|
||||
/*! Write the LTC6813 COMM register */
|
||||
//!@return void
|
||||
void LTC6813_wrcomm(uint8_t total_ic, //!< Number of ICs in the daisy chain
|
||||
cell_asic *ic //!< A two dimensional array of the comm data that will be written
|
||||
);
|
||||
|
||||
/*! Reads comm registers of a LTC6813 daisy chain
|
||||
@return int8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
int8_t LTC6813_rdcomm(uint8_t total_ic, //!< number of ICs in the daisy chain
|
||||
cell_asic *ic //!< Two dimensional array that the function stores the read comm data.
|
||||
);
|
||||
|
||||
/*! Issues a stcomm command and clocks data out of the COMM register */
|
||||
//!@return void
|
||||
void LTC6813_stcomm(void);
|
||||
|
||||
/*! Helper Function to Set DCC bits in the CFGR Registers*/
|
||||
//!@return void
|
||||
void LTC6813_set_discharge(int Cell, //!< The cell to be discharged
|
||||
uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function to clear DCC bits in the CFGR Registers*/
|
||||
//!@return void
|
||||
void LTC6813_clear_discharge(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function that counts overall PEC errors and register/IC PEC errors*/
|
||||
//!@return void
|
||||
void LTC6813_check_pec(uint8_t total_ic, //!< Number of ICs in the system
|
||||
uint8_t reg, //!< Type of register
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Helper Function that resets the PEC error counters */
|
||||
//!@return void
|
||||
void LTC6813_reset_crc_count(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Write the 6813 PWM/Sctrl Register B */
|
||||
//!@return void
|
||||
void LTC6813_wrpsb(uint8_t total_ic, //!< Number of ICs in the system
|
||||
cell_asic *ic //!< A two dimensional array that will store the data
|
||||
);
|
||||
|
||||
/*! Reading pwm/s control register B
|
||||
@return uint8_t, PEC Status.
|
||||
0: Data read back has matching PEC
|
||||
-1: Data read back has incorrect PEC
|
||||
*/
|
||||
uint8_t LTC6813_rdpsb(uint8_t total_ic, //!< number of ICs in the daisy chain
|
||||
cell_asic *ic //!< a two dimensional array that the function stores the read pwm data
|
||||
);
|
||||
|
||||
/*! Mutes the LTC6813 discharge transistors */
|
||||
//!@return void
|
||||
void LTC6813_mute(void);
|
||||
|
||||
/*! Clears the LTC6813 Mute Discharge */
|
||||
//!@return void
|
||||
void LTC6813_unmute(void);
|
||||
|
||||
#endif
|
||||
1322
APP_R3323/App/Hardware/ltc681x.c
Normal file
1322
APP_R3323/App/Hardware/ltc681x.c
Normal file
File diff suppressed because it is too large
Load Diff
519
APP_R3323/App/Hardware/ltc681x.h
Normal file
519
APP_R3323/App/Hardware/ltc681x.h
Normal file
@@ -0,0 +1,519 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : ltc681x.h
|
||||
* Description : This file provides code for the configuration
|
||||
* of ltc681x driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2021 Amogreentech Co., Ltd.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _LTC681X_H_
|
||||
#define _LTC681X_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported define -----------------------------------------------------------*/
|
||||
#define IC_LTC6813
|
||||
|
||||
#define MD_422HZ_1KHZ 0
|
||||
#define MD_27KHZ_14KHZ 1
|
||||
#define MD_7KHZ_3KHZ 2
|
||||
#define MD_26HZ_2KHZ 3
|
||||
|
||||
#define ADC_OPT_ENABLED 1
|
||||
#define ADC_OPT_DISABLED 0
|
||||
|
||||
#define CELL_CH_ALL 0
|
||||
#define CELL_CH_1and7 1
|
||||
#define CELL_CH_2and8 2
|
||||
#define CELL_CH_3and9 3
|
||||
#define CELL_CH_4and10 4
|
||||
#define CELL_CH_5and11 5
|
||||
#define CELL_CH_6and12 6
|
||||
|
||||
#define SELFTEST_1 1
|
||||
#define SELFTEST_2 2
|
||||
|
||||
#define AUX_CH_ALL 0
|
||||
#define AUX_CH_GPIO1 1
|
||||
#define AUX_CH_GPIO2 2
|
||||
#define AUX_CH_GPIO3 3
|
||||
#define AUX_CH_GPIO4 4
|
||||
#define AUX_CH_GPIO5 5
|
||||
#define AUX_CH_VREF2 6
|
||||
|
||||
#define STAT_CH_ALL 0
|
||||
#define STAT_CH_SOC 1
|
||||
#define STAT_CH_ITEMP 2
|
||||
#define STAT_CH_VREGA 3
|
||||
#define STAT_CH_VREGD 4
|
||||
|
||||
#define DCP_DISABLED 0
|
||||
#define DCP_ENABLED 1
|
||||
|
||||
#define PULL_UP_CURRENT 1
|
||||
#define PULL_DOWN_CURRENT 0
|
||||
|
||||
#define NUM_RX_BYT 8
|
||||
#define CELL 1
|
||||
#define AUX 2
|
||||
#define STAT 3
|
||||
#define CFGR 0
|
||||
#define CFGRB 4
|
||||
|
||||
#define CS_PIN_HIGH SPI1_NSS_HIGH
|
||||
#define CS_PIN_LOW SPI1_NSS_LOW
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
//! Cell Voltage data structure.
|
||||
typedef struct
|
||||
{
|
||||
uint16_t c_codes[18]; //!< Cell Voltage Codes
|
||||
uint8_t pec_match[6]; //!< If a PEC error was detected during most recent read cmd
|
||||
} cv;
|
||||
|
||||
//! AUX Reg Voltage Data
|
||||
typedef struct
|
||||
{
|
||||
uint16_t a_codes[12]; //!< Aux Voltage Codes
|
||||
uint8_t pec_match[4]; //!< If a PEC error was detected during most recent read cmd
|
||||
} ax;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t stat_codes[4]; //!< A two dimensional array of the stat voltage codes.
|
||||
uint8_t flags[3]; //!< byte array that contains the uv/ov flag data
|
||||
uint8_t mux_fail[1]; //!< Mux self test status flag
|
||||
uint8_t thsd[1]; //!< Thermal shutdown status
|
||||
uint8_t pec_match[2]; //!< If a PEC error was detected during most recent read cmd
|
||||
} st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t tx_data[6];
|
||||
uint8_t rx_data[8];
|
||||
uint8_t rx_pec_match; //!< If a PEC error was detected during most recent read cmd
|
||||
} ic_register;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t pec_count;
|
||||
uint16_t cfgr_pec;
|
||||
uint16_t cell_pec[6];
|
||||
uint16_t aux_pec[4];
|
||||
uint16_t stat_pec[2];
|
||||
} pec_counter;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cell_channels;
|
||||
uint8_t stat_channels;
|
||||
uint8_t aux_channels;
|
||||
uint8_t num_cv_reg;
|
||||
uint8_t num_gpio_reg;
|
||||
uint8_t num_stat_reg;
|
||||
} register_cfg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ic_register config;
|
||||
ic_register configb;
|
||||
cv cells;
|
||||
ax aux;
|
||||
st stat;
|
||||
ic_register com;
|
||||
ic_register pwm;
|
||||
ic_register pwmb;
|
||||
ic_register sctrl;
|
||||
ic_register sctrlb;
|
||||
bool isospi_reverse;
|
||||
pec_counter crc_count;
|
||||
register_cfg ic_reg;
|
||||
long system_open_wire;
|
||||
} cell_asic;
|
||||
|
||||
/* Exported variables ------------------------------------------------------- */
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
/*! calculates and returns the CRC15
|
||||
@returns The calculated pec15 as an unsigned int
|
||||
*/
|
||||
uint16_t pec15_calc(uint8_t len, //!< the length of the data array being passed to the function
|
||||
uint8_t *data //!< the array of data that the PEC will be generated from
|
||||
);
|
||||
|
||||
/*! Wake isoSPI up from idle state */
|
||||
void wakeup_idle(uint8_t total_ic);//!< number of ICs in the daisy chain
|
||||
|
||||
/*! Wake the LTC6813 from the sleep state */
|
||||
void wakeup_sleep(uint8_t total_ic); //!< number of ICs in the daisy chain
|
||||
|
||||
/*! Sense a command to the bms IC. This code will calculate the PEC code for the transmitted command*/
|
||||
void cmd_68(uint8_t tx_cmd[2]); //!< 2 Byte array containing the BMS command to be sent
|
||||
|
||||
//! Writes an array of data to the daisy chain
|
||||
void write_68(uint8_t total_ic , //!< number of ICs in the daisy chain
|
||||
uint8_t tx_cmd[2], //!< 2 Byte array containing the BMS command to be sent
|
||||
uint8_t data[] //!< Array containing the data to be written to the BMS ICs
|
||||
);
|
||||
//! Issues a command onto the daisy chain and reads back 6*total_ic data in the rx_data array
|
||||
int8_t read_68( uint8_t total_ic, //!< number of ICs in the daisy chain
|
||||
uint8_t tx_cmd[2], //!< 2 Byte array containing the BMS command to be sent
|
||||
uint8_t *rx_data); //!< Array that the read back data will be stored.
|
||||
|
||||
/*! Starts the Mux Decoder diagnostic self test
|
||||
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
*/
|
||||
void LTC681x_diagn(void);
|
||||
|
||||
/*! Starts cell voltage conversion
|
||||
|
||||
Starts ADC conversions of the LTC6811 Cpin inputs.
|
||||
The type of ADC conversion executed can be changed by setting the following parameters:
|
||||
*/
|
||||
void LTC681x_adcv(uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP, //!< Controls if Discharge is permitted during conversion
|
||||
uint8_t CH //!< Sets which Cell channels are converted
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and GPIO 1&2 conversion
|
||||
*/
|
||||
void LTC681x_adcvax(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
|
||||
/*! Starts cell voltage self test conversion
|
||||
*/
|
||||
void LTC681x_cvst(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Self Test Mode
|
||||
);
|
||||
|
||||
/*! Starts cell voltage and SOC conversion
|
||||
*/
|
||||
void LTC681x_adcvsc(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
/*! Starts cell voltage overlap conversion
|
||||
*/
|
||||
void LTC681x_adol(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t DCP //!< Discharge permitted during conversion
|
||||
);
|
||||
|
||||
/*! Start an open wire Conversion
|
||||
*/
|
||||
void LTC681x_adow(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t PUP //!< Controls if Discharge is permitted during conversion
|
||||
);
|
||||
|
||||
|
||||
/*! Start a GPIO and Vref2 Conversion
|
||||
*/
|
||||
void LTC681x_adax(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Start an GPIO Redundancy test
|
||||
*/
|
||||
void LTC681x_adaxd(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHG //!< Sets which GPIO channels are converted
|
||||
);
|
||||
|
||||
/*! Start an Auxiliary Register Self Test Conversion
|
||||
*/
|
||||
void LTC681x_axst(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
|
||||
|
||||
/*! Start a Status ADC Conversion
|
||||
*/
|
||||
void LTC681x_adstat(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t CHST //!< Sets which Stat channels are converted
|
||||
);
|
||||
|
||||
/*! Start a Status register redundancy test Conversion
|
||||
*/
|
||||
void LTC681x_adstatd(
|
||||
uint8_t MD, //!< ADC Mode
|
||||
uint8_t CHST //!< Sets which Status channels are converted
|
||||
);
|
||||
|
||||
|
||||
/*! Start a Status Register Self Test Conversion
|
||||
*/
|
||||
void LTC681x_statst(
|
||||
uint8_t MD, //!< ADC Conversion Mode
|
||||
uint8_t ST //!< Sets if self test 1 or 2 is run
|
||||
);
|
||||
|
||||
void LTC681x_rdcv_reg(uint8_t reg, //!<Determines which cell voltage register is read back
|
||||
uint8_t total_ic, //!<the number of ICs in the
|
||||
uint8_t *data //!<An array of the unparsed cell codes
|
||||
);
|
||||
/*! helper function that parses voltage measurement registers
|
||||
*/
|
||||
int8_t parse_cells(uint8_t current_ic,
|
||||
uint8_t cell_reg,
|
||||
uint8_t cell_data[],
|
||||
uint16_t *cell_codes,
|
||||
uint8_t *ic_pec);
|
||||
|
||||
/*! helper function that parses aux volatge measurement registers
|
||||
*/
|
||||
int8_t parse_auxs(uint8_t current_ic,
|
||||
uint8_t aux_reg,
|
||||
uint8_t aux_data[],
|
||||
uint16_t *aux_codes,
|
||||
uint8_t *ic_pec);
|
||||
|
||||
/*! Read the raw data from the LTC681x auxiliary register
|
||||
|
||||
The function reads a single GPIO voltage register and stores thre read data
|
||||
in the *data point as a byte array. This function is rarely used outside of
|
||||
the LTC681x_rdaux(void) command.
|
||||
*/
|
||||
void LTC681x_rdaux_reg( uint8_t reg, //Determines which GPIO voltage register is read back
|
||||
uint8_t total_ic, //The number of ICs in the system
|
||||
uint8_t *data //Array of the unparsed auxiliary codes
|
||||
);
|
||||
/*! Read the raw data from the LTC681x stat register
|
||||
|
||||
The function reads a single GPIO voltage register and stores thre read data
|
||||
in the *data point as a byte array. This function is rarely used outside of
|
||||
the LTC681x_rdstat(void) command.
|
||||
*/
|
||||
void LTC681x_rdstat_reg(uint8_t reg, //Determines which stat register is read back
|
||||
uint8_t total_ic, //The number of ICs in the system
|
||||
uint8_t *data //Array of the unparsed stat codes
|
||||
);
|
||||
|
||||
/*! Clears the LTC681x cell voltage registers
|
||||
|
||||
The command clears the cell voltage registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clrcell(void);
|
||||
/*! Clears the LTC681x Auxiliary registers
|
||||
|
||||
The command clears the Auxiliary registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clraux(void);
|
||||
|
||||
/*! Clears the LTC681x Stat registers
|
||||
|
||||
The command clears the Stat registers and initializes
|
||||
all values to 1. The register will read back hexadecimal 0xFF
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clrstat(void);
|
||||
|
||||
/*! Clears the LTC681x SCTRL registers
|
||||
|
||||
The command clears the SCTRL registers and initializes
|
||||
all values to 0. The register will read back hexadecimal 0x00
|
||||
after the command is sent.
|
||||
*/
|
||||
void LTC681x_clrsctrl(void);
|
||||
|
||||
/*! Starts the Mux Decoder diagnostic self test
|
||||
|
||||
Running this command will start the Mux Decoder Diagnostic Self Test
|
||||
This test takes roughly 1mS to complete. The MUXFAIL bit will be updated,
|
||||
the bit will be set to 1 for a failure and 0 if the test has been passed.
|
||||
*/
|
||||
void LTC681x_diagn(void);
|
||||
|
||||
/*! Reads and parses the LTC681x cell voltage registers.
|
||||
|
||||
The function is used to read the cell codes of the LTC6811.
|
||||
This function will send the requested read commands parse the data
|
||||
and store the cell voltages in the cell_asic structure.
|
||||
*/
|
||||
uint8_t LTC681x_rdcv(uint8_t reg, // Controls which cell voltage register is read back.
|
||||
uint8_t total_ic, // the number of ICs in the system
|
||||
cell_asic ic[] // Array of the parsed cell codes
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC681x auxiliary registers.
|
||||
|
||||
The function is used to read the parsed GPIO codes of the LTC6811. This function will send the requested
|
||||
read commands parse the data and store the gpio voltages in the cell_asic structure.
|
||||
*/
|
||||
int8_t LTC681x_rdaux(uint8_t reg, //Determines which GPIO voltage register is read back.
|
||||
uint8_t total_ic,//the number of ICs in the system
|
||||
cell_asic ic[]//!< Measurement Data Structure
|
||||
);
|
||||
|
||||
/*! Reads and parses the LTC681x stat registers.
|
||||
|
||||
The function is used to read the parsed status codes of the LTC6811. This function will send the requested
|
||||
read commands parse the data and store the status voltages in the cell_asic structure
|
||||
*/
|
||||
int8_t LTC681x_rdstat( uint8_t reg, //!<Determines which Stat register is read back.
|
||||
uint8_t total_ic,//!<the number of ICs in the system
|
||||
cell_asic ic[]//!< Measurement Data Structure
|
||||
);
|
||||
/*! Write the LTC681x CFGRA
|
||||
|
||||
This command will write the configuration registers of the LTC681xs
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void LTC681x_wrcfg(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic ic[] //A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*! Write the LTC681x CFGRB
|
||||
|
||||
This command will write the configuration registers of the LTC681xs
|
||||
connected in a daisy chain stack. The configuration is written in descending
|
||||
order so the last device's configuration is written first.
|
||||
*/
|
||||
void LTC681x_wrcfgb(uint8_t total_ic, //The number of ICs being written to
|
||||
cell_asic ic[] //A two dimensional array of the configuration data that will be written
|
||||
);
|
||||
|
||||
/*! Reads the LTC681x CFGRA register
|
||||
*/
|
||||
int8_t LTC681x_rdcfg(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic ic[] //A two dimensional array that the function stores the read configuration data.
|
||||
);
|
||||
|
||||
/*! Reads the LTC681x CFGRB register
|
||||
*/
|
||||
int8_t LTC681x_rdcfgb(uint8_t total_ic, //Number of ICs in the system
|
||||
cell_asic ic[] //A two dimensional array that the function stores the read configuration data.
|
||||
);
|
||||
|
||||
/*! Selft Test Helper Function*/
|
||||
uint16_t LTC681x_st_lookup(
|
||||
uint8_t MD, //ADC Mode
|
||||
uint8_t ST //Self Test
|
||||
);
|
||||
|
||||
/*! Helper Function to clear DCC bits in the CFGR Registers*/
|
||||
void clear_discharge(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function that runs the ADC Self Tests*/
|
||||
int16_t LTC681x_run_cell_adc_st(uint8_t adc_reg,
|
||||
uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function that runs the ADC Digital Redudancy commands and checks output for errors*/
|
||||
int16_t LTC681x_run_adc_redundancy_st(uint8_t adc_mode,
|
||||
uint8_t adc_reg,
|
||||
uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function that runs the datasheet open wire algorithm*/
|
||||
void LTC681x_run_openwire(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper Function that counts overall PEC errors and register/IC PEC errors*/
|
||||
void LTC681x_check_pec(uint8_t total_ic,
|
||||
uint8_t reg,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper Function that resets the PEC error counters */
|
||||
void LTC681x_reset_crc_count(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper Function to initialize the CFGR data structures*/
|
||||
void LTC681x_init_cfg(uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
/*! Helper function to set appropriate bits in CFGR register based on bit function*/
|
||||
void LTC681x_set_cfgr(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool refon,
|
||||
bool adcopt,
|
||||
bool gpio[5],
|
||||
uint16_t dcc);
|
||||
|
||||
/*! Helper function to turn the refon bit HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_refon(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool refon);
|
||||
|
||||
/*! Helper function to turn the ADCOPT bit HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_adcopt(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool adcopt);
|
||||
|
||||
/*! Helper function to turn the GPIO bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_gpio(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
bool gpio[]);
|
||||
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_dis(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
uint16_t dcc);
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_dcto(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
uint8_t dcto);
|
||||
/*! Helper function to turn the DCC bits HIGH or LOW*/
|
||||
void LTC681x_set_cfgr_uv(uint8_t nIC,
|
||||
cell_asic ic[],
|
||||
uint16_t UV);
|
||||
|
||||
|
||||
//********************************** LTC6811 ******************************************//
|
||||
void LTC6811_init_reg_limits(uint8_t total_ic, cell_asic ic[]);
|
||||
|
||||
void LTC6811_set_discharge(int Cell,
|
||||
uint8_t total_ic,
|
||||
cell_asic ic[]);
|
||||
|
||||
//********************************** SPI ******************************************//
|
||||
/*
|
||||
Writes an array of bytes out of the SPI port
|
||||
*/
|
||||
void spi_write_array(uint8_t len, // Option: Number of bytes to be written on the SPI port
|
||||
uint8_t data[] //Array of bytes to be written on the SPI port
|
||||
);
|
||||
/*
|
||||
Writes and read a set number of bytes using the SPI port.
|
||||
|
||||
*/
|
||||
|
||||
void spi_write_read(uint8_t tx_Data[],//array of data to be written on SPI port
|
||||
uint8_t tx_len, //length of the tx data arry
|
||||
uint8_t *rx_data,//Input: array that will store the data read by the SPI port
|
||||
uint8_t rx_len //Option: number of bytes to be read from the SPI port
|
||||
);
|
||||
|
||||
uint8_t spi_read_byte(uint8_t tx_dat);//name conflicts with linduino also needs to take a byte as a parameter
|
||||
|
||||
#endif /* _LTC681X_H_ */
|
||||
|
||||
/*******************(C)COPYRIGHT 2021 Amogreentech *********END OF FILE********/
|
||||
180
APP_R3323/App/Hardware/malloc.c
Normal file
180
APP_R3323/App/Hardware/malloc.c
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : can_comm.c
|
||||
* Description : This file provides code for the configuration
|
||||
* of the CAN communication instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "malloc.h"
|
||||
|
||||
//Memory pool (4-byte alignment)
|
||||
__align(4) uint8_t membase[MEM_MAX_SIZE]; // __attribute__((at(0x10000000))); //CMM within the memory pool
|
||||
|
||||
//Memory management tables
|
||||
__align(4) uint16_t memmapbase[MEM_ALLOC_TABLE_SIZE]; // __attribute__((at(0X10000000 + MEM3_MAX_SIZE))); //Internal CCM pools MAP
|
||||
|
||||
//Memory management parameters
|
||||
const uint32_t memtblsize = MEM_ALLOC_TABLE_SIZE; //Memory table size
|
||||
const uint32_t memblksize = MEM_BLOCK_SIZE; //Memory block size
|
||||
const uint32_t memsize = MEM_MAX_SIZE; //Total memory size
|
||||
|
||||
//Memory management controller
|
||||
struct _m_mallco_dev mallco_dev =
|
||||
{
|
||||
mymem_init, //Memory initialization
|
||||
mem_perused, //Memory usage
|
||||
membase, //Memory pool
|
||||
memmapbase, //Memory management tables
|
||||
0, //Memory management is not ready
|
||||
};
|
||||
|
||||
//Copy memory
|
||||
//*des:Destination address
|
||||
//*src:Source address
|
||||
//n:Need to copy memory length (bytes)
|
||||
void mymemcpy(void *des,void *src,uint32_t n)
|
||||
{
|
||||
uint8_t *xdes = des;
|
||||
uint8_t *xsrc = src;
|
||||
while(n--) *xdes++ = *xsrc++;
|
||||
}
|
||||
|
||||
//Setting memory
|
||||
//*s:Memory address
|
||||
//c :The value to be set
|
||||
//count:Need to set the memory size(Bytes)
|
||||
void mymemset(void*s,uint8_t c,uint32_t count)
|
||||
{
|
||||
uint8_t *xs = s;
|
||||
while(count--) *xs++=c;
|
||||
}
|
||||
|
||||
//Memory management class
|
||||
//memx:Belongs to a block of memory
|
||||
void mymem_init(void)
|
||||
{
|
||||
mymemset(mallco_dev.memmap, 0, memtblsize * 2); // Memory status table is cleared to zero
|
||||
mymemset(mallco_dev.membase, 0, memsize); // Memory pool all data to zero
|
||||
mallco_dev.memrdy = 1; // Memory initialized OK
|
||||
}
|
||||
|
||||
//Get memory usage
|
||||
//memx:Belongs to a block of memory
|
||||
//Return value: usage (0~100)
|
||||
uint8_t mem_perused(void)
|
||||
{
|
||||
uint32_t used = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < memtblsize; i++)
|
||||
{
|
||||
if (mallco_dev.memmap[i]) used++;
|
||||
}
|
||||
return (used * 100) / (memtblsize);
|
||||
}
|
||||
|
||||
// Memory allocation (internal call)
|
||||
// size:Amount of memory to allocate (in bytes)
|
||||
// The return value:0XFFFFFFFF,To indicate an error; the other, the memory offset
|
||||
uint32_t _mem_malloc(uint32_t size)
|
||||
{
|
||||
signed long offset = 0;
|
||||
uint16_t nmemb; // Required number of memory blocks
|
||||
uint16_t cmemb = 0; // Number of contiguous blocks of free memory
|
||||
uint32_t i;
|
||||
|
||||
if (!mallco_dev.memrdy) mallco_dev.init(); // Is not initialized, perform the initialization
|
||||
if (size == 0) return 0XFFFFFFFF; // Do not need to allocate
|
||||
nmemb = size / memblksize; // Gets the required number of contiguous blocks of memory allocated
|
||||
if (size % memblksize) nmemb++;
|
||||
for (offset = memtblsize - 1; offset >= 0; offset--) // Search the entire memory control
|
||||
{
|
||||
if (!mallco_dev.memmap[offset]) cmemb++; // Increase the number of contiguous blocks of free memory
|
||||
else cmemb = 0; // Contiguous blocks of memory to zero
|
||||
if (cmemb == nmemb) // Find nmemb consecutive empty memory blocks
|
||||
{
|
||||
for (i = 0; i < nmemb; i++) // Mark a block of memory is not empty
|
||||
{
|
||||
mallco_dev.memmap[offset+i] = nmemb;
|
||||
}
|
||||
return (offset*memblksize); // Returns the offset address
|
||||
}
|
||||
}
|
||||
return 0XFFFFFFFF; // Not found consistent with allocated memory block
|
||||
}
|
||||
|
||||
//Free memory (internal call)
|
||||
//offset:Memory address of offset
|
||||
//Return values: 0, release success; 1, release failed;
|
||||
uint8_t _mem_free(uint32_t offset)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!mallco_dev.memrdy) // Is not initialized, perform the initialization
|
||||
{
|
||||
mallco_dev.init();
|
||||
return 1; // Not initialized
|
||||
}
|
||||
if (offset < memsize) // Offset within the memory pool.
|
||||
{
|
||||
int index = offset / memblksize; // Offset where the memory block number
|
||||
int nmemb=mallco_dev.memmap[index]; // Number of memory blocks
|
||||
for (i = 0; i < nmemb; i++) // Zero out memory blocks
|
||||
{
|
||||
mallco_dev.memmap[index+i] = 0;
|
||||
}
|
||||
return 0;
|
||||
} else return 2; // Offset Super.
|
||||
}
|
||||
|
||||
//Free memory (external call)
|
||||
//ptr:Memory address
|
||||
void myfree(void *ptr)
|
||||
{
|
||||
uint32_t offset;
|
||||
|
||||
if (ptr == NULL) return; // Address 0.
|
||||
offset = (uint32_t)ptr - (uint32_t)mallco_dev.membase;
|
||||
_mem_free(offset); //Free up memory
|
||||
}
|
||||
|
||||
//Allocating memory(External call)
|
||||
//size:Memory size (in bytes)
|
||||
//Return values: the first address of the allocated memory.
|
||||
void *mymalloc(uint32_t size)
|
||||
{
|
||||
uint32_t offset;
|
||||
|
||||
offset = _mem_malloc(size);
|
||||
if (offset == 0XFFFFFFFF) return NULL;
|
||||
else return (void*)((uint32_t)mallco_dev.membase + offset);
|
||||
}
|
||||
|
||||
//Reallocating memory (external call)
|
||||
//*ptr:The old memory address
|
||||
//size:Amount of memory to allocate (in bytes)
|
||||
//Return values: the first address of the newly allocated memory.
|
||||
void *myrealloc(void *ptr,uint32_t size)
|
||||
{
|
||||
uint32_t offset;
|
||||
offset = _mem_malloc(size);
|
||||
if (offset == 0XFFFFFFFF) return NULL;
|
||||
else
|
||||
{
|
||||
mymemcpy((void*)((uint32_t)mallco_dev.membase + offset), ptr, size); // Copy the old memory contents to the new memory
|
||||
myfree(ptr); // Free old memory
|
||||
return (void*)((uint32_t)mallco_dev.membase + offset); // Returns a new memory address
|
||||
}
|
||||
}
|
||||
78
APP_R3323/App/Hardware/malloc.h
Normal file
78
APP_R3323/App/Hardware/malloc.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file malloc.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides code for the configuration of
|
||||
* the memory heap instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __malloc_H
|
||||
#define __malloc_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
// Define three memory pools
|
||||
#define MEM_BLOCK_SIZE 32 // Block size is 32 bytes
|
||||
#define MEM_MAX_SIZE (20 * 1024) // Maximum memory management 20k
|
||||
#define MEM_ALLOC_TABLE_SIZE (MEM_MAX_SIZE / MEM_BLOCK_SIZE) // Memory table size
|
||||
|
||||
//Memory management controller
|
||||
struct _m_mallco_dev
|
||||
{
|
||||
void (*init)(void); // Initialize
|
||||
uint8_t (*perused)(void); // Memory usage
|
||||
uint8_t *membase; // Memory pool management SRAMBANK a region of memory
|
||||
uint16_t *memmap; // Memory status table
|
||||
uint8_t memrdy; // Memory management is ready to
|
||||
};
|
||||
extern struct _m_mallco_dev mallco_dev; //Defined in malloc.c
|
||||
|
||||
void mymemset(void *s,uint8_t c,uint32_t count); // Setting memory
|
||||
void mymemcpy(void *des,void *src,uint32_t n); // Copy memory
|
||||
void mymem_init(void); // Memory initialization function (external/internal calls)
|
||||
uint8_t mem_perused(void); // For memory usage (external/internal calls)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//Users call a function
|
||||
void myfree(void *ptr); // Memory release (external call)
|
||||
void *mymalloc(uint32_t size); // Memory allocation (external call)
|
||||
void *myrealloc(void *ptr, uint32_t size); // Reallocating memory (external call)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /*__ brtc_H */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
|
||||
|
||||
135
APP_R3323/App/Hardware/relay.c
Normal file
135
APP_R3323/App/Hardware/relay.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file relay.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of relay control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "relay.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
//Relay port definitions
|
||||
/* Charge Relay Port/Pin definition */
|
||||
#define CHG_RLY_PORT (PortC)
|
||||
#define CHG_RLY_PIN (Pin09)
|
||||
|
||||
/* Discharge Relay Port/Pin definition */
|
||||
#define DSG_RLY_PORT (PortD)
|
||||
#define DSG_RLY_PIN (Pin15)
|
||||
|
||||
/* Pre-Charge Relay Port/Pin definition */
|
||||
#define PCHG_RLY_PORT (PortD)
|
||||
#define PCHG_RLY_PIN (Pin13)
|
||||
|
||||
/* Charge Relay Status Port/Pin definition */
|
||||
#define CHG_RLY_STS_PORT (PortC)
|
||||
#define CHG_RLY_STS_PIN (Pin08)
|
||||
|
||||
/* Discharge Relay Status Port/Pin definition */
|
||||
#define DSG_RLY_STS_PORT (PortD)
|
||||
#define DSG_RLY_STS_PIN (Pin14)
|
||||
|
||||
/* Discharge Relay Status Port/Pin definition */
|
||||
#define PCHG_RLY_STS_PORT (PortD)
|
||||
#define PCHG_RLY_STS_PIN (Pin12)
|
||||
|
||||
// Relay port definitions
|
||||
#define CHG_RLY_OFF PORT_ResetBits(CHG_RLY_PORT , CHG_RLY_PIN );
|
||||
#define CHG_RLY_ON PORT_SetBits (CHG_RLY_PORT , CHG_RLY_PIN );
|
||||
|
||||
#define DSG_RLY_OFF PORT_ResetBits(DSG_RLY_PORT , DSG_RLY_PIN );
|
||||
#define DSG_RLY_ON PORT_SetBits (DSG_RLY_PORT , DSG_RLY_PIN );
|
||||
|
||||
#define PRE_CHG_RLY_ON PORT_ResetBits(PCHG_RLY_PORT, PCHG_RLY_PIN);
|
||||
#define PRE_CHG_RLY_OFF PORT_SetBits (PCHG_RLY_PORT, PCHG_RLY_PIN);
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
// Relay IO Initialize
|
||||
void Relay_Init(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enPinOType = Pin_OType_Od;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* Relay Control Port/Pin initialization */
|
||||
PORT_Init(CHG_RLY_PORT , CHG_RLY_PIN , &stcPortInit);
|
||||
PORT_Init(DSG_RLY_PORT , DSG_RLY_PIN , &stcPortInit);
|
||||
PORT_Init(PCHG_RLY_PORT, PCHG_RLY_PIN, &stcPortInit);
|
||||
|
||||
CHG_RLY_OFF;
|
||||
DSG_RLY_OFF;
|
||||
PRE_CHG_RLY_OFF;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* Relay Status Port/Pin initialization */
|
||||
PORT_Init(CHG_RLY_STS_PORT , CHG_RLY_STS_PIN , &stcPortInit);
|
||||
PORT_Init(DSG_RLY_STS_PORT , DSG_RLY_STS_PIN , &stcPortInit);
|
||||
PORT_Init(PCHG_RLY_STS_PORT, PCHG_RLY_STS_PIN, &stcPortInit);
|
||||
}
|
||||
|
||||
void Relay_On(uint8_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case '0': DSG_RLY_ON; break;
|
||||
case '1': CHG_RLY_ON; break;
|
||||
case '2': PRE_CHG_RLY_ON; break;
|
||||
}
|
||||
}
|
||||
|
||||
void Relay_Off(uint8_t id)
|
||||
{
|
||||
switch (id) {
|
||||
case '0': DSG_RLY_OFF; break;
|
||||
case '1': CHG_RLY_OFF; break;
|
||||
case '2': PRE_CHG_RLY_OFF; break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Relay_Status(uint8_t id)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
switch (id) {
|
||||
case 0: result = PORT_GetBit(DSG_RLY_STS_PORT , DSG_RLY_STS_PIN ); break;
|
||||
case 1: result = PORT_GetBit(CHG_RLY_STS_PORT , CHG_RLY_STS_PIN ); break;
|
||||
case 2: result = PORT_GetBit(PCHG_RLY_STS_PORT, PCHG_RLY_STS_PIN); break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
45
APP_R3323/App/Hardware/relay.h
Normal file
45
APP_R3323/App/Hardware/relay.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file relay.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of relay control functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _RELAY_H
|
||||
#define _RELAY_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void Relay_Init(void); // Initialize
|
||||
void Relay_DeInit(void); // DeInitialize
|
||||
|
||||
void Relay_On(uint8_t id);
|
||||
void Relay_Off(uint8_t id);
|
||||
|
||||
uint8_t Relay_Status(uint8_t id);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
367
APP_R3323/App/Hardware/rtc_io.c
Normal file
367
APP_R3323/App/Hardware/rtc_io.c
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rtc_io.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the code of the realtime clock functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//// DS1302.C ////
|
||||
//// Driver for Real Time Clock ////
|
||||
//// ////
|
||||
//// rtc_init() Call after power up////
|
||||
//// ////
|
||||
//// rtc_set_datetime(day,mth,year,dow,hour,min) Set the date/time ////
|
||||
//// ////
|
||||
//// rtc_get_date(day,mth,year,dow) Get the date ////
|
||||
//// ////
|
||||
//// rtc_get_time(hr,min,sec) Get the time ////
|
||||
//// ////
|
||||
//// rtc_write_nvr(address,data) Write to NVR ////
|
||||
//// ////
|
||||
//// data = rtc_read_nvr(address) Read from NVR ////
|
||||
//// ////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//// (C) Copyright 1996,2003 Custom Computer Services ////
|
||||
//// This source code may only be used by licensed users of the CCS C ////
|
||||
//// compiler. This source code may only be distributed to other ////
|
||||
//// licensed users of the CCS C compiler. No other use, reproduction////
|
||||
//// or distribution is permitted without written permission. ////
|
||||
//// Derivative programs created using this software in object code ////
|
||||
//// form are not restricted in any way. ////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "rtc_io.h"
|
||||
#include "delay.h"
|
||||
#include "stdio.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* RTC IO Port/Pin definition */
|
||||
#define RTC_IO_CLK_PORT (PortD)
|
||||
#define RTC_IO_CLK_PIN (Pin11)
|
||||
|
||||
#define RTC_IO_DAT_PORT (PortD)
|
||||
#define RTC_IO_DAT_PIN (Pin10)
|
||||
|
||||
#define RTC_IO_RST_PORT (PortD)
|
||||
#define RTC_IO_RST_PIN (Pin09)
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// RTC-Bus-Line
|
||||
// --------------------------------------------------------------------------------
|
||||
#define RTC_CLK_LOW PORT_ResetBits(RTC_IO_CLK_PORT, RTC_IO_CLK_PIN) // rtc data line Low-Level
|
||||
#define RTC_CLK_HIGH PORT_SetBits(RTC_IO_CLK_PORT, RTC_IO_CLK_PIN) // rtc data line High-Level
|
||||
|
||||
#define RTC_DAT_LOW PORT_ResetBits(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN) // rtc data line Low-Level
|
||||
#define RTC_DAT_HIGH PORT_SetBits(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN) // rtc data line High-Level
|
||||
#define RTC_DAT_IN PORT_GetBit(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN) // rtc data line read
|
||||
|
||||
#define RTC_RST_LOW PORT_ResetBits(RTC_IO_RST_PORT, RTC_IO_RST_PIN) // rtc data line Low-Level
|
||||
#define RTC_RST_HIGH PORT_SetBits(RTC_IO_RST_PORT, RTC_IO_RST_PIN) // rtc data line High-Level
|
||||
|
||||
#define CLK_DIV 10
|
||||
|
||||
#define Tdc 200 / CLK_DIV // Min.
|
||||
#define Tcdh 280 / CLK_DIV // Min.
|
||||
#define Tcdd 800 / CLK_DIV // Max.
|
||||
#define Tcl 1000 / CLK_DIV // Min.
|
||||
#define Tch 1000 / CLK_DIV // Min.
|
||||
#define Tcc 4000 / CLK_DIV // Min.
|
||||
#define Tcch 240 / CLK_DIV // Min.
|
||||
#define Tcwh 4000 / CLK_DIV // Min.
|
||||
#define Tcdz 280 / CLK_DIV // Max.
|
||||
#define Tccz 280 / CLK_DIV // Max.
|
||||
|
||||
#define RD_ADDR_RTC_YEAR 0x8D
|
||||
#define RD_ADDR_RTC_MONTH 0x89
|
||||
#define RD_ADDR_RTC_DATE 0x87
|
||||
#define RD_ADDR_RTC_WDAY 0x8B
|
||||
|
||||
#define RD_ADDR_RTC_HOUR 0x85
|
||||
#define RD_ADDR_RTC_MIN 0x83
|
||||
#define RD_ADDR_RTC_SEC 0x81
|
||||
|
||||
#define WR_ADDR_RTC_YEAR 0x8C
|
||||
#define WR_ADDR_RTC_MONTH 0x88
|
||||
#define WR_ADDR_RTC_DATE 0x86
|
||||
#define WR_ADDR_RTC_WDAY 0x8A
|
||||
|
||||
#define WR_ADDR_RTC_HOUR 0x84
|
||||
#define WR_ADDR_RTC_MIN 0x82
|
||||
#define WR_ADDR_RTC_SEC 0x80
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private prototype functions -----------------------------------------------*/
|
||||
|
||||
// send 'databyte' to 'port'
|
||||
void outp(uint8_t HighLow);
|
||||
// read byte from 'port'
|
||||
uint8_t inp(void);
|
||||
|
||||
// 1-Wire Timing Generation
|
||||
// Pause for exactly 'tick' number of ticks = 0.25us
|
||||
void tickDelay(uint16_t tick); // Implementation is platform specific
|
||||
//-----------------------------------------------------------------------------
|
||||
// Set the 1-Wire timing to 'standard' (standard=1) or 'overdrive' (standard=0).
|
||||
//
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
void tickDelay(uint16_t tick)
|
||||
{
|
||||
delay_us(tick);
|
||||
}
|
||||
|
||||
void RTC_IO_Config(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
|
||||
/* LED Port/Pin initialization */
|
||||
PORT_Init(RTC_IO_CLK_PORT, RTC_IO_CLK_PIN, &stcPortInit);
|
||||
PORT_Init(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN, &stcPortInit);
|
||||
PORT_Init(RTC_IO_RST_PORT, RTC_IO_RST_PIN, &stcPortInit);
|
||||
|
||||
PORT_ResetBits(RTC_IO_CLK_PORT, RTC_IO_CLK_PIN);
|
||||
PORT_ResetBits(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN);
|
||||
PORT_ResetBits(RTC_IO_RST_PORT, RTC_IO_RST_PIN);
|
||||
}
|
||||
|
||||
void rtc_dat_config(uint8_t inout)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
if (inout == 1)
|
||||
{
|
||||
// Output
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
PORT_ResetBits(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN);
|
||||
PORT_Init(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN, &stcPortInit);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Input
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Disable;
|
||||
PORT_Init(RTC_IO_DAT_PORT, RTC_IO_DAT_PIN, &stcPortInit);
|
||||
}
|
||||
}
|
||||
|
||||
void outp(uint8_t HighLow)
|
||||
{
|
||||
if (HighLow) RTC_DAT_HIGH;
|
||||
else RTC_DAT_LOW;
|
||||
}
|
||||
|
||||
uint8_t inp(void)
|
||||
{
|
||||
return RTC_DAT_IN;
|
||||
}
|
||||
|
||||
void write_ds1302_byte(uint8_t cmd)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
outp((cmd >> i) & 0x01);
|
||||
delay_ns(Tcl);
|
||||
RTC_CLK_HIGH;
|
||||
delay_ns(Tch);
|
||||
RTC_CLK_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
void write_ds1302(uint8_t cmd, uint8_t data)
|
||||
{
|
||||
rtc_dat_config(1);
|
||||
|
||||
RTC_RST_HIGH;
|
||||
delay_ns(Tcc);
|
||||
|
||||
write_ds1302_byte(cmd);
|
||||
write_ds1302_byte(data);
|
||||
|
||||
RTC_RST_LOW;
|
||||
delay_ns(Tcwh);
|
||||
}
|
||||
|
||||
uint8_t read_ds1302(uint8_t cmd)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
|
||||
rtc_dat_config(1);
|
||||
|
||||
if (cmd == 0)
|
||||
cmd = cmd;
|
||||
RTC_RST_HIGH;
|
||||
delay_ns(Tcc - Tcl);
|
||||
|
||||
write_ds1302_byte(cmd);
|
||||
rtc_dat_config(0);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
delay_ns(Tcdd);
|
||||
data |= (inp() << i);
|
||||
delay_ns(Tcl-Tcdd);
|
||||
RTC_CLK_HIGH;
|
||||
delay_ns(Tch);
|
||||
RTC_CLK_LOW;
|
||||
}
|
||||
|
||||
RTC_RST_LOW;
|
||||
rtc_dat_config(1);
|
||||
delay_ns(Tcwh);
|
||||
|
||||
return (data);
|
||||
}
|
||||
|
||||
void rtc_init(void)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
RTC_IO_Config();
|
||||
|
||||
RTC_RST_HIGH;
|
||||
delay_ns(Tch);
|
||||
|
||||
RTC_CLK_LOW;
|
||||
|
||||
write_ds1302(0x8e, 0);
|
||||
write_ds1302(0x90, 0xa6);
|
||||
x = read_ds1302(0x81);
|
||||
|
||||
if ((x & 0x80) != 0)
|
||||
write_ds1302(0x80, 0);
|
||||
}
|
||||
|
||||
uint8_t bcd2byte(uint8_t bcd)
|
||||
{
|
||||
return ((bcd >> 4) * 10) + (bcd & 0x0F);
|
||||
}
|
||||
|
||||
uint8_t byte2bcd(uint8_t byte)
|
||||
{
|
||||
return ((byte / 10) << 4) + (byte % 10);
|
||||
}
|
||||
|
||||
void rtc_set_datetime(uint8_t *DateTime)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
write_ds1302(WR_ADDR_RTC_YEAR , byte2bcd(DateTime[i++]));
|
||||
write_ds1302(WR_ADDR_RTC_MONTH, byte2bcd(DateTime[i++]));
|
||||
write_ds1302(WR_ADDR_RTC_DATE , byte2bcd(DateTime[i++]));
|
||||
write_ds1302(WR_ADDR_RTC_HOUR , byte2bcd(DateTime[i++]));
|
||||
write_ds1302(WR_ADDR_RTC_MIN , byte2bcd(DateTime[i++]));
|
||||
write_ds1302(WR_ADDR_RTC_SEC , byte2bcd(DateTime[i++]));
|
||||
}
|
||||
|
||||
void rtc_get_datetime(uint8_t *DateTime)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_YEAR));
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_MONTH));
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_DATE));
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_WDAY));
|
||||
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_HOUR));
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_MIN));
|
||||
DateTime[i++] = bcd2byte(read_ds1302(RD_ADDR_RTC_SEC));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_year(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_YEAR));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_month(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_MONTH));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_date(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_DATE));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_wday(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_WDAY));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_hour(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_HOUR));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_min(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_MIN));
|
||||
}
|
||||
|
||||
uint8_t rtc_get_sec(void)
|
||||
{
|
||||
return bcd2byte(read_ds1302(RD_ADDR_RTC_SEC));
|
||||
}
|
||||
|
||||
void rtc_get_date1(uint8_t *day, uint8_t *mth, uint8_t *year, uint8_t *dow)
|
||||
{
|
||||
*day = read_ds1302(0x87);
|
||||
*mth = read_ds1302(0x89);
|
||||
*year = read_ds1302(0x8d);
|
||||
*dow = read_ds1302(0x8b);
|
||||
}
|
||||
|
||||
void rtc_get_time(uint8_t *hr, uint8_t *min, uint8_t *sec)
|
||||
{
|
||||
*hr = read_ds1302(0x85);
|
||||
*min = read_ds1302(0x83);
|
||||
*sec = read_ds1302(0x81);
|
||||
}
|
||||
|
||||
void rtc_write_nvr(uint8_t address, uint8_t data)
|
||||
{
|
||||
write_ds1302((address << 1) | 0xc0, data);
|
||||
}
|
||||
|
||||
uint8_t rtc_read_nvr(uint8_t address)
|
||||
{
|
||||
return (read_ds1302((address << 1) | 0xc1));
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
55
APP_R3323/App/Hardware/rtc_io.h
Normal file
55
APP_R3323/App/Hardware/rtc_io.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file rtc_io.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the realtime clock functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef _RTC_IO_H_
|
||||
#define _RTC_IO_H_
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void rtc_init(void);
|
||||
void rtc_set_datetime(uint8_t *DateTime);
|
||||
void rtc_get_datetime(uint8_t *DateTime);
|
||||
|
||||
uint8_t rtc_get_year(void);
|
||||
uint8_t rtc_get_month(void);
|
||||
uint8_t rtc_get_date(void);
|
||||
uint8_t rtc_get_wday(void);
|
||||
uint8_t rtc_get_hour(void);
|
||||
uint8_t rtc_get_min(void);
|
||||
uint8_t rtc_get_sec(void);
|
||||
|
||||
void rtc_write_nvr(uint8_t address, uint8_t data);
|
||||
uint8_t rtc_read_nvr(uint8_t address);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
232
APP_R3323/App/Hardware/spi.c
Normal file
232
APP_R3323/App/Hardware/spi.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file spi.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the code of the spi communication.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "spi.h"
|
||||
#include "console.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* SPI1 Configuration */
|
||||
/* SPI_SCK Port/Pin definition */
|
||||
#define SPI1_SCK_PORT (PortC)
|
||||
#define SPI1_SCK_PIN (Pin12)
|
||||
#define SPI1_SCK_FUNC (Func_Spi1_Sck)
|
||||
|
||||
/* SPI_MOSI Port/Pin definition */
|
||||
#define SPI1_MOSI_PORT (PortD)
|
||||
#define SPI1_MOSI_PIN (Pin02)
|
||||
#define SPI1_MOSI_FUNC (Func_Spi1_Mosi)
|
||||
|
||||
/* SPI_MISO Port/Pin definition */
|
||||
#define SPI1_MISO_PORT (PortD)
|
||||
#define SPI1_MISO_PIN (Pin01)
|
||||
#define SPI1_MISO_FUNC (Func_Spi1_Miso)
|
||||
|
||||
/* SPI3 Configuration */
|
||||
/* SPI_SCK Port/Pin definition */
|
||||
#define SPI3_SCK_PORT (PortB)
|
||||
#define SPI3_SCK_PIN (Pin13)
|
||||
#define SPI3_SCK_FUNC (Func_Spi3_Sck)
|
||||
|
||||
/* SPI_MOSI Port/Pin definition */
|
||||
#define SPI3_MOSI_PORT (PortB)
|
||||
#define SPI3_MOSI_PIN (Pin15)
|
||||
#define SPI3_MOSI_FUNC (Func_Spi3_Mosi)
|
||||
|
||||
/* SPI_MISO Port/Pin definition */
|
||||
#define SPI3_MISO_PORT (PortB)
|
||||
#define SPI3_MISO_PIN (Pin14)
|
||||
#define SPI3_MISO_FUNC (Func_Spi3_Miso)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
//Following is the SPI module initialization code, and configured to master mode
|
||||
//SPI port initialization
|
||||
//Needle is SPI1 initialization
|
||||
void Spi1_Config(void)
|
||||
{
|
||||
stc_spi_init_t stcSpiInit;
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Enable;
|
||||
|
||||
/* SPI Port/Pin initialization */
|
||||
PORT_Init(SPI1_MISO_PORT, SPI1_MISO_PIN, &stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
|
||||
PORT_Init(SPI1_MOSI_PORT, SPI1_MOSI_PIN, &stcPortInit);
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcSpiInit);
|
||||
|
||||
/* Configuration peripheral clock */
|
||||
PWC_Fcg1PeriphClockCmd(SPI1_UNIT_CLOCK, Enable);
|
||||
|
||||
/* Configuration SPI pin */
|
||||
PORT_SetFunc(SPI1_SCK_PORT, SPI1_SCK_PIN, SPI1_SCK_FUNC, Disable);
|
||||
PORT_SetFunc(SPI1_MOSI_PORT, SPI1_MOSI_PIN, SPI1_MOSI_FUNC, Disable);
|
||||
PORT_SetFunc(SPI1_MISO_PORT, SPI1_MISO_PIN, SPI1_MISO_FUNC, Disable);
|
||||
|
||||
/* Configuration SPI structure */
|
||||
stcSpiInit.enClkDiv = SpiClkDiv64;
|
||||
stcSpiInit.enFrameNumber = SpiFrameNumber1;
|
||||
stcSpiInit.enDataLength = SpiDataLengthBit8;
|
||||
stcSpiInit.enFirstBitPosition = SpiFirstBitPositionMSB;
|
||||
stcSpiInit.enSckPolarity = SpiSckIdleLevelLow;
|
||||
stcSpiInit.enSckPhase = SpiSckOddSampleEvenChange;
|
||||
stcSpiInit.enReadBufferObject = SpiReadReceiverBuffer;
|
||||
stcSpiInit.enWorkMode = SpiWorkMode3Line;
|
||||
stcSpiInit.enTransMode = SpiTransFullDuplex;
|
||||
stcSpiInit.enCommAutoSuspendEn = Disable;
|
||||
stcSpiInit.enModeFaultErrorDetectEn = Disable;
|
||||
stcSpiInit.enParitySelfDetectEn = Disable;
|
||||
stcSpiInit.enParityEn = Disable;
|
||||
stcSpiInit.enParity = SpiParityEven;
|
||||
stcSpiInit.enMasterSlaveMode = SpiModeMaster;
|
||||
stcSpiInit.stcDelayConfig.enSsSetupDelayOption = SpiSsSetupDelayCustomValue;
|
||||
stcSpiInit.stcDelayConfig.enSsSetupDelayTime = SpiSsSetupDelaySck1;
|
||||
stcSpiInit.stcDelayConfig.enSsHoldDelayOption = SpiSsHoldDelayCustomValue;
|
||||
stcSpiInit.stcDelayConfig.enSsHoldDelayTime = SpiSsHoldDelaySck1;
|
||||
stcSpiInit.stcDelayConfig.enSsIntervalTimeOption = SpiSsIntervalCustomValue;
|
||||
stcSpiInit.stcDelayConfig.enSsIntervalTime = SpiSsIntervalSck6PlusPck2;
|
||||
|
||||
SPI_Init(SPI1_UNIT, &stcSpiInit);
|
||||
SPI_Cmd(SPI1_UNIT, Enable);
|
||||
}
|
||||
|
||||
//Following is the SPI module initialization code, and configured to master mode
|
||||
//SPI port initialization
|
||||
//Needle is SPI3 initialization
|
||||
void Spi3_Config(void)
|
||||
{
|
||||
stc_spi_init_t stcSpiInit;
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
stcPortInit.enExInt = Disable;
|
||||
stcPortInit.enPullUp = Enable;
|
||||
|
||||
/* SPI Port/Pin initialization */
|
||||
PORT_Init(SPI3_MISO_PORT, SPI3_MISO_PIN, &stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_In;
|
||||
|
||||
PORT_Init(SPI3_MOSI_PORT, SPI3_MOSI_PIN, &stcPortInit);
|
||||
|
||||
/* configuration structure initialization */
|
||||
MEM_ZERO_STRUCT(stcSpiInit);
|
||||
|
||||
/* Configuration peripheral clock */
|
||||
PWC_Fcg1PeriphClockCmd(SPI3_UNIT_CLOCK, Enable);
|
||||
|
||||
/* Configuration SPI pin */
|
||||
PORT_SetFunc(SPI3_SCK_PORT, SPI3_SCK_PIN, SPI3_SCK_FUNC, Disable);
|
||||
PORT_SetFunc(SPI3_MOSI_PORT, SPI3_MOSI_PIN, SPI3_MOSI_FUNC, Disable);
|
||||
PORT_SetFunc(SPI3_MISO_PORT, SPI3_MISO_PIN, SPI3_MISO_FUNC, Disable);
|
||||
|
||||
/* Configuration SPI structure */
|
||||
stcSpiInit.enClkDiv = SpiClkDiv2;
|
||||
stcSpiInit.enFrameNumber = SpiFrameNumber1;
|
||||
stcSpiInit.enDataLength = SpiDataLengthBit8;
|
||||
stcSpiInit.enFirstBitPosition = SpiFirstBitPositionMSB;
|
||||
stcSpiInit.enSckPolarity = SpiSckIdleLevelLow;
|
||||
stcSpiInit.enSckPhase = SpiSckOddSampleEvenChange;
|
||||
stcSpiInit.enReadBufferObject = SpiReadReceiverBuffer;
|
||||
stcSpiInit.enWorkMode = SpiWorkMode3Line;
|
||||
stcSpiInit.enTransMode = SpiTransFullDuplex;
|
||||
stcSpiInit.enCommAutoSuspendEn = Disable;
|
||||
stcSpiInit.enModeFaultErrorDetectEn = Disable;
|
||||
stcSpiInit.enParitySelfDetectEn = Disable;
|
||||
stcSpiInit.enParityEn = Disable;
|
||||
stcSpiInit.enParity = SpiParityEven;
|
||||
stcSpiInit.enMasterSlaveMode = SpiModeMaster;
|
||||
stcSpiInit.stcDelayConfig.enSsSetupDelayOption = SpiSsSetupDelayCustomValue;
|
||||
stcSpiInit.stcDelayConfig.enSsSetupDelayTime = SpiSsSetupDelaySck1;
|
||||
stcSpiInit.stcDelayConfig.enSsHoldDelayOption = SpiSsHoldDelayCustomValue;
|
||||
stcSpiInit.stcDelayConfig.enSsHoldDelayTime = SpiSsHoldDelaySck1;
|
||||
stcSpiInit.stcDelayConfig.enSsIntervalTimeOption = SpiSsIntervalCustomValue;
|
||||
stcSpiInit.stcDelayConfig.enSsIntervalTime = SpiSsIntervalSck6PlusPck2;
|
||||
|
||||
SPI_Init(SPI3_UNIT, &stcSpiInit);
|
||||
SPI_Cmd(SPI3_UNIT, Enable);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief SPI3 flash write byte function
|
||||
**
|
||||
** \param [in] u8Data SPI write data to flash
|
||||
**
|
||||
** \retval uint8_t SPI receive data from flash
|
||||
**
|
||||
******************************************************************************/
|
||||
uint8_t Spi3Flash_WriteReadByte(uint8_t u8Data)
|
||||
{
|
||||
uint8_t u8Byte = 0;
|
||||
|
||||
/* Wait tx buffer empty */
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSendBufferEmpty))
|
||||
{
|
||||
}
|
||||
/* Send data */
|
||||
SPI_SendData8(SPI3_UNIT, u8Data);
|
||||
/* Wait rx buffer full */
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagReceiveBufferFull))
|
||||
{
|
||||
}
|
||||
/* Receive data */
|
||||
u8Byte = SPI_ReceiveData8(SPI3_UNIT);
|
||||
|
||||
return u8Byte;
|
||||
}
|
||||
|
||||
// SPI1 read and write bytes
|
||||
// TxData: the bytes to write
|
||||
// Return value: reads a byte
|
||||
uint8_t SPI1_ReadWriteByte(uint8_t TxData)
|
||||
{
|
||||
while (Reset == SPI_GetFlag(SPI1_UNIT, SpiFlagSendBufferEmpty)) { }//Waiting to be sent
|
||||
|
||||
SPI_SendData8(SPI1_UNIT, TxData);
|
||||
|
||||
while (Reset == SPI_GetFlag(SPI1_UNIT, SpiFlagReceiveBufferFull)) {}
|
||||
|
||||
return SPI_ReceiveData8(SPI1_UNIT); //Returned by SPIx recently received data
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
79
APP_R3323/App/Hardware/spi.h
Normal file
79
APP_R3323/App/Hardware/spi.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file spi.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the spi communication.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS3
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __SPI_H
|
||||
#define __SPI_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* Exported defines ----------------------------------------------------------*/
|
||||
/* SPI_NSS Port/Pin definition */
|
||||
#define SPI1_NSS_PORT (PortD)
|
||||
#define SPI1_NSS_PIN (Pin00)
|
||||
#define SPI1_NSS_HIGH() (PORT_SetBits(SPI1_NSS_PORT, SPI1_NSS_PIN))
|
||||
#define SPI1_NSS_LOW() (PORT_ResetBits(SPI1_NSS_PORT, SPI1_NSS_PIN))
|
||||
|
||||
#define SPI3_NSS_PORT (PortB)
|
||||
#define SPI3_NSS_PIN (Pin12)
|
||||
#define SPI3_NSS_HIGH() (PORT_SetBits(SPI3_NSS_PORT, SPI3_NSS_PIN))
|
||||
#define SPI3_NSS_LOW() (PORT_ResetBits(SPI3_NSS_PORT, SPI3_NSS_PIN))
|
||||
|
||||
/* SPI unit and clock definition */
|
||||
#define SPI1_UNIT (M4_SPI1)
|
||||
#define SPI1_UNIT_CLOCK (PWC_FCG1_PERIPH_SPI1)
|
||||
|
||||
#define SPI3_UNIT (M4_SPI3)
|
||||
#define SPI3_UNIT_CLOCK (PWC_FCG1_PERIPH_SPI3)
|
||||
|
||||
/* FLASH parameters */
|
||||
#define FLASH_PAGE_SIZE (0x100u)
|
||||
#define FLASH_SECTOR_SIZE (0x1000u)
|
||||
#define FLASH_MAX_ADDR (0x800000ul)
|
||||
#define FLASH_DUMMY_BYTE_VALUE (0xffu)
|
||||
#define FLASH_BUSY_BIT_MASK (0x01u)
|
||||
|
||||
/* FLASH instruction */
|
||||
#define FLASH_INSTR_WRITE_ENABLE (0x06u)
|
||||
#define FLASH_INSTR_PAGE_PROGRAM (0x02u)
|
||||
#define FLASH_INSTR_STANDARD_READ (0x03u)
|
||||
#define FLASH_INSTR_ERASE_4KB_SECTOR (0x20u)
|
||||
#define FLASH_INSTR_READ_SR1 (0x05u)
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* Exported functions ------------------------------------------------------- */
|
||||
|
||||
void Spi1_Config(void);
|
||||
void Spi3_Config(void);
|
||||
|
||||
uint8_t Spi3Flash_WriteReadByte(uint8_t u8Data); //SPI bus read/write bytes
|
||||
uint8_t SPI1_ReadWriteByte(uint8_t TxData);
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
341
APP_R3323/App/Hardware/usart.c
Normal file
341
APP_R3323/App/Hardware/usart.c
Normal file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usart.c
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the codes of the usart comm. functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usart.h"
|
||||
#include <includes.h>
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#ifdef CONSOLE_DEBUG
|
||||
/* USART channel definition */
|
||||
#define DEBUG_CH (M4_USART1)
|
||||
|
||||
/* USART baudrate definition */
|
||||
#define DEBUG_BAUDRATE (115200ul)
|
||||
|
||||
/* USART RX Port/Pin definition */
|
||||
#define DEBUG_RX_PORT (PortA)
|
||||
#define DEBUG_RX_PIN (Pin10)
|
||||
#define DEBUG_RX_FUNC (Func_Usart1_Rx)
|
||||
|
||||
/* USART TX Port/Pin definition */
|
||||
#define DEBUG_TX_PORT (PortA)
|
||||
#define DEBUG_TX_PIN (Pin09)
|
||||
#define DEBUG_TX_FUNC (Func_Usart1_Tx)
|
||||
|
||||
/* USART interrupt number */
|
||||
#define DEBUG_RI_NUM (INT_USART1_RI)
|
||||
#define DEBUG_EI_NUM (INT_USART1_EI)
|
||||
#define DEBUG_TI_NUM (INT_USART1_TI)
|
||||
#define DEBUG_TCI_NUM (INT_USART1_TCI)
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void debug_port_init(void);
|
||||
|
||||
void DebugRxIrqCallback(void); //Serial port 1 interrupt service routine
|
||||
void DebugTxIrqCallback(void); //Serial port 1 interrupt service routine
|
||||
void DebugErrIrqCallback(void);
|
||||
void DebugTxCmpltIrqCallback(void);
|
||||
#endif /* CONSOLE_DEBUG */
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief Re-target fputc function.
|
||||
**
|
||||
** \param [in] ch
|
||||
** \param [in] f
|
||||
**
|
||||
** \retval int32_t
|
||||
**
|
||||
******************************************************************************/
|
||||
int32_t fputc(int32_t ch, FILE *f)
|
||||
{
|
||||
(void)f; /* Prevent unused argument compilation warning */
|
||||
|
||||
#ifdef CONSOLE_DEBUG
|
||||
Debug_PutChar(ch);
|
||||
#endif // #ifdef CONSOLE_DEBUG
|
||||
return ch;
|
||||
}
|
||||
|
||||
#ifdef CONSOLE_DEBUG
|
||||
|
||||
UART1_Info Uart1;
|
||||
|
||||
//Initializes IO serial port 1
|
||||
//Bound: baud rate
|
||||
void debug_usart_init(void)
|
||||
{
|
||||
en_result_t enRet = Ok;
|
||||
stc_irq_regi_conf_t stcIrqRegiCfg;
|
||||
|
||||
const stc_usart_uart_init_t stcInitCfg = {
|
||||
UsartIntClkCkNoOutput,
|
||||
UsartClkDiv_1,
|
||||
UsartDataBits8,
|
||||
UsartDataLsbFirst,
|
||||
UsartOneStopBit,
|
||||
UsartParityNone,
|
||||
UsartSampleBit8,
|
||||
UsartStartBitFallEdge,
|
||||
UsartRtsEnable,
|
||||
};
|
||||
|
||||
debug_port_init();
|
||||
|
||||
/* Initialize UART */
|
||||
enRet = USART_UART_Init(DEBUG_CH, &stcInitCfg);
|
||||
if (enRet != Ok)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Set baudrate */
|
||||
enRet = USART_SetBaudrate(DEBUG_CH, DEBUG_BAUDRATE);
|
||||
if (enRet != Ok)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/* Set USART RX IRQ */
|
||||
stcIrqRegiCfg.enIRQn = Int000_IRQn;
|
||||
stcIrqRegiCfg.pfnCallback = &DebugRxIrqCallback;
|
||||
stcIrqRegiCfg.enIntSrc = DEBUG_RI_NUM;
|
||||
enIrqRegistration(&stcIrqRegiCfg);
|
||||
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
||||
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
||||
|
||||
/* Set USART RX error IRQ */
|
||||
stcIrqRegiCfg.enIRQn = Int001_IRQn;
|
||||
stcIrqRegiCfg.pfnCallback = &DebugErrIrqCallback;
|
||||
stcIrqRegiCfg.enIntSrc = DEBUG_EI_NUM;
|
||||
enIrqRegistration(&stcIrqRegiCfg);
|
||||
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
||||
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
||||
|
||||
/* Set USART TX IRQ */
|
||||
stcIrqRegiCfg.enIRQn = Int002_IRQn;
|
||||
stcIrqRegiCfg.pfnCallback = &DebugTxIrqCallback;
|
||||
stcIrqRegiCfg.enIntSrc = DEBUG_TI_NUM;
|
||||
enIrqRegistration(&stcIrqRegiCfg);
|
||||
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
||||
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
||||
|
||||
/* Set USART TX complete IRQ */
|
||||
stcIrqRegiCfg.enIRQn = Int003_IRQn;
|
||||
stcIrqRegiCfg.pfnCallback = &DebugTxCmpltIrqCallback;
|
||||
stcIrqRegiCfg.enIntSrc = DEBUG_TCI_NUM;
|
||||
enIrqRegistration(&stcIrqRegiCfg);
|
||||
NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
|
||||
NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
|
||||
NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
|
||||
|
||||
/*Enable RX && RX interupt function*/
|
||||
USART_FuncCmd(DEBUG_CH, UsartRx, Enable);
|
||||
// USART_FuncCmd(DEBUG_CH, UsartTx, Enable);
|
||||
USART_FuncCmd(DEBUG_CH, UsartRxInt, Enable);
|
||||
// USART_FuncCmd(DEBUG_CH, UsartTxAndTxEmptyInt, Enable);
|
||||
|
||||
}
|
||||
|
||||
void debug_port_init(void)
|
||||
{
|
||||
uint32_t u32Fcg1Periph = PWC_FCG1_PERIPH_USART1 | PWC_FCG1_PERIPH_USART2 | \
|
||||
PWC_FCG1_PERIPH_USART3 | PWC_FCG1_PERIPH_USART4;
|
||||
|
||||
/* Enable peripheral clock */
|
||||
PWC_Fcg1PeriphClockCmd(u32Fcg1Periph, Enable);
|
||||
|
||||
/* Initialize USART IO */
|
||||
PORT_SetFunc(DEBUG_RX_PORT, DEBUG_RX_PIN, DEBUG_RX_FUNC, Disable);
|
||||
PORT_SetFunc(DEBUG_TX_PORT, DEBUG_TX_PIN, DEBUG_TX_FUNC, Disable);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief Debug RX irq callback function.
|
||||
**
|
||||
** \param [in] None
|
||||
**
|
||||
** \retval None
|
||||
**
|
||||
******************************************************************************/
|
||||
void DebugRxIrqCallback(void) //Serial port 1 interrupt service routine
|
||||
{
|
||||
uint8_t rx_data;
|
||||
|
||||
if (Set == USART_GetStatus(DEBUG_CH, UsartRxNoEmpty)) {
|
||||
rx_data = USART_RecData(DEBUG_CH) & 0xFF; /* Read one byte from the receive data register. */
|
||||
|
||||
Uart1.RxBuf[Uart1.RxInPos++] = rx_data;
|
||||
Uart1.RxInPos %= UART1_RX_BUFFER_SIZE;
|
||||
|
||||
if (Uart1.RxInPos == Uart1.RxOutPos) {
|
||||
Uart1.RxOutPos++;
|
||||
Uart1.RxOutPos %= UART1_RX_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
NVIC_ClearPendingIRQ(Int000_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief Debug RX error irq callback function.
|
||||
**
|
||||
** \param [in] None
|
||||
**
|
||||
** \retval None
|
||||
**
|
||||
******************************************************************************/
|
||||
static void DebugErrIrqCallback(void)
|
||||
{
|
||||
if (Set == USART_GetStatus(DEBUG_CH, UsartFrameErr))
|
||||
{
|
||||
USART_ClearStatus(DEBUG_CH, UsartFrameErr);
|
||||
}
|
||||
|
||||
if (Set == USART_GetStatus(DEBUG_CH, UsartParityErr))
|
||||
{
|
||||
USART_ClearStatus(DEBUG_CH, UsartParityErr);
|
||||
}
|
||||
|
||||
if (Set == USART_GetStatus(DEBUG_CH, UsartOverrunErr))
|
||||
{
|
||||
USART_ClearStatus(DEBUG_CH, UsartOverrunErr);
|
||||
}
|
||||
|
||||
NVIC_ClearPendingIRQ(Int001_IRQn);
|
||||
}
|
||||
|
||||
void DebugTxIrqCallback(void) //Serial port 1 interrupt service routine
|
||||
{
|
||||
if (Set == USART_GetStatus(DEBUG_CH, UsartTxEmpty)) {
|
||||
/* Write one byte to the transmit data register */
|
||||
USART_SendData(DEBUG_CH, Uart1.TxBuf[Uart1.TxOutPos++]);
|
||||
Uart1.TxOutPos %= UART1_TX_BUFFER_SIZE;
|
||||
|
||||
if (Uart1.TxOutPos == Uart1.TxInPos) {
|
||||
/* Disable the USART1 Transmit interrupt */
|
||||
USART_FuncCmd(DEBUG_CH, UsartTxEmptyInt, Disable);
|
||||
USART_FuncCmd(DEBUG_CH, UsartTxCmpltInt, Enable);
|
||||
}
|
||||
}
|
||||
NVIC_ClearPendingIRQ(Int002_IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief USART TX complete irq callback function.
|
||||
**
|
||||
** \param [in] None
|
||||
**
|
||||
** \retval None
|
||||
**
|
||||
******************************************************************************/
|
||||
static void DebugTxCmpltIrqCallback(void)
|
||||
{
|
||||
USART_FuncCmd(DEBUG_CH, UsartTxCmpltInt, Disable);
|
||||
USART_FuncCmd(DEBUG_CH, UsartTx, Disable);
|
||||
|
||||
NVIC_ClearPendingIRQ(Int003_IRQn);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : void UART1_PutChar(char data)
|
||||
* Description : Send 1 byte via UART1
|
||||
* Parameters : ASCII code
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void Debug_PutChar(const uint8_t ascii)
|
||||
{
|
||||
CPU_SR_ALLOC();
|
||||
|
||||
while (((Uart1.TxInPos + 1)% UART1_TX_BUFFER_SIZE) == (Uart1.TxOutPos % UART1_TX_BUFFER_SIZE)) {
|
||||
USART_FuncCmd(DEBUG_CH, UsartTxAndTxEmptyInt, Enable);
|
||||
}
|
||||
|
||||
CPU_CRITICAL_ENTER();
|
||||
|
||||
Uart1.TxBuf[Uart1.TxInPos++] = ascii;
|
||||
Uart1.TxInPos %= UART1_TX_BUFFER_SIZE;
|
||||
|
||||
USART_FuncCmd(DEBUG_CH, UsartTxAndTxEmptyInt, Enable);
|
||||
|
||||
CPU_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : uint8_t UART1_GetChar(char *data)
|
||||
* Description : Send 1 byte data to UART1 transmit buffer
|
||||
* Parameters : none
|
||||
* Return : Transmission result (0: buffer empty, 1: buffer has data)
|
||||
*******************************************************************************/
|
||||
int Debug_GetChar(uint8_t *data)
|
||||
{
|
||||
if (Uart1.RxInPos != Uart1.RxOutPos) {
|
||||
data[0] = Uart1.RxBuf[Uart1.RxOutPos];
|
||||
Uart1.RxOutPos++;
|
||||
Uart1.RxOutPos %= UART1_RX_BUFFER_SIZE;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : uint8_t UART1_GetChar(char *data)
|
||||
* Description : Send 1 byte data to UART1 transmit buffer
|
||||
* Parameters : none
|
||||
* Return : Transmission result (0: buffer empty, 1: buffer has data)
|
||||
*******************************************************************************/
|
||||
uint8_t UART1_GC(void)
|
||||
{
|
||||
uint8_t result = 0;
|
||||
|
||||
if (Uart1.RxInPos != Uart1.RxOutPos)
|
||||
{
|
||||
result = Uart1.RxBuf[Uart1.RxOutPos];
|
||||
Uart1.RxOutPos++;
|
||||
Uart1.RxOutPos %= UART1_RX_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // #ifdef CONSOLE_DEBUG
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
60
APP_R3323/App/Hardware/usart.h
Normal file
60
APP_R3323/App/Hardware/usart.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file usart.h
|
||||
* @author AMG Energy Solution Team
|
||||
* @version V1.0.0
|
||||
* @date 07-Feb-2022
|
||||
* @brief This file provides all the headers of the usart comm. functions.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||||
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*
|
||||
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/** @addtogroup mBMS2
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __USART_H
|
||||
#define __USART_H
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
#ifdef CONSOLE_DEBUG
|
||||
/* Defines -------------------------------------------------------------------*/
|
||||
#define UART1_TX_BUFFER_SIZE 1024
|
||||
#define UART1_RX_BUFFER_SIZE 128
|
||||
|
||||
/* Type declarations ---------------------------------------------------------*/
|
||||
typedef struct{
|
||||
uint16_t RxInPos, RxOutPos;
|
||||
uint16_t TxInPos, TxOutPos;
|
||||
uint8_t RxBuf[UART1_RX_BUFFER_SIZE];
|
||||
uint8_t TxBuf[UART1_TX_BUFFER_SIZE];
|
||||
} UART1_Info;
|
||||
|
||||
void debug_usart_init(void);
|
||||
|
||||
//void uart1_init(uint32_t bound);
|
||||
int Debug_GetChar(uint8_t *data);
|
||||
void Debug_PutChar(const uint8_t ascii);
|
||||
//void UART1_PutStr(uint8_t *str, uint16_t len);
|
||||
//void UART1_printf(const char *fmt,...);
|
||||
|
||||
uint8_t UART1_GC(void);
|
||||
|
||||
#endif /* CONSOLE_DEBUG */
|
||||
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
349
APP_R3323/App/Hardware/w25qxx.c
Normal file
349
APP_R3323/App/Hardware/w25qxx.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* File Name : w25qxx.c
|
||||
* Description : This file provides code for the configuration
|
||||
* of w25qxx configuration.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stdio.h"
|
||||
#include "spi.h"
|
||||
#include "w25qxx.h"
|
||||
#include "delay.h"
|
||||
#include "usart.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
uint16_t W25QXX_TYPE = W25Q128; // The default is W25Q128
|
||||
uint8_t W25QXX_BUFFER[4096];
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
en_result_t SpiFlash_WaitForWriteEnd(void);
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
// 4Kbytes to a Sector
|
||||
// 16 slices for 1 Block
|
||||
// W25Q40 : Capacity of 512K bytes, and a total of 16 Block, 128 Sector
|
||||
// W25Q128: Capacity of 16M bytes, and a total of 128 Block, 4096 Sector
|
||||
|
||||
//Initializes IO port SPI FLASH
|
||||
void W25QXX_Init(void)
|
||||
{
|
||||
stc_port_init_t stcPortInit;
|
||||
|
||||
/* configure structure initialization */
|
||||
MEM_ZERO_STRUCT(stcPortInit);
|
||||
|
||||
stcPortInit.enPinMode = Pin_Mode_Out;
|
||||
PORT_Init(SPI3_NSS_PORT, SPI3_NSS_PIN, &stcPortInit);
|
||||
SPI3_NSS_HIGH();
|
||||
|
||||
Spi3_Config();
|
||||
|
||||
W25QXX_TYPE = W25QXX_ReadID(); // Read FLASH ID.
|
||||
}
|
||||
|
||||
// The status register read W25QXX
|
||||
// BIT7 6 5 4 3 2 1 0
|
||||
// SPR RV TB BP2 BP1 BP0 WEL BUSY
|
||||
// SPR:Default 0, the State Register protection, used with WP
|
||||
// TB,BP2,BP1,BP0:FLASH write-protect setting
|
||||
// WEL: write lock
|
||||
// BUSY: busy flag bits (1, busy; 0, idle)
|
||||
// Default:0x00
|
||||
uint8_t W25QXX_ReadSR(void)
|
||||
{
|
||||
uint8_t byte = 0;
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(W25X_ReadStatusReg); // Sends a read status register command
|
||||
byte = Spi3Flash_WriteReadByte(FLASH_DUMMY_BYTE_VALUE); // Read a byte
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle));
|
||||
SPI3_NSS_HIGH();
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
// Write W25QXX status register
|
||||
// Only the SPR,TB,BP2,BP1,BP0(bit 7,5,4,3,2)You can write!!!
|
||||
void W25QXX_Write_SR(uint8_t sr)
|
||||
{
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(W25X_WriteStatusReg); // Sending of taking the State register command
|
||||
Spi3Flash_WriteReadByte(sr); // Writes a byte
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle));
|
||||
SPI3_NSS_HIGH();
|
||||
W25QXX_Wait_Busy(); //Waiting to be written to the end
|
||||
}
|
||||
|
||||
//W25QXX write enable
|
||||
//WEL is set
|
||||
void W25QXX_Write_Enable(void)
|
||||
{
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(W25X_WriteEnable); // Send written
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle));
|
||||
SPI3_NSS_HIGH(); // Cancel selected
|
||||
}
|
||||
|
||||
//W25QXX write protect
|
||||
//WEL reset
|
||||
void W25QXX_Write_Disable(void)
|
||||
{
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(W25X_WriteDisable); // Send written
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle));
|
||||
SPI3_NSS_HIGH(); // Cancel selected
|
||||
}
|
||||
|
||||
//Read the chip ID
|
||||
//Return values are as follows:
|
||||
//0XEF13,Chip and the model is W25Q80
|
||||
//0XEF14,Chip and the model is W25Q16
|
||||
//0XEF15,Chip and the model is W25Q32
|
||||
//0XEF16,Chip and the model is W25Q64
|
||||
//0XEF17,Chip and the model is W25Q128
|
||||
uint16_t W25QXX_ReadID(void)
|
||||
{
|
||||
uint16_t Temp = 0;
|
||||
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(0x90);//Send the read ID command
|
||||
Spi3Flash_WriteReadByte(0x00);
|
||||
Spi3Flash_WriteReadByte(0x00);
|
||||
Spi3Flash_WriteReadByte(0x00);
|
||||
Temp|=Spi3Flash_WriteReadByte(0xFF)<<8;
|
||||
Temp|=Spi3Flash_WriteReadByte(0xFF);
|
||||
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle))
|
||||
{
|
||||
}
|
||||
SPI3_NSS_HIGH();
|
||||
|
||||
return Temp;
|
||||
}
|
||||
//Read SPI FLASH
|
||||
//Starting at the specified address reads the specified length of data
|
||||
//pBuffer:The data store
|
||||
//ReadAddr:Read start address(24bit)
|
||||
//NumByteToRead:Number of bytes to read(Max 65535)
|
||||
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead)
|
||||
{
|
||||
uint16_t i;
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
|
||||
Spi3Flash_WriteReadByte(W25X_ReadData); //Send read commands
|
||||
Spi3Flash_WriteReadByte((uint8_t)((ReadAddr)>>16)); //Send 24bit
|
||||
Spi3Flash_WriteReadByte((uint8_t)((ReadAddr)>>8));
|
||||
Spi3Flash_WriteReadByte((uint8_t)ReadAddr);
|
||||
|
||||
for(i=0;i<NumByteToRead;i++)
|
||||
{
|
||||
pBuffer[i]=Spi3Flash_WriteReadByte(0XFF); //Cycle readings
|
||||
}
|
||||
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle))
|
||||
{
|
||||
}
|
||||
|
||||
SPI3_NSS_HIGH();
|
||||
}
|
||||
//SPI in one page (0~65535) written in less than 256 bytes of data
|
||||
//Start write up to 256 bytes of data at the specified address
|
||||
//pBuffer:The data store
|
||||
//WriteAddr:Start writing the address (24bit)
|
||||
//NumByteToWrite:Number of bytes to be written (up to 256), this number should not exceed the number of remaining bytes of the page!!!
|
||||
void W25QXX_Write_Page(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint16_t i;
|
||||
W25QXX_Write_Enable(); //SET WEL
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
|
||||
Spi3Flash_WriteReadByte(W25X_PageProgram); //Send a written page command
|
||||
Spi3Flash_WriteReadByte((uint8_t)((WriteAddr)>>16)); //Send 24bit
|
||||
Spi3Flash_WriteReadByte((uint8_t)((WriteAddr)>>8));
|
||||
Spi3Flash_WriteReadByte((uint8_t)WriteAddr);
|
||||
for(i=0;i<NumByteToWrite;i++)Spi3Flash_WriteReadByte(pBuffer[i]);//Circulating wrote
|
||||
SPI3_NSS_HIGH(); //Cancel selected
|
||||
W25QXX_Wait_Busy(); //Waiting to be written to the end
|
||||
}
|
||||
//No test write SPI FLASH
|
||||
//Must ensure that writes all the data in the range of addresses to 0XFF, or write data in non-0XFF will fail!
|
||||
//With automatic feed function
|
||||
//Starting at the specified address to write to the specified length of data, but make sure that the address is out of range!
|
||||
//pBuffer:The data store
|
||||
//WriteAddr:Start write address(24bit)
|
||||
//NumByteToWrite:Number of bytes to write(Max 65535)
|
||||
//CHECK OK
|
||||
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint16_t pageremain;
|
||||
pageremain=256-WriteAddr%256; //Number of bytes remaining single page
|
||||
if(NumByteToWrite<=pageremain)pageremain=NumByteToWrite;//Less than 256 bytes
|
||||
while(1)
|
||||
{
|
||||
W25QXX_Write_Page(pBuffer,WriteAddr,pageremain);
|
||||
if(NumByteToWrite==pageremain)break;//Write end
|
||||
else //NumByteToWrite>pageremain
|
||||
{
|
||||
pBuffer+=pageremain;
|
||||
WriteAddr+=pageremain;
|
||||
|
||||
NumByteToWrite-=pageremain; //Minus has written a number of bytes
|
||||
if(NumByteToWrite>256)pageremain=256; //Once you can write to 256 bytes
|
||||
else pageremain=NumByteToWrite; //Less than 256 bytes
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//Write SPI FLASH
|
||||
//Starting at the specified address to write to the specified length of data
|
||||
//This function erases the operation!
|
||||
//pBuffer:The data store
|
||||
//WriteAddr:Start write address(24bit)
|
||||
//NumByteToWrite:Number of bytes to write(Max 65535)
|
||||
|
||||
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite)
|
||||
{
|
||||
uint32_t secpos;
|
||||
uint16_t secoff;
|
||||
uint16_t secremain;
|
||||
uint16_t i;
|
||||
uint8_t * W25QXX_BUF;
|
||||
W25QXX_BUF=W25QXX_BUFFER;
|
||||
secpos=WriteAddr/4096;//Sector address
|
||||
secoff=WriteAddr%4096;//In the sector of migration
|
||||
secremain=4096-secoff;//Slice the remaining space
|
||||
//printf("ad:%X,nb:%X\r\n",WriteAddr,NumByteToWrite);//Testing
|
||||
if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//Not greater than 4,096 bytes
|
||||
while(1)
|
||||
{
|
||||
WDT_RefreshCounter();
|
||||
W25QXX_Read(W25QXX_BUF,secpos*4096,4096);//Read out the contents of an entire sector
|
||||
for(i=0;i<secremain;i++)//Calibration data
|
||||
{
|
||||
if(W25QXX_BUF[secoff+i]!=0XFF)break;//Need to erase
|
||||
}
|
||||
if(i<secremain)//Need to erase
|
||||
{
|
||||
W25QXX_Erase_Sector(secpos);//Erase this sector
|
||||
for(i=0;i<secremain;i++) //Copy
|
||||
{
|
||||
W25QXX_BUF[i+secoff]=pBuffer[i];
|
||||
}
|
||||
W25QXX_Write_NoCheck(W25QXX_BUF,secpos*4096,4096);//Write the whole sector
|
||||
|
||||
}else W25QXX_Write_NoCheck(pBuffer,WriteAddr,secremain);//Writing has been erased, write directly to the sector the remaining interval.
|
||||
if(NumByteToWrite==secremain)break;//Write end
|
||||
else//Write over
|
||||
{
|
||||
secpos++;//Increased sector address 1
|
||||
secoff=0;//Offset is 0
|
||||
|
||||
pBuffer+=secremain; //Offset pointer
|
||||
WriteAddr+=secremain;//Write the address offset
|
||||
NumByteToWrite-=secremain; //Diminishing bytes
|
||||
if(NumByteToWrite>4096)secremain=4096; //Next sector but still not finished
|
||||
else secremain=NumByteToWrite; //Next slice to finish
|
||||
}
|
||||
};
|
||||
}
|
||||
//Erase the entire chip
|
||||
//Wait for long...
|
||||
void W25QXX_Erase_Chip(void)
|
||||
{
|
||||
W25QXX_Write_Enable(); //SET WEL
|
||||
W25QXX_Wait_Busy();
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
|
||||
Spi3Flash_WriteReadByte(W25X_ChipErase); //Send erase command
|
||||
|
||||
SPI3_NSS_HIGH(); //Cancel selected
|
||||
W25QXX_Wait_Busy(); //Wait for end of the chip erase
|
||||
}
|
||||
//Erase one sector
|
||||
//Dst_Addr:Sector address set according to actual capacity
|
||||
//Erasing a mountain at least time: 150ms
|
||||
void W25QXX_Erase_Sector(uint32_t Dst_Addr)
|
||||
{
|
||||
//Monitor Falsh erasure, testing
|
||||
// printf("fe:%x\r\n",Dst_Addr);
|
||||
Dst_Addr*=4096;
|
||||
W25QXX_Write_Enable(); //SET WEL
|
||||
W25QXX_Wait_Busy();
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
|
||||
Spi3Flash_WriteReadByte(W25X_SectorErase); //Send sector erase command
|
||||
Spi3Flash_WriteReadByte((uint8_t)((Dst_Addr)>>16)); //Send 24bit
|
||||
Spi3Flash_WriteReadByte((uint8_t)((Dst_Addr)>>8));
|
||||
Spi3Flash_WriteReadByte((uint8_t)Dst_Addr);
|
||||
|
||||
SPI3_NSS_HIGH(); //Cancel selected
|
||||
W25QXX_Wait_Busy(); //Wait for the erase to complete
|
||||
}
|
||||
//Waiting for a free
|
||||
void W25QXX_Wait_Busy(void)
|
||||
{
|
||||
while((W25QXX_ReadSR() & 0x01) == 0x01); // Wait for the BUSY emptying
|
||||
}
|
||||
//Enter the power off mode
|
||||
void W25QXX_PowerDown(void)
|
||||
{
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(W25X_PowerDown); //Send the power command
|
||||
SPI3_NSS_HIGH(); //Cancel selected
|
||||
delay_us(3); //Wait for the TPD
|
||||
}
|
||||
//Wake up
|
||||
void W25QXX_WAKEUP(void)
|
||||
{
|
||||
SPI3_NSS_LOW(); // Enabling devices
|
||||
Spi3Flash_WriteReadByte(W25X_ReleasePowerDown); // send W25X_PowerDown command 0xAB
|
||||
SPI3_NSS_HIGH(); //Cancel selected
|
||||
delay_us(3); //Waiting for TRES1
|
||||
}
|
||||
|
||||
/**
|
||||
*******************************************************************************
|
||||
** \brief SPI flash wait for write operation end function
|
||||
**
|
||||
** \param [in] None
|
||||
**
|
||||
** \retval Ok Flash internal operation finish
|
||||
** \retval ErrorTimeout Flash internal operation timeout
|
||||
**
|
||||
******************************************************************************/
|
||||
en_result_t SpiFlash_WaitForWriteEnd(void)
|
||||
{
|
||||
en_result_t enRet = Ok;
|
||||
uint8_t u8Status = 0u;
|
||||
uint32_t u32Timeout;
|
||||
stc_clk_freq_t stcClkFreq;
|
||||
|
||||
CLK_GetClockFreq(&stcClkFreq);
|
||||
u32Timeout = stcClkFreq.sysclkFreq / 1000u;
|
||||
SPI3_NSS_LOW();
|
||||
Spi3Flash_WriteReadByte(FLASH_INSTR_READ_SR1);
|
||||
do
|
||||
{
|
||||
u8Status = Spi3Flash_WriteReadByte(FLASH_DUMMY_BYTE_VALUE);
|
||||
u32Timeout--;
|
||||
} while ((u32Timeout != 0ul) &&
|
||||
((u8Status & FLASH_BUSY_BIT_MASK) == FLASH_BUSY_BIT_MASK));
|
||||
|
||||
if (FLASH_BUSY_BIT_MASK == u8Status)
|
||||
{
|
||||
enRet = ErrorTimeout;
|
||||
}
|
||||
while (Reset == SPI_GetFlag(SPI3_UNIT, SpiFlagSpiIdle))
|
||||
{
|
||||
}
|
||||
SPI3_NSS_HIGH();
|
||||
|
||||
return enRet;
|
||||
}
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
80
APP_R3323/App/Hardware/w25qxx.h
Normal file
80
APP_R3323/App/Hardware/w25qxx.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef __W25QXX_H
|
||||
#define __W25QXX_H
|
||||
#include "hc32_ddl.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//This program is for educational purposes only, without the author's permission, may not be used for any other purpose
|
||||
//ALIENTEK STM32F4 Explorer Board
|
||||
//W25QXX Driver code
|
||||
//Hot Atomic @ALIENTEK
|
||||
//Forum: www.openedv.com
|
||||
//Date modified: 2014/5/6
|
||||
//Version: V1.0
|
||||
//All rights reserved pirated reserved.
|
||||
//Copyright(C) Guangzhou wing electronic technology limited company 2009-2019
|
||||
//All rights reserved
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//W25X/Q series chip list
|
||||
//W25Q80 ID 0XEF13
|
||||
//W25Q16 ID 0XEF14
|
||||
//W25Q32 ID 0XEF15
|
||||
//W25Q64 ID 0XEF16
|
||||
//W25Q128 ID 0XEF17
|
||||
#define W25Q40 0XEF12
|
||||
#define W25Q80 0XEF13
|
||||
#define W25Q16 0XEF14
|
||||
#define W25Q32 0XEF15
|
||||
#define W25Q64 0XEF16
|
||||
#define W25Q128 0XEF17
|
||||
|
||||
#define SPI_FLASH_ADDR (0x00000000)
|
||||
#define SPI_FLASH_LAST_64K_BLOCK (0x00070000)
|
||||
#define SPI_FLASH_LAST_32K_BLOCK (0x00078000)
|
||||
#define SPI_FLASH_LAST_4K_SECTOR (0x0007F000)
|
||||
|
||||
#define SPI_FLASH_BLOCK_SIZE (0X10000)
|
||||
#define SPI_FLASH_SECTOR_SIZE (0X1000)
|
||||
#define SPI_FLASH_PAGESIZE (0x100) // 256 bytes
|
||||
|
||||
#define FLASH_DUMMY_BYTE_VALUE (0xffu)
|
||||
#define FLASH_BUSY_BIT_MASK (0x01u)
|
||||
|
||||
extern uint16_t W25QXX_TYPE; //Define W25QXX chips
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//Instruction list
|
||||
#define W25X_WriteEnable 0x06
|
||||
#define W25X_WriteDisable 0x04
|
||||
#define W25X_ReadStatusReg 0x05
|
||||
#define W25X_WriteStatusReg 0x01
|
||||
#define W25X_ReadData 0x03
|
||||
#define W25X_FastReadData 0x0B
|
||||
#define W25X_FastReadDual 0x3B
|
||||
#define W25X_PageProgram 0x02
|
||||
#define W25X_BlockErase 0xD8
|
||||
#define W25X_SectorErase 0x20
|
||||
#define W25X_ChipErase 0xC7
|
||||
#define W25X_PowerDown 0xB9
|
||||
#define W25X_ReleasePowerDown 0xAB
|
||||
#define W25X_DeviceID 0xAB
|
||||
#define W25X_ManufactDeviceID 0x90
|
||||
#define W25X_JedecDeviceID 0x9F
|
||||
|
||||
void W25QXX_Init(void);
|
||||
uint16_t W25QXX_ReadID(void); //Read FLASH ID
|
||||
uint8_t W25QXX_ReadSR(void); //Read status register
|
||||
void W25QXX_Write_SR(uint8_t sr); //Write status register
|
||||
void W25QXX_Write_Enable(void); //Write enable
|
||||
void W25QXX_Write_Disable(void); //Write-protect
|
||||
void W25QXX_Write_NoCheck(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);
|
||||
void W25QXX_Read(uint8_t* pBuffer,uint32_t ReadAddr,uint16_t NumByteToRead); //Read Flash
|
||||
void W25QXX_Write(uint8_t* pBuffer,uint32_t WriteAddr,uint16_t NumByteToWrite);//Write Flash
|
||||
void W25QXX_Erase_Chip(void); //All erase
|
||||
void W25QXX_Erase_Sector(uint32_t Dst_Addr); //Sector erase
|
||||
void W25QXX_Wait_Busy(void); //Waiting for a free
|
||||
void W25QXX_PowerDown(void); //Enter the power off mode
|
||||
void W25QXX_WAKEUP(void); //Wake up
|
||||
#endif
|
||||
|
||||
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|
||||
Reference in New Issue
Block a user