请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
器件型号:MSP430F5529 工具/软件:Code Composer Studio
我尝试使用 TI 网站上提供的示例代码从 AD5933 IC 读取寄存器、但它始终卡在左侧的数据接收 ISR 例程中、如下图所示
我粘贴了下面的代码、有人能不能指出我做了什么错?
#include
#include
#include
//
//示例命令(Example Commands Commands
//
#define SLAVE_ADDR 0x0D
/* CMD_TYPE_X_SLAVE 是主器件发送到从器件的示例命令。
*从属方将发送示例 SlaveTypeX 缓冲区进行响应。
*
* CMD_TYPE_X_MASTER 是主器件发送到从器件的示例命令。
*从器件将初始化自身以接收 MasterTypeX 示例缓冲区。
**/
#define CMD_TYPE_0_SLAVE 0
#define CMD_TYPE_1_SLAVE 1
#define CMD_TYPE_2_SLAVE 2
#define CMD_TYPE_0_MASTER 3
#define CMD_TYPE_1_MASTER 4
#define CMD_TYPE_2_MASTER 5
#define TYPE_0_LENGTH 1
#define TYPE_1_LENGTH 2
#define TYPE_2_LENGTH 6
#define MAX_BUFFER_SIZE 20
/* MasterTypeX 是在主设备中初始化的示例缓冲
区,主设备将*将它们发送给从设备。
* SlaveTypeX 是在从器件中初始化的示例缓冲
区,它们将由从器件*发送到主器件。
*/
uint8_t MasterType2 [type_2_length]={'F'、'4'、'1'、'9'、'2'、 'b'};
uint8_t MasterType1 [type_1_length]={8、9};
uint8_t MasterType0 [type_0_length]={11};
uint8_t SlaveType2 [type_2_length]={0};
uint8_t SlaveType1 [type_1_length]=
{uint0_0
};uint0_uint_length ={uint8}
//通用 I2C 状态机
//
typedef 枚举 I2C_ModeEnum{
IDLE_MODE、
NACK_MODE、
TX_REG_ADDRESS_MODE、
RX_REG_ADDRESS_MODE、
TX_DATA_MODE、
RX_DATA_MODE、
切换至 RX_MODE、
SWITHC_TO_TX_MODE、
TIMEOUT_MODE
}I2C_Mode;
//用于跟踪软件状态机的状态*/
I2C_Mode MasterMode = IDLE_MODE;
//要使用的寄存器地址/命令*/
uint8_t TransmitRegAddr = 0;
// ReceiveBuffer:用于在 ISR 中接收数据的缓冲区
* RXIndex ByteCtr:剩余要接收的字节数
*: ReceiveBuffer
* TransmitBuffer:用于在 ISR 中传输数据的缓冲区
* TXByteCtr:剩余要传输的字节数
* TransmitIndex:要在 TransmitBuffer 中传输的下一个字节的索引
*/
uint8_t ReceiveBuffer[MAX_buffer_size]={0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_buffer_size]={0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;
//
针对具有 dev_addr 数据
的从设备*////////*在 dr 中指定的从设备* addr:
* 示例:SLAVE_ADDR
* REG_addr:要发送到从器件的寄存器或命令。
* 示例:CMD_TYPE_0_MASTER
** REG_DATA:要写入的缓冲
区* 示例:MasterType0
* count:* reg_data
*的长度 示例:TYPE_0_LENGTH
*/
I2C_Mode I2C_Master_WriteReg (uint8_t DEV_addr、uint8_t REG_addr、uint8_t * REG_DATA、uint8_t COUNT);
//对于具有 DEV_addr 的从器件、请读取从器件 REG_addr 中指定的数据。
*接收到的数据在 ReceiveBuffer
中可用*
DEV_addr:从器件地址。
* 示例:SLAVE_ADDR
* REG_addr:要发送到从器件的寄存器或命令。
* 示例:CMD_TYPE_0_SLAVE
*计数:要读取的数据长度
* 示例:type_0_length
**/
I2C_Mode I2C_Master_ReadReg (uint8_t dev_addr、uint8_t reg_addr、uint8_t count);
void CopyArray (uint8_t * source、uint8_t * dest、 uint8_t count);
I2C_Mode I2C_Master_ReadReg (uint8_t dev_addr、uint8_t reg_addr、uint8_t count)
{
/*初始化状态机*/
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
RXByteCtr =计数;
TXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/*初始化从地址和中断*/
UCB0I2CSA = DEV_addr;
UCB0IFG &=~(UCTXIFG + UCRXIFG); //清除所有挂起的中断
UCB0IE &=~UCRXIE; //禁用 RX 中断
UCB0IE |= UCTXIE; //启用 TX 中断
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX、启动条件
_bis_SR_register (LPM0_bits + GIE); //输入带中断的 LPM0
返回 MasterMode;
}
I2C_Mode I2C_Master_WriteReg (uint8_t dev_addr、uint8_t reg_addr、uint8_t * reg_data、uint8_t count)
{
/*初始化状态机*/
MasterMode = TX_REG_ADDRESS_MODE;
TransmitRegAddr = reg_addr;
//将寄存器数据复制到 TransmitBuffer
CopyArray (reg_data、TransmitBuffer、count);
TXByteCtr =计数;
RXByteCtr = 0;
ReceiveIndex = 0;
TransmitIndex = 0;
/*初始化从地址和中断*/
UCB0I2CSA = DEV_addr;
UCB0IFG &=~(UCTXIFG + UCRXIFG); //清除所有挂起的中断
UCB0IE &=~UCRXIE; //禁用 RX 中断
UCB0IE |= UCTXIE; //启用 TX 中断
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX、启动条件
_bis_SR_register (LPM0_bits + GIE); //输入带中断的 LPM0
返回 MasterMode;
}
void CopyArray (uint8_t *源、uint8_t * dest、uint8_t count)
{
uint8_t copyIndex = 0;
for (copyIndex = 0;copyIndex < count;copyIndex++)
{
dest[copyIndex]= source[copyIndex];
}
}
//*********
//设备初始化
//
void initClockTo16MHz()
{
UCSCTL3 |= SELREF_2; //设置 DCO FLL 基准= REFO
UCSCTL4 |= SE拉美 经济体系2; //设置 ACLK = REFO
_bis_SR_register (SCG0); //禁用 FLL 控制环路
UCSCTL0 = 0x0000; //设置可能的最低 DCOx、MODx
UCSCTL1 = DCORSEL_5; //选择 DCO 范围16MHz 操作
UCSCTL2 = FLLD_0 + 487; //将 DCO 乘法器设置为16MHz
//(N + 1)* FLLRef = Fdco
//(487 + 1)* 32768 = 16MHz
//设置 FLL Div = fDCOCLK
_BIC_SR_register (SCG0); //启用 FLL 控制环路
// DCO 范围位已经存在时、DCO 的最坏情况稳定时间
//已更改 n x 32 x 32 x f_MCLK / f_FLL_reference。 请参阅5xx 中的 UCS 一章
// UG 进行优化。
// 32 x 32 x 16 MHz/32、768Hz = 500000 = DCO 稳定的 MCLK 周期
_DELAY_CYCLES (50000);//
//循环直到 XT1、XT2和 DCO 故障标志被清除
操作
{
UCSCTL7 &=~(XT2OFFG + XT1LFOFFG + DCOFFG);//清除 XT2、XT1、DCO 故障标志
SFRIFG1 &=~OFIFG; //清除故障标志
} while (SFRIFG1&OFIFG); //测试振荡器故障标志
}
uint16_t setVCoreUp (uint8_t level){
uint32_t PMMRIE_BACKUP、SVSMHCTL_BACKUP、SVSMLCTL_BACKUP;
//增加 Vcore 的代码流已被修改为有效
//勘 误表 FLASH37。
//请参阅勘误表以了解特定器件是否受到影响
//不要更改此功能
//打开 PMM 寄存器进行写访问
PMMCTL0_H = 0xA5;
//禁用专用中断
//备份所有寄存器
PMMRIE_BACKUP = PMMRIE;
PMMRIE &=~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
SVSLPE | SVMHVLRIE | SVMHIE |
SVSMHDLYIE | SVMLVLRIE | SVMLIE |
SVSMLDLYIE
);
SVSMHCTL_BACKUP = SVSMHCTL;
SVSMLCTL_BACKUP = SVSMLCTL;
//清除标志
PMMIFG=0;
//set SVM highside to new level and check if a VCORE increase is possible
SVSMHCTL = SVMHE | SVSHE |(SVSMHRRL0 *电平);
//等待 SVM 高侧稳定
while (((PMMIFG & SVSMHDLYIFG)=0)
{
;
}
//清除标志
PMMIFG &=~SVSMHDLYIFG;
//检查是否可以增加 VCORE
if ((PMMIFG & SVMHIFG)== SVMHIFG)
{
//->Vcc 对于 Vcore 增加来说太低
//恢复以前的设置
PMMIFG &=~SVSMHDLYIFG;
SVSMHCTL = SVSMHCTL_BACKUP;
//等待 SVM 高侧稳定
while (((PMMIFG & SVSMHDLYIFG)=0)
{
;
}
//清除所有标志
PMMIFG &=~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG |
SVSMLDLYIFG
);
//恢复 PMM 中断使能寄存器
PMMRIE = PMMRIE_BACKUP;
//锁定 PMM 寄存器以进行写访问
PMMCTL0_H = 0x00;
//返回:未设置电压
返回 false;
}
//set also SVS highside to new leve.(//将 SVS 高侧设置为新的水平。
//Vcc 足够高、足以使 Vcore 增加
SVSMHCTL |=(SVSHRVL0 *电平);
//等待 SVM 高侧稳定
while (((PMMIFG & SVSMHDLYIFG)=0)
{
;
}
//清除标志
PMMIFG &=~SVSMHDLYIFG;
//将 VCORE 设置为新的电平
PMMCTL0_L = PMMCOREV0 *电平;
//将 SVM、SVS 低电平侧设置为新的电平
SVSMLCTL = SVMLE |(SVSMLRRL0 *电平)|
SVSLE |(SVSLRVL0 *级别);
//等待 SVM、SVS 低电平侧稳定
while (((PMMIFG & SVSMLDLYIFG)=0)
{
;
}
//清除标志
PMMIFG &=~SVSMLDLYIFG;
//SVS、SVM 内核和高侧现在被设置为针对新的内核级别进行保护
//恢复低侧设置
//清除所有其他位_exbel_级别设置
SVSMLCTL &=(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +
SVSMLRRL1 + SVSMLRRL2
);
//清除备份寄存器中的级别设置,保留所有其它位
SVSMLCTL_BACKUP &=
~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
//恢复低电平侧 SVS 监视器设置
SVSMLCTL |= SVSMLCTL_BACKUP;
//恢复高侧设置
//清除除级别设置之外的所有其他位
SVSMHCTL &=(SVSHRVL0 + SVSHRVL1 +
SVSMHRRL0 + SVSMHRRL1 +
SVSMHRRL2
);
//清除备份寄存器中的级别设置,保留所有其它位
SVSMHCTL_BACKUP &=
~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
//恢复备份
SVSMHCTL |= SVSMHCTL_BACKUP;
//等待高侧、低侧稳定
while ((((PMMIFG & SVSMLDLYIFG)=0)&&
((PMMIFG & SVSMHDLYIFG)=0))
{
;
}
//清除所有标志
PMMIFG &=~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
);
//恢复 PMM 中断使能寄存器
PMMRIE = PMMRIE_BACKUP;
//锁定 PMM 寄存器以进行写访问
PMMCTL0_H = 0x00;
返回 true;
}
bool increaseVCoreToLevel2()
{
uint8_t level = 2;
uint8_t actlevel;
bool status = true;
//为最大值设置掩码 电平
Level &= PMMCOREV_3;
//获取实际 VCORE
actlevel = PMMCTL0和 PMMCOREV_3;
//逐步增加或减少
while ((level!= actlevel)&&(status = true))
{
if (级别> actlevel)
{
状态= setVCoreUp (++actlevel);
}
}
return (status);
}
void initGPIO()
{
//LED
P1OUT = 0x00; 针对 LED 和复位输出的// P1设置
P1DIR |= BIT0;
P4DIR |= BIT7;
P4OUT &=~(BIT7);
//I2C 引脚
P3SEL |= BIT0 + BIT1; // P3.0,1选项选择
}
void initI2C()
{
UCB0CTL1 |= UCSWRST; //启用 SW 复位
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C 主设备,同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST; //使用 SMCLK、保持软件复位
UCB0BR0 = 160; // fSCL = SMCLK/160 =~100kHz
UCB0BR1 = 0;
UCB0I2CSA = SLAVE_ADDR; //从机地址为048h
UCB0CTL1 &=~UCSWRST; //清除 SW 复位,恢复操作
UCB0IE |= UCNACKIE;
}
//*********
//主要内容
//发送和接收三条包含示例命令*******的消息
//
int main (void){
WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器
increaseVCoreToLevel2();
initClockTo16MHz();
initGPIO();
initI2C ();
// I2C_Master_WriteReg (slave_ADDR、CMD_TYPE_0_MASTER、MasterType0、TYPE_0_LENGTH);
// I2C_Master_WriteReg (SLAVE_ADDR、CMD_TYPE_1_MASTER、MasterType1、TYPE_1_LENGTH);
// I2C_Master_WriteReg (SLAVE_ADDR、 CMD_TYPE_2_MASTER、MasterType2、TYPE_2_LENGTH);
I2C_Master_ReadReg (SLAVE_ADDR、0x8F、TYPE_0_LENGTH);
CopyArray (ReceiveBuffer、SlaveType0、TYPE_0_LENGTH);
// I2C_Master_ReadReg (SLAVE_ADDR、CMD_TYPE_1_SLAVE、 TYP_1_LENGTH);
// CopyArray (ReceiveBuffer、SlaveType1、TYP_1_LENGTH);
//
I2C_Master_ReadReg (SLAVE_ADDR、 CMD_TYPE_2_SLAVE、TYPE_2_LENGTH);
// CopyArray (ReceiveBuffer、SlaveType2、TYPE_2_LENGTH);
_bis_SR_register (LPM0_bits + GIE);
返回0;
}
//*********
// I2C 中断
//
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector=USCI_B0_vector
__interrupt void USCI_B0_ISR (void)
#Elif defined (__GNU__)
void __attribute__(interrupt (USCI_B0_vector)#USCI_ISR vector (void
)#USCI_编译器0 (void)错误!
#endif
{
//必须从 UCB0RXBUF
uint8_t Rx_val 读取;
switch (_even_in_range (UCB0IV、0xC))
{
案例 USCI_NONE:break; //向量0 -无中断
案例 USCI_I2C_UCALIFG:break; //中断矢量:I2C 模式:UCALIFG
案例 USCI_I2C_UCNACKIFG:break; //中断矢量:I2C 模式:UCNACKIFG
案例 USCI_I2C_UCSTTIFG:break; //中断矢量:I2C 模式:UCSTTIFG
案例 USCI_I2C_UCSTPIFG:break; //中断矢量:I2C 模式:UCSTPIFG
USCI_I2C_UCRXIFG 案例:
RX_val = UCB0RXBUF;
IF (RXByteCtr)
{
ReceiveBuffer[ReceiveIndex++]= Rx_val;
RXByteCtr --;
}
IF (RXByteCtr = 1)
{
UCB0CTL1 |= UCTXSTP;
}
否则、如果(RXByteCtr = 0)
{
UCB0IE &=~UCRXIE;
MasterMode = IDLE_MODE;
_BIC_SR_REGISTER_ON_EXIT (CPUOFF); //退出 LPM0
}
中断; //中断矢量:I2C 模式:UCRXIFG
USCI_I2C_UCTXIFG 案例:
开关(主模式)
{
案例 TX_REG_ADDRESS_MODE:
UCB0TXBUF = TransmitRegAddr;
IF (RXByteCtr)
MasterMode = SWITCH_TO_RX_MODE;//需要立即开始接收
其他
MasterMode = TX_DATA_MODE; //继续与发送缓冲区中的数据一起传输
中断;
案例切换至 RX_MODE:
UCB0IE |= UCRXIE; //启用 RX 中断
UCB0IE &=~UCTXIE; //禁用 TX 中断
UCB0CTL1 &=~UCTR; //切换到接收器
MasterMode = RX_DATA_MODE;//状态是接收数据
UCB0CTL1 |= UCTXSTT; //发送重复起始
IF (RXByteCtr = 1)
{
//必须发送停止,因为这是 N-1字节
while ((UCB0CTL1 & UCTXSTT));
UCB0CTL1 |= UCTXSTP; //发送停止条件
}
中断;
案例 TX_DATA_MODE:
IF (TXByteCtr)
{
UCB0TXBUF =传输缓冲器[TransmitIndex++];
TXByteCtr --;
}
其他
{
//传输完成
UCB0CTL1 |= UCTXSTP; //发送停止条件
MasterMode = IDLE_MODE;
UCB0IE &=~UCTXIE; //禁用 TX 中断
_BIC_SR_REGISTER_ON_EXIT (CPUOFF); //退出 LPM0
}
中断;
默认值:
__no_operation();
中断;
}
中断; //中断矢量:I2C 模式:UCTXIFG
默认值:中断;
}
}

