工具/软件:Code Composer Studio
大家好
现在、我需要两个 EXP_MSP430F5529LP 开发板来验证 SPI 通信、一个主模式(运行 ti-RTOS)、另一个运行 SPI 从模式(没有 ti-RTOS)、现在我使用【MSP430F55xx_USCI_SPI_standard_slave】SPI 从模式的示例代码。
现在 、我发现 SPI 主模式在第一次读取数据时只是正常的、其余的则发生故障、您必须将从模式开发板复位一次才能读取正常数据。我不知道为什么? 现在只想将从模块板仿真为 SPI 闪存、谁有更好的建议?
谢谢你
XC_MO
MSP430F55xx_USCI_SPI_standard_slave 代码
//
// MSP430F552x 演示- USCI_A0、SPI 三线制从器件多字节 RX/TX
//
说明:SPI 主器件与 SPI 从器
件通信发送和接收// 3条不同长度的消息。 SPI 从器
件将在等待使用 SPI 中断发送/接收消息时进入 LPM0 //。
// ACLK = nA、MCLK = SMCLK = DCO 16MHz。
//
//
//////// MSP430F5529
// --------
// /|\| P2.0|<-主器件的 GPIO (芯片选择)
// || |
// ---|RST RST |<-主器件的 GPIO (用于复位从器件)
// | |
// | P3.3|<-数据输入(UCA0SIMO)
// | |
// | P3.4|->数据输出(UCA0SOMI)
// | |
// | P2.7|-串行时钟输入(UCA0CLK)
//
Nima Eskandari
// Texas Instruments Inc.
// 2017年4月
//使用 CCS V7.0构建
/*********
#include
#include
#include
//
//示例命令(Example Commands Commands
//
#define 虚拟0xFF
#define SLAVE_CS_IN P2IN
#define SLAVE_CS_DIR P2DIR
#define SLAVE_CS_PIN BIT0
/* 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 MasterType2 [type_2_length]={0};
uint8_t MasterType1 [type_1_length]={0、0};
uint8_t MasterType0 [type_0_length]={0};
uint8_t SlaveType2 [type_2_length]={1、'D'、'D'、'1'、'D' '2'};
uint8_t SlaveType1 [TYP_1_LENGTH]={0x15、0x16};
uint8_t SlaveType0 [TYP_0_LENGTH]={0x11};
//*********
//通用 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 SlaveMode = RX_REG_ADDRESS_MODE;
//要使用的寄存器地址/命令*/
uint8_t ReceiveRegAddr = 0;
// ReceiveBuffer:用于接收 ISR 中数据的缓冲
区* RXByteCtr:要接收的字节数
*索引: ReceiveBuffer
* TransmitBuffer:用于在 ISR 中传输数据的缓冲区
* TXByteCtr:剩余要传输的字节数
* TransmitIndex:要在 TransmitBuffer 中传输的下一个字节的索引
*/
uint8_t ReceiveBuffer[MAX_buffer_size]={0};
uint8_t RXByteCtr = 0;
uint8_t ProcesseIndex = 0;
uint8_t TransmitBuffer[MAX_buffer_size]={0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;
//根据接收到的 cmd
*
命令初始化软件状态机* cmd:uint8_t transmitCtr
= 0;uint8_t received * uint8命令* uintmtrl * void * mcmd_t register
/*从设备和主设备之间的传输已完成。 使用 cmd
*执行事务后操作。 (将数据从 SendeBuffer
*放置到基于上次接收的相应缓冲区 cmd)
*
cmd:与已完成
的*事务对应的命令/寄存器地址
*
/ void SPI_Slave_TransactionDone (uint8_t cmd);
void CopyArray (uint8_t * source、uint8_t * dest、uint8_t count);
void CopyData (uint8_t);uint0ival (uint0uintval)
void SendUCA0Data (uint8_t val)
{
while (!(UCA0IFG & UCTXIFG)); // USCI_A0 TX 缓冲器就绪?
UCA0TXBUF = val;
}
void SPI_Slave_ProcessCMD (uint8_t cmd)
{
ReceiveIndex = 0;
TransmitIndex = 0;
RXByteCtr = 0;
TXByteCtr = 0;
开关(cmd)
{
情况(CMD_TYPE_0_SLAVE): //发送从属设备 ID (此设备的 ID)
SlaveMode = TX_DATA_MODE;
TXByteCtr = TYPE_0_LENGTH;
//填充 TransmitBuffer
CopyArray (SlaveType0、TransmitBuffer、TYPE_0_LENGTH);
//发送第一个字节
SendUCA0Data (TransmitBuffer[TransmitIndex++]);
TXByteCtr --;
中断;
情况(CMD_TYPE_1_SLAVE): //发送从设备时间(该设备的时间)
SlaveMode = TX_DATA_MODE;
TXByteCtr = TYPE_1_LENGTH;
//填充 TransmitBuffer
CopyArray (SlaveType1、TransmitBuffer、type_1_length);
//发送第一个字节
SendUCA0Data (TransmitBuffer[TransmitIndex++]);
TXByteCtr --;
中断;
情况(CMD_TYPE_2_SLAVE): //发送从属设备位置(该设备的位置)
SlaveMode = TX_DATA_MODE;
TXByteCtr = TYPE_2_LENGTH;
//填充 TransmitBuffer
CopyArray (SlaveType2、TransmitBuffer、TYPE_2_LENGTH);
//发送第一个字节
SendUCA0Data (TransmitBuffer[TransmitIndex++]);
TXByteCtr --;
中断;
情况(CMD_TYPE_0_MASTER):
SlaveMode = RX_DATA_MODE;
RXByteCtr = TYPE_0_LENGTH;
中断;
情况(CMD_TYPE_1_MASTER):
SlaveMode = RX_DATA_MODE;
RXByteCtr = TYPE_1_LENGTH;
中断;
情况(CMD_TYPE_2_MASTER):
SlaveMode = RX_DATA_MODE;
RXByteCtr = TYPE_2_LENGTH;
中断;
默认值:
//while (1);
__no_operation();
中断;
}
}
void SPI_Slave_TransactionDone (uint8_t cmd)
{
开关(cmd)
{
情况(CMD_TYPE_0_SLAVE): //从设备 ID 已发送(此设备的 ID)
中断;
情况(CMD_TYPE_1_SLAVE): //从器件时间已发送(此器件的时间)
中断;
情况(CMD_TYPE_2_SLAVE): //发送从属设备位置(该设备的位置)
中断;
情况(CMD_TYPE_0_MASTER):
CopyArray (ReceiveBuffer、MasterType0、TYPE_0_LENGTH);
中断;
情况(CMD_TYPE_1_MASTER):
CopyArray (ReceiveBuffer、MasterType1、Type_1_length);
中断;
情况(CMD_TYPE_2_MASTER):
CopyArray (ReceiveBuffer、MasterType2、TYPE_2_LENGTH);
中断;
默认值:
__no_operation();
中断;
}
}
void CopyArray (uint8_t *源、uint8_t * dest、uint8_t count)
{
uint8_t copyIndex = 0;
for (copyIndex = 0;copyIndex < count;copyIndex++)
{
dest[copyIndex]= source[copyIndex];
}
}
//*********
//设备初始化
//
void initGPIO()
{
//LEDs
P1OUT = 0x00; //针对 LED 和复位输出 P1DIR 的 P1设置
|= BIT0 + BIT4;
P4DIR |= BIT7;
P4OUT &=~(BIT4);
//SPI 引脚
P3SEL |= BIT3 + BIT4; // P3.3、4选项选择
P2SEL |= BIT7; // P2.7选项选择
}
void initSPI()
{//
时钟极性:无效状态为高
电平//MSB 优先,8位,主器件,3引脚模式,同步
UCA0CTL1 = UCSWRST; //**将状态机复位**
UCA0CTL0 |= UCCKPL + UCMSB + UCSYNC; // 3引脚8位 SPI 从
器件 UCA0CTL1 &=~UCSWRST; //**初始化 USCI 状态机**
UCA0IE |= UCRXIE; //启用 USCI0 RX 中断
slave_CS_DIR &=~(slave_CS_PIN);
}
void initClockTo16MHz ()
{
UCSCTL3 |= SELREF_2; //设置 DCO FLL 基准= REFO
UCSCTL4 |= SE拉美 经济体系2; //设置 ACLK = REFO
_bis_SR_register (SCG0); //禁用 FLL 控制环路
UCSCTL0 = 0x0000; //设置可能的最低 DCOx、MODx
UCSCTL1 = DCORSEL_5; //选择 DCO 范围16MHz 操作
UCSCTL2 = FLLD_0 + 487; //将 DCO 乘法器设置为16MHz
//(N + 1)* FLLRef = Fdco
//(487 + 1)* 32768 = 16MHz
//设置 FLL Div = fDCOCLK
_BIC_SR_register (SCG0); //启用 FLL 控制环路
// DCO 范围位已经存在时、DCO 的最坏情况稳定时间
//已更改 n x 32 x 32 x f_MCLK / f_FLL_reference。 请参阅5xx 中的 UCS 一章
// UG 进行优化。
// 32 x 32 x 16 MHz/32、768Hz = 500000 = DCO 稳定的 MCLK 周期
_DELAY_CYCLES (50000);//
//循环直到 XT1、XT2和 DCO 故障标志被清除
操作
{
UCSCTL7 &=~(XT2OFFG + XT1LFOFFG + DCOFFG);//清除 XT2、XT1、DCO 故障标志
SFRIFG1 &=~OFIFG; //清除故障标志
} while (SFRIFG1&OFIFG); //测试振荡器故障标志
}
void SetVcoreUp (无符号整型)
{
//打开 PMM 寄存器进行写入
PMMCTL0_H = PMMPW_H;
//设置 SVS/SVM 高侧新电平
SVSMHCTL = SVSHE + SVSHRVL0 *电平+ SVMHE + SVSMHRRL0 *电平;
//将 SVM 低电平设置为新电平
SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 *电平;
//等待 SVM 稳定
时间((((PMMIFG & SVSMLDLYIFG)=0);
//清除已设置的标志
PMMIFG &=~(SVMLVLRIFG + SVMLMRYIFG)
= 0;//将 PMMCL0设置为新电平
//如果
((PMMIFG & SVMLIFG))、则等待达到新的电平
while (((PMMIFG & SVMLVLRIFG)=0);
//将 SVS/SVM 低电平设置为新的电平
SVSMLCTL = SVSLE + SVSLRVL0 *电平+ SVMLE + SVSMLRRL0 *电平;
//锁定 PMM 寄存器以进行写访问
PMMCTL0_H = 0x00;
}
//主要内容
//进入 LPM0并等待 SPI 中断。 从主器件发送的数据是*
//然后被解释、器件将相应地做出响应 *
//*********
void main (void){
WDTCTL = WDTPW + WDTHOLD; //停止看门狗计时器
//while (!(P1IN & BIT4)); //如果来自 MSTR 的时钟信号保持低电平、
//尚未处于 SPI 模式
//???
对于16MHz 时钟、//设置 VCORE = 2
SetVcoreUp (0x01);
SetVcoreUp (0x02);
initClockTo16MHz();
initGPIO();
initspi();
_bis_SR_register (LPM0_bits + GIE); //输入 LPM0,启用中断
__NO_OPERAT();
}//*********
// SPI 中断
//
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector=USCI_A0_vector
__interrupt void USCI_A0_ISR (void)
#Elif defined (__GNU__)
void __attribute__(interrupt (USCI_A1_vector))#USCI_A0
Compiler #a0_aid!
#endif
{
uint8_t uca0_rx_val = 0;
switch (_even_in_range (UCA0IV、4))
{
情况0:中断; //向量0 -无中断
案例2:
UCA0_Rx_val = UCA0RXBUF;
如果(!(SLAVE_CS_IN 和 SLAVE_CS_PIN)//!!!!!!!!!!!!!!!!!!!!!!!!
{
切换(SlaveMode)
{
情况(RX_REG_ADDRESS_MODE):
ReceiveRegAddr = uca0_Rx_val;
SPI_Slave_ProcessCMD (ReceiveRegAddr);
中断;
情况(RX_DATA_MODE):
ReceiveBuffer[ReceiveIndex++]= uca0_Rx_val;
RXByteCtr---;
IF (RXByteCtr = 0)
{
//完成接收 MSG
SlaveMode = RX_REG_ADDRESS_MODE;
SPI_Slave_TransactionDone (ReceiveRegAddr);
}
中断;
情况(TX_DATA_MODE):
IF (TXByteCtr > 0)
{
SendUCA0Data (TransmitBuffer[TransmitIndex++]);
TXByteCtr --;
}
IF (TXByteCtr = 0)
{
//完成发送 MSG
SlaveMode = RX_REG_ADDRESS_MODE;
SPI_Slave_TransactionDone (ReceiveRegAddr);
}
中断;
默认值:
__no_operation();
中断;
}
}
中断;
案例4:中断; //向量4 - TXIFG
默认值:中断;
}
}


