This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CC3235S:尽管总线上的值正确、但 SPI 总线接收到错误的值(提供了 O-SCOPE);相同的设置适用于 MSP432 Launchpad

Guru**** 2539500 points
Other Parts Discussed in Thread: CC3235S

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/wi-fi-group/wifi/f/wi-fi-forum/1033467/cc3235s-spi-bus-receiving-wrong-value-despite-correct-value-being-on-bus-o-scope-provided-same-setup-works-fine-with-msp432-launchpad

器件型号:CC3235S

您好!  

我是一名从事我的 Capstone 项目的学生。 我正在尝试在机器人项目中使用 CC3235S、其中一项功能是通过 TCP 套接字流式传输视频数据。  

简而言之、我尝试从 SPI 从器件上的寄存器读取和写入值。 当使用 CC3235S 时、它始终返回错误的值、但对于 MSP432、它在使用与 TI RTOS 驱动程序基本相同的 SPI 设置时工作正常。 我不确定 CC3235S 上是否只有额外的设置、我需要进行配置以使其正确。 我通过查看示波器并在不同的微控制器上尝试相同的测试来确定它不是总线噪声。  

我还尝试了 CC3235S 上的所有4个极性、但都没有结果、即使从器件数据表看起来与 POL0_PHA0完全一致。

代码

摄像机:

在某些背景下、我目前使用的是提供 SPI 接口的 T本 公司的 T本 公司的图像缓冲区数据。  

数据表: https://www.arducam.com/ov2640/

https://www.uctronics.com/download/Amazon/ArduCAM_Mini_2MP_Camera_Shield_Hardware_Application_Note.pdf

摄像机 SPI 组帧:  

利用此图、它似乎与 TI MCU 的 POL0_PHA0相匹配。 这适用于 MSP432、但不适用于 CC3235S

测试描述:

现在、我只是尝试将值0x55写入寄存器地址、并尝试将其读回、正如 Arduino 摄像机提供的一些示例代码中所示。 因此、在两个 MCU 上、我将尝试将0x55写入地址0x00。 根据 Arducam 文档、它将为0x80 (将位7设置为读取)用于写入、为0x00用于读取。

CC3235S 测试:

当尝试在 CC3235S 上执行此操作时、它会成功写入 C9CCam、并且相机在尝试读回总线上返回正确的值。 但在软件中、它读取的是0x33而不是0x55。  

总线上的正确值;蓝色表示 MISO 线路、MOSI 表示橙色线路。 我目前无法同时探测 SCLK、因为它会使示波器和软件中的值失真。  

 

UART 终端结果

0x33 = 51十进制

我还在 CC3235S 上尝试了多个其他值、似乎有一种将低半字节内插为4位的模式、就像对低4位进行双采样一样。  

这些是尝试多个其他值的结果。  

测试1:
0xAA TX
101010.
0xCC Rx
1100 1100

测试2:
0x55 TX
0101 0101
0x33 Rx
0011 0011

测试3:
0xF0 TX
1111 0000
0xFF Rx
0000 00000

测试4:
0x0F TX
0000 1111
0xFF Rx
0000 0000

测试5:
0x77 TX
0111 0111
0x3F
00 11 1111

MSP432测试:

我还有一个 msp432 launchpad、在这里我设置了相同的测试、它的工作效果非常好。  

0x55 = 85十进制

CC3235S 代码:

/*
 * Copyright (c) 2018-2019, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== spimaster.c ========
 */
#include <stddef.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>

/* Driver configuration */
#include "ti_drivers_config.h"

#define THREADSTACKSIZE (1024)

#define SPI_MSG_LENGTH  (2)
#define MASTER_MSG      ("Hello from master, msg#: ")

#define MAX_LOOP        (10)

static Display_Handle display;

unsigned char masterRxBuffer[SPI_MSG_LENGTH] = {0x00,0x00};
unsigned char masterTxBuffer[SPI_MSG_LENGTH] = {0x80,0x55};

/* Semaphore to block master until slave is ready for transfer */
sem_t masterSem;

/*
 *  ======== slaveReadyFxn ========
 *  Callback function for the GPIO interrupt on CONFIG_SPI_SLAVE_READY.
 */
