Other Parts Discussed in Thread: MSP-EXP430F5529LP,
Hi,
I have designed a board from the TI application note which TRF7960 is used. For testing purpose I use MSP-EXP430F5529LP.
I can send data through MOSI to TRF7960 . But there is no response.
(Click to enlarge)
This is the oscilloscope screen:
(Click to enlarge)
And code:
Sorry, I think code insert does not work properly
//******************************************************************************
// MSP430F552x Demo - USCI_A0, SPI 3-Wire Master multiple byte RX/TX
//
// Description: SPI master communicates to SPI slave sending and receiving
// 3 different messages of different length. SPI master will enter LPM0 mode
// while waiting for the messages to be sent/receiving using SPI interrupt.
// SPI Master will initially wait for a port interrupt in LPM0 mode before
// starting the SPI communication.
// ACLK = NA, MCLK = SMCLK = DCO 16MHz.
//
//
// MSP430F5529
// -----------------
// /|\ | P2.0|-> Slave Chip Select (GPIO)
// | | |
// ---|RST
// | |
// | P3.3|-> Data Out (UCA0SIMO)
// | |
// Button ->|P1.1 P3.4|<- Data In (UCA0SOMI)
// | |
// | P2.7|-> Serial Clock Out (UCA0CLK)
//
//******************************************************************************
#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>
//******************************************************************************
// Example Commands ************************************************************
//******************************************************************************
#define DUMMY 0xFF
#define SLAVE_SELECT_DIR P2DIR |= BIT0
#define CHIP_STATE_CONTROL 0x00
#define SLAVE_SELECT_LOW P2OUT &= ~BIT0
#define SLAVE_SELECT_HIGH P2OUT |= BIT0
uint8_t temp = 0;
uint8_t command[2];
/* CMD_TYPE_X_SLAVE are example commands the master sends to the slave.
* The slave will send example SlaveTypeX buffers in response.
*
* CMD_TYPE_X_MASTER are example commands the master sends to the slave.
* The slave will initialize itself to receive MasterTypeX example buffers.
* */
#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 are example buffers initialized in the master, they will be
* sent by the master to the slave.
* SlaveTypeX are example buffers initialized in the slave, they will be
* sent by the slave to the master.
* */
uint8_t MasterType0[TYPE_0_LENGTH] = {0x55};
uint8_t MasterType1[TYPE_1_LENGTH]= {8, 9};
uint8_t MasterType2[TYPE_2_LENGTH] = {'F', '4' , '1' , '9', '2', 'B'};
uint8_t SlaveType0[TYPE_0_LENGTH] = {0};
uint8_t SlaveType1[TYPE_1_LENGTH] = {0};
uint8_t SlaveType2[TYPE_2_LENGTH] = {0};
//******************************************************************************
// General SPI State Machine ***************************************************
//******************************************************************************
typedef enum SPI_ModeEnum{
IDLE_MODE,
TX_REG_ADDRESS_MODE,
RX_REG_ADDRESS_MODE,
TX_DATA_MODE,
RX_DATA_MODE,
TIMEOUT_MODE
} SPI_Mode;
/* Used to track the state of the software state machine*/
SPI_Mode MasterMode = IDLE_MODE;
/* The Register Address/Command to use*/
uint8_t TransmitRegAddr = 0;
/* ReceiveBuffer: Buffer used to receive data in the ISR
* RXByteCtr: Number of bytes left to receive
* ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
* TransmitBuffer: Buffer used to transmit data in the ISR
* TXByteCtr: Number of bytes left to transfer
* TransmitIndex: The index of the next byte to be transmitted in 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 Write and Read Functions */
/* For slave device, writes the data specified in *reg_data
*
* reg_addr: The register or command to send to the slave.
* Example: CMD_TYPE_0_MASTER
* *reg_data: The buffer to write
* Example: MasterType0
* count: The length of *reg_data
* Example: TYPE_0_LENGTH
* */
//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************
void initClockTo16MHz()
{
UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO
UCSCTL4 |= SELA_2; // Set ACLK = REFO
__bis_SR_register(SCG0); // Disable the FLL control loop
UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation
UCSCTL2 = FLLD_0 + 487; // Set DCO Multiplier for 16MHz
// (N + 1) * FLLRef = Fdco
// (487 + 1) * 32768 = 16MHz
// Set FLL Div = fDCOCLK
__bic_SR_register(SCG0); // Enable the FLL control loop
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
// UG for optimization.
// 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle
__delay_cycles(500000);//
// Loop until XT1,XT2 & DCO fault flag is cleared
do
{
UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags
SFRIFG1 &= ~OFIFG; // Clear fault flags
}while (SFRIFG1&OFIFG); // Test oscillator fault flag
}
uint16_t setVCoreUp(uint8_t level){
uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
//The code flow for increasing the Vcore has been altered to work around
//the erratum FLASH37.
//Please refer to the Errata sheet to know if a specific device is affected
//DO NOT ALTER THIS FUNCTION
//Open PMM registers for write access
PMMCTL0_H = 0xA5;
//Disable dedicated Interrupts
//Backup all registers
PMMRIE_backup = PMMRIE;
PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
SVSLPE | SVMHVLRIE | SVMHIE |
SVSMHDLYIE | SVMLVLRIE | SVMLIE |
SVSMLDLYIE
);
SVSMHCTL_backup = SVSMHCTL;
SVSMLCTL_backup = SVSMLCTL;
//Clear flags
PMMIFG = 0;
//Set SVM highside to new level and check if a VCore increase is possible
SVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);
//Wait until SVM highside is settled
while((PMMIFG & SVSMHDLYIFG) == 0)
{
;
}
//Clear flag
PMMIFG &= ~SVSMHDLYIFG;
//Check if a VCore increase is possible
if((PMMIFG & SVMHIFG) == SVMHIFG)
{
//-> Vcc is too low for a Vcore increase
//recover the previous settings
PMMIFG &= ~SVSMHDLYIFG;
SVSMHCTL = SVSMHCTL_backup;
//Wait until SVM highside is settled
while((PMMIFG & SVSMHDLYIFG) == 0)
{
;
}
//Clear all Flags
PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG |
SVSMLDLYIFG
);
//Restore PMM interrupt enable register
PMMRIE = PMMRIE_backup;
//Lock PMM registers for write access
PMMCTL0_H = 0x00;
//return: voltage not set
return false;
}
//Set also SVS highside to new level
//Vcc is high enough for a Vcore increase
SVSMHCTL |= (SVSHRVL0 * level);
//Wait until SVM highside is settled
while((PMMIFG & SVSMHDLYIFG) == 0)
{
;
}
//Clear flag
PMMIFG &= ~SVSMHDLYIFG;
//Set VCore to new level
PMMCTL0_L = PMMCOREV0 * level;
//Set SVM, SVS low side to new level
SVSMLCTL = SVMLE | (SVSMLRRL0 * level) |
SVSLE | (SVSLRVL0 * level);
//Wait until SVM, SVS low side is settled
while((PMMIFG & SVSMLDLYIFG) == 0)
{
;
}
//Clear flag
PMMIFG &= ~SVSMLDLYIFG;
//SVS, SVM core and high side are now set to protect for the new core level
//Restore Low side settings
//Clear all other bits _except_ level settings
SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
SVSMLRRL1 + SVSMLRRL2
);
//Clear level settings in the backup register,keep all other bits
SVSMLCTL_backup &=
~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
//Restore low-side SVS monitor settings
SVSMLCTL |= SVSMLCTL_backup;
//Restore High side settings
//Clear all other bits except level settings
SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +
SVSMHRRL0 + SVSMHRRL1 +
SVSMHRRL2
);
//Clear level settings in the backup register,keep all other bits
SVSMHCTL_backup &=
~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
//Restore backup
SVSMHCTL |= SVSMHCTL_backup;
//Wait until high side, low side settled
while(((PMMIFG & SVSMLDLYIFG) == 0) &&
((PMMIFG & SVSMHDLYIFG) == 0))
{
;
}
//Clear all Flags
PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
);
//Restore PMM interrupt enable register
PMMRIE = PMMRIE_backup;
//Lock PMM registers for write access
PMMCTL0_H = 0x00;
return true;
}
bool increaseVCoreToLevel2()
{
uint8_t level = 2;
uint8_t actlevel;
bool status = true;
//Set Mask for Max. level
level &= PMMCOREV_3;
//Get actual VCore
actlevel = PMMCTL0 & PMMCOREV_3;
//step by step increase or decrease
while((level != actlevel) && (status == true))
{
if(level > actlevel)
{
status = setVCoreUp(++actlevel);
}
}
return (status);
}
void initGPIO()
{
//LEDs
P1OUT = 0x00; // P1 setup for LED & reset output
P1DIR |= BIT0 | BIT5;
P4DIR |= BIT7;
P4OUT &= ~(BIT7);
P2OUT = 0x00;
P2DIR |= BIT0; // SS
//SPI Pins
P3SEL |= BIT3 | BIT4; // P3.3,4 option select
P2SEL |= BIT7; // P2.7 option select
//Button to initiate transfer
P1DIR &= ~BIT1; // Set P1.1 to inpput direction
P1REN |= BIT1; // Enable P1.1 internal resistance
P1OUT |= BIT1; // Set P1.1 as pull-Up resistance
P1IES |= BIT1; // P1.1 Hi/Lo edge
P1IFG &= ~BIT1; // P1.1 IFG cleared
P1IE |= BIT1; // P1.1 interrupt enabled
}
void UartInit(void)
{
// Always use the step-by-step init procedure listed in the USCI chapter of
// the F5xx Family User's Guide
UCA1CTL1 |= UCSWRST; // Put the USCI state machine in reset
UCA1CTL1 |= UCSSEL__SMCLK; // Use SMCLK as the bit clock
// Set the baudrate
UCA1BR0 = 17;
UCA1BR1 = 0;
UCA1MCTL = (6 << 4) | (0 << 1) | (1);
P4SEL |= BIT4+BIT5; // Configure these pins as TXD/RXD
UCA1CTL1 &= ~UCSWRST; // Take the USCI out of reset
UCA1IE |= UCRXIE; // Enable the RX interrupt. Now, when bytes are
// rcv'ed, the USCI_A1 vector will be generated.
}
void UartSendChar(char ch)
{
while(!(UCTXIFG==(UCTXIFG & UCA1IFG))&&((UCA1STAT & UCBUSY)==UCBUSY));
UCA1TXBUF = (ch & 0x1FF);
}
void UartSendString(char * str)
{
while(*str != 0)
{
UartSendChar(*str);
str++;
}
}
void SendUCA0Data(uint8_t val)
{
while (!(UCA0IFG & UCTXIFG)); // USCI_A0 TX buffer ready?
UCA0TXBUF = val;
}
void initSPI()
{
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL0 |= UCCKPH | UCMSB | UCMST | UCSYNC; //MSB First, 8-bit, Master, 3-pin mode, Synchronous
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 |= 8; // SPI clock frequency = SMCLK / 8
UCA0BR1 = 0; //
UCA0MCTL = 0; // No modulation must be cleared for SPI
SLAVE_SELECT_DIR;
SLAVE_SELECT_HIGH;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
//UCA0IE |= UCRXIE; // Enable USCI0 RX interrupt
}
void SpiStartCondition(void) //Make the SCLK High
{
P2SEL &= ~ BIT7;
P2DIR |= BIT7;
P2OUT |= BIT7; //Make SCLK High
}
//******************************************************************************
// Main ************************************************************************
// Send and receive three messages containing the example commands *************
//******************************************************************************
void SpiWriteSingle(uint8_t *pbuf, uint8_t length)
{
unsigned char i = 0;
SLAVE_SELECT_LOW; // Start SPI Mode
while(length > 0)
{
// Address/Command Word Bit Distribution
// address, write, single (fist 3 bits = 0)
*pbuf = (0x1f &*pbuf); // register address
for(i = 0; i < 2; i++)
{
while (!(UCA0IFG & UCTXIFG)); // USCI_A0 TX buffer ready?
{
;
}
UCA0TXBUF = *pbuf; // Previous data to TX, RX
while(UCA0STAT & UCBUSY)
{
;
}
temp = UCA0TXBUF;
pbuf++;
length--;
}
}
while(UCA0STAT & UCBUSY)
{
;
}
SLAVE_SELECT_HIGH; // Stop SPI Mode
}
void SpiReadSingle(uint8_t *pbuf, uint8_t number)
{
SLAVE_SELECT_LOW; // Start SPI Mode
while(number > 0)
{
// Address/Command Word Bit Distribution
*pbuf = (0x40 | *pbuf); // address, read, single
*pbuf = (0x5f & *pbuf); // register address
while (!(UCA0IFG & UCTXIFG)) // USCI_B0 TX buffer ready?
{
;
}
UCA0TXBUF = *pbuf; // Previous data to TX, RX
while(UCA0STAT & UCBUSY)
{
;
}
temp=UCA0RXBUF;
UCA0CTL1 |= UCSWRST; // **Put state machine in reset**
UCA0CTL0 &= ~UCCKPH;
UCA0CTL1 &= ~UCSWRST;
SpiStartCondition();
P2SEL |= BIT7;
while (!(UCA0IFG & UCTXIFG)) // USCI_B0 TX buffer ready?
{
;
}
UCA0TXBUF = 0x00; // Receive initiated by a dummy TX write???
while (!(UCA0IFG & UCRXIFG)) // USCI_B0 RX buffer ready?
{
;
}
_NOP();
_NOP();
*pbuf = UCA0RXBUF;
UartSendChar(*pbuf);
pbuf++;
number--;
UCA0CTL0 |= UCCKPH; // revert to original clock polarity
}
while(UCA0STAT & UCBUSY)
{
;
}
SLAVE_SELECT_HIGH; // Stop SPI Mode
}
void Trf796xTurnRfOn(void){
command[0] = CHIP_STATE_CONTROL;
command[1] = CHIP_STATE_CONTROL;
SpiReadSingle(&command[1], 1);
// command[1] &= 0x3F;
// command[1] |= 0x20;
// SpiWriteSingle(command, 2);
}
void Trf796xInitialSettings(void)
{
uint8_t mod_control[4];
mod_control[0] = 0x09;
mod_control[1] = 0x21; // 6.78MHz, OOK 100%
SpiWriteSingle(mod_control, 2);
}
void
Iso15693FindTag(void)
{
Trf796xTurnRfOn();
//Trf796xWriteIsoControl(0x02);
// The VCD should wait at least 1 ms after it activated the
// powering field before sending the first request, to
// ensure that the VICCs are ready to receive it. (ISO15693-3)
// McuDelayMillisecond(1);
//flags = SIXTEEN_SLOTS;
//buf[20] = 0x00;
// Iso15693Anticollision(&buf[20], 0); // send Inventory request
// Trf796xTurnRfOff();
// Trf796xResetIrqStatus();
// clear any IRQs
}
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
increaseVCoreToLevel2();
initClockTo16MHz();
initGPIO();
initSPI();
UartInit();
P1DIR = 1<<0;
P4DIR = 1<<7;
P1OUT &= ~BIT5; // Now with SPI signals initialized,
// __delay_cycles(100000);
P1OUT |= BIT5; // reset slave
// __delay_cycles(100000); // Wait for slave to initialize
Trf796xInitialSettings();
Trf796xTurnRfOn();
UartSendString("Start\r\n");
while(1){
//UART_PRINT("aa");
Trf796xTurnRfOn();
//SpiReadSingle(0x6C,1);
/* __bis_SR_register(LPM0_bits + GIE); // CPU off, enable interrupts
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);
__no_operation();
P1OUT ^= (1<<0);
__delay_cycles(10000000);
P4OUT ^= (1<<7);
}
}
//******************************************************************************
// SPI Interrupt ***************************************************************
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
#else
#error Compiler not supported!
#endif
{
uint8_t uca0_rx_val = 0;
switch(__even_in_range(UCA0IV,4))
{
case 0:break; // Vector 0 - no interrupt
case 2: // Vector 2 - RXIFG
uca0_rx_val = UCA0RXBUF;
switch (MasterMode)
{
case TX_REG_ADDRESS_MODE:
if (RXByteCtr)
{
MasterMode = RX_DATA_MODE; // Need to start receiving now
//Send Dummy To Start
__delay_cycles(2000000);
SendUCA0Data(DUMMY);
}
else
{
MasterMode = TX_DATA_MODE; // Continue to transmision with the data in Transmit Buffer
//Send First
SendUCA0Data(TransmitBuffer[TransmitIndex++]);
TXByteCtr--;
}
break;
case TX_DATA_MODE:
if (TXByteCtr)
{
SendUCA0Data(TransmitBuffer[TransmitIndex++]);
TXByteCtr--;
}
else
{
//Done with transmission
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
break;
case RX_DATA_MODE:
if (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++] = uca0_rx_val;
//Transmit a dummy
RXByteCtr--;
}
if (RXByteCtr == 0)
{
MasterMode = IDLE_MODE;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}
else
{
SendUCA0Data(DUMMY);
}
break;
default:
__no_operation();
break;
}
__delay_cycles(1000);
break;
case 4:break; // Vector 4 - TXIFG
default: break;
}
}
//******************************************************************************
// PORT1 Interrupt *************************************************************
// Interrupt occurs on button press and initiates the SPI data transfer ********
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(PORT1_VECTOR))) Port_1 (void)
#else
#error Compiler not supported!
#endif
{
P4OUT ^= BIT7; // P1.0 = toggle
P1IFG &= ~BIT1; // P1.1 IFG cleared
P1IE &= ~BIT1;
__bic_SR_register_on_exit(CPUOFF); // Exit LPM0
}