stm32f103

关于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);

}

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值