关于stm32f103的时钟关系,
可以清楚的看到各个外设模块所属的时钟总线。
stm32f103的flash和boot部分:
可以看到boot引脚的配置直接影响boot程序的运行位置。
关于STM32CubeIDE这个软件的一个提醒,***这个软件不支持在监控过程中更改变量,如果更改了,会造成程序死机。***这个在以后的调试工作中一定要谨记。
关于调试stm32f`03Cbt6 的spi与BMS1818通讯的经验。我发现我的mcu主频会影响到spi发送的数据,当主频72M时,我发现发送的数据有问题,但不影响接收到的数据。我把主频调到16M后,spi收发正常。
我非常疑惑,为什么主频大小会影响spi的发送。我的程序里使用了DMA进行spi的收发,接收时没有问题的,无论在哪个主频,都没问题,就是发送。我调试了很长时间没有解决这个问题。我突然想到,会不会是由于DMA发送导致的,也就是说,当主频72M 时,DMA发送太快,cs引脚拉高太快,导致从设备接收到的数据有问题。于是我使用纯spi发送,并且堵塞2ms发送,发现可行,数据正常了。分析之后,很可能是由于这个2ms的堵塞,使得数据有足够的时间被接收到。也就是说,当使用spi发送数据时,最好是使用纯spi发送,不要使用DMA发送。
/*
- Stm32_1818.c
- Created on: Jan 16, 2024
-
Author: admin
*/
#include “main.h”
#include “ADBMS181x.h”
#include “ADBMS1818.h”
#include “Stm32_1818.h”
cell_asic BMS1818_stu= {0};
cell_asic Bms_Balance = {0};
Us_Str User_Struct = {0};
void ADBMS1818_Balancing(void);
void output_low(uint8_t value)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
}
void output_high(uint8_t value)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
}
void delayMicroseconds(uint32_t delay)
{
uint32_t ticks;
uint32_t told,tnow,tcnt = 0;
uint32_t reload = SysTick->VAL;
ticks = delay*(SystemCoreClock / 1000000);
told = SysTick->VAL;
while(1)
{
tnow=SysTick->VAL; //获取当前数值寄存器值
if(tnow!=told) //当前值不等于开始值说明已在计数
{
if(tnow<told) //当前值小于开始数值,说明未计到0
tcnt+=told-tnow; //计数值=开始值-当前值
else //当前值大于开始数值,说明已计到0并重新计数
tcnt+=reload-tnow+told; //计数值=重装载值-当前值+开始值 (已
//从开始值计到0)
told=tnow; //更新开始值
if(tcnt>=ticks)break; //时间超过/等于要延迟的时间,则退出.
}
}
}
uint8_t DMA_rec_En_flag = 0;
uint8_t DMA_rec_finish_flag = 0;
uint8_t Rx_buff[56] = {0};
uint32_t Time_output = 0;
uint8_t Stm32spi2_TRx(uint8_t *data,uint8_t *Rxdata,uint16_t txlen,uint16_t rxlen)
{
uint8_t error;
HAL_StatusTypeDef err;
uint32_t delay_us = 1000000;
if((txlen == 0)||(rxlen == 0))
{
error = 4;
return error;
}
HAL_SPI_Abort(&hspi2);
output_low(1);
DMA_rec_En_flag = 1;
err = HAL_SPI_TransmitReceive_DMA(&hspi2,data, Rx_buff, txlen + rxlen);
if(err != HAL_OK)
{
error = 1;
return error;
}
while((DMA_rec_finish_flag == 0)&&(delay_us))
{
delay_us -= 10;
}
output_high(1);
if(delay_us <= 0)
{
error = 3;
}
else
{
DMA_rec_finish_flag = 0;
}
for(int i = 0;i<rxlen;i++)
{
Rxdata[i] = Rx_buff[i + txlen];
}
Time_output = delay_us;
return error;
}
uint8_t DMA_Send_En_flag = 0;
uint8_t DMA_Send_finish_flag = 0;
uint8_t Stm32spi2_Tx(uint8_t *data,uint16_t txlen)
{
uint8_t error = 0;
HAL_StatusTypeDef err;
if(txlen == 0)
{
error = 4;
return error;
}
err = HAL_SPI_Transmit(&hspi2, data, txlen, 2);
if(err != HAL_OK)
{
error = 1;
return error;
}
return error;
}
uint8_t Stm32spi2_Tx_wake(uint8_t *data,uint8_t len)
{
uint8_t error;
HAL_StatusTypeDef err;
err = HAL_SPI_Transmit(&hspi2, data, len, 1);
if(err != HAL_OK)
{
error = 1;
}
return error;
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
}
//如果使用纯spi发送数据,则这里的中断处理不需要。
void SPI_DMA_Sen_Fin(void)
{
if ((((hdma_spi2_tx.DmaBaseAddress->ISR & (DMA_FLAG_TC1 << hdma_spi2_tx.ChannelIndex)) != RESET)
&& ((hdma_spi2_tx.Instance->CCR & DMA_IT_TC) != RESET))&&(DMA_Send_En_flag))
{
DMA_Send_finish_flag = 1;
DMA_Send_En_flag = 0;
}
}
void SPI_DMA_Rec_Fin(void)
{
if ((((hdma_spi2_rx.DmaBaseAddress->ISR & (DMA_FLAG_TC1 << hdma_spi2_rx.ChannelIndex)) != RESET)
&& ((hdma_spi2_rx.Instance->CCR & DMA_IT_TC) != RESET))&&(DMA_rec_En_flag))
{
DMA_rec_finish_flag = 1;
DMA_rec_En_flag = 0;
}
}
uint8_t flag_t = 0;
void ADBMS1818_Mainfunc(void)
{
static int8_t tADBMS1818Sampling = BIO_TASK_IDLE;// PRE_BAL_CMD
BMS1818_stu.ic_reg.num_cv_reg = 6;
BMS1818_stu.config.tx_data[0] = 0b1110;//REFON on
Bms_Balance.config.tx_data[0] = 0b1110;//REFON on
Bms_Balance.config.tx_data[4] = 0x0f;//set DCC1,2,3,4 四个电芯做均衡
Bms_Balance.config.tx_data[5] = 0x10;//set DCTO 1,means 30s discharge time
Bms_Balance.pwm.tx_data[0] = 0xFF;//100% duty cell1,2
Bms_Balance.pwm.tx_data[1] = 0x88;//13.3% duty cell3,4
while(1)
{
switch(tADBMS1818Sampling)
{
case BIO_TASK_IDLE:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_wrcfg(1,&BMS1818_stu);
tADBMS1818Sampling = BIO_BAT_RD_CFG;
break;
case BIO_BAT_RD_CFG:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_rdcfg(1,&BMS1818_stu);
tADBMS1818Sampling = BIO_BAT_RD_CAL;
break;
case BIO_BAT_RD_CAL:
if(BMS1818_stu.config.rx_data[0] == BMS1818_stu.config.tx_data[0])
{
tADBMS1818Sampling = BIO_BAT_MEAS_CMD;
}
else
tADBMS1818Sampling = BIO_TASK_IDLE;
break;
case BIO_BAT_MEAS_CMD:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_adcv(2,0,0);//7HZ,cell all by 7HZ
// ADBMS181x_adcv(2,0,1);//7HZ,cell 1 7 13 by 7HZ
// ADBMS181x_adcv(2,0,2);//7HZ,cell 2 8 14 by 7HZ
// ADBMS181x_adcv(2,0,3);//7HZ,cell 3 9 15 by 7HZ
tADBMS1818Sampling = BIO_BAT_WAIT;
break;
case BIO_BAT_WAIT:
delayMicroseconds(1000);
tADBMS1818Sampling = BIO_BAT_RD;
break;
case BIO_BAT_RD:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_rdcv(0,1,&BMS1818_stu);//
for(int i = 0;i<18;i++)
{
User_Struct.V_cell[i] = (float)(0.0001*BMS1818_stu.cells.c_codes[i]) ;//* CELL_K + CELL_B
}
tADBMS1818Sampling = BIO_BAT_AUX;
break;
case BIO_BAT_AUX:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_adax(2,0);
tADBMS1818Sampling = BIO_BAT_AUX_WAIT;
break;
case BIO_BAT_AUX_WAIT:
delayMicroseconds(4000);
tADBMS1818Sampling = BIO_BAT_RD_AUX;
break;
case BIO_BAT_RD_AUX:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS1818_rdaux(1,1,&BMS1818_stu);
ADBMS1818_rdaux(2,1,&BMS1818_stu);
ADBMS1818_rdaux(3,1,&BMS1818_stu);
// ADBMS1818_rdaux(4,1,&BMS1818_stu);
for(int i = 0;i<9;i++)
{
User_Struct.V_gpio[i] = 0.0001*BMS1818_stu.aux.a_codes[i];
}
tADBMS1818Sampling = MEAS_BAL_CHOOS;
break;
case MEAS_BAL_CHOOS:
if(User_Struct.balance_switch == 0)//
{
tADBMS1818Sampling = BIO_BAT_MEAS_CMD;
}
else
{
tADBMS1818Sampling = PRE_BAL_CMD;//
}
break;
case PRE_BAL_CMD:
HAL_Delay(4000);
// wakeup_sleep(1);
// wakeup_idle(1);
tADBMS1818Sampling = BAL_CMD;
break;
case BAL_CMD:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_wrcfg(1,&Bms_Balance);
tADBMS1818Sampling = BAL_CMD_ENSU;
break;
case BAL_CMD_ENSU:
ADBMS181x_rdcfg(1,&Bms_Balance);
if((Bms_Balance.config.rx_data[0] == Bms_Balance.config.tx_data[0])&&
(Bms_Balance.config.rx_data[4] == Bms_Balance.config.tx_data[4])&&
(Bms_Balance.config.rx_data[5] == Bms_Balance.config.tx_data[5]))
{
tADBMS1818Sampling = BAL_WAIT;
ADBMS1818_wrpwm(1,0,&Bms_Balance);
}
else
{
tADBMS1818Sampling = BAL_CMD;
}
break;
case BAL_WAIT://balance for 1000ms
HAL_Delay(10000);
// delayMicroseconds(10000);
tADBMS1818Sampling = BAL_MUT;
break;
case BAL_MUT:
wakeup_sleep(1);
wakeup_idle(1);
ADBMS1818_mute();
tADBMS1818Sampling = BAL_MEAS_CMD;
break;
case BAL_MEAS_CMD:
// wakeup_sleep(1);
// wakeup_idle(1);
ADBMS181x_adcv(2,0,0);//7HZ,cell all by 7HZ and Discharge permitted
tADBMS1818Sampling = BAL_MEAS_READ;
break;
case BAL_MEAS_READ:
wakeup_sleep(1);
wakeup_idle(1);
delayMicroseconds(3000);
ADBMS181x_rdcv(0,1,&BMS1818_stu);//
for(int i = 0;i<18;i++)
{
User_Struct.V_cell[i] = (float)(0.0001BMS1818_stu.cells.c_codes[i]) ;// CELL_K + CELL_B
}
tADBMS1818Sampling = BAL_ENSU_COUNT;
break;
case BAL_ENSU_COUNT:
User_Struct.Count_Flag = 1;
if(User_Struct.Tim_Count >= 5000)//mearsure cell voltage for 5s
{
User_Struct.Tim_Count = 0;
User_Struct.Count_Flag = 0;
tADBMS1818Sampling = BAL_UNMUT;
}
else
tADBMS1818Sampling = BAL_MEAS_CMD;
break;
case BAL_UNMUT:
ADBMS1818_unmute();
tADBMS1818Sampling = BAL_FINISH_CHOOS;
break;
case BAL_FINISH_CHOOS:
if(User_Struct.balance_switch == 0)
tADBMS1818Sampling = BIO_TASK_IDLE;
else
tADBMS1818Sampling = BAL_CMD;
break;
}
}
}
/*
-
timer interrupt for 1ms
-
run every 1ms
*/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if(htim == &htim2)
{
if(User_Struct.Count_Flag == 1)
{
User_Struct.Tim_Count++;
}
}
}
void BMS1818_RxTx_func(void)
{
BMS1818_stu.config.tx_data[0] = 0b1110;//REFON on
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_wrcfg(1,&BMS1818_stu);
wakeup_sleep(1);
wakeup_idle(1);
ADBMS181x_rdcfg(1,&BMS1818_stu);
}