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.

[参考译文] MSP430FR5994:无法读取器件 ID

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1161367/msp430fr5994-unable-to-read-device-id

器件型号:MSP430FR5994

尊敬的先生/女士

我尝试使用 SPI 将 ADXL345加速计与 msp430fr5994连接。 当我运行程序时、我将在发送缓冲区获得0xFF 的虚拟值。我在这里共享代码。我已将头文件用作标准 MASTER_SPI 的 SDK。 请解决我的错误。

#include
#include
#include
#include
#include

unsigned char addr[30]="";

空 initSPI()

//时钟极性:无效状态为高电平
//MSB 优先、8位、主器件、3引脚模式、同步
UCB1CTLW0 = UCSWRST;//**将状态机复位
UCB1CTLW0 |= UCCKPL | UCMSB | UCSYNC
| UCMST | UCSSEL_SMCLK;// 3引脚8位 SPI 从 SMCLK=16MHz
UCB1BRW = 0x160;//16000000 / 160=100kHz
//UCB1MCTLW = 0;
UCB1CTLW0 &=~UCSWRST;//**初始化 USCI 状态机**
UCB1IE |= UCRXIE;//启用 USCI0 RX 中断


空 initGPIO()

//LED
comms_LED_DIR |= comms_LED_PIN;
comms_LED_OUT &=~comms_LED_PIN;

button_LED_DIR |= button_LED_PIN;
button_LED_OUT &=~button_LED_PIN;

//配置 SPI
P5SEL0 |= BIT0 | BIT1 | BIT2;

SLAVE_RST_DIR |= SLAVE_RST_PIN;
SLAVE_RST_OUT |= SLAVE_RST_PIN;

SLAVE_CS_DIR |= SLAVE_CS_PIN;
SLAVE_CS_OUT |= SLAVE_CS_PIN;

//按钮启动传输
button_DIR &=~(button_PIN);// Button 输入
button_out |= button_PIN;// Button pullup
button_REN |= button_PIN;//按钮上拉/下拉电阻使能
button_IES |= button_PIN;//按钮高/低边沿
button_IE |= button_PIN;//启用按钮中断

//禁用 GPIO 上电默认高阻抗模式以激活
//先前配置的端口设置
PM5CTL0 &=~LOCKLPM5;

button_IFG &=~button_PIN;//清除 Button IFG

空 initClockTo16MHz()

//根据 MCLK 的器件数据表的要求配置一个 FRAM 等待状态
//在配置时钟系统之前在8MHz 以上运行。
FRCTL0 = FRCTLPW | NWAITS_1;

//时钟系统设置
CSCTL0_H = CSKKEY_H;//解锁 CS 寄存器
CSCTL1 = DCOFSEL_0;//将 DCO 设置为1MHz

//设置 SMCLK = MCLK = DCO、ACLK = LFXTCLK (如果 VLOCLK 不可用)
CSCTL2 = SELA_LFXTCLK | SELESS__DCOCLK | SELM_DCOCLK;

//每个器件勘误表在将频率更改为之前将分频器设置为4
//防止因过冲瞬态而超出规格运行
CSCTL3 = DIVA__4 | DIVM_4;//针对勘误表将所有相应的时钟源设置为4分频
CSCTL1 = DCOFSEL_4 | DCORSEL;//将 DCO 设置为16MHz

//延迟~10us 以使 DCO 稳定。 60个周期= 20个周期缓冲器+(10us /(1/4MHz))
_DELAY_CYCLLES (60);
CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1;//针对16MHz 运行将所有分频器设置为1
CSCTL0_H = 0;//锁定 CS 寄存器

int adxl_device_id ()

unsigned int id;
SPI_Master_ReadReg (CMD_TYPE_0_SLAVE、TYPE_0_LENGTH);
id=ReceiveBuffer[0];
退货 ID;

