遇到一个很扎心的问题,APM32F030C8初始化SPI2失败,而且不知道是哪儿出了问题...
各位大佬晚上好,如题所说,我自己画的板子,打算使用SPI2连接FM25V01铁电来记录数据,可是初始化SPI2后,用逻辑分析仪测SPI2各个引脚电平变化,发现除了CS脚之外,其它3个脚全都没电平转变;我的例程是按照官方 SDK 的 SPI1 的栗子改过来的,查了两个晚上,每个该改的改了,到今晚上还是没反应,数据手册和用户手册我都看过了,也没说过有什么SPI2有关的,真的有点怀疑人生了~~~附件有4个文件,分别是main与SPI2的C文件和H文件,
hi,我在官方例程SPI_TwoBoards修改过来了一份SPI2的初始化通信测试,发现测试可以通过的。使用的引脚如下:
板卡1 APM32F030R8 Master 板卡2 APM32F030R8 Slave
程序 SPI_TwoBoards_Master SPI2 SPI_TwoBoards_Slave
NSS PA8 PA4
SCK PB13 PA5
MISO PB14 PA6
MOSI PB15 PA7
代码:
/*!
* @file main.c
*
* @brief Main program body
*
* @version V1.0.3
*
* @date 2022-09-20
*
* @attention
*
*Copyright (C) 2020-2022 Geehy Semiconductor
*
*You may not use this file except in compliance with the
*GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
*
*The program is only for reference, which is distributed in the hope
*that it will be useful and instructional for customers to develop
*their software. Unless required by applicable law or agreed to in
*writing, the program is distributed on an "AS IS" BASIS, WITHOUT
*ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
*See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
*and limitations under the License.
*/
/* Includes */
#include "Board.h"
#include "stdio.h"
#include "apm32f0xx_gpio.h"
#include "apm32f0xx_misc.h"
#include "apm32f0xx_eint.h"
#include "apm32f0xx_spi.h"
/** @addtogroup Examples
@{
*/
/** @addtogroup SPI_TwoBoards_Master
@{
*/
/** @defgroup SPI_TwoBoards_Master_Macros Macros
@{
*/
/* printf function configs to USART2 */
#define DEBUG_USARTUSART2
/* Buffsize */
#define BuffSize 56
/**@} end of group SPI_TwoBoards_Master_Macros */
/** @defgroup SPI_TwoBoards_Master_Enumerations Enumerations
@{
*/
/**@} end of group SPI_TwoBoards_Master_Enumerations */
/** @defgroup SPI_TwoBoards_Master_Structures Structures
@{
*/
/**@} end of group SPI_TwoBoards_Master_Structures */
/** @defgroup SPI_TwoBoards_Master_Variables Variables
@{
*/
/* SPI TX Buffer*/
uint8_t SPI_Buffer_TX =
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0X07,
};
/**@} end of group SPI_TwoBoards_Master_Variables */
/** @defgroup SPI_TwoBoards_Master_Functions Functions
@{
*/
/* Delay */
void Delay(uint16_t count);
/* SPI Init */
void APM_MINI_SPIInit(void);
/* Buffer Compare*/
BOOL BufferCompare(uint8_t* buf1, uint8_t* buf2, uint8_t size);
/*!
* @brief Main program
*
* @param None
*
* @retval None
*
* @note
*/
int main(void)
{
/* index of TxData*/
volatile uint8_t TxIdx = 0;
/* index of RxData*/
volatile uint8_t RxIdx = 0;
/* SPI Receive Buffer*/
uint8_t SPI_Buffer_RX = {0x00};
APM_MINI_LEDInit(LED2);
APM_MINI_LEDInit(LED3);
APM_MINI_COMInit(COM2);
APM_MINI_SPIInit();
printf("I am Master\r\n");
/* Low Down NSS for communication*/
GPIO_ClearBit(GPIOA, GPIO_PIN_8);
while (TxIdx < BuffSize)
{
while (SPI_ReadStatusFlag(SPI2, SPI_FLAG_TXBE) == RESET);
SPI_I2S_TxData16(SPI2, SPI_Buffer_TX);
while (SPI_ReadStatusFlag(SPI2, SPI_FLAG_RXBNE) == RESET);
SPI_Buffer_RX = SPI_I2S_RxData16(SPI2);
}
for (int i = 0; i < BuffSize; i++)
{
if (i % 7 == 0)
{
printf("\r\n");
}
printf(" %02x ,", SPI_Buffer_RX);
}
/* Set NSS high for close communication*/
GPIO_SetBit(GPIOA, GPIO_PIN_8);
/* Compare Buffer*/
if (BufferCompare(SPI_Buffer_TX, SPI_Buffer_RX, BuffSize) == TRUE)
{
APM_MINI_LEDOn(LED2);
}
for (;;)
{
Delay(0x5f5f);
APM_MINI_LEDToggle(LED3);
}
}
/*!
* @brief SPI Init
*
* @param None
*
* @retval None
*
* @note
*/
void APM_MINI_SPIInit(void)
{
GPIO_Config_T gpioConfig;
SPI_Config_T spiConfig;
/* Enable related clock*/
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2);
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA|RCM_AHB_PERIPH_GPIOB);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
/* Config alter function*/
// GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_5, GPIO_AF_PIN0);
// GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_6, GPIO_AF_PIN0);
// GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_PIN0);
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_13, GPIO_AF_PIN0);
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_14, GPIO_AF_PIN0);
GPIO_ConfigPinAF(GPIOB, GPIO_PIN_SOURCE_15, GPIO_AF_PIN0);
/* config PIN_13->SCK , PIN_15->MOSI*/
gpioConfig.pin =GPIO_PIN_13 | GPIO_PIN_15;
gpioConfig.mode = GPIO_MODE_AF;
gpioConfig.outtype = GPIO_OUT_TYPE_PP;
gpioConfig.speed = GPIO_SPEED_50MHz;
gpioConfig.pupd = GPIO_PUPD_PU;
GPIO_Config(GPIOB, &gpioConfig);
/* config PIN_8->NSS*/
gpioConfig.pin =GPIO_PIN_8;
gpioConfig.outtype = GPIO_OUT_TYPE_PP;
gpioConfig.speed = GPIO_SPEED_50MHz;
gpioConfig.pupd = GPIO_PUPD_PU;
gpioConfig.mode = GPIO_MODE_OUT;
GPIO_Config(GPIOA, &gpioConfig);
GPIO_SetBit(GPIOA, GPIO_PIN_8);
/* config PIN_14MISO*/
gpioConfig.pin = GPIO_PIN_14;
gpioConfig.mode = GPIO_MODE_AF;
gpioConfig.pupd = GPIO_PUPD_PU;
gpioConfig.speed = GPIO_SPEED_50MHz;
GPIO_Config(GPIOB, &gpioConfig);
/* SPI RESET*/
SPI_Reset(SPI2);
SPI_ConfigStructInit(&spiConfig);
/* SPI configuration*/
/* Set Clock polarity is Low, but Slave is High*/
spiConfig.polarity = SPI_CLKPOL_LOW;
/* select master mode*/
spiConfig.mode = SPI_MODE_MASTER;
/* SPI Clock Phase is 1EDGE, but Slave is 1EDGE*/
spiConfig.phase = SPI_CLKPHA_1EDGE;
/* Enable Software slave control */
spiConfig.slaveSelect = SPI_SSC_ENABLE;
/* Set SPI BaudRate divider*/
spiConfig.baudrateDiv = SPI_BAUDRATE_DIV_256;
/* SPI data length*/
spiConfig.length = SPI_DATA_LENGTH_16B;
/* Set internal slave*/
SPI_EnableInternalSlave(SPI2);
SPI_Config(SPI2, &spiConfig);
SPI_ConfigFIFOThreshold(SPI2, SPI_RXFIFO_QUARTER);
SPI_Enable(SPI2);
}
/*!
* @brief Delay
*
* @param None
*
* @retval None
*
* @note
*/
void Delay(uint16_t count)
{
volatile uint32_t delay = count;
while (delay--);
}
/*!
* @brief Compares two buffers
*
* @param buf1: First buffer to be compared
*
* @param buf1: Second buffer to be compared
*
* @param size: Buffer size
*
* @retval Return TRUE if buf1 = buf2. If not then return FALSE
*
* @note
*/
BOOL BufferCompare(uint8_t* buf1, uint8_t* buf2, uint8_t size)
{
uint8_t i;
for (i = 0; i < size; i++)
{
if (buf1 != buf2)
{
return FALSE;
}
}
return TRUE;
}
#if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch:The characters that need to be send.
*
* @param *f:pointer to a FILE that can recording all information
* needed to control a stream
*
* @retval The characters that need to be send.
*
* @note
*/
int fputc(int ch, FILE* f)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, (uint8_t)ch);
/* wait for the data to be send*/
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return (ch);
}
#elif defined (__GNUC__)
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param ch:The characters that need to be send.
*
* @retval The characters that need to be send.
*
* @note
*/
int __io_putchar(int ch)
{
/* send a byte of data to the serial port */
USART_TxData(DEBUG_USART, ch);
/* wait for the data to be send*/
while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
return ch;
}
/*!
* @brief Redirect C Library function printf to serial port.
* After Redirection, you can use printf function.
*
* @param file:Meaningless in this function.
*
* @param *ptr:Buffer pointer for data to be sent.
*
* @param len:Length of data to be sent.
*
* @retval The characters that need to be send.
*
* @note
*/
int _write(int file, char* ptr, int len)
{
int i;
for (i = 0; i < len; i++)
{
__io_putchar(*ptr++);
}
return len;
}
#else
#warning Not supported compiler type
#endif
/**@} end of group SPI_TwoBoards_Master_Functions */
/**@} end of group SPI_TwoBoards_Master */
/**@} end of group Examples */
仿真情况:
逻辑分析仪抓取情况:
你可以看看你的代码是否有需要改动的地方,建议你在debug窗口查看一下SPI2的寄存器,若初始化成功,SPI2的寄存器应该是相应的内容。
如何查看外设寄存器值:
SPI2初始化前:
SPI2初始化后:
同样的可以检查SPI相关GPIO和RCM的相关寄存器是否设置正确,设置正确时再检查硬件设计是否有误。
楼上回复很仔细 kai迪皮 发表于 2025-2-7 10:57
hi,我在官方例程SPI_TwoBoards修改过来了一份SPI2的初始化通信测试,发现测试可以通过的。使用的引脚如下 ...
我今天下班回家后能看到大佬这么详细的信息,心里可乐开花。但是事与愿违...
我回到家里立马先对比大佬的代码,到底我写的是缺了那些代码,然后不上那些缺的代码,然后烧录进单片机测试,试过后发现逻辑分析仪式的时钟脚,MISO,MOSI都是没信号,除了CS脚外...接着我把铁电芯片拆了再测试,结果还是一样,最后没办法了,换单片机....测试结果还是一样....
(刚新年开头,还真是出师不利 ‘鸭’ ~~~)
既然硬件不信,那就使用软件处理吧,还好我测试过了,作为普通IO口,还是能正常运作的!
不过还是谢谢大佬帮忙!!! bks882 发表于 2025-2-7 20:16
我今天下班回家后能看到大佬这么详细的信息,心里可乐开花。但是事与愿违...
我回到家里立马先对比大佬的 ...
这都补焊了,芯片也换过了,用作普通IO也是正常的,那说明硬件通路上应该是没有问题的,如果还是不行的话,那大概率和你的配置有关系。 直接看寄存器,是不是时钟没开,或者IO口配置不对。 天意无罪 发表于 2025-2-8 09:19
这都补焊了,芯片也换过了,用作普通IO也是正常的,那说明硬件通路上应该是没有问题的,如果还是不行的话 ...
昨天晚上,我用了2个钟头就把模拟SPI接上FM25V01的驱动调好了。不过我在调模拟SPI前,查看过SPI2寄存器的配置值,跟2楼的发出来的只是一模一样,SPI2的时钟也使能了,GPIO也是配好了,反正我就没配出SPI2出来,现在想,估计是我手上的芯片的问题了。最终我也把驱动调好了,通过模拟SPI方式。只要能使用就可以了!谢谢大家的关注!!! delin17 发表于 2025-2-8 18:22
直接看寄存器,是不是时钟没开,或者IO口配置不对。
昨天晚上,我用了2个钟头就把模拟SPI接上FM25V01的驱动调好了。不过我在调模拟SPI前,查看过SPI2寄存器的配置值,跟2楼的发出来的只是一模一样,SPI2的时钟也使能了,GPIO也是配好了,反正我就没配出SPI2出来,现在想,估计是我手上的芯片的问题了。最终我也把驱动调好了,通过模拟SPI方式。只要能使用就可以了!谢谢大家的关注! kai迪皮 发表于 2025-2-7 10:57
hi,我在官方例程SPI_TwoBoards修改过来了一份SPI2的初始化通信测试,发现测试可以通过的。使用的引脚如下 ...
遇到一样的情况,用SPI2出问题,搞了两天,最好发现把分频系数改成2分频就正常了:SPI_BAUDRATE_DIV_2。不知道是什么原因,除了这个分频外,其他的都无输出。 请确保你的板子上SPI2的线路没有短路或者断路,同时检查FM25V01的连接是否正确。
页:
[1]