void slaveReadyFxn(uint_least8_t index)
{
    sem_post(&masterSem);
}

/*
 *  ======== masterThread ========
 *  Master SPI sends a message to slave while simultaneously receiving a
 *  message from the slave.
 */
void *masterThread(void *arg0)
{
    SPI_Handle      masterSpi;
    SPI_Params      spiParams;
    SPI_Transaction transaction;
    uint32_t        i;
    bool            transferOK;
    int32_t         status;

    /*
     * CONFIG_SPI_MASTER_READY & CONFIG_SPI_SLAVE_READY are GPIO pins connected
     * between the master & slave.  These pins are used to synchronize
     * the master & slave applications via a small 'handshake'.  The pins
     * are later used to synchronize transfers & ensure the master will not
     * start a transfer until the slave is ready.  These pins behave
     * differently between spimaster & spislave examples:
     *
     * spimaster example:
     *     * CONFIG_SPI_MASTER_READY is configured as an output pin.  During the
     *       'handshake' this pin is changed from low to high output.  This
     *       notifies the slave the master is ready to run the application.
     *       Afterwards, the pin is used by the master to notify the slave it
     *       has opened CONFIG_SPI_MASTER.  When CONFIG_SPI_MASTER is opened, this
     *       pin will be pulled low.
     *
     *     * CONFIG_SPI_SLAVE_READY is configured as an input pin. During the
     *       'handshake' this pin is read & a high value will indicate the slave
     *       ready to run the application.  Afterwards, a falling edge interrupt
     *       will be configured on this pin.  When the slave is ready to perform
     *       a transfer, it will pull this pin low.
     *
     * Below we set CONFIG_SPI_MASTER_READY & CONFIG_SPI_SLAVE_READY initial
     * conditions for the 'handshake'.
     */
//    GPIO_setConfig(CONFIG_SPI_MASTER_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
//    GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_INPUT);
//
//    /*
//     * Handshake - Set CONFIG_SPI_MASTER_READY high to indicate master is ready
//     * to run.  Wait CONFIG_SPI_SLAVE_READY to be high.
//     */
//    GPIO_write(CONFIG_SPI_MASTER_READY, 1);
//    while (GPIO_read(CONFIG_SPI_SLAVE_READY) == 0) {}
//
//    /* Handshake complete; now configure interrupt on CONFIG_SPI_SLAVE_READY */
//    GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);
//    GPIO_setCallback(CONFIG_SPI_SLAVE_READY, slaveReadyFxn);
//    GPIO_enableInt(CONFIG_SPI_SLAVE_READY);

    /* Open SPI as master (default) */
    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL0_PHA0;
    spiParams.bitRate = 4000000;
    spiParams.dataSize = 8;
    masterSpi = SPI_open(CONFIG_SPI_MASTER, &spiParams);
    if (masterSpi == NULL) {
        Display_printf(display, 0, 0, "Error initializing master SPI\n");
        while (1);
    }
    else {
        Display_printf(display, 0, 0, "Master SPI initialized\n");
    }

    while(1){

            /* Initialize master SPI transaction structure */
            GPIO_write(CONFIG_GPIO_0, 0); //CS low
            masterTxBuffer[1] = 0x55;
            masterTxBuffer[0] = 0x80;
            transaction.count = 2;
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;

            /* Perform SPI transfer */
            transferOK = SPI_transfer(masterSpi, &transaction);
            if (transferOK) {
                Display_printf(display, 0, 0, "\nMaster received: %d", masterRxBuffer[1]);
            }
            else {
                Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
            }
            GPIO_write(CONFIG_GPIO_0, 1); //CS high
            GPIO_write(CONFIG_GPIO_0, 0); //CS low
            /* Initialize master SPI transaction structure */
            masterTxBuffer[1] = 0x00;
            masterTxBuffer[0] = 0x00;
            transaction.count = 2;
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;

            /* Perform SPI transfer */
            transferOK = SPI_transfer(masterSpi, &transaction);
            if (transferOK) {
                Display_printf(display, 0, 0, "\nMaster received: %d", masterRxBuffer[1]);
            }
            else {
                Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
            }
            GPIO_write(CONFIG_GPIO_0, 1); //CS high

    }

    SPI_close(masterSpi);
//
//    /* Example complete - set pins to a known state */
//    GPIO_disableInt(CONFIG_SPI_SLAVE_READY);
//    GPIO_setConfig(CONFIG_SPI_SLAVE_READY, GPIO_CFG_OUTPUT | GPIO_CFG_OUT_LOW);
//    GPIO_write(CONFIG_SPI_MASTER_READY, 0);

    Display_printf(display, 0, 0, "\nDone");

    return (NULL);
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    pthread_t           thread0;
    pthread_attr_t      attrs;
    struct sched_param  priParam;
    int                 retc;
    int                 detachState;

    /* Call driver init functions. */
    Display_init();
    GPIO_init();
    SPI_init();

    /* Open the display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while (1);
    }

    Display_printf(display, 0, 0, "Starting the SPI master example");
    Display_printf(display, 0, 0, "This example requires external wires to be "
        "connected to the header pins. Please see the Board.html for details.\n");

    GPIO_write(CONFIG_GPIO_0, 1);

    /* Create application threads */
    pthread_attr_init(&attrs);

    detachState = PTHREAD_CREATE_DETACHED;
    /* Set priority and stack size attributes */
    retc = pthread_attr_setdetachstate(&attrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }

    retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }

    /* Create master thread */
    priParam.sched_priority = 1;
    pthread_attr_setschedparam(&attrs, &priParam);

    retc = pthread_create(&thread0, &attrs, masterThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }

    return (NULL);
}

