“线程: 测试”中讨论的其它部件
我正在与 MSP430F5438A 微控制器合作,我正在使用 FreeRTOS 合作模式,勾选时间为1毫秒。
我有一个场景,需要确保在传输完成后(1毫秒内)尽快将芯片选择拉高(取消选择)。
因此,在最后一个字节被发送出去后,我试图将 ISR 内的 CS 值拉高。
但是,我在示波器上注意到,CS 在最后一个字节完全传输之前被拉高。
我尝试以两种不同的 SPI 时钟频率(12.8KHz 和128KHz)观察结果,并附加了示波器图像。
SPI 时钟(黄色)
芯片选择(粉红色)
莫西语(绿色) 
带 SPI 时钟12.8KHz (UCA1BR0设置为100) 
带 SPI 时钟128KHz (UCA1BR0设置为10)
从图像中可以看出,在 CS 被拉高后,最后几位仍在传输中。 漏掉的位数似乎随 SPI 时钟速率的不同而不同。
#include <msp430.h>
#include <stdio.h>
#include <stdint.h>
#include "msp430f5xx_6xxgeneric.h"
/**
* main.c
*/
typedef void (*myCallback)(void);
#define HWREG8(x) \
(*((volatile uint8_t *)((uint16_t)x)))
/*******************************************************************************
* Function declaration
******************************************************************************/
void spib_init(void);
void spib_setTx_buf(const uint8_t spibTxBuf[], uint16_t spibTxLen,
myCallback spibLocalCallback);
void transmit_data(void);
void deselect_CS(void);
/******************************************************************************/
uint8_t tx_testdata[6] = {'A','B','C','D','E','\n'};
void main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
// config CS pin
P9SEL &= ~0x40;
P9DIR |= 0x40;
P9OUT |= 0x40;
spib_init();
__bis_SR_register(GIE); // CPU off, enable interrupts
transmit_data();
while (1)
{
}
// return 0;
}
void transmit_data(void)
{
P9OUT &= ~0x40;
spib_setTx_buf(tx_testdata, 6, &deselect_CS);
}
void deselect_CS(void)
{
P9OUT |= 0x40;
__delay_cycles(1000000);
transmit_data();
}
//******************************************************************************
//
//SPI
//
//******************************************************************************
myCallback spibCallback;
volatile uint8_t *spibPTxData; // Pointer to TX data
volatile uint16_t spibTXByteCtr;
void spib_init(void)
{
// config UCA1 MOSI and MISO pin
P5SEL |= 0xC0;
P5DIR |= 0x40;
// config UCA1 clk pin
P3SEL |= 0x40;
P3DIR |= 0x40;
UCA1CTL1 |= UCSWRST;
UCA1CTL0 |= UCMST+UCSYNC+UCMODE_0+UCCKPH+UCCKPL+UCMSB;
UCA1CTL1 |= UCSSEL__SMCLK;
UCA1BR0 = 0x64; // 100
UCA1BR1 = 0;
UCA1CTL1 &= ~UCSWRST;
}
void spib_setTx_buf(const uint8_t spibTxBuf[], uint16_t spibTxLen,
myCallback spibLocalCallback)
{
spibCallback = spibLocalCallback;
spibPTxData = (unsigned char *)spibTxBuf; // TX array start address
// Place breakpoint here to see each
// transmit operation.
spibTXByteCtr = spibTxLen; // Load TX byte counter
HWREG8(USCI_A1_BASE + OFS_UCAxIFG) &= ~UCTXIE;
HWREG8(USCI_A1_BASE + OFS_UCAxIE) |= UCTXIE;
if (spibTXByteCtr > 0)
{
if (spibPTxData == NULL)
{
UCA1TXBUF = 0xFF;
}
else
{
UCA1TXBUF = *spibPTxData++;
}
spibTXByteCtr--;
}
// UCA1TXBUF = spitxbufdata;
}
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=USCI_A1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(USCI_A1_VECTOR)))
#endif
void USCI_A1_ISR (void)
{
switch (__even_in_range(UCA1IV,4)){
//Vector 2 - RXIFG
case 2:
break;
case 4:
if(0 < spibTXByteCtr)
{
// UCA1TXBUF = spitxbufdata;
if (spibPTxData == NULL)
{
UCA1TXBUF = 0xFF;
}
else
{
UCA1TXBUF = *spibPTxData++;
}
spibTXByteCtr--;
}
else if(0 == spibTXByteCtr)
{
HWREG8(USCI_A1_BASE + OFS_UCAxIFG) &= ~UCTXIE;
HWREG8(USCI_A1_BASE + OFS_UCAxIE) &= ~UCTXIE;
if(NULL != spibCallback)
(*spibCallback)();
}
break;
default:
break;
}
}
这是我用于生成上述结果的简化代码。
我想问,如果在最后一个字节传输后立即将 CS 置于 ISR 内部,为什么在 CS 被拉高后会出现最后几个周期?
此外, 为何在 SPI 时钟频率发生变化时,CS 被拉高后剩下的周期数会有所不同?
除 SPI 时钟频率外,是否还有其他可能的因素会导致 CS HIGH 后剩余的周期数不同(因此,在 CS 被拉高之前需要不同的延迟量)?