请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
部件号:MSP432P401R 您好,
我正在尝试修改随MSP DriverLib提供的SPI 3线增量示例,以控制信号发生器(SparkFun MiniGen,基本上是AD9837)。 MiniGen提供了一些用于设置信号发生器的有用功能,似乎我只需要通过SPI发送几个控制位即可正确配置生成器。
但是,我遇到了一个问题,因为SPI数据实际上没有传输。 我对示例代码做了很多更改,我当前的项目如下所示:
/************************************************************************
* MSP432 SPI - 3线主控增量数据
*
此示例显示SPI主控如何使用3线模式与SPI从属设备进行对话。
*从0x01开始,由主服务器发送递增数据。 接收的数据
*预期与以前的传输相同。eUSCI RX ISR用于
*处理与CPU的通信,通常为LPM0。 因为
LPM0后的所有执行*都在ISR中,初始化等待DCO稳定于
* ACLK。
*
**请注意,在此示例中,EUSCIB0用于SPI端口。 如果用户
*要使用EUSCIA进行SPI操作,他们可以使用相同的API
*和EUSCI_AX参数。
*
* ACLK =~32.768kHz,MCLK = SMCLK = DCO 3MHz
*
**与SPI从属数据回波代码示例配合使用。
*
** MSP432P401
* --------
* | |
* | |
* | |
* | WFP 1.6 (美国国家档案局)|-> Data Out (UCB0SIMO)
* | |
* | WFP 1.7 (美国国家档案局)|<-数据输入(UCB0SOMI)
* | |
* | 世界食物局(1.5)|->串行时钟输出(UCB0CLK)
*************************************************************************************** /*
DriverLib包括*/
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <ti/drivers/GPI.h>
#include <ti/drivers/SPI.h>
#include "minigen.h"
/* Standard包括*/
#include <stdintinting.h>
spi=esi_static Data/spi>简单
spi
= x_statuth/ spi> spi = x_static配置<statut_statuth/ spi> spi = x_static <statuth> spi_statics/spx_static配置<x_spi>参数x_spi>
EUSCI_B_SPI_CLOCKSOURCE_SMCLK, // SMCLK时钟源
300万, // SMCLK = DCO = 3MHz
50万, // SPICLK = 500kHz
EUSCI_B_SPI_MSB_FIRST, // MSB优先
EUSCI_B_SPI_PHASE DATA_Changed_ONFIRST_Captured_on_NEXT,//相位
EUSCI_B_SPI_CLOCKPOLARITY_INactivity HIGH,//高极性
EUSCI_B_SPI_3引脚 // 3Wire SPI模式
};//![Simple
SPI Config]
int main(void){
/*正在停止WDT */
WDT_A_HoldTimer();
//![简单SPI示例]
/*在SPi模式下选择WFP 1.5 ,WFP,1.6 和1.7 */
GPIO _setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P1,
GPIO _PIN5 | GPIO _PIN6 | GPIO _PIN7,GPIO主要模块功能);
// MSP432数据表中的主要模块功能;WFP 1.5 = BSLCLK, WFP 1.6 SIMO, 1.7
/*在3Wire主模式下配置SPI */
SPI_initMaster(EUSI_B0_BASE,&spiMasterConfig);
/*启用SPI模块*/
SPI_enableModule(EUSI_B0_BASE;
/*启用中断*/
//SPI_enableInterrupt (EUSCI_B0_BBASE,EUSCI_B_SPI_receive _interrupt);
//Interrupt_enableInterrupt (INT_EUSCIB0);
//Interrupt_enableSleepOnIsrExit();
//![简单SPI示例]
/*轮询以查看TX缓冲区是否就绪*/
//同时(!(SPI_getInterruptStatus (EUSCI_B0_BBASE,EUSCI_B_SPI_Transmit_Interrupt)));
/*将数据传输到从属设备*/
//minigen_reset();
minigen_setMode(square);
uINT32_t newFreq = minigen_freqCalc( 14万.0 ;
minigen_AdjustFreq (FREQ0,Full,newFreq);
//SPI_TXData(EUSI_B0_BASE,TXData);
PCM_gotoLPM0();
__no_operation();
}//**********************************************************************************************
//
//这是EUSCI_B0中断向量服务例程。
////************************************************************************************************
void EUSCIB0_IRQHandler(void)
{/*
UINT32_t status = SPI_getEnabledInterruptStatus(EUSSCI_B0_BASE;
uINT32_t j;
SPI_clearInterruptFlag (EUSCI_B0_BASE,STATUS);
IF (STATUS和EUSCI_B_SPI_Receive_interrupt)
{
/* USI_B0 TX缓冲器就绪?
同时(!(SPI_getInterruptStatus (EUSCI_B0_BASE,EUSCI_B_SPI_Transmit_Interrupt)));
RXData = SPI_receiveData (EUSCI_B0_BASE);
/*发送下一个数据包
SPI_TXData(EUSI_B0_base,++TXData);
/*从机处理信息的传输之间的延迟
对于(jj=50;jj<50;jj++);
}
*/
}
我删除了ISR,因为每当对SPI寄存器进行任何修改时,它都会导致程序中断和休眠。 如果我不使用SPI RX,此ISR在任何方面是否至关重要? 这是我能想到的唯一一件事,它可能会在上述代码中受到影响。
下面是MiniGen功能的代码。 正如我所提到的,从表面上看,它非常简单,因为它只需要为每个配置发送几处更改。 我认为这里唯一的问题是我在某种程度上错误地使用SPI_SpenicData函数。 有人能指出问题可能出在这里吗?
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include <ti/drivers/GPIC.h>
#include <ti/drivers/SPI.h>
#include "minigen.h"
void minigen_reset(){
uINT32_t defaultFreq = minigen_freqCalc( 100.0 ;
minigen_AdjustFreq (FREQ0,FULL,defaultFreq);
minigen_AdjustFreq (FREQ1,FULL,defaultFreq);
minigen_AdjustPhaseShift (PHASE0,0x0000);
SPI_SPI_传输数据(EUSI_B0_BASE,0x0100);
SPI_SPI_SpenDate(EUSI_B0_base, 0x0000);
}//
设置部件的模式。 模式(trinagle,sine或square)由
//状态寄存器中的三个位设置:D5 (OPBITEN),D3 (DIV2)和D1 (mode)。
//下面是这些设置的一个很好的真实表:
// D5 d1 d3//
0 0 x正弦波输出
// 01 x三角形波输出
// 1 0 0方波@ 1/2频率
// 01方波@频率
// 1 x不允许
void minigen_setMode(mode newMode){
//我们要调整配置寄存器中的三位
//感兴趣,而不会拧紧其它任何东西。 不幸的是,这是
//零件是只写的,因此我们需要保留一个局部阴影,调整它,
//然后编写。
configReg &=~0x002A;//清除D5,D3和D1。
//此switch语句在配置寄存器中设置适当的位。
交换机(newMode)
{
大小写三角形:
configReg || 0x0002;
中断;
大小写square_2:
configReg |=0x0020;
中断;
方形大小写:
configReg |=0x0028;
中断;
正弦值:
configReg |=0x0000;
中断;
}
SPI_SPI_SpenData(EUSI_B0_BASE,configReg);//现在将我们的阴影副本写入该部件。
}
// AD9837有两个频率寄存器,可以独立调整。
//这允许我们在不影响
设备输出//的情况下摆弄一个值。 用于计算输出的寄存器通过
//切换配置寄存器的位11来选择。
void minigen_selectFreqReg (FREQREG REG)
{
//对于寄存器FREQ0,我们要清除位11。
如果(reg == FREQ0) configReg &=~0x0800;
//否则,设置位11。
否则 configReg |= 0x0800;
SPI_S é rendData (EUSI_B0_BASE,configReg);
}//
同样,有两个相位寄存器,由config
//寄存器的位10选择。
void minigen_selectPhaseReg (PHASEREG REG)
{
IF (reg == PHASE0) Reg &=~0x0400;
else configReg |= 0x0400;
SPI_S距Data(EUSI_B0_BBASE,configReg);
}//
频率寄存器大小为28位(将较低的14位
//两个16位写入结合起来;较高的2位是要写入的寄存器地址)。
//配置寄存器的第13位和第12位选择如何处理这些写入:
// 13 12
// 0对频率寄存器的任何写入被视为对较低
//的写入 14位;这允许快速微调。
// 01写入被发送到上14位,允许快速粗略调整。
//一对的第一个写入被转到LSB,第二个被转到MSB。 请注意
,// 在这种情况下,用户必须确保成对写入,以避免
// 意外结果!
void minigen_setFreqAdjustMode(FREQADJUSTMODE newMode){
//首先清除有问题的位。
configReg &=~0x3000;
//现在,调整位以匹配上面的真值表。
交换机(newMode)
{
粗箱:// D13:12 = 01
configReg || 0x1000;
中断;
案件细分:// D13:12 = 00
中断;
完整案例:// d13:12 = 1x (我们使用10)
configReg || 0x2000;
中断;
}
SPI_S传播数据(EUSSCI_B0_BAS, configReg);
}//
相移值为12位长;它根据
3个MSB的值路由到正确的相位//寄存器(第4个MSB被忽略)。
void minigen_conparitionPhaseShift(PHASEREG REG, uint16_t newPhase){
//首先,让我们将前四位留空。 因为这是正确的
//您知道吗?
newPhase &=~0xF000;
//现在,我们需要设置前三位以正确路由数据。
// D15:D13 = 110 (对于PHASE0)...
如果(reg == PHASE0) newPhase || 0xC000;
//...和D15:D13 = 111 (第1阶段)。
否则 newPhase |= 0xE000;
SPI_SPI_SpenData(EUSI_B0_BASE,configReg);
}//
好的,现在我们将处理频率调整。 这
比相位调整要复杂一些,因为除了正确地路由
//数据外,我们还需要知道是写入全部32位还是只写入16位。 我已
//将此函数调用过载了三种情况:使用模式更改写入(如果
需要//),使用现有模式写入。
//调整给定寄存器的内容,如有必要,切换模式
//以执行此操作。 这可能是更新寄存器的最慢方法。
void minigen_adjuminfreq(FREQREG REG, FREQADJUSTMODE MODE, UINT32_t newFreq)
{
minigen_setFreqAdjustMode(mode);
//我们需要将32位输入拆分为两个16位值,将顶部留空
//这些值中的两位,并根据设置顶部的两位
//注册值
//从获取低16位开始...
uINT16_t temp =(uint16_t)newFreq;
//...并清空前两位。
温度&=~0xC000;
//现在,根据reg参数设置前两位。
如果(reg=FREQ0) temp |=0x4000;
否则 温度|= 0x8000;
//现在,我们可以在设备中写入临时输出。
SPI_SPI_SpenDate(EUSI_B0_base, temp);
//好的,这是14位的下限。 现在,让我们抓住上14个。
temp =(uint16_t)(newFreq>>14);
//...现在,我们可以重复这个过程。
温度&=~0xC000;
//现在,根据reg参数设置前两位。
如果(reg=FREQ0) temp |=0x4000;
否则 温度|= 0x8000;
//现在,我们可以在设备中写入临时输出。
SPI_SPI_SpenData(EUSI_B0_base, temp)
;}//
Helper函数,用于计算要写入
// freq寄存器以获得所需输出频率的整数值。
//输出频率为fclk/2^28* FREQREG。 对我们来说,fclk是16MHz。 我们可以
//通过为fclk/2^28-.0596指定一个常量来节省处理器时间。 即
,//,以Hz为单位,调整输出频率的最小步长。
uINT32_t minigen_freqCalc(浮点期望频率)
{
返回(UINT32_t)(desredFrequency/.0596);
}