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.
Tool/software: Code Composer Studio
Hi everyone,
I'm using MSP430FR2355, I'm going to send data to CC2640R2F with SPI. So I set P1.5, P1.6 and P1.7 as the SPI ports.
The MCU works in the slave mode. Considering about the CC2640R2F's NPI interface, I set P2.1 as the SRDY port which will be set to low level when data put into the TX buffer. The polarity is 0 and the phase is 1 on both side. The MOSI and MISO on CC2640R2F are DIO09 and DIO08, so I connect P1.6 to DIO08 and P1.7 to DIO09.
Here is my problem: When I keep sending the data(for example, 0x0A) to the SPI, the result I got on the CC2640R2F part is always 0x00. If I try to send data from CC2640R2F to the MCU and see the result on the UART, I got nothing.
Here are my codes:
unsigned char TXData = 0x0A;
#define MCLK_FREQ_MHZ 8
/**
* main.c
*/
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
__enable_interrupt();
Set_ClockSystem();
Set_GPIO();
Set_UCA1_UART();
Set_UCA0_SPI();
//TXData = 0x0A;
PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode
// to activate previously configured port settings
while(1)
{
P2OUT |= BIT1;
UCA0IE |= UCTXIE; // Enable TX interrupt
//__bis_SR_register(LPM0_bits | GIE); // enable global interrupts, enter LPM0
//__no_operation(); // For debug,Remain in LPM0
//__delay_cycles(2000); // Delay before next transmission
__delay_cycles(400000);
//TXData++; // Increment transmit data
// if(TXData == 0x0A){
// TXData = 0x00;
// }
}
//return 0;
}
void Set_GPIO(void)
{
P2DIR |= BIT1; // Set P2.1 as SDRY.
P2OUT |= BIT1;
}
void Set_UCA1_UART(void){
// Configure UART pins
P4SEL0 |= BIT2 | BIT3; // set 2-UART pin as second function
// Configure UART
UCA1CTLW0 |= UCSWRST;
UCA1CTLW0 |= UCSSEL__SMCLK;
// Baud Rate calculation
// 8000000/(16*9600) = 52.083
// Fractional portion = 0.083
// User's Guide Table 14-4: UCBRSx = 0x49
// UCBRFx = int ( (52.083-52)*16) = 1
UCA1BR0 = 52; // 8000000/16/9600
UCA1BR1 = 0x00;
UCA1MCTLW = 0x4900 | UCOS16 | UCBRF_1;
UCA1CTLW0 &= ~UCSWRST; // Initialize eUSCI
UCA1IE |= UCRXIE; // Enable USCI_A0 RX interrupt
}
void Set_UCA0_SPI(void)
{
P1SEL0 |= BIT7 + BIT5 + BIT6; // Set SPI peripheral bits
UCA0CTL1 |= UCSWRST; // Enable SW reset
// UCA0CTL0 |= UCMSB + UCMST + UCSYNC + UCCKPH; //[b0] 1 - Synchronous mode
UCA0CTL0 |= UCMSB + UCSYNC + UCCKPH;
//[b2-1] 00- 3-pin SPI
//[b3] 1 - Master mode
//[b4] 0 - 8-bit data
//[b5] 1 - MSB first
//[b6] 0 - Clock polarity low.
//[b7] 1 - Clock phase - Data is captured on the first UCLK edge and changed on the following edge.
UCA0CTL1 |= UCSSEL__SMCLK; // SMCLK
UCA0BR0 = 7; // 1 MHz
UCA0BR1 = 0;
UCA0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCA0IE |= UCRXIE;
}
void Set_ClockSystem(void){
CSCTL3 |= SELREF__REFOCLK; // Set REFO as FLL reference source
CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_3;// DCOFTRIM=3, DCO Range = 8MHz
CSCTL2 = FLLD_0 + 243; // DCODIV = 8MHz
__delay_cycles(3);
__bic_SR_register(SCG0); // enable FLL
Software_Trim(); // Software Trim to get the best DCOFTRIM value
CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK; // set default REFO(~32768Hz) as ACLK source, ACLK = 32768Hz
// default DCODIV as MCLK and SMCLK source
}
void Software_Trim(void)
{
unsigned int oldDcoTap = 0xffff;
unsigned int newDcoTap = 0xffff;
unsigned int newDcoDelta = 0xffff;
unsigned int bestDcoDelta = 0xffff;
unsigned int csCtl0Copy = 0;
unsigned int csCtl1Copy = 0;
unsigned int csCtl0Read = 0;
unsigned int csCtl1Read = 0;
unsigned int dcoFreqTrim = 3;
unsigned char endLoop = 0;
do
{
CSCTL0 = 0x100; // DCO Tap = 256
do
{
CSCTL7 &= ~DCOFFG; // Clear DCO fault flag
}while (CSCTL7 & DCOFFG); // Test DCO fault flag
__delay_cycles((unsigned int)3000 * MCLK_FREQ_MHZ);// Wait FLL lock status (FLLUNLOCK) to be stable
// Suggest to wait 24 cycles of divided FLL reference clock
while((CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)) && ((CSCTL7 & DCOFFG) == 0));
csCtl0Read = CSCTL0; // Read CSCTL0
csCtl1Read = CSCTL1; // Read CSCTL1
oldDcoTap = newDcoTap; // Record DCOTAP value of last time
newDcoTap = csCtl0Read & 0x01ff; // Get DCOTAP value of this time
dcoFreqTrim = (csCtl1Read & 0x0070)>>4;// Get DCOFTRIM value
if(newDcoTap < 256) // DCOTAP < 256
{
newDcoDelta = 256 - newDcoTap; // Delta value between DCPTAP and 256
if((oldDcoTap != 0xffff) && (oldDcoTap >= 256)) // DCOTAP cross 256
endLoop = 1; // Stop while loop
else
{
dcoFreqTrim--;
CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
}
}
else // DCOTAP >= 256
{
newDcoDelta = newDcoTap - 256; // Delta value between DCPTAP and 256
if(oldDcoTap < 256) // DCOTAP cross 256
endLoop = 1; // Stop while loop
else
{
dcoFreqTrim++;
CSCTL1 = (csCtl1Read & (~DCOFTRIM)) | (dcoFreqTrim<<4);
}
}
if(newDcoDelta < bestDcoDelta) // Record DCOTAP closest to 256
{
csCtl0Copy = csCtl0Read;
csCtl1Copy = csCtl1Read;
bestDcoDelta = newDcoDelta;
}
}while(endLoop == 0); // Poll until endLoop == 1
CSCTL0 = csCtl0Copy; // Reload locked DCOTAP
CSCTL1 = csCtl1Copy; // Reload locked DCOFTRIM
while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // Poll until FLL is locked
}
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A_ISR(void)
{
switch(__even_in_range(UCA0IV,USCI_SPI_UCTXIFG))
{
case USCI_NONE: break; // Vector 0 - no interrupt
case USCI_SPI_UCRXIFG:
while(!(UCA1IFG&UCTXIFG));
UCA1TXBUF = UCA0RXBUF;
break;
case USCI_SPI_UCTXIFG:
UCA0TXBUF = TXData; // Transmit characters
UCA0IE &= ~UCTXIE;
P2OUT &= ~BIT1;
break;
default: break;
}
}
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR(void)
{
switch(__even_in_range(UCA1IV,USCI_UART_UCTXIFG))
{
case USCI_NONE: break; // Vector 0 - no interrupt
case USCI_UART_UCRXIFG:
while(!(UCA1IFG&UCTXIFG));
UCA1TXBUF = UCA1RXBUF;
break;
case USCI_UART_UCTXIFG:
break;
default: break;
}
}
I wish someone could help me find where my issue is.
Thanks a lot,
Yuhang.
Dear customer,
sorry for the belated response. Due to some internal issues we had a delay in our response, but will come back to you on this tomorrow.
Best regards
Peter
Hello Yuhang,
as far as I can see, you have commented out the only instruction enabling general interrupt.
//__bis_SR_register(LPM0_bits | GIE); // enable global interrupts, enter LPM0
For maskable interrupts you need always both, the respective module interrupt enable and GIE.
Best regards
Peter
Hi Peter,
I set the __enable_interrupt() at the beginning of main() function to replace __bis_SR_register(LPM0_bits | GIE).
I also test the SPI with the UART which communicates with my PC, and I am sure that the data is put in SPI TXBuffer successfully. But in the CC2640R2F part, I still get wrong result. I cannot found the issue in the code of CC2640R2F. Because if I use the SPI port on the CC2640R2F to communicate with a AD chip, it works fine.
Could the issue lie in the code of CC2640r2f?
Hi Yuhang,
sorry, I overlooked the GIE interrupt enable, as I was not expecting it to be set right after WDTHOLD and before all the module initialisation. This is definitely something, I would not recommend you to do, as during the peripheral inits, this might trigger erroneous interrupts. The GIE should be only set, when all HW configurations are done.
Of course with bi-directional and two counterpart communication each side could contribute to the problem. To be able to make a comment on that, this would require looking at the signals. That would be my recommendation. Please check the signals the device is transmitting. It might be, e.g. that the baud rate is at the tolerance limits, and the other device is still able to cope with it, while another one not.
But there might be other signal related aspects as well.
In addition, please consider also our application report on debugging serial communication with MSP430 too.
Best regards
Peter
**Attention** This is a public forum