您好!
我能否使用以下示例演示代码通过 MSP430G2553发送/接收16位 SPI 帧?
此演示代码来自适用于 MSP430G2553器件的 TI CCS 云资源。
//
// MSP430G2xx3演示- USCI_A0、SPI 3线制主器件多字节 RX/TX
//
//说明:SPI 主设备与 SPI 从设备通信发送和接收
// 3条不同长度的消息。 SPI 主器件将进入 LPM0模式
//等待使用 SPI 中断发送/接收消息时。
// SPI 主设备将在之前的 LPM0模式中最初等待端口中断
//开始 SPI 通信。
// ACLK = nA、MCLK = SMCLK = DCO 16MHz。
//
//
// MSP430G2553
//------------
///|\| P2.0|->从器件芯片选择(GPIO)
//|||
//--|RST P1.5|->从器件复位(GPIO)
//||
//| P1.2|->数据输出(UCA0SIMO)
//||
//按钮-|P1.3 P1.1|<-数据输入(UCA0SOMI)
//||
//| P1.4|->串行时钟输出(UCA0CLK)
//
// Nima Eskandari
// Texas Instruments Inc.
// 2017年4月
//使用 CCS V7.0构建
//
#include
#include
//
//示例命令(Example Commands Commands
//
#define 虚拟0xFF
#define SLAVE_CS_OUT P2OUT
#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 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 SendUCA0Data (uint8_t 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);
SendUCA0Data (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;
RXByteCtr =计数;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
Slave_CS_OUT &=~(SLAVE_CS_PIN);
SendUCA0Data (TransmitRegAddr);
_bis_SR_register (CPUOFF + GIE);//输入 LPM0、带中断
SLAVE_CS_OUT |= SLAVE_CS_PIN;
返回 MasterMode;
}
void SendUCA0Data (uint8_t val)
{
while (!(IFG2 & UCA0TXIFG));// USCI_A0 TX 缓冲器准备就绪?
UCA0TXBUF = val;
}
//
//设备初始化
//
空 initClockTo16MHz()
{
IF (CALBC1_16MHz=0xFF)//如果校准常数被擦除
{
while (1);//请勿加载,陷阱 CPU!!
}
DCOCTL = 0;//选择最低 DCOx 和 MODx 设置
BCSCTL1 = CALBC1_16MHz;//设置 DCO
DCOCTL = CALDCO_16MHz;
}
空 initGPIO()
{
//LED
P1OUT = 0x00;//针对 LED 和复位输出设置 P1
P1DIR |= BIT0 + BIT5 + BIT6;
//SPI 引脚
P1SEL = BIT1 + BIT2 + BIT4;
P1SEL2 = BIT1 + BIT2 + BIT4;
//按钮启动传输
P1DIR &=~(BIT3);
P1OUT |= BIT3;// P1.3上拉
P1REN |= BIT3;// P1.3上拉/下拉电阻使能
P1IE |= BIT3;// P1.3中断被启用
P1IES |= BIT3;// P1.3高/低边沿
P1IFG &=~BIT3;// P1.3 IFG 被清零
}
空 initSPI()
{
//时钟极性:无效状态为高电平
//MSB 优先、8位、主器件、3引脚模式、同步
UCA0CTL0 |= UCCKPL + UCMSB + UCMST + UCSYNC;
UCA0CTL1 |= UCSSEL_2;// SMCLK
UCA0BR0 |= 0x20;///2
UCA0BR1 = 0;//
UCA0MCTL = 0;// SPI 必须清除无调制
UCA0CTL1 &=~UCSWRST;//**初始化 USCI 状态机**
IE2 |= UCA0RXIE;//启用 USCI0 RX 中断
SLAVE_CS_DIR |= SLAVE_CS_PIN;
SLAVE_CS_OUT |= SLAVE_CS_PIN;
}
//
//主要内容
//发送和接收三条包含示例命令*******的消息
//
int main (空)
{
WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器
initClockTo16MHz();
initGPIO();
initspi();
P1OUT &=~BIT4;//现在 SPI 信号已初始化、
_DELAY_CYCLES (100000);
P1OUT |= BIT5;//复位从器件
_DELAY_CYCLES (100000);//等待从器件初始化
P1OUT |= BIT0;
_bis_SR_register (LPM0_bits + GIE);// CPU 关闭、启用中断
SPI_Master_ReadReg (CMD_TYPE_2_SLAVE、TYPE_2_LENGTH);
CopyArray (ReceiveBuffer、SlaveType2、TYPE_2_LENGTH);
SPI_Master_ReadReg (CMD_TYPE_1_SLAVE、TYPE_1_LENGTH);
CopyArray (ReceiveBuffer、SlaveType1、type_1_length);
SPI_Master_ReadReg (CMD_TYPE_0_SLAVE、TYPE_0_LENGTH);
CopyArray (ReceiveBuffer、SlaveType0、TYPE_0_LENGTH);
SPI_Master_WriteReg (CMD_TYPE_2_MASTER、MasterType2、TYPE_2_LENGTH);
SPI_Master_WriteReg (CMD_TYPE_1_MASTER、MasterType1、TYPE_1_LENGTH);
SPI_Master_WriteReg (CMD_TYPE_0_MASTER、MasterType0、TYPE_0_LENGTH);
_bis_SR_register (LPM0_bits + GIE);
}
//
// SPI 中断
//
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=USCIAB0RX_vector
_interrupt void USCIA0RX_ISR (void)
#Elif defined (_GNU_)
void __attribute__((interrupt (USCIAB0RX_vector)) USCIA0RX_ISR (void)
其他
错误编译器不受支持!
#endif
{
IF (IFG2 & UCA0RXIFG)
{
uint8_t uca0_rx_val = UCA0RXBUF;
开关(主模式)
{
案例 TX_REG_ADDRESS_MODE:
IF (RXByteCtr)
{
MasterMode = RX_DATA_MODE;//需要立即开始接收
//发送虚拟到开始
_DELAY_CYCLES (2000);
SendUCA0Data (虚拟);
}
其他
{
MasterMode = TX_DATA_MODE;//继续转换发送缓冲区中的数据
//首先发送
SendUCA0Data (TransmitBuffer[TransmitIndex++]);
TXByteCtr --;
}
中断;
案例 TX_DATA_MODE:
IF (TXByteCtr)
{
SendUCA0Data (TransmitBuffer[TransmitIndex++]);
TXByteCtr --;
}
其他
{
//传输完成
MasterMode = IDLE_MODE;
_BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM0
}
中断;
RX_DATA_MODE case:
IF (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++]= uca0_Rx_val;
//发送虚拟
RXByteCtr---;
}
IF (RXByteCtr = 0)
{
MasterMode = IDLE_MODE;
_BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出 LPM0
}
其他
{
SendUCA0Data (虚拟);
}
中断;
默认值:
__no_operation();
中断;
}
_DELAY_CYCLES (50);
}
}
//
//端口1中断
//按下按钮时发生中断并启动 SPI 数据传输****
//
#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=Port1_vector
_interrupt void Port_1 (void)
#Elif defined (_GNU_)
void __attribute__((interrupt (Port1_vector))) Port_1 (void)
其他
错误编译器不受支持!
#endif
{
P1OUT |= BIT6;
P1IFG &=~BIT3;// P1.3 IFG 被清零
P1IE &=~BIT3;
//启动
_BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//退出 LPM0
}