STM32L151 SPI2调试笔记

STM32L151 SPI2调试笔记

项目中SPI1已使用,另一个芯片SPI通信方式,不得不采用SPI2通信,前面使用的是正点原子的代码,但是发现调试发现程序会卡死在发送这里

u8 SPI2_ReadWriteByte(u8 TxData)
{		 			 
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空  	
	SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个byte数据	
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个byte  
	return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据			    
}

调试读取SPI2寄存器的值,对比SPI1发现SPI2->CR1寄存器没有写入数据,也就是配置的值没有写进去,所以发送数据就会卡死。
改之前的代码:

/******************************************
初始化SPI2引脚
PB12-SPI2_NSS==>不使用硬件CS
PB13-SPI2_SCK
PB14-SPI2_MISO
PB15-SPI2_MOSI
******************************************/
void SPI2_Init(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
	SPI_InitTypeDef  SPI_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);		
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);			
 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  				
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;				
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;			
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);						
	
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_SPI2); 		
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_SPI2); 		
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_SPI2); 		
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);			
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,DISABLE);		

	SPI_InitStructure.SPI_Direction = 	SPI_Direction_2Lines_FullDuplex;  	//设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = 		SPI_Mode_Master;					//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = 	SPI_DataSize_8b;					//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = 		SPI_CPOL_Low;						//串行同步时钟的空闲状态为低电平
	SPI_InitStructure.SPI_CPHA = 		SPI_CPHA_1Edge;						//串行同步时钟的第一个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = 		SPI_NSS_Soft;						//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;		//定义波特率预分频的值:波特率预分频值为256
	SPI_InitStructure.SPI_FirstBit = 	SPI_FirstBit_MSB;					//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;								//CRC值计算的多项式
	SPI_Init(SPI2, &SPI_InitStructure); 								    //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
 
	SPI_Cmd(SPI2, ENABLE); 			 
}

修改之后的代码:

/******************************************
初始化SPI2引脚
PB12-SPI2_NSS==>不使用硬件CS
PB13-SPI2_SCK
PB14-SPI2_MISO
PB15-SPI2_MOSI
******************************************/
void SPI2_Init(void)
{
	u32 data;
	
	SPI_InitTypeDef  SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	/* 使能SPI2时钟 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);	 
	/* 使能SPI引脚相关的时钟 */
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB,ENABLE);		
	/*指令IO的复用功能*/
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,GPIO_AF_SPI2);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,GPIO_AF_SPI2);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,GPIO_AF_SPI2);
	/*  SCK、MOSI、MISO */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode =  GPIO_Mode_AF;  
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);

	RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);
	
	SPI_InitStructure.SPI_Direction = 	SPI_Direction_2Lines_FullDuplex;  	//设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
	SPI_InitStructure.SPI_Mode = 		SPI_Mode_Master;					//设置SPI工作模式:设置为主SPI
	SPI_InitStructure.SPI_DataSize = 	SPI_DataSize_8b;					//设置SPI的数据大小:SPI发送接收8位帧结构
	SPI_InitStructure.SPI_CPOL = 		SPI_CPOL_Low;						//串行同步时钟的空闲状态为低电平
	SPI_InitStructure.SPI_CPHA = 		SPI_CPHA_1Edge;						//串行同步时钟的第一个跳变沿(上升或下降)数据被采样
	SPI_InitStructure.SPI_NSS = 		SPI_NSS_Soft;						//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;		//定义波特率预分频的值:波特率预分频值为256
	SPI_InitStructure.SPI_FirstBit = 	SPI_FirstBit_MSB;					//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
	SPI_InitStructure.SPI_CRCPolynomial = 7;								//CRC值计算的多项式
	SPI_Init(SPI2, &SPI_InitStructure); 								    //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器

	SPI_Cmd(SPI2, ENABLE);	
	data= *(vu32*)0x40003800;
	sprintf(mrh,"data:0x%X",data);
	RS485_SendStr(mrh);	
	SPI2_ReadWriteByte(0xFF);	
}

后面部分是为了验证SPI2寄存器是否成功写入值。其实,对比发现,代码不同的地方就是这一段

改之前:
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);			
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,DISABLE);		
改之后:
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,ENABLE);
	RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2,DISABLE);

原来是自己在写代码时,把这个复位操作写成了时钟使能,造成了以上错误,还是太粗心

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用HAL库初始化STM32L151SPI2通道的示例代码: ```c #include "stm32l1xx_hal.h" SPI_HandleTypeDef hspi2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_SPI2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI2_Init(); while (1) { // 在这里添加你的代码 } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.LSIState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { Error_Handler(); } } static void MX_SPI2_Init(void) { hspi2.Instance = SPI2; hspi2.Init.Mode = SPI_MODE_MASTER; hspi2.Init.Direction = SPI_DIRECTION_2LINES; hspi2.Init.DataSize = SPI_DATASIZE_8BIT; hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi2.Init.CRCPolynomial = 7; if (HAL_SPI_Init(&hspi2) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 在上面的代码中,我们使用了以下HAL库函数: - HAL_RCC_OscConfig:用于配置时钟源。 - HAL_RCC_ClockConfig:用于配置系统时钟和外设时钟。 - HAL_SPI_Init:用于初始化SPI2外设。 - HAL_GPIO_Init:用于初始化GPIO外设。 上述代码初始化了SPI2通道所需的GPIO和SPI外设,并配置了SPI的主模式、8位数据传输、时钟极性和相位。你可以根据自己的需要修改这些参数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值