MSP432代码:  

/*
 * Copyright (c) 2018-2019, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== spimaster.c ========
 */
#include <stddef.h>
#include <stdint.h>
#include <string.h>

/* POSIX Header files */
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

/* Driver configuration */
#include "ti_drivers_config.h"

/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>
#include <ti/display/Display.h>
#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerMSP432.h>

#define THREADSTACKSIZE (1024)

#define SPI_MSG_LENGTH  (30)
#define MASTER_MSG      ("Hello from master, msg#: ")

#define MAX_LOOP        (10)

static Display_Handle display;

unsigned char masterRxBuffer[SPI_MSG_LENGTH];
unsigned char masterTxBuffer[SPI_MSG_LENGTH];

/* Semaphore to block master until slave is ready for transfer */
sem_t masterSem;

/*
 *  ======== slaveReadyFxn ========
 *  Callback function for the GPIO interrupt on CONFIG_SPI_SLAVE_READY.
 */
void slaveReadyFxn(uint_least8_t index)
{
    sem_post(&masterSem);
}

/*
 *  ======== masterThread ========
 *  Master SPI sends a message to slave while simultaneously receiving a
 *  message from the slave.
 */
void *masterThread(void *arg0)
{
    SPI_Handle      masterSpi;
    SPI_Params      spiParams;
    SPI_Transaction transaction;
    uint32_t        i;
    bool            transferOK;
    int32_t         status;


    /* Open SPI as master (default) */
    SPI_Params_init(&spiParams);
    spiParams.frameFormat = SPI_POL0_PHA0;
    spiParams.bitRate = 4000000;
    masterSpi = SPI_open(CONFIG_SPI_MASTER, &spiParams);
    if (masterSpi == NULL) {
        Display_printf(display, 0, 0, "Error initializing master SPI\n");
        while (1);
    }
    else {
        Display_printf(display, 0, 0, "Master SPI initialized\n");
    }

    /* Copy message to transmit buffer */
    strncpy((char *) masterTxBuffer, MASTER_MSG, SPI_MSG_LENGTH);

    while(1){

            /* Initialize master SPI transaction structure */
            GPIO_write(CONFIG_GPIO_0, 0); //CS low
            masterTxBuffer[1] = 0x55;
            masterTxBuffer[0] = 0x80;
            transaction.count = 2;
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;

            /* Perform SPI transfer */
            transferOK = SPI_transfer(masterSpi, &transaction);
            if (transferOK) {
//                Display_printf(display, 0, 0, "\nMaster received: %d", masterRxBuffer[1]);
            }
            else {
                Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
            }
            GPIO_write(CONFIG_GPIO_0, 1); //CS high

            /* Initialize master SPI transaction structure */
            GPIO_write(CONFIG_GPIO_0, 0); //CS low
            masterTxBuffer[1] = 0x00;
            masterTxBuffer[0] = 0x00;
            transaction.count = 2;
            transaction.txBuf = (void *) masterTxBuffer;
            transaction.rxBuf = (void *) masterRxBuffer;

            /* Perform SPI transfer */
            transferOK = SPI_transfer(masterSpi, &transaction);
            if (transferOK) {
                Display_printf(display, 0, 0, "\nMaster received: %d", masterRxBuffer[1]);
            }
            else {
                Display_printf(display, 0, 0, "Unsuccessful master SPI transfer");
            }
            GPIO_write(CONFIG_GPIO_0, 1); //CS high

    }

    SPI_close(masterSpi);

    Display_printf(display, 0, 0, "\nDone");

    return (NULL);
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    pthread_t           thread0;
    pthread_attr_t      attrs;
    struct sched_param  priParam;
    int                 retc;
    int                 detachState;

    /* Call driver init functions. */
    Display_init();
    GPIO_init();
    SPI_init();

//    /* Configure the LED pins */
//    GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
//    GPIO_setConfig(CONFIG_GPIO_LED_1, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);

    /* Set performance level to allow custom SPI Frequency */
    Power_releaseConstraint(PowerMSP432_DISALLOW_PERFLEVEL_4);
    Power_setPerformanceLevel(4);

    /* Open the display for output */
    display = Display_open(Display_Type_UART, NULL);
    if (display == NULL) {
        /* Failed to open display driver */
        while (1);
    }

//    /* Turn on user LED */
    GPIO_write(CONFIG_GPIO_0, 1);

    Display_printf(display, 0, 0, "Starting the SPI master example");
    Display_printf(display, 0, 0, "This example requires external wires to be "
        "connected to the header pins. Please see the Board.html for details.\n");

    /* Create application threads */
    pthread_attr_init(&attrs);

    detachState = PTHREAD_CREATE_DETACHED;
    /* Set priority and stack size attributes */
    retc = pthread_attr_setdetachstate(&attrs, detachState);
    if (retc != 0) {
        /* pthread_attr_setdetachstate() failed */
        while (1);
    }

    retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE);
    if (retc != 0) {
        /* pthread_attr_setstacksize() failed */
        while (1);
    }

    /* Create master thread */
    priParam.sched_priority = 1;
    pthread_attr_setschedparam(&attrs, &priParam);

    retc = pthread_create(&thread0, &attrs, masterThread, NULL);
    if (retc != 0) {
        /* pthread_create() failed */
        while (1);
    }

    return (NULL);
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Marquez、

    调试时、事务前后缓冲区的内容是什么? 您是否能够使用两个 LaunchPad 来获取 spimaster 和 spislave 演示?

    此致、

    Sarah

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Sarah、

    感谢您的回答!

    因此、我再次对该设置进行了反复讨论;它似乎将跳线拉开来解决了该问题。 我想这对于 cc3235s launchpad 是个问题、但对于 msp432则不是。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Marquez

    我遇到相同的问题。
    如何修复 Launchpad 上的跳线?
    了解详情很好。

    此致、
    Kiyoshi  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    嗨、Kiyoshi、

    您知道跳线通常是如何卡在一起的? 我想所发生的情况是、我的 SPI 时钟线和接地线之间的距离太近、因此将它们分开可以解决我的问题。 不过、我不太确定当我迁移到定制硬件时会发生什么情况。  

    这是我的设置、我使用跳线将 SPI 和电源连接到摄像头模块:

    希望这对您有所帮助。

    最棒的

    Marquez

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 、Marquez

    感谢您的回复和建议。
    我使用跳线引脚以相同的方式连接它们。
    我将使用不同的时钟线和其他安排来尝试它。

    此致、
    Kiyoshi  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 、Marquez

    我先介绍一下时钟线路由、现在 MCU 可以读取与示波器相同的值!
    感谢您的建议。
    令我惊讶的是、对于 MCPU 制造商的开发板而言、这种措施是必要的。
    非常感谢您的帮助!

    此致、
    Kiyoshi