打印
[APM32F0]

遇到一个很扎心的问题,APM32F030C8初始化SPI2失败,而且不知道是哪儿出了问题...

[复制链接]
1425|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
bks882|  楼主 | 2025-2-6 23:52 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
各位大佬晚上好,如题所说,我自己画的板子,打算使用SPI2连接FM25V01铁电来记录数据,可是初始化SPI2后,用逻辑分析仪测SPI2各个引脚电平变化,发现除了CS脚之外,其它3个脚全都没电平转变;我的例程是按照官方 SDK 的 SPI1 的栗子改过来的,查了两个晚上,每个该改的改了,到今晚上还是没反应,数据手册和用户手册我都看过了,也没说过有什么SPI2有关的,真的有点怀疑人生了~~~
附件有4个文件,分别是main与SPI2的C文件和H文件,

SPI2有问题的地方.zip

3.19 KB

使用特权

评论回复
沙发
kai迪皮| | 2025-2-7 10:57 | 只看该作者
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



代码:
/*!
* [url=home.php?mod=space&uid=288409]@file[/url]        main.c
*
* [url=home.php?mod=space&uid=247401]@brief[/url]       Main program body
*
* [url=home.php?mod=space&uid=895143]@version[/url]     V1.0.3
*
* [url=home.php?mod=space&uid=212281]@date[/url]        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_USART  USART2

/* 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[BuffSize] =
{
    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[BuffSize] = {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[TxIdx++]);

        while (SPI_ReadStatusFlag(SPI2, SPI_FLAG_RXBNE) == RESET);
        SPI_Buffer_RX[RxIdx++] = SPI_I2S_RxData16(SPI2);

    }
    for (int i = 0; i < BuffSize; i++)
    {
        if (i % 7 == 0)
        {
            printf("\r\n");
        }
        printf(" %02x ,", SPI_Buffer_RX[i]);

    }
    /* 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_14  MISO*/
    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[i] != buf2[i])
        {
            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的相关寄存器是否设置正确,设置正确时再检查硬件设计是否有误。

使用特权

评论回复
板凳
xionghaoyun| | 2025-2-7 13:56 | 只看该作者
楼上回复很仔细

使用特权

评论回复
地板
bks882|  楼主 | 2025-2-7 20:16 | 只看该作者
kai迪皮 发表于 2025-2-7 10:57
hi,我在官方例程SPI_TwoBoards修改过来了一份SPI2的初始化通信测试,发现测试可以通过的。使用的引脚如下 ...

我今天下班回家后能看到大佬这么详细的信息,心里可乐开花。但是事与愿违...
我回到家里立马先对比大佬的代码,到底我写的是缺了那些代码,然后不上那些缺的代码,然后烧录进单片机测试,试过后发现逻辑分析仪式的时钟脚,MISO,MOSI都是没信号,除了CS脚外...接着我把铁电芯片拆了再测试,结果还是一样,最后没办法了,换单片机....测试结果还是一样....
(刚新年开头,还真是出师不利 ‘鸭’ ~~~)
既然硬件不信,那就使用软件处理吧,还好我测试过了,作为普通IO口,还是能正常运作的!
不过还是谢谢大佬帮忙!!!

使用特权

评论回复
5
天意无罪| | 2025-2-8 09:19 | 只看该作者
bks882 发表于 2025-2-7 20:16
我今天下班回家后能看到大佬这么详细的信息,心里可乐开花。但是事与愿违...
我回到家里立马先对比大佬的 ...

这都补焊了,芯片也换过了,用作普通IO也是正常的,那说明硬件通路上应该是没有问题的,如果还是不行的话,那大概率和你的配置有关系。

使用特权

评论回复
6
delin17| | 2025-2-8 18:22 | 只看该作者
直接看寄存器,是不是时钟没开,或者IO口配置不对。

使用特权

评论回复
7
bks882|  楼主 | 2025-2-8 19:49 | 只看该作者
天意无罪 发表于 2025-2-8 09:19
这都补焊了,芯片也换过了,用作普通IO也是正常的,那说明硬件通路上应该是没有问题的,如果还是不行的话 ...

昨天晚上,我用了2个钟头就把模拟SPI接上FM25V01的驱动调好了。不过我在调模拟SPI前,查看过SPI2寄存器的配置值,跟2楼的发出来的只是一模一样,SPI2的时钟也使能了,GPIO也是配好了,反正我就没配出SPI2出来,现在想,估计是我手上的芯片的问题了。最终我也把驱动调好了,通过模拟SPI方式。只要能使用就可以了!谢谢大家的关注!!!

使用特权

评论回复
8
bks882|  楼主 | 2025-2-8 19:50 | 只看该作者
delin17 发表于 2025-2-8 18:22
直接看寄存器,是不是时钟没开,或者IO口配置不对。

昨天晚上,我用了2个钟头就把模拟SPI接上FM25V01的驱动调好了。不过我在调模拟SPI前,查看过SPI2寄存器的配置值,跟2楼的发出来的只是一模一样,SPI2的时钟也使能了,GPIO也是配好了,反正我就没配出SPI2出来,现在想,估计是我手上的芯片的问题了。最终我也把驱动调好了,通过模拟SPI方式。只要能使用就可以了!谢谢大家的关注!

使用特权

评论回复
9
ucmic| | 2025-3-31 13:29 | 只看该作者
kai迪皮 发表于 2025-2-7 10:57
hi,我在官方例程SPI_TwoBoards修改过来了一份SPI2的初始化通信测试,发现测试可以通过的。使用的引脚如下 ...

遇到一样的情况,用SPI2出问题,搞了两天,最好发现把分频系数改成2分频就正常了:SPI_BAUDRATE_DIV_2。不知道是什么原因,除了这个分频外,其他的都无输出。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

35

帖子

0

粉丝