我有一 个24位 ADC、我正在尝试通过 MSP430FR2355 LaunchPad 上的 SPI 进行原 型通信。 操作相当简单:
按下按钮触发 IRQ 后、MCU 的 SIMO 首先通过写入 MSP430的 UCA0TXBUF 寄存器向从 ADC 输入发送命令字节(0b01000101)。 为了响应命令字节、ADC 首先向 MCU 的 SOMI 线输出一个状态字节(0x17)、然后输出一 个配置字节0x33、只要我继续写入 UCA0TXBUF (使用一个虚拟字节)、同时保持 STE 线处于活动状态、此字节就会被重复发送 ( 我在 GPIO 上手动执行的操作)。 在我的代码中、我在 命令字节之后发送三个虚拟字节、我希望按以下顺序读取 UCA0RXBUF
(1)向 UCA0TXBUF 写入命令字节(0x01000101)、在 UCA0RXBUF 中读取0x17 并保存在接收[0]中
(2)将第1 个虚拟字节(0x00)写入 UCA0TXBUF、在 UCA0RXBUF 中读取0x33 并保存在接收中[1]
(3)将第2 个虚拟字节(0x00)写入 UCA0TXBUF、在 UCA0RXBUF 中读取0x33 并保存到接收[2]中
(4)将第3 个虚拟字节(0x00)写入 UCA0TXBUF、在 UCA0RXBUF 中读取0x33 并保存到接收[3]
当 我在 CCS 中调试程序并逐行执行时、我确实得到 了我所期望的结果-变量数组 receive[4]= {0x17、0x33、0x33、0x33}。
但是、如果我让调试运行并在 SPI 事件后任意暂停程序以读取缓冲变量、我会得到接收[4]= {0x33、0x33、0x17、0x33}<-错误顺序
我重复了几次、这些结果是一致的。 我还使用混合示波器监视 SOMI、以确保 ADC 确实按照 我预期的顺序输出{0x17、0x33、0x33}-这是这样的。 因此、我不知道可以在哪里解决此问题。
我希望有人能够帮助解释为什么会发生这种情况、或者我应该尝试自行解决这种问题。 谢谢、
#include <msp430.h>
char send[] =
{
0b01000101, // command
0x00, 0x00, 0x00 // dummy
};
unsigned int position;
unsigned int receive[4];
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
UCA0CTLW0 |= UCSWRST; // put eUSCI_A0 into SW reset
UCA0CTLW0 |= UCSSEL__SMCLK; // choose 1MHz SMCLK as BRCLK
UCA0BRW = 10; // 1MHz divide by 10 = 100kHz
UCA0CTLW0 |= UCSYNC; // set bit to SPI mode
UCA0CTLW0 |= UCMST; // set bit to SPI master mode
UCA0CTLW0 |= UCMSB_1; // UCMSB_0=LSB; UCMSB_1=MSB
//UCA0CTLW0 |= UCMODE1; // 0b10:4-pin with STE active LOW
//UCA0CTLW0 &= ~UCMODE0; // ..
//UCA0CTLW0 |= UCSTEM; // enable STE output pin
UCA0CTLW0 &= ~UCMODE1; // 0b00:3-pin SPI (handle P1.4 STE manually as a port)
UCA0CTLW0 &= ~UCMODE0;
UCA0CTLW0 &= ~UCSTEM;
P1SEL1 &= ~BIT5; // P1.5 (UCA0SCLK)
P1SEL0 |= BIT5; // P1.5 ..
P1SEL1 &= ~BIT7; // P1.7 (UCA0SIMO)
P1SEL0 |= BIT7; // P1.7 ..
P1SEL1 &= ~BIT6; // P1.6 (UCA0SOMI)
P1SEL0 |= BIT6; // P1.6 ..
//P1SEL1 &= ~BIT4; // P1.4 (STE)
//P1SEL0 |= BIT4; // P1.4 ..
P1DIR |= BIT4; // P1.4 set as output (manual STE)
P1OUT |= BIT4; // P1.4 stays HIGH by default (to be cleared LOW to initiate SPI)
P4DIR &= ~BIT1; // P4.1 (SW1) clear as input
P4REN |= BIT1; // P4.1 (SW1) enable pull-up/down resistance
P4OUT |= BIT1; // P4.1 (SW1) pull-up
P4IES |= BIT1; // P4.1 (SW) interrupt edge select: high-to-low transition
PM5CTL0 &= ~LOCKLPM5; // get out of LPM
UCA0CTLW0 &= ~UCSWRST; // get out of SW reset
P4IFG &= ~BIT1; // P4.1 (SW1) clear IFG
P4IE |= BIT1; // P4.1 (SW1) enable IRQ
UCA0IFG &= ~UCTXIFG; // clear SPI Tx IFG
UCA0IE |= UCTXIE; // enable SPI TX IRQ
__enable_interrupt();
while(1)
{
// do nothing
}
return 0;
}
#pragma vector = PORT4_VECTOR
__interrupt void ISR_Port4_S1(void)
{
position = 0;
P1OUT &= ~BIT4; // P1.4 (manual STE) pull LOW to initiate SPI
UCA0TXBUF = send[position];
receive[0] = UCA0RXBUF;
P4IFG &= ~BIT1;
}
#pragma vector = EUSCI_A0_VECTOR
__interrupt void ISR_EUSCI_A0(void)
{
position++;
if(position < sizeof(send))
{
UCA0TXBUF = send[position];
receive[position] = UCA0RXBUF;
}
else
{
UCA0IFG &= ~UCTXIFG;
// add delays to ensure last UCA0RXBUF is read before P1.4 (STE) is set HIGH
// P1.4 (manual STE) set HIGH to stop SPI
__delay_cycles(200);
P1OUT |= BIT4;
}
}