int main (void){
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

initClockTo16MHz();
initGPIO();
initspi();

SLAVE_RST_OUT 和=~SLAVE_RST_PIN;//现在已初始化 SPI 信号、
_DELAY_CYCLES (100000);
SLAVE_RST_OUT |= SLAVE_RST_PIN;//复位从器件
_DELAY_CYCLES (100000);//等待从器件初始化

comms_LED_OUT |= comms_LED_PIN;

while (1)

int adxl_id;
adxl_id=adxl_device_id ();


返回0;

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

    缺少执行实际 SPI 读取的代码。 您可能正在使用某些驱动程序库。 我看到的那个具有它自己的 SLAVE_CS_OUT 定义。 除非这与您在此处选择的内容相匹配、否则它将永远不起作用。

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

    尊敬的 David

    正如您所说、我正在与错过的代码共享代码。实际上、我使用了 TI 的 SDK 作为头文件、但我之前没有共享。因此、请检查代码。 在驱动程序库中、我使用了与我之前的程序中使用的相同的库。

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MAIN.C///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #include
    #include
    #include
    #include
    #include

    unsigned char addr[30]="";


    空 initSPI()

    //时钟极性:无效状态为高电平
    //MSB 优先、8位、主器件、3引脚模式、同步
    UCB1CTLW0 = UCSWRST;//**将状态机复位
    UCB1CTLW0 |= UCCKPL | UCMSB | UCSYNC
    | UCMST | UCSSEL_SMCLK;// 3引脚8位 SPI 从 SMCLK=16MHz
    UCB1BRW = 0x160;//16000000 / 160=100kHz
    //UCB1MCTLW = 0;
    UCB1CTLW0 &=~UCSWRST;//**初始化 USCI 状态机**
    UCB1IE |= UCRXIE;//启用 USCI0 RX 中断


    空 initGPIO()

    //LED
    comms_LED_DIR |= comms_LED_PIN;
    comms_LED_OUT &=~comms_LED_PIN;

    button_LED_DIR |= button_LED_PIN;
    button_LED_OUT &=~button_LED_PIN;

    //配置 SPI
    P5SEL0 |= BIT0 | BIT1 | BIT2;

    SLAVE_RST_DIR |= SLAVE_RST_PIN;
    SLAVE_RST_OUT |= SLAVE_RST_PIN;

    SLAVE_CS_DIR |= SLAVE_CS_PIN;
    SLAVE_CS_OUT |= SLAVE_CS_PIN;

    //按钮启动传输
    button_DIR &=~(button_PIN);// Button 输入
    button_out |= button_PIN;// Button pullup
    button_REN |= button_PIN;//按钮上拉/下拉电阻使能
    button_IES |= button_PIN;//按钮高/低边沿
    button_IE |= button_PIN;//启用按钮中断

    //禁用 GPIO 上电默认高阻抗模式以激活
    //先前配置的端口设置
    PM5CTL0 &=~LOCKLPM5;

    button_IFG &=~button_PIN;//清除 Button IFG

    空 initClockTo16MHz()

    //根据 MCLK 的器件数据表的要求配置一个 FRAM 等待状态
    //在配置时钟系统之前在8MHz 以上运行。
    FRCTL0 = FRCTLPW | NWAITS_1;

    //时钟系统设置
    CSCTL0_H = CSKKEY_H;//解锁 CS 寄存器
    CSCTL1 = DCOFSEL_0;//将 DCO 设置为1MHz

    //设置 SMCLK = MCLK = DCO、ACLK = LFXTCLK (如果 VLOCLK 不可用)
    CSCTL2 = SELA_LFXTCLK | SELESS__DCOCLK | SELM_DCOCLK;

    //每个器件勘误表在将频率更改为之前将分频器设置为4
    //防止因过冲瞬态而超出规格运行
    CSCTL3 = DIVA__4 | DIVM_4;//针对勘误表将所有相应的时钟源设置为4分频
    CSCTL1 = DCOFSEL_4 | DCORSEL;//将 DCO 设置为16MHz

    //延迟~10us 以使 DCO 稳定。 60个周期= 20个周期缓冲器+(10us /(1/4MHz))
    _DELAY_CYCLLES (60);
    CSCTL3 = DIVA__1 | DIVM_1 | DIVM__1;//针对16MHz 运行将所有分频器设置为1
    CSCTL0_H = 0;//锁定 CS 寄存器

    int adxl_device_id ()

    unsigned int id;
    SPI_Master_ReadReg (CMD_TYPE_0_SLAVE、TYPE_0_LENGTH);
    id=ReceiveBuffer[0];
    退货 ID;


    int main (void){
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

    initClockTo16MHz();
    initGPIO();
    initspi();

    SLAVE_RST_OUT 和=~SLAVE_RST_PIN;//现在已初始化 SPI 信号、
    _DELAY_CYCLES (100000);
    SLAVE_RST_OUT |= SLAVE_RST_PIN;//复位从器件
    _DELAY_CYCLES (100000);//等待从器件初始化

    comms_LED_OUT |= comms_LED_PIN;
    // SPI_Master_WriteReg (CMD_TYPE_0_MASTER、MasterType0、TYPE_0_LENGTH);
    //_bis_SR_register (LPM0_Bits + GIE);// CPU 关闭、启用中断
    while (1)

    int adxl_id;
    adxl_id=adxl_device_id ();
    printf ("%x"、adxl_id);

    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// SPI.h//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #include
    #include
    #include
    //
    //引脚配置
    //
    volatile int Tx_index=0;
    volatile int rx_index=0;
    volatile unsigned int rx_key=0;
    volatile unsigned int Tx_key=0;
    int size=0;
    unsigned char Data[15]="";
    unsigned char RXData[5]="";
    #define SLAVE_CS_OUT P5OUT
    #define SLAVE_CS_DIR P5DIR
    #define SLAVE_CS_PIN BIT2

    #define SLAVE_RST_OUT P1OUT
    #define SLAVE_RST_DIR P1DIR
    #define SLAVE_RST_PIN BIT4

    #define button_DIR P5DIR
    #define button_out P5OUT
    #define button_REN P5REN
    #define button_PIN BIT5
    #define button_IES P5IES
    #define button_IE P5IE
    #define button_IFG P5IFG
    #define button_vector PORT5_vector

    #define button_LED_OUT P1OUT
    #define button_LED_DIR P1DIR
    #define button_LED_PIN BIT1

    #define comms_LED_OUT P1OUT
    #define comms_LED_DIR P1DIR
    #define comms_LED_PIN BIT0

    //
    //示例命令(Example Commands Commands
    //

    #define 虚拟0xFF

    /* CMD_TYPE_X_SLAVE 是主设备发送到从设备的示例命令。
    *从属方将发送示例 SlaveTypeX 缓冲区进行响应。
    *
    * CMD_TYPE_X_MASTER 是主器件发送到从器件的示例命令。
    *从器件将初始化自身以接收 MasterTypeX 示例缓冲区。
    ***/

    #define CMD_TYPE_0_SLAVE 0
    #define CMD_TYPE_1_SLAVE 1.
    #define CMD_TYPE_2_SLAVE 2.

    #define CMD_TYPE_0_MASTER 3.
    #define CMD_TYPE_1_MASTER 4.
    #define CMD_TYPE_2_MASTER 5.

    #define TYPE_0_LENGTH 1.
    #define TYPE_1_LENGTH 2.
    #define TYPE_2_LENGTH 6.

    #define MAX_BUFFER_SIZE 20

    /* MasterTypeX 是在主设备中初始化的示例缓冲区,它们将是
    *由主器件发送到从器件。
    * SlaveTypeX 是在从器件中初始化的示例缓冲区,它们将是
    *由从器件发送到主器件。
    ***/

    uint8_t MasterType0 [TYPE_0_LENGTH]={0x11};
    uint8_t MasterType1 [type_1_length]={8、9};
    uint8_t MasterType2 [type_2_length]={'F'、'4'、'1'、'9'、'2'、 "b"};

    uint8_t SlaveType2 [type_2_length]={0};
    uint8_t SlaveType1 [type_1_length]={0};
    uint8_t SlaveType0 [type_0_length]={0};


    //
    //通用 SPI 状态机
    //

    typedef 枚举 SPI_ModeEnum{
    IDLE_MODE、
    TX_REG_ADDRESS_MODE、
    RX_REG_ADDRESS_MODE、
    TX_DATA_MODE、
    RX_DATA_MODE、
    TIMEOUT_MODE
    } SPI_Mode;


    /*用于跟踪软件状态机的状态*/
    SPI_Mode MasterMode = IDLE_MODE;

    /*要使用的寄存器地址/命令*/
    uint8_t TransmitRegAddr = 0;

    /* ReceiveBuffer:用于在 ISR 中接收数据的缓冲区
    * RXByteCtr:剩余要接收的字节数
    * ReceiveIndex:ReceiveBuffer 中要接收的下一个字节的索引
    * TransmitBuffer:用于在 ISR 中传输数据的缓冲区
    * TXByteCtr:剩余要传输的字节数
    * TransmitIndex:要在 TransmitBuffer 中传输的下一个字节的索引
    ***/
    uint8_t ReceiveBuffer[MAX_Buffer_SIZE]={0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_Buffer_SIZE]={0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;

    /* SPI 写入和读取函数*/

    //对于从属设备,写入*reg_data 中指定的数据
    *
    * reg_addr:要发送到从器件的寄存器或命令。
    *示例:CMD_TYPE_0_MASTER
    **REG_DATA:要写入的缓冲区
    *示例:MasterType0
    * count:* reg_data 的长度
    *示例:type_0_length
    ***/
    SPI_Mode SPI_Master_WriteReg (uint8_t reg_addr、uint8_t * reg_data、uint8_t count);

    /*对于从器件,读取从器件 REG_addr 中指定的数据。
    *接收到的数据在 ReceiveBuffer 中可用
    *
    * reg_addr:要发送到从器件的寄存器或命令。
    *示例:CMD_TYPE_0_SLAVE
    * count:要读取的数据长度
    *示例:type_0_length
    ***/
    SPI_Mode SPI_Master_ReadReg (uint8_t reg_addr、uint8_t count);
    void CopyArray (uint8_t *源、uint8_t * dest、uint8_t count);
    void SendUCB1Data (uint8_t val);

    void SendUCB1Data (uint8_t val)

    while (!(UCB1IFG & UCTXIFG));// USCI_B1 TX 缓冲区准备就绪?
    UCB1TXBUF = val;

    void CopyArray (uint8_t *源、uint8_t *目标、uint8_t 计数)

    uint8_t copyIndex = 0;
    for (copyIndex = 0;copyIndex < count;copyIndex++)

    dest[copyIndex]= source[copyIndex];


    SPI_Mode SPI_Master_WriteReg (uint8_t reg_addr、uint8_t * reg_data、uint8_t count)

    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;

    //将寄存器数据复制到 TransmitBuffer
    CopyArray (reg_data、TransmitBuffer、count);

    TXByteCtr =计数;
    RXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    Slave_CS_OUT &=~(SLAVE_CS_PIN);
    SendUCB1Data (TransmitRegAddr);

    _bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断

    SLAVE_CS_OUT |= SLAVE_CS_PIN;
    返回 MasterMode;

    SPI_Mode SPI_Master_ReadReg (uint8_t reg_addr、uint8_t count)

    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;//0X00、1
    RXByteCtr =计数;
    TXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    Slave_CS_OUT &=~(SLAVE_CS_PIN);
    SendUCB1Data (TransmitRegAddr);/0x00

    _bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断

    SLAVE_CS_OUT |= SLAVE_CS_PIN;
    返回 MasterMode;

    //
    // SPI 中断
    //

    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=USCI_B1_Vector
    _interrupt void USCI_B1_ISR (void)
    #Elif defined (_GNU_)
    void __attribute__((中断(USCI_B1_Vector)) USCI_B1_ISR (void)
    其他
    错误编译器不受支持!
    #endif

    uint8_t ucb1_rx_val = 0;
    开关(__evo_in_range (UCB1IV、USCI_SPI_UCTXIFG))

    USCI_NONE 案例:中断;
    USCI_SPI_UCRXIFG 案例:
    ucb1_Rx_val = UCB1RXBUF;
    UCB1IFG &=~UCRXIFG;
    开关(主模式)

    案例 TX_REG_ADDRESS_MODE:
    IF (RXByteCtr)

    MasterMode = RX_DATA_MODE;//需要立即开始接收
    //发送虚拟到开始
    _DELAY_CYCLES (2000000);
    SendUCB1Data (虚拟);

    其他

    MasterMode = TX_DATA_MODE;//继续转换发送缓冲区中的数据
    //首先发送
    SendUCB1Data (TransmitBuffer[TransmitIndex++]);
    TXByteCtr --;

    中断;

    案例 TX_DATA_MODE:
    IF (TXByteCtr)

    SendUCB1Data (TransmitBuffer[TransmitIndex++]);
    TXByteCtr --;

    其他

    //传输完成
    MasterMode = IDLE_MODE;
    _BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM0

    中断;

    RX_DATA_MODE case:
    IF (RXByteCtr)

    ReceiveBuffer[ReceiveIndex++]= ucb1_Rx_val;
    //发送虚拟
    RXByteCtr---;

    IF (RXByteCtr = 0)

    MasterMode = IDLE_MODE;
    _BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM0

    其他

    SendUCB1Data (虚拟);

    中断;

    默认值:
    __no_operation();
    中断;

    _DELAY_CYCLES (1000);
    中断;
    USCI_SPI_UCTXIFG 案例:
    中断;
    默认值:break;


    //
    //按钮端口中断
    //按下按钮时发生中断并启动 SPI 数据传输****
    //

    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=button_vector
    _interrupt void button_ISR (void)
    #Elif defined (_GNU_)
    void __attribute__((中断(button_vector))) button_ISR (void)
    其他
    错误编译器不受支持!
    #endif

    button_LED_OUT |= button_LED_PIN;
    button_IFG &=~button_PIN;//清除 Button IFG
    button_IE &=~button_PIN;
    //启动
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0

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

    似乎您正在尝试使用端口5位2作为芯片选择、即使该引脚已分配给 SPI 时钟输出。 这没用。 您是否确实将 CS 连接到 SPI 时钟或其他引脚?

    // Configure SPI
    P5SEL0 |= BIT0 | BIT1 | BIT2;
    
    #define SLAVE_CS_OUT P5OUT
    #define SLAVE_CS_DIR P5DIR
    #define SLAVE_CS_PIN BIT2

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

    我已检查引脚并将宏 P5的 P8更改为 CS -引脚为 P8.2。 但我仍然在发送缓冲区中得到一个虚拟(0xFF)。

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

    很难远程调试硬件/软件系统。 您必须了解如何执行该操作。 开始简单的测试。 您能否从 SPI 端口获取数据和时钟? 芯片选择? 然后返回数据。 有时可能会比较棘手。 我最近有一个 OLED 显示屏、让我感到合适。 然后我发现、尽管数据表中说过、它关心 SPI 时钟的空闲状态。

    中断会使您的生活变得非常复杂。 它们似乎没有太多的添加、对于简单的系统、我更喜欢使用轮询方法、通过简单的函数写入一个字节并返回一个字节。 它真的很简单:将数据放入 TXBUF、等待 RXIFG、读取 RXBUF。

    这是我与 OLED 一起使用的东西。 (MSP430不同、因此细节当然会有所不同。)

    char spi_write(char data)
    {
      UCB0TXBUF = data;
      while(!(IFG2 & UCB0RXIFG))
        ;
      return UCB0RXBUF;
    }
    
    

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

    您能不能告诉我天气 UCB1BRW 值是正确的。 您能告诉我如何为 SPI 编程选择模式吗? 因为对于 SPI、有4种通过时钟相位和时钟极性实现的模式。 那么、您能回答这2个问题吗?

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

    我不知道您的 BRW 值是否"正确"。 它肯定比保持时钟频率足够慢所需的大得多。 至于时钟相位和极性、您必须查看数据表。 我在 I2C 模式下使用过 ADXL335、但从未使用过345。

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

    1.我建议您使用逻辑分析仪(可以接受示波器)捕获波形、以查看发送的数据是否 符合预期。

    2.您需要查看 ADXL335的数据表以了解发出的 SPI 数据是否正确。

    然后、您可以知道如何更改代码。

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

    尊敬的 David:

    非常感谢您回答问题!

    伊斯天

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

    我在 Receive_buffer 上获得设备 ID E5,但它没有进入 RX_DATA_MODE,该模式在 SPI.h 的 mastermode=RX_DATA_MODE 上触发,命令0x00不会加载到  SPI.h 读取函数中的 TransmitRegAddr 中。

    我认为 SPI 初始化是正确的、因为如果初始化错误、接收缓冲区上不会接收到正确的 ID。 我在这里共享代码、请告诉我缺失的位置。

     (二 main.c

    #include
    #include
    #include
    #include
    #include

    unsigned char addr[30]="";
    uint8_t x、y、z;

    空 UART_CONFIG ()

    P2SEL0 &=~(BIT0 | BIT1);
    P2SEL1 |=(BIT0 | BIT1);// USCI_A0 UART 操作
    PM5CTL0 &=~LOCKLPM5;
    UCA0CTLW0=UCSWRST;//eUSCI 处于复位模式(禁用)、这将自动置位 UCTXIFG 并复位 UCRXIFG、UCRXIE、UCTXIE
    UCA0CTLW0 |=UCSSEL_SMCLK;//时钟为 SMCLK=8MHZ
    UCA0BRW = 52;
    UCA0MCTLW |= UCOS16 | UCBRF_1 | 0x49;
    UCA0CTLW0 &=~UCSWRST;//初始化 eUSCI
    UCA0IE |= UCRXIE;//启用 USCI_A0 RX 中断

    空 initSPI()

    UCB1CTLW0 = UCSWRST;//**将状态机置于复位状态**
    UCB1CTLW0 |= UCMSB | UCSYNC | UCMST | UCSSEL_SMCLK | UCCKPL;// UCCKPH | 3引脚、8位 SPI 从器件
    //UCB1CTLW0 |= UCMSB | UCSYNC | UCMST | UCSSEL_SMCLK;// UCCKPH | 3引脚、8位 SPI 从器件
    UCB1BRW = 2;
    UCB1CTLW0 &=~UCSWRST;//**初始化 USCI 状态机**
    UCB1IE |= UCRXIE;//启用 USCI0 RX 中断

    空 initGPIO()

    //LED
    comms_LED_DIR |= comms_LED_PIN;
    comms_LED_OUT &=~comms_LED_PIN;

    //配置 SPI
    P5SEL0 |= BIT0 | BIT1 | BIT2;

    SLAVE_CS_DIR |= SLAVE_CS_PIN;
    SLAVE_CS_OUT |= SLAVE_CS_PIN;

    //禁用 GPIO 上电默认高阻抗模式以激活
    //先前配置的端口设置
    PM5CTL0 &=~LOCKLPM5;


    void LPM1_Clock_config ()

    CSCTL0_H = CSKKEY_H;
    CSCTL1 = DCOFSEL_6;//8MHz |DCOFSEL_0 -1MHz
    CSCTL2 = SELA_VLOCLK | SELESS__DCOCLK | SELM_DCOCLK;//设置 SMCLK = MCLK = DCO
    CSCTL3 = DIVA_1|DIVS_1|DIVM_1;
    CSCTL0_H = 0;


    int adxl_device_id ()

    unsigned int id;
    SPI_Master_ReadReg (CMD_TYPE_0_SLAVE、TYPE_0_LENGTH);
    id=ReceiveBuffer[0];
    退货 ID;

    void id_print (unsigned char *str)

    strcpy (数据、str);
    size = strlen (Data);
    TX_index=0;
    UCA0IE |= UCTXIE | UCTXCPTIE;
    UCA0TXBUF=数据[Tx_index];
    TX_index++;
    _bis_SR_register (LPM0_bits|GIE);

    int main (void){
    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

    //initClockTo16MHz();
    LPM1_Clock_config ();
    initGPIO();
    initspi();
    UART_CONFIG();

    comms_LED_OUT |= comms_LED_PIN;

    while (1)

    int adxl_id;
    adxl_id=adxl_device_id ();
    sprintf (addr、"ID=%x\r\n"、adxl_id);//函数、用于将任何 ddata 类型转换为字符串
    ID_PRINT (addr);
    UCA0IE &=~UCTXIE;
    UCA0IE &=~UCTXCPTIE;

    _delay_cycles (8000000);

    (一 SPI.h

    #include
    #include
    #include
    //
    //引脚配置
    //
    volatile int Tx_index=0;
    volatile int rx_index=0;
    volatile unsigned int rx_key=0;
    volatile unsigned int Tx_key=0;
    int size=0;
    unsigned char Data[15]="";
    unsigned char RXData[5]="";
    #define SLAVE_CS_OUT P8OUT
    #define SLAVE_CS_DIR P8DIR
    #define SLAVE_CS_PIN BIT2

    #define SLAVE_RST_OUT P1OUT
    #define SLAVE_RST_DIR P1DIR
    #define SLAVE_RST_PIN BIT5

    #define button_DIR P5DIR
    #define button_out P5OUT
    #define button_REN P5REN
    #define button_PIN BIT5
    #define button_IES P5IES
    #define button_IE P5IE
    #define button_IFG P5IFG
    #define button_vector PORT5_vector

    #define button_LED_OUT P1OUT
    #define button_LED_DIR P1DIR
    #define button_LED_PIN BIT1

    #define comms_LED_OUT P1OUT
    #define comms_LED_DIR P1DIR
    #define comms_LED_PIN BIT0

    //
    //示例命令(Example Commands Commands
    //

    #define 虚拟0xFF

    /* CMD_TYPE_X_SLAVE 是主设备发送到从设备的示例命令。
    *从属方将发送示例 SlaveTypeX 缓冲区进行响应。
    *
    * CMD_TYPE_X_MASTER 是主器件发送到从器件的示例命令。
    *从器件将初始化自身以接收 MasterTypeX 示例缓冲区。
    ***/
    #define CMD_TYPE_0_SLAVE 0
    #define CMD_TYPE_1_SLAVE 1.
    #define CMD_TYPE_2_SLAVE 2.

    #define CMD_TYPE_0_MASTER 3.
    #define CMD_TYPE_1_MASTER 4.
    #define CMD_TYPE_2_MASTER 5.

    #define TYPE_0_LENGTH 1.
    #define TYPE_1_LENGTH 2.
    #define TYPE_2_LENGTH 6.

    #define MAX_BUFFER_SIZE 20

    /* MasterTypeX 是在主设备中初始化的示例缓冲区,它们将是
    *由主器件发送到从器件。
    * SlaveTypeX 是在从器件中初始化的示例缓冲区,它们将是
    *由从器件发送到主器件。
    ***/

    uint8_t MasterType0 [TYPE_0_LENGTH]={0x11};
    uint8_t MasterType1 [type_1_length]={8、9};
    uint8_t MasterType2 [type_2_length]={'F'、'4'、'1'、'9'、'2'、 "b"};

    uint8_t SlaveType2 [type_2_length]={0};
    uint8_t SlaveType1 [type_1_length]={0};
    uint8_t SlaveType0 [type_0_length]={0};


    //
    //通用 SPI 状态机
    //

    typedef 枚举 SPI_ModeEnum{
    IDLE_MODE、
    TX_REG_ADDRESS_MODE、
    RX_REG_ADDRESS_MODE、
    TX_DATA_MODE、
    RX_DATA_MODE、
    TIMEOUT_MODE
    } SPI_Mode;


    /*用于跟踪软件状态机的状态*/
    SPI_Mode MasterMode = IDLE_MODE;

    /*要使用的寄存器地址/命令*/
    uint8_t TransmitRegAddr = 0;

    /* ReceiveBuffer:用于在 ISR 中接收数据的缓冲区
    * RXByteCtr:剩余要接收的字节数
    * ReceiveIndex:ReceiveBuffer 中要接收的下一个字节的索引
    * TransmitBuffer:用于在 ISR 中传输数据的缓冲区
    * TXByteCtr:剩余要传输的字节数
    * TransmitIndex:要在 TransmitBuffer 中传输的下一个字节的索引
    ***/
    uint8_t ReceiveBuffer[MAX_Buffer_SIZE]={0};
    uint8_t RXByteCtr = 0;
    uint8_t ReceiveIndex = 0;
    uint8_t TransmitBuffer[MAX_Buffer_SIZE]={0};
    uint8_t TXByteCtr = 0;
    uint8_t TransmitIndex = 0;

    /* SPI 写入和读取函数*/

    //对于从属设备,写入*reg_data 中指定的数据
    *
    * reg_addr:要发送到从器件的寄存器或命令。
    *示例:CMD_TYPE_0_MASTER
    **REG_DATA:要写入的缓冲区
    *示例:MasterType0
    * count:* reg_data 的长度
    *示例:type_0_length
    ***/
    SPI_Mode SPI_Master_WriteReg (uint8_t reg_addr、uint8_t * reg_data、uint8_t count);

    /*对于从器件,读取从器件 REG_addr 中指定的数据。
    *接收到的数据在 ReceiveBuffer 中可用
    *
    * reg_addr:要发送到从器件的寄存器或命令。
    *示例:CMD_TYPE_0_SLAVE
    * count:要读取的数据长度
    *示例:type_0_length
    ***/
    SPI_Mode SPI_Master_ReadReg (uint8_t reg_addr、uint8_t count);
    void CopyArray (uint8_t *源、uint8_t * dest、uint8_t count);
    void SendUCB1Data (uint8_t val);

    void SendUCB1Data (uint8_t val)

    while (!(UCB1IFG & UCTXIFG));// USCI_B1 TX 缓冲区准备就绪?
    UCB1TXBUF = val;

    void CopyArray (uint8_t *源、uint8_t *目标、uint8_t 计数)

    uint8_t copyIndex = 0;
    for (copyIndex = 0;copyIndex < count;copyIndex++)

    dest[copyIndex]= source[copyIndex];


    SPI_Mode SPI_Master_WriteReg (uint8_t reg_addr、uint8_t * reg_data、uint8_t count)

    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;

    //将寄存器数据复制到 TransmitBuffer
    CopyArray (reg_data、TransmitBuffer、count);

    TXByteCtr =计数;
    RXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    Slave_CS_OUT &=~(SLAVE_CS_PIN);
    SendUCB1Data (TransmitRegAddr);

    _bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断

    SLAVE_CS_OUT |= SLAVE_CS_PIN;
    返回 MasterMode;

    SPI_Mode SPI_Master_ReadReg (uint8_t reg_addr、uint8_t count)

    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = reg_addr;//0X00、1
    RXByteCtr =计数;
    TXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    Slave_CS_OUT &=~(SLAVE_CS_PIN);
    SendUCB1Data (TransmitRegAddr);/0x00

    _bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断

    SLAVE_CS_OUT |= SLAVE_CS_PIN;
    返回 MasterMode;

    //
    // SPI 中断
    //

    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=USCI_B1_Vector
    _interrupt void USCI_B1_ISR (void)
    #Elif defined (_GNU_)
    void __attribute__((中断(USCI_B1_Vector)) USCI_B1_ISR (void)
    其他
    错误编译器不受支持!
    #endif

    uint8_t ucb1_rx_val = 0;
    开关(__evo_in_range (UCB1IV、USCI_SPI_UCTXIFG))

    USCI_NONE 案例:中断;
    USCI_SPI_UCRXIFG 案例:
    ucb1_Rx_val = UCB1RXBUF;
    UCB1IFG &=~UCRXIFG;
    开关(主模式)

    案例 TX_REG_ADDRESS_MODE:
    IF (RXByteCtr)

    MasterMode = RX_DATA_MODE;//需要立即开始接收
    //发送虚拟到开始
    //__delay_cycles (2000000);
    SendUCB1Data (虚拟);

    其他

    MasterMode = TX_DATA_MODE;//继续转换发送缓冲区中的数据
    //首先发送
    SendUCB1Data (TransmitBuffer[TransmitIndex++]);
    TXByteCtr --;

    中断;

    案例 TX_DATA_MODE:
    IF (TXByteCtr)

    SendUCB1Data (TransmitBuffer[TransmitIndex++]);
    TXByteCtr --;

    其他

    //传输完成
    MasterMode = IDLE_MODE;
    _BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM0

    中断;

    RX_DATA_MODE case:
    IF (RXByteCtr)

    ReceiveBuffer[ReceiveIndex++]= ucb1_Rx_val;
    //发送虚拟
    RXByteCtr---;

    IF (RXByteCtr = 0)

    MasterMode = IDLE_MODE;
    _BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM0

    其他

    SendUCB1Data (虚拟);

    中断;

    默认值:
    __no_operation();
    中断;

    _DELAY_CYCLES (1000);
    中断;
    USCI_SPI_UCTXIFG 案例:
    中断;
    默认值:break;


    //
    //按钮端口中断
    //按下按钮时发生中断并启动 SPI 数据传输****
    //

    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=button_vector
    _interrupt void button_ISR (void)
    #Elif defined (_GNU_)
    void __attribute__((中断(button_vector))) button_ISR (void)
    其他
    错误编译器不受支持!
    #endif

    button_LED_OUT |= button_LED_PIN;
    button_IFG &=~button_PIN;//清除 Button IFG
    button_IE &=~button_PIN;
    //启动
    _BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0


    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// UART.H///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    #pragma vector = EUSCI_A0_Vector
    _interrupt void USCI_A0_ISR (void)

    switch (__evo_in_range (UCA0IV、USCI_UART_UCTXCPTIFG))

    USCI_NONE 案例:中断;
    USCI_UART_UCRXIFG 案例:
    RX_KEY = 0;
    RXData[RX_index]=UCA0RXBUF;
    if (((RXData[RX_index]='\x0d'/*'\r'*/)||(RXData[RX_index]='\n')||(RXData[RX_index]=='\r'))

    _BIC_SR_REGISTER_ON_EXIT (CPUOFF|GIE);
    UCA0IE &=~UCRXIE;
    RX_index=0;
    RX_KEY = 0;
    中断;

    RX_index++;
    中断;
    USCI_UART_UCTXIFG 案例:
    if (Tx_key=1)

    if (Tx_index>size)

    _BIC_SR_REGISTER_ON_EXIT (CPUOFF|GIE);
    UCA0IE &=~UCTXIE;
    UCA0IE &=~UCTXCPTIE;
    TX_KEY = 0;
    中断;

    UCA0TXBUF =数据[Tx_index];
    TX_index++;
    TX_KEY = 0;

    中断;
    案例 USCI_UART_UCSTTIFG:中断;
    USCI_UART_UCTXCPTIFG 案例:
    TX_KEY = 1;
    UCA0IFG|=UCTXIFG;
    中断;
    默认值:break;

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

    1.很抱歉,我无法清楚地理解您的描述。 可以使用逻辑分析仪(可以接受示波器)捕获波形、以查看发送的数据是否 符合预期?

    2.我认为你是最熟悉 守则的人。 我们所能做的就是提供一些方向。

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

    我将通过 UART 获取输出、尽管该数据不是由变量从接收缓冲区收集的。 您能不能说出原因是什么?

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

    我想知道您能否 使用逻辑分析仪(可以接受示波器)捕获波?

    很难只查看您的代码来找到 SPI 无法接收任何内容的原因。