尝试使用MSP430f169与AD5933进行通信,但程序始终卡死在发送字节部分,判断是否空闲的语句
观察发现I2CBUSY位一直为1
请问这是什么问题?真诚求教。后附主程序和I2C程序
主程序
/********************
void main(void)
{
WDT_Init();
Clock_Init(); //系统时钟设置
I2c_Init();
_EINT(); //打开中断
I2CWriteInit();
/*-----启动频率扫描--------------
ad5933_write ( 0x82, 0x0e);delay_ms(5);
//频率增量:0
// Transmit to frequency increment register
// program 1Khz frequency increment assuming internal osc of 16.776Khz
ad5933_write ( 0x87, 0x02);delay_ms(5);
ad5933_write ( 0x86, 0x7D);delay_ms(5);
ad5933_write ( 0x85, 0x00);delay_ms(5);
//增量数:(随意设定)
// Transmit to NUMBER OF INCREMENTS register
// program 10 frequency increments
ad5933_write ( 0x89, 0x0A);delay_ms(5);
ad5933_write ( 0x88, 0x00);delay_ms(5);
// Transmit to settling time cycles register
// program 15 output cycles at each frequency before a adc conversion
ad5933_write ( 0x8B, 0x0F);delay_ms(5);
ad5933_write ( 0x8A, 0x00);delay_ms(5);
/*----------------读取数据----------------------*/
while(1)
{
ZT = ad5933_read(0x8f);
while((ZT&0x02)!=0x02)
{
ZT = ad5933_read(0x8f);
delay_ms(5);
ad5933_write ( 0x80, 0x40);
delay_ms(5);
}
P = ad5933_read(0x80);//控制寄存器
P1 = ad5933_read(0x84);//实值低四位
R[0] = ad5933_read(0x94);//实值低四位
R[1] = ad5933_read(0x95);//实值高四位
I[0] = ad5933_read(0x96);//虚值低四位
I[1] = ad5933_read(0x97);//虚值高四位
I2C函数
#include <msp430x16x.h>
#define SDA_1 P3OUT |= BIT1 //串行数据线,SDA = 1
#define SDA_0 P3OUT &=~ BIT1 //SDA = 0
#define SCL_1 P3OUT |= BIT3 //串行时钟线,SCL = 1
#define SCL_0 P3OUT &=~ BIT3 //SCL = 0
#define SDADIR_IN P3DIR &=~ BIT1 //SDA,I/O口为输入
#define SDADIR_OUT P3DIR |= BIT1 //I/0口为输出
#define SDA_IN ((P3IN >> 1) & 0x01) //Read SDA
#define SCLDIR_IN P3DIR &=~ BIT3 //SCL,I/O口为输入
#define SCLDIR_OUT P3DIR |= BIT3 //I/0口为输出
#define SCL_IN ((P3IN >> 3) & 0x01) //Read SCL
#define CPU_F ((double)8000000)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
/*当BRCLK=CPU_F时用下面的公式可以计算,否则要根据设置加入分频系数*/
#define baud 9600 //设置波特率的大小
#define baud_setting (uint)((ulong)CPU_F/((ulong)baud)) //波特率计算公式
#define baud_h (uchar)(baud_setting>>8) //提取高位
#define baud_l (uchar)(baud_setting) //低位
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define SLAVEADDR 0x0D;
int tx_count;
int rx_count;
unsigned int i;
unsigned char I2CBuffer[3];
unsigned int n=3;
/*--------------------------------------------------------
---I2C初始化函数
----------------------------------------------------------*/
void I2c_Init(void)
{
//将P3.1和P3.3设置为I2C管脚
//P3SEL |= 0X0A;
//设置P3.1和P3.3管脚的方向
P3DIR |= 0x0A;
SDA_1;
SCL_1;
P3SEL |= 0X0A;
for(i= 0; i <9 ; i++)
{
P3OUT |= BIT3;
__delay_cycles(8000);
P3OUT &= ~BIT3;
__delay_cycles(8000);
}
//选择为I2C模式
U0CTL |= I2C + SYNC;
//禁止I2C模块
U0CTL &= ~I2CEN;
//设置I2C为7位地址模式,不使用DMA,
//字节模式,时钟源为SMCLK,
//设置成传输模式
I2CTCTL = I2CTRX + I2CSSEL_2;
//定义从器件地址
I2CSA = SLAVEADDR;
//设置本身的地址
I2COA = 0x01A5;
//I2C时钟为SMCLK / 160
I2CPSC = 159;
//SCL 高电平为:5 *I2C 时钟
I2CSCLH = 0x03;
//SCL 低电平为:5 *I2C 时钟
I2CSCLL = 0x03;
//I2C 模块有效
U0CTL |= I2CEN;
tx_count = 0;
rx_count = 0;
}
//------------------ MSP430 I2C 写数据初始化 -------------
/*--------------------------------------------------------
--功能描述:对于从器件的写操作是置成主模式并置位中断使能.
----------------------------------------------------------*/
void I2CWriteInit(void)
{
//主(Master)模式
U0CTL |= MST;
//传输模式,R/W 为:0
I2CTCTL |= I2CTRX;
//清除中断标志
I2CIFG &= ~TXRDYIFG;
//发送中断使能
I2CIE = TXRDYIE;
}
//------------------ MSP430 I2C 读数据初始化 -------------
/*--------------------------------------------------------
--功能描述:对于从器件的写操作是置成主模式并置位中断使能.
----------------------------------------------------------*/
void I2CReadInit(void)
{
//接收模式,R/W 为:1
I2CTCTL &= ~I2CTRX;
//接收中断使能
I2CIE = RXRDYIE;
}
//----------------- AD5933 写入数据 --------------------
/*--------------------------------------------------------
--功能描述:向从器件中nAddr地址,写入nVal数据
----------------------------------------------------------*/
void ad5933_write(unsigned char nAddr, unsigned char nVal)
{
//等待I2C模块完成所有操作
while (I2CDCTL&I2CBUSY) ;
//设置地址数据
I2CBuffer[1] = nAddr;
//设置数据
I2CBuffer[0] = nVal;
//设置缓冲区指针
tx_count = 1;
//写数据初始化
I2CWriteInit(); //设置为主模式
//发送数据的长度
//一共2个字节,包括1个地址字节,1个数据字节
I2CNDAT = 2;
//开始和停止条件产生
//开始I2C通信
I2CTCTL |= I2CSTT+I2CSTP;
//delay_ms(5);
return;
}
//----------------- AD5933 读出数据 --------------------
/*--------------------------------------------------------
--功能描述:从器件中nAddr地址读数据
----------------------------------------------------------*/
unsigned char ad5933_read(unsigned char nAddr)
{
//等待I2C模块完成所有操作
while (I2CDCTL&I2CBUSY) ;
//指针命令代码
I2CBuffer[1] = 0xb0;
//设置数据(指针指向寄存器地址)
I2CBuffer[0] = nAddr;
//设置缓冲区指针
tx_count = 1;
//写数据初始化
I2CWriteInit(); //设置为主模式
//发送数据的长度
//一共2个字节,包括1个指针命令代码,1个缓冲区指针
I2CNDAT = 2;
//开始条件产生
//开始I2C通信
I2CTCTL |= I2CSTT;
//I2CNDAT = 1;
//清除中断标志
//I2CIFG &= ~ARDYIFG;
//开始接收,产生重新起始和停止条件
delay_ms(5);
while ((~I2CIFG)&ARDYIFG);
//读操作初始化
I2CReadInit();
//接收一个字节的数据
I2CNDAT = 1;
//清除中断标志
//I2CIFG &= ~ARDYIFG;
//开始接收,产生重新起始和停止条件
I2CTCTL |= I2CSTT + I2CSTP;
//等待传输完成
while ((~I2CIFG)&ARDYIFG);
//返回数据
//I2CBuffer[0]=I2CDRB;
delay_ms(5);
return I2CBuffer[0];
}
#pragma vector=USART0TX_VECTOR //IIC中断向量,包括八个中断标志位
__interrupt void ISR_I2C(void)
{
switch (I2CIV) //中断向量寄存器,决定了IIC中具体哪个中断被出发
{
case I2CIV_AL:
{
//仲裁中断
break;
}
case I2CIV_NACK: //无应答信号中断
{
//NACK中断
P3OUT |=BIT2;
delay_ms(10);
P3OUT &=~BIT2;
break;
}
case I2CIV_OA:
{
//自己地址中断
break;
}
case I2CIV_ARDY:
{
//访问准备好中断
break;
}
case I2CIV_RXRDY:
{
//接收准备好中断
I2CBuffer[0]=I2CDRB;
break;
}
case I2CIV_TXRDY:
{
//发送准备好中断
I2CDRB = I2CBuffer[tx_count];
tx_count = tx_count - 1;
if (tx_count < 0)
{
//禁止发送中断
I2CIE &= ~TXRDYIE;
}
break;
}
case I2CIV_GC:
{
//一般调用中断
break;
}
case I2CIV_STT:
{
//起始条件中断
break;
}
}
}
黄色部分为程序卡死的部分