各位老师帮帮忙,有人知道我MSP430f149与LMX2592实现SPI通信为什么失败吗?代码如下:
#include <msp430x14x.h>
#include <stdint.h>
// 引脚定义
#define SDI BIT1
#define MUXOUT BIT2
#define SCK BIT3
#define CSB BIT0
#define CE BIT4
/************************** 函数声明 **************************/
void GPIO_Init(void); // GPIO引脚初始化
void SPI_Init(void); // SPI通信初始化
void LMX2592_SendSingleReg(uint32_t reg); // 单寄存器写入(
void LMX2592_WriteAllRegs(void); // 写入所有目标寄存器
void Delay_us(uint16_t us); // 微秒延时
void Delay_ms(uint16_t ms); // 毫秒延时
void System_Clock_Init(void);
/************************** 主函数(入口) **************************/
void main(void) {
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗定时器
System_Clock_Init(); // 初始化系统时钟
GPIO_Init(); // 初始化GPIO引脚
SPI_Init(); // 初始化SPI通信
Delay_ms(100); // 上电延时()
LMX2592_WriteAllRegs(); // 执行所有寄存器写入
while(1); // 程序循环
}
/************************** 系统时钟初始化实现 **************************/
void System_Clock_Init(void)
{
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
// 关闭不需要的振荡器以节省功耗
BCSCTL1 |= XT2OFF; // 关闭XT2
BCSCTL1 &= ~XTS; // 低频模式
//DCOCTL = 0x00;
// 使用16MHz的校准数据来配置RSELx=11,以达到稳定的8MHz或更高频率
//BCSCTL1 = (0xC0 | (*(unsigned char *)(0x10FE)));
//DCOCTL = (*(unsigned char *)(0x10FF));
// 明确配置DCO为8MHz,避免使用不稳定的校准数据
DCOCTL |= DCO0 + DCO1 + DCO2; // DCO = 8MHz
BCSCTL1 |= RSEL0 + RSEL1 + RSEL2; // RSEL = 7, 最高频率范围
//DCOCTL = CALDCO_8MHz;
// 配置时钟源和分频
BCSCTL2 &= ~(SELM_3 | DIVM_3 | SELS | DIVS_3);
// MCLK配置:使用DCO,不分频
BCSCTL2 |= SELM_0;
BCSCTL2 &= ~DIVM_3;
// SMCLK配置:使用DCO,不分频
BCSCTL2 &= ~SELS;
BCSCTL2 &= ~DIVS_3;
// 确保使用内部电阻
BCSCTL2 &= ~DCOR;
}
/************************** GPIO初始化实现 **************************/
void GPIO_Init(void) {
// 打开电平转换,方向为3.3V-5V
P6DIR |= BIT2;
P6OUT &=~ BIT2;
P2DIR |= BIT3;
P2OUT &=~ BIT3;
// 配置SPI引脚
P5SEL |= SDI + MUXOUT + SCK; // 配置为外设功能
P5DIR |= CSB+SDI+SCK; // 设置CSB+SDI+SCK为输出
P5DIR &= ~MUXOUT; // MISO为输入
P5OUT |= CSB+SDI+SCK; //默认输出高
P5DIR |= CE;
P5OUT |= CE;
Delay_us(1); // 电平稳定延时(满足手册1-134节tEWH≥2ns要求)
LMX2592_SendSingleReg(0x00231E); //复位芯片
LMX2592_SendSingleReg(0x00231C); //去掉芯片复位
}
/************************** SPI初始化实现 **************************/
void SPI_Init(void) {
U1CTL |= SWRST; // 复位USART1模块
U1CTL |= CHAR + SYNC + MM; // 八位字符长度 + 同步模式(SPI) + 主机模式
U1TCTL &= ~(CKPL + CKPH); //确保 CKPL=0, CKPH=0 (SPI Mode 0)
U1TCTL |= STC + SSEL1 ; // 时钟极性(低电平空闲)+上升沿采样+3线+时钟源(SMCLK)
U1BR0 = 0x02; // 分频系数=2 (8MHz/2=4MHz SPI时钟)
U1BR1 = 0x00;
U1MCTL = 0x00; // 无调制
ME2 |= USPIE1; //模块使能
U1CTL &= ~SWRST; // 释放复位
IE2 |= URXIE1; //接受中断使能
}
/************************** 单寄存器写入实现 **************************/
void LMX2592_SendSingleReg(uint32_t reg) {
uint8_t addr_byte, data_hbyte, data_lbyte;
// 拆分24位寄存器数据(手册1-309节:bit23=R/W,bit22-16=地址,bit15-0=数据)
addr_byte = (reg >> 16) & 0xFF; // 地址字节(含R/W=0,写入)
data_hbyte = (reg >> 8) & 0xFF; // 数据高8位
data_lbyte = reg & 0xFF; // 数据低8位
P5OUT &= ~CSB; // 拉低CSB,选中LMX2592
Delay_us(1); // 满足手册1-134节tCES(使能到时钟建立时间≥5ns)
// 等待发送缓冲区空,依次发送3个字节(地址→高8位→低8位)
while (!(IFG2 & UTXIFG1)); // 等待发送缓冲区为空
U1TXBUF = addr_byte; // 发送第一个字节
while (!(IFG2 & UTXIFG1));
U1TXBUF = data_hbyte; // 发送第二个字节
while (!(IFG2 & UTXIFG1));
U1TXBUF = data_lbyte; // 发送第三个字节
while (U1TCTL & TXEPT); // 等待所有数据发送完成(移位寄存器空)
P5OUT |= CSB; // 拉高CSB,结束当前寄存器写入
Delay_us(1); // 满足手册1-134节tEWH≥2ns
}
/************************** 全部寄存器写入实现 **************************/
void LMX2592_WriteAllRegs(void) {
// 1. 软复位:写R0[1]=1
LMX2592_SendSingleReg(0x000002); // 地址0x00,数据0x0002(RESET=1)
Delay_ms(1); // 等待复位完成
LMX2592_SendSingleReg(0x460000); // R70
LMX2592_SendSingleReg(0x450000); // R69
LMX2592_SendSingleReg(0x440089); // R68
LMX2592_SendSingleReg(0x400077); // R64
LMX2592_SendSingleReg(0x3E0000); // R62
LMX2592_SendSingleReg(0x3D0001); // R61
LMX2592_SendSingleReg(0x3B0000); // R59
LMX2592_SendSingleReg(0x3003FC); // R48
LMX2592_SendSingleReg(0x2F00CF); // R47
LMX2592_SendSingleReg(0x2E0FA3); // R46
LMX2592_SendSingleReg(0x2D0000); // R45
LMX2592_SendSingleReg(0x2C0000); // R44
LMX2592_SendSingleReg(0x2B0000); // R43
LMX2592_SendSingleReg(0x2A0000); // R42
LMX2592_SendSingleReg(0x2903E8); // R41
LMX2592_SendSingleReg(0x280000); // R40
LMX2592_SendSingleReg(0x278204); // R39
LMX2592_SendSingleReg(0x260048); // R38
LMX2592_SendSingleReg(0x254000); // R37
LMX2592_SendSingleReg(0x240411); // R36
LMX2592_SendSingleReg(0x23021B); // R35
LMX2592_SendSingleReg(0x22C3EA); // R34
LMX2592_SendSingleReg(0x212A0A); // R33
LMX2592_SendSingleReg(0x20210A); // R32
LMX2592_SendSingleReg(0x1F0601); // R31
LMX2592_SendSingleReg(0x1E0034); // R30
LMX2592_SendSingleReg(0x1D0084); // R29
LMX2592_SendSingleReg(0x1C2924); // R28
LMX2592_SendSingleReg(0x190000); // R25
LMX2592_SendSingleReg(0x180509); // R24
LMX2592_SendSingleReg(0x178842); // R23
LMX2592_SendSingleReg(0x162300); // R22
LMX2592_SendSingleReg(0x14012C); // R20
LMX2592_SendSingleReg(0x130965); // R19
LMX2592_SendSingleReg(0x0E018C); // R14
LMX2592_SendSingleReg(0x0D4000); // R13
LMX2592_SendSingleReg(0x0C7001); // R12
LMX2592_SendSingleReg(0x0B0018); // R11
LMX2592_SendSingleReg(0x0A10D8); // R10
LMX2592_SendSingleReg(0x090302); // R9
LMX2592_SendSingleReg(0x081084); // R8
LMX2592_SendSingleReg(0x0728B2); // R7
LMX2592_SendSingleReg(0x041943); // R4
LMX2592_SendSingleReg(0x020500); // R2
LMX2592_SendSingleReg(0x010808); // R1
// 3. 最后写R0触发校准(FCAL_EN=1)
LMX2592_SendSingleReg(0x00221C); // 地址0x00,数据0x221C
Delay_ms(1); // 等待校准完成(手册要求590-800μs)
}
/************************** 微秒延时实现 **************************/
void Delay_us(uint16_t us) {
TACCR0 = 8 * us - 1; // 8MHz SMCLK:1μs对应8个计数周期
TACTL = TASSEL_2 + MC_1; // 时钟源=SMCLK,增计数模式
TACCTL0 &= ~CCIFG; // 清除中断标志
while (!(TACCTL0 & CCIFG)); // 等待计数完成
TACTL = MC_0; // 停止定时器
}
/************************** 毫秒延时实现 **************************/
void Delay_ms(uint16_t ms) {
while (ms--) {
Delay_us(1000); // 1ms = 1000μs
}
}