This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/MSP430F5529:CAN#39;t EXIT LPM0和/或 ISR。 CPU

Guru**** 657930 points
Other Parts Discussed in Thread: OPT3001
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/733792/ccs-msp430f5529-can-t-exit-lpm0-and-or-isr-cpu

器件型号:MSP430F5529
主题中讨论的其他器件:OPT3001

工具/软件:Code Composer Studio

您好!

我一直在研究 DriverLib 示例、并尝试开发 i2c 驱动器、以读取/写入 opt3001 ALS。  我对了解中断和 ISR 比较陌生、认为我在调试代码时遇到了一些问题、在 i2c_write 结束时、器件进入 LPM0+GIE、大概通过 ISR、但我无法单步执行或退出 LPM 和相应的 ISR。

由于我不熟悉中断、我的 ISR 代码很可能不正确、但由于我无法单步执行、我有一个硬时间引脚指出发生了什么错误。  第113行是我第一次遇到问题的地方,但我希望155也会有同样的问题。

有什么问题吗?

"MSP430:不能单步执行目标程序:CPU 当前处于关闭状态、调试功能将受到限制。"

/*
i2c_driver.c
*
*创建日期:2014年7月16日
* 作者:a0272990
*
*版权所有2014 Texas Instruments Incorporated。 保留所有权利。
*
*/

//**********************
//#includes
//*********
#include "driverlib.h"
#include "i2c_driver.h"
#include "QmathLib.h"
#include "IQmathLib.h"
#include "math.h"



//*********
//#defines
//*********

#define OPT3001_ADDRESS 0x44 // OPT3001的 I2C 地址

#define CHECK_POLARITY 0x80 //极性标志(MSB 的 MSB)

//*********
//全局变量
//*********

#define RXCOUNT 0x05
#define TXLENGTH 0x04

uint8_t i2c_transmitCounter = 0;//可用于存储 I2C
uint8_t i2c_transmitData[40]的发送状态的变量; //
uint8_t * p_i2c_transmitData; //发送数据的指针
uint8_t i2c_receivedCounter = 0; //可用于存储 I2C
uint8_t i2c_receivedBuffer[40]的接收状态的变量; //
uint8_t * p_i2c_receivedBuffer; //指向接收数据的指针

//无符号字符接收缓冲区[10]={0x01、0x01、0x01、0x01、0x01、0x01、 0x01、0x01、0x01、0x01、0x01};
//unsigned char * receiveBufferPointer;
//unsigned char receiveCount = 0;

uint16_t i2c_mode = 0; //用于存储 i2c 模式(TX 或 Rx)的变量
//*********
// I2C 库函数
//*********
void init_i2c (void)
{

//将 I2C 引脚分配给 USCI_B1
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN1 + GPIO_PIN2);

//初始化主控
USCI_B_I2C_initMasterParam param ={0};
param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
param.i2cClk = UCS_getSMCLK ();
param.datarate = USCI_B_I2C_SET_DATA_RATE_100KBPS;USCI_B1_initMaster_B
(USCI_B1) param);//

启用 I2C 模块以启动操作
USCI_B_I2C_ENABLE (USCI_B1_base);

//启用主器件接收中断
USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_receive_interrupt);

}

void i2c_write (uint8_t slave_address)
{&t


//初始化主设备
USCI_B_I2C_initMasterParam param ={0};
param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
param.i2cClk = UCS_getSMCLK ();
param.datarate = USCI_B_I2C_SET_DATA_RATE_400KBPS;
USCI_B_I2C_initMaster (USCI_B1_base、&param);

//指定从器件地址
USCI_B_I2C_setSlaveAddress (USCI_B1_BASE、SLAVE_ADDRESS
);

//设置发送模式
USCI_B_I2C_setMode (USCI_B1_BASE、
USCI_B_I2C_Transmit 模式
);

//启用 I2C 模块以启动操作
USCI_B_I2C_ENABLE (USCI_B1_BASE);


while (1)
{
//启用发送中断
USCI_B_I2C_clearInterrupt (USCI_B1_base、USCI_B_I2C_Transmit 中断);
USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_Transmit _interrupt);

//每次传输之间的延迟
_DELAY_CYCLES (50);//替换为计时器 ISR?

//加载 TX 字节计数器
I2C_transmitCounter = 1;

//启动开始并发送第一个字符
USCI_B_I2C_masterSendMultiByteStart (USCI_B1_base、i2c_transmitData[0]);

//输入启用中断的 LPM0
_bis_SR_register (LPM0_bits + GIE);
__no_operation();

//延迟直到传输完成
while (USCI_B_I2C_isBusy (USCI_B1_base));
}
}

void i2c_read_Byte (uint8_t slave_address、uint8_t byte_count)
{

//初始化主设备
USCI_B_I2C_initMasterParam param ={0};
param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
param.i2cClk = UCS_getSMCLK ();
param.datarate = USCI_B_I2C_SET_DATA_RATE_100KBPS;
USCI_B_I2C_initMaster (USCI_B1_base、&param);

//指定从器件地址
USCI_B_I2C_setSlaveAddress (USCI_B1_BASE、SLAVE_ADDRESS);

//设置接收模式
USCI_B_I2C_setMode (USCI_B1_base、USCI_B_I2C_Receive_mode);

//启用 I2C 模块以启动操作
USCI_B_I2C_ENABLE (USCI_B1_BASE);

//启用主机接收中断
USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_receive_interrupt);

//等待总线空闲
while (USCI_B_I2C_isBusy (USCI_B1_base));

while (1)
{
P_i2c_receivedBuffer =(unsigned char *) i2c_receivedBuffer;
I2C_receivedCounter = i2c_receivedBuffer 的大小;

//初始化多接收
USCI_B_I2C_masterReceiveMultiByteStart (USCI_B1_BASE);

//进入启用中断的低功耗模式0。
_bis_SR_register (LPM0_bits + GIE);
__no_operation();
}
}


void OPT3001_init (void)
{

uint8_t OPT3001_Config_SW_RESET[3]=
{
0x01、//CDC 配置寄存器地址
0xC2、//MSB 配置(设置100ms 转换时间、单次触发模式)
0x10 //LSB 配置
};

P_i2c_transmitData =(uint8_t *) OPT3001_Config_sw_reset;//传输阵列起始地址
I2C_transmitCounter = OPT3001_Config_SW_RESET 的大小; //加载发送字节计数器
I2C_WRITE (OPT3001_ADDRESS);
__DELAY_CYCLES (DELAY_10_MS);
}

Int32_t OPT3001_SingleRead (void)
{

//uint8_t CDC_Config[2]={0};//测试变量
uint8_t Lux_Measur1_MSB[2]={0x00、0x00};//电容 MEAS1的 MSB
//uint32_t luxVal=0;

int32_t Lux_MEAS1 = 0;来自 MEAS1的//24位 Lux 值(32位变量)

uint8_t OPT3001_initMEAS1[3]=
{
0x01、//选择配置寄存器地址
0xC2、//MSB 配置(设置100ms 转换时间、单次触发模式)
0x10 //LSB 配置
};

const uint8_t OPT3001_ResultAddr[1]={0x00};//Lux_MEAS1_MSB 寄存器地址

P_i2c_transmitData =(uint8_t *) OPT3001_initMEAS1; //发送阵列起始地址
I2C_transmitCounter = OPT3001_initMEAS1的大小; //加载发送字节计数器
I2C_WRITE (OPT3001_ADDRESS);

_delay_cycles (delay_10_ms);

P_i2c_transmitData =(uint8_t *) OPT3001_ResultAddr;//传输阵列起始地址
I2C_transmitCounter = OPT3001_ResultAddr 的大小; //加载发送字节计数器
I2C_WRITE (OPT3001_ADDRESS);

P_i2c_receivedBuffer =(uint8_t *) Lux_Measur1_MSB; //接收阵列起始地址
I2C_READ_BYTE (OPT3001_ADDRESS、LUX_Meas1_MSB 的大小);//读取两个字节的 lux 数据形式结果寄存器

LUX_MEAS1 = 0x0FFF &(uint16_t) LUX_Measur1_MSB[0]<< 8 |(uint16_t) LUX_Measur1_MSB[1];
int8_t exp = lux_Meas1_MSB[0]>4;//指数是前四位
Lux_MEAS1 = 0.01 * pow (2、exp)* Lux_MEAS1;
返回 LUX_MEAS1;
}
//*********
//
////这是 USCI_B1中断矢量处理例程。
////
*********
#if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
#pragma vector=USCI_B1_vector
__interrupt
#elif defined (__GNU__)
__attribute__(INTERRUPT (USCI_B1_vector)))
#endif
void USCI_B1_ISR (void
)(void)
开关(_偶数_在范围内(UCB1IV、12)){
USCI_I2C_UCTXIFG 案例:
{
//检查 TX 字节计数器
IF (i2c_transmitCounter < i2c_transmitData 的大小)
{
//启动从主设备到从设备的字符发送
USCI_B_I2C_masterSendMultiByteNext (USCI_B1_BASE、
I2C_transmitData[i2c_transmitCounter]
);

//递增 TX 字节计数器
I2C_transmitCounter++;
}
其他
{
//仅启动停止
USCI_B_I2C_masterSendMultiByteStop (USCI_B1_BASE);

//清除主机中断状态
USCI_B_I2C_clearInterrupt (USCI_B1_base、
USCI_B_I2C_Transmit 中断);

//在中断返回时退出 LPM0
__BIC_SR_REGISTER_ON_EXIT (LPM0_Bits);
}
中断;
}

USCI_I2C_UCRXIFG 案例:
{
//递减 RX 字节计数器
I2C_receivedCounter--;

if (i2c_receivedCounter)
{
if (i2c_receivedCounter = 1)
{
//启动接收结束->接收字节与 NAK
*p_i2c_receivedBuffer++=
USCI_B_I2C_masterReceiveMultiByteFinish (
USCI_B1_BASE
);
}
其他
{
//每次接收一个字节
*p_i2c_receivedBuffer++= USCI_B_I2C_masterReceiveMultiByteNext (
USCI_B1_BASE
);
}
}
其他
{
//接收最后一个字节
*p_i2c_receivedBuffer = USCI_B_I2C_masterReceiveMultiByteNext (
USCI_B1_BASE
);
__BIC_SR_REGISTER_ON_EXIT (LPM0_Bits);
}

中断;
}
}



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Dan、您好!

    您能否在第250行和284行设置断点、代码是否在这两个位置中的任何一个处中断? (确保为正确调试设置编译器优化= none)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的优化级别=关闭,speedvsize =,内联硬件乘法= F5。

    对于您建议的断点、它甚至不会进入 ISR。 它在进入 LMP0+GIE 后锁定
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Dan、您好!

    您的问题可能与以下主题有关。 问题在于 CCS 中的 MSPDEBUG 堆栈最近更改了单步执行时涉及中断的行为。 这种行为将在不久的将来的某个时候纠正。 同时、您能否尝试以下链接中报告的修复程序、以查看它是否可以解决您的问题?

    e2e.ti.com/.../2667628
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Jace、这可能是其中的一部分、但我仍然无法进入 ISR。

    虽然(USCI_B_I2C_isBusBusy (USCI_B1_BASE))始终返回 USCI_B_I2C_BUS_BUS_BUSY、因为该函数从未进入 ISR 以调用 USCI_B_I2C_masterSendMultiByteStop (USCI_B1_BASE)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Dan、

    因此、我不确定使用 DriverLib 正确设置内容、但您是否确保启用 I2C 特定中断以及常规中断? (GEI 位是系统寄存器)在调试时、您可以对这些寄存器中的每个寄存器进行双次检查、并且您将到达代码中等待中断的位置。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在 main ()期间调用_bis_sr_register (GIE)、如上面第113行所示。 它已启用
    我还检查了 UCB1IE @ UCTXIE、它也是1 (我现在在 i2c TX 期间卡住、因此我无法检查 UCB1IE @ UCRXIE 是否正确启用)。

    中断标志 UCB1IFG @ UCTXIFG 未被使能、而是 NAK 标志被置位。 我确定每个数据表中的7位从器件地址为0x44
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    假设您的第一次调用是 OPT3001_init(),则程序将重复发送(40-1)个字节:
    > IF (i2c_transmitCounter < i2c_transmitData 的大小)

    0:
    > USCI_B_I2C_masterSendMultiByteNext (USCI_B1_BASE、
    > I2C_transmitData[i2c_transmitCounter]

    永久:
    > while (1)

    opt3001数据表将发送超过(1+2)个有效载荷字节时发生的情况静音。 一个合理的响应是 NAK。 如果它这么做、您将看不到更多的 TXIFG、程序将停止。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我犯了一个错误,因为我最初要传递的初始化数据只有3个字节,但它们在 opt3001_int()中本地声明; 我更新了第110行上的代码,以实际使用 p_i2c_transmitData,而不是直接传递配置字节。

    USCI_B_I2C_masterSendMultiByteStart (USCI_B1_BASE,* p_i2c_transmitData); 

    我还初始化了 receivata 和 transmitBuffer @[5]而不是[40];

    我看到在我执行 i2c_write()之前首先启用 UCTXIFG;在这里禁用 UCNACKIFG,然后在 USCI_B_I2C_masterSendMultiByteStart()期间启用 UCNACKIFG;

    Bruce、

    我是否误解了 ISR 会中断;应该让我离开 while (1);在 i2c_write()中;? 具有 ISR 的此函数直接从 DriverLib 中提取(我确实在 DriverLib 中添加了 I2C TX 和 RX 的 case 语句)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    1) 1)您尝试同时使用 i2c_transmitCounter 作为计数/限制和索引、这是相互矛盾的。 定义一个单独的索引变量(或按照您在 Rx 路径中的方式增加指针)。
    2) i2c_transmitCounter 具有传输计数(至少在初始时)。 您不应与 sizeof 进行比较、因为它没有相关性。
    3) 3)"中断"为局部中断。 一个函数中的中断本身不会导致另一个函数中的循环中断。 LPM 唤醒后、从 LPM 语句继续执行。 鉴于此程序的结构、我建议您完全删除 while (1)循环。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    1. 好的、我看到了您的意思。  我将 ISR 更改为仅检查 i2c_transmit count!= 0

    2、除了数字1、我改变了概念、将数据大小调整为 TX 或 RX 递减计数器、直到没有剩余字节。

    3. 同样有意义的是,我删除了它。  这是更新后的代码。   

    /*
    i2c_driver.c
    *
    *创建日期:2014年7月16日
    * 作者:a0272990
    *
    *版权所有2014 Texas Instruments Incorporated。 保留所有权利。
    *
    */
    
    //**********************
    //#includes
    //*********
    #include "driverlib.h"
    #include "i2c_driver.h"
    #include "QmathLib.h"
    #include "IQmathLib.h"
    #include "math.h"
    
    
    
    //*********
    //#defines
    //*********
    
    #define OPT3001_ADDRESS 0x44 // OPT3001的 I2C 地址
    
    #define CHECK_POLARITY 0x80 //极性标志(MSB 的 MSB)
    
    //*********
    //全局变量
    //*********
    
    #define RXCOUNT 0x05
    #define TXLENGTH 0x04
    
    uint8_t i2c_transmitCounter = 0;//可用于存储 I2C
    uint8_t i2c_transmitData[5]的发送状态的变量; //
    uint8_t * p_i2c_transmitData; //发送数据的指针
    uint8_t i2c_receivedCounter = 0; //可用于存储 I2C
    uint8_t i2c_receivedBuffer[40]的接收状态的变量; //
    uint8_t * p_i2c_receivedBuffer; //指向接收数据的指针
    
    //无符号字符接收缓冲区[10]={0x01、0x01、0x01、0x01、0x01、0x01、 0x01、0x01、0x01、0x01、0x01};
    //unsigned char * receiveBufferPointer;
    //unsigned char receiveCount = 0;
    
    uint16_t i2c_mode = 0; //用于存储 i2c 模式(TX 或 Rx)的变量
    //*********
    // I2C 库函数
    //*********
    void init_i2c (void)
    {
    
    //将 I2C 引脚分配给 USCI_B1
    GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN1 + GPIO_PIN2);
    
    //初始化主控
    USCI_B_I2C_initMasterParam param ={0};
    param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    param.i2cClk = UCS_getSMCLK ();
    param.datarate = USCI_B_I2C_SET_DATA_RATE_100KBPS;USCI_B1_initMaster_B
    (USCI_B1) param);//
    
    启用 I2C 模块以启动操作
    USCI_B_I2C_ENABLE (USCI_B1_base);
    
    //启用主器件接收中断
    USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_receive_interrupt);
    
    }
    
    void i2c_write (uint8_t slave_address)
    {&t
    
    
    //初始化主设备
    USCI_B_I2C_initMasterParam param ={0};
    param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    param.i2cClk = UCS_getSMCLK ();
    param.datarate = USCI_B_I2C_SET_DATA_RATE_400KBPS;
    USCI_B_I2C_initMaster (USCI_B1_base、&param);
    
    uint8_t SL_ADDR_WR =((slave_address<1));//将地址向左移位。 写入位使能= 0
    
    //指定从器件地址
    USCI_B_I2C_setSlaveAddress (USCI_B1_BASE、SL_ADDR_WR
    );
    
    //设置发送模式
    USCI_B_I2C_setMode (USCI_B1_BASE、
    USCI_B_I2C_Transmit 模式
    );
    
    //启用 I2C 模块以启动操作
    USCI_B_I2C_ENABLE (USCI_B1_BASE);
    
    //启用发送中断
    USCI_B_I2C_clearInterrupt (USCI_B1_base、USCI_B_I2C_Transmit _interrupt + USCI_B_I2C_NAK_INTERRUPT);
    USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_Transmit _interrupt);
    
    //每次传输之间的延迟
    _DELAY_CYCLES (50);//替换为计时器 ISR?
    
    
    //启动开始并发送第一个字符
    USCI_B_I2C_masterSendMultiByteStart (USCI_B1_base、* p_i2c_transmitData++);//p_i2c_data 是数据包的第一个地址。 在 opt3001_init()中指定;
    
    I2C_transmitCounter --;
    
    //启用中断
    _ bis_SR_register (GIE);//LPM0_bits + GIE
    _ no_operation ();
    
    
    //延迟直到传输完成
    while (USCI_B_I2C_isBusBusy (USCI_B1_base));
    
    }
    
    void i2c_read_Byte (uint8_t slave_address、uint8_t byte_count)
    {
    
    //初始化主设备
    USCI_B_I2C_initMasterParam param ={0};
    param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    param.i2cClk = UCS_getSMCLK ();
    param.datarate = USCI_B_I2C_SET_DATA_RATE_100KBPS;
    USCI_B_I2C_initMaster (USCI_B1_base、&param);
    
    //指定从器件地址
    uint8_t SL_ADDR_R =((slave_address<<1)| 0x01);//左移位地址&添加读取位
    USCI_B_I2C_setSlaveAddress (USCI_B1_BASE、SLAVE_ADDRESS);
    
    //设置接收模式
    USCI_B_I2C_setMode (USCI_B1_base、USCI_B_I2C_Receive_mode);
    
    //启用 I2C 模块以启动操作
    USCI_B_I2C_ENABLE (USCI_B1_BASE);
    
    //启用主机接收中断
    USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_receive_interrupt);
    
    //等待总线空闲
    while (USCI_B_I2C_isBusy (USCI_B1_base));
    
    while (1)
    {
    P_i2c_receivedBuffer =(unsigned char *) i2c_receivedBuffer;
    I2C_receivedCounter = i2c_receivedBuffer 的大小;
    
    //初始化多接收
    USCI_B_I2C_masterReceiveMultiByteStart (USCI_B1_BASE);
    
    //进入启用中断的低功耗模式0。
    //_bis_SR_register (GIE);//LPM0_bits + GIE
    __no_operation();
    }
    }
    
    
    void OPT3001_init (void)
    {
    
    uint8_t OPT3001_Config_SW_RESET[3]=
    {
    0x01、//CDC 配置寄存器地址
    0xC2、//MSB 配置(设置100ms 转换时间、单次触发模式)
    0x10 //LSB 配置
    };
    
    P_i2c_transmitData =(uint8_t *) OPT3001_Config_sw_reset;//传输阵列起始地址
    I2C_transmitCounter = OPT3001_Config_SW_RESET 的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    __DELAY_CYCLES (DELAY_10_MS);
    }
    
    Int32_t OPT3001_SingleRead (void)
    {
    
    //uint8_t CDC_Config[2]={0};//测试变量
    uint8_t Lux_Measur1_MSB[2]={0x00、0x00};//电容 MEAS1的 MSB
    //uint32_t luxVal=0;
    
    int32_t Lux_MEAS1 = 0;来自 MEAS1的//24位 Lux 值(32位变量)
    
    uint8_t OPT3001_initMEAS1[3]=
    {
    0x01、//选择配置寄存器地址
    0xc4、//MSB 配置(设置100ms 转换时间、连续转换
    0x10 //LSB 配置
    };
    
    const uint8_t OPT3001_ResultAddr[1]={0x00};//Lux_MEAS1_MSB 寄存器地址
    
    P_i2c_transmitData =(uint8_t *) OPT3001_initMEAS1; //发送阵列起始地址
    I2C_transmitCounter = OPT3001_initMEAS1的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    
    _delay_cycles (delay_10_ms);
    
    P_i2c_transmitData =(uint8_t *) OPT3001_ResultAddr;//传输阵列起始地址
    I2C_transmitCounter = OPT3001_ResultAddr 的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    
    P_i2c_receivedBuffer =(uint8_t *) Lux_Measur1_MSB; //接收阵列起始地址
    I2C_READ_BYTE (OPT3001_ADDRESS、LUX_Meas1_MSB 的大小);//读取两个字节的 lux 数据形式结果寄存器
    
    LUX_MEAS1 = 0x0FFF &(uint16_t) LUX_Measur1_MSB[0]<< 8 |(uint16_t) LUX_Measur1_MSB[1];
    int8_t exp = lux_Meas1_MSB[0]>4;//指数是前四位
    Lux_MEAS1 = 0.01 * pow (2、exp)* Lux_MEAS1;
    返回 LUX_MEAS1;
    }
    //*********
    //
    ////这是 USCI_B1中断矢量处理例程。
    ////
    *********
    #if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
    #pragma vector=USCI_B1_vector
    __interrupt
    #elif defined (__GNU__)
    __attribute__(INTERRUPT (USCI_B1_vector)))
    #endif
    void USCI_B1_ISR (void
    )(void)
    开关(_偶数_在范围内(UCB1IV、12)){
    USCI_I2C_UCTXIFG 案例:
    {
    //检查 TX 字节计数器
    IF (i2c_transmitCounter)
    {
    //启动从主设备到从设备的字符发送
    USCI_B_I2C_masterSendMultiByteNext (USCI_B1_BASE、
    *p_i2c_transmitData++
    );
    
    //递增 TX 字节计数器
    I2C_transmitCounter--;
    }
    其他
    {
    //仅启动停止
    USCI_B_I2C_masterSendMultiByteStop (USCI_B1_BASE);
    
    //清除主机中断状态
    USCI_B_I2C_clearInterrupt (USCI_B1_base、
    USCI_B_I2C_Transmit 中断);
    
    //在中断返回时退出 LPM0
    //_BIC_SR_REGISTER_ON_EXIT (LPM0_Bits);不在低功耗模式
    中}
    中断;
    }
    
    USCI_I2C_UCRXIFG 案例:
    {
    //递减 RX 字节计数器
    I2C_receivedCounter--;
    
    if (i2c_receivedCounter)
    {
    if (i2c_receivedCounter = 1)
    {
    //启动接收结束->接收字节与 NAK
    *p_i2c_receivedBuffer++=
    USCI_B_I2C_masterReceiveMultiByteFinish (
    USCI_B1_BASE
    );
    }
    其他
    {
    //每次接收一个字节
    *p_i2c_receivedBuffer++= USCI_B_I2C_masterReceiveMultiByteNext (
    USCI_B1_BASE
    );
    }
    }
    其他
    {
    //接收最后一个字节
    *p_i2c_receivedBuffer = USCI_B_I2C_masterReceiveMultiByteNext (
    USCI_B1_BASE
    );
    //_BIC_SR_REGISTER_ON_EXIT (LPM0_Bits);不在低功耗模式
    中}
    
    中断;
    }
    }
    
    
    
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    >uint8_t SL_ADDR_WR =((slave_address<1));//向左移位地址。 写入位使能= 0
    您不应该这样做。 setSlaveAddress 需要一个7位地址(UCB1I2CSA)、0x44看起来可以。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你是对的。  我进行了测试、以查看这是否是一个问题。  不是。

    我观察到的几件事:

    在调试启动时 UCTXIFG 为1。  它在中断清除期间被禁用(看起来正常)。  

    2.当我单步执行 I2C_materSendMultiByteStart()时; UCTXIFG 最终在" while (!(HWREG8 (baseAddress + OFS_UCBxIFG)& UCTXIFG)"阶段被重新启用;(在 USCI_B_i2c.c 中、下面的第15行)

    下一步是 HWREG8 (baseAddress + OFS_UCBxTXBUF)= txData;(同样、在 USCI_B_i2c.c 中)并且 UCTXIFG 再次被禁用。  这个分配正在将 TX 数据的第一个字节载入 TXBUF。  寄存器 UCB1TXBUF 显示来自 transmitData 的第一个字节的正确值(下面的第18行)

    下面是数据捕获。  我实际上在寄存器中获得了一个 NACK 标志、但它不会显示在数据采集中。  也许我需要一个新主题、但我仍然不明白为什么当有数据被载入 UCB1TXBUF 时 UCTXIFG 不被启用



    void USCI_B_I2C_masterSendMultiByteStart (uint16_t baseAddress、 uint8_t txData ) { //存储当前发送中断使能 uint8_t txieStatus = HWREG8 (baseAddress + OFS_UCBxIE)& UCTXIE; //禁用发送中断使能 HWREG8 (baseAddress + OFS_UCBxIE)&=~(UCTXIE); //发送启动条件。 HWREG8 (baseAddress + OFS_UCBxCTL1)|= UCTR + UCTXSTT; //轮询发送中断标志。 while (!(HWREG8 (baseAddress + OFS_UCBxIFG)& UCTXIFG)); //发送单字节数据。 HWREG8 (baseAddress + OFS_UCBxTXBUF)= txData; //恢复发送中断使能 HWREG8 (baseAddress + OFS_UCBxIE)|= txieStatus; }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果要调试单步执行事务、请记住、OPT3001会强制执行28ms 超时(SCL 为低电平)。 I2C 单元在等待 Tx 字节加载到 TXBUF 时保持(延伸) SCL 为低电平、TXBUF 大概是分析仪跟踪结束时的状态。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我认为调试步进可能是主要问题之一。  根据设置断点的位置、TXIFG 可能无法正确触发。 我通过让代码在没有断点的情况下运行来发现这一点、并在 i2c 分析器中查看所有预期数据。

    我现在似乎可以正常工作、但我确实发现 TIDA 00754中存在一些错误、其中 MSB 未正确分配到正确的变量中。  在任何情况下、这里都是最终代码。  我必须将 RXCOUNT 调整为固定的2个字节、以避免卡在 RX 环路中。

    我想让它进入连续模式、而不是单次触发模式、但这是另一天的问题。

    /*
    i2c_driver.c
    *
    *创建日期:2014年7月16日
    * 作者:a0272990
    *
    *版权所有2014 Texas Instruments Incorporated。 保留所有权利。
    *
    */
    
    //**********************
    //#includes
    //*********
    #include "driverlib.h"
    #include "i2c_driver.h"
    #include "QmathLib.h"
    #include "IQmathLib.h"
    #include "math.h"
    
    
    
    //*********
    //#defines
    //*********
    
    #define OPT3001_ADDRESS 0x44 // OPT3001的 I2C 地址
    
    #define CHECK_POLARITY 0x80 //极性标志(MSB 的 MSB)
    
    //*********
    //全局变量
    //*********
    
    #define RXCOUNT 0x02 // opt3001寄存器读取
    的预期长度#define TXLENGTH 0x04
    
    uint8_t i2c_transmitCounter = 0;//可用于存储 I2C
    uint8_t i2c_transmitData[5]的发送状态的变量; //
    uint8_t * p_i2c_transmitData; //发送数据的指针
    uint8_t i2c_receivedCounter = 0; //可用于存储 I2C
    uint8_t i2c_receivedBuffer[2]的接收状态的变量; //仅适用于 opt3001
    uint8_t *p_i2c_receivedBuffer; //指向接收数据的指针
    
    //无符号字符接收缓冲区[10]={0x01、0x01、0x01、0x01、0x01、0x01、 0x01、0x01、0x01、0x01、0x01};
    //unsigned char * receiveBufferPointer;
    //unsigned char receiveCount = 0;
    
    uint16_t i2c_mode = 0; //用于存储 i2c 模式(TX 或 Rx)的变量
    //*********
    // I2C 库函数
    //*********
    void init_i2c (void)
    {
    
    //将 I2C 引脚分配给 USCI_B1
    GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P4、GPIO_PIN1 + GPIO_PIN2);
    
    //初始化主控
    USCI_B_I2C_initMasterParam param ={0};
    param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    param.i2cClk = UCS_getSMCLK ();
    param.datarate = USCI_B_I2C_SET_DATA_RATE_100KBPS;USCI_B1_initMaster_B
    (USCI_B1) param);//
    
    启用 I2C 模块以启动操作
    USCI_B_I2C_ENABLE (USCI_B1_base);
    
    //启用主器件接收中断
    USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_receive_interrupt);
    
    }
    
    void i2c_write (uint8_t slave_address)
    {&t
    
    
    //初始化主设备
    USCI_B_I2C_initMasterParam param ={0};
    param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    param.i2cClk = UCS_getSMCLK ();
    param.datarate = USCI_B_I2C_SET_DATA_RATE_400KBPS;
    USCI_B_I2C_initMaster (USCI_B1_base、&param);
    
    //uint8_t SL_ADDR_WR =((slave_address<<1));//向左移位地址。 写入位使能= 0
    
    //指定从器件地址
    USCI_B_I2C_setSlaveAddress (USCI_B1_BASE、SLAVE_ADDRESS
    );
    
    //设置发送模式
    USCI_B_I2C_setMode (USCI_B1_BASE、
    USCI_B_I2C_Transmit 模式
    );
    
    //启用 I2C 模块以启动操作
    USCI_B_I2C_ENABLE (USCI_B1_BASE);
    
    //启用发送中断
    USCI_B_I2C_clearInterrupt (USCI_B1_base、USCI_B_I2C_Transmit _interrupt + USCI_B_I2C_NAK_INTERRUPT);
    USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_Transmit _interrupt);
    
    //每次传输之间的延迟
    _DELAY_CYCLES (50);//替换为计时器 ISR?
    
    
    //启动开始并发送第一个字符
    USCI_B_I2C_masterSendMultiByteStart (USCI_B1_base、* p_i2c_transmitData++);//p_i2c_data 是数据包的第一个地址。 在 opt3001_init()中指定;
    
    I2C_transmitCounter --;
    
    //启用中断
    _ bis_SR_register (GIE);//LPM0_bits + GIE
    _ no_operation ();
    
    
    //延迟直到传输完成
    while (USCI_B_I2C_isBusBusy (USCI_B1_base));
    
    }
    
    void i2c_read_Byte (uint8_t slave_address、uint8_t byte_count)
    {
    
    //初始化主设备
    USCI_B_I2C_initMasterParam param ={0};
    param.selectClockSource = USCI_B_I2C_CLOCKSOURCE_SMCLK;
    param.i2cClk = UCS_getSMCLK ();
    param.datarate = USCI_B_I2C_SET_DATA_RATE_100KBPS;
    USCI_B_I2C_initMaster (USCI_B1_base、&param);
    
    //指定从器件地址。 使用7BIT 从器件 ADDR
    USCI_B_I2C_setSlaveAddress (USCI_B1_BASE、SLAVE_ADDRESS);
    
    //设置接收模式
    USCI_B_I2C_setMode (USCI_B1_base、USCI_B_I2C_Receive_mode);
    
    //启用 I2C 模块以启动操作
    USCI_B_I2C_ENABLE (USCI_B1_BASE);
    
    //启用主机接收中断
    USCI_B_I2C_enableInterrupt (USCI_B1_base、USCI_B_I2C_receive_interrupt);
    
    //等待总线空闲
    while (USCI_B_I2C_isBusy (USCI_B1_base));
    
    P_i2c_receivedBuffer =(unsigned char *) i2c_receivedBuffer;
    I2C_receivedCounter = RXCOUNT;
    
    //初始化多接收
    USCI_B_I2C_masterReceiveMultiByteStart (USCI_B1_BASE);
    
    //进入启用中断的低功耗模式0。
    _bis_SR_register (GIE);//LPM0_bits + GIE
    __no_operation();
    
    }
    
    
    void OPT3001_init (void)
    {
    
    uint8_t OPT3001_Config_SW_RESET[3]=
    {
    0x01、//CDC 配置寄存器地址
    0xC2、//MSB 配置(设置100ms 转换时间、单次触发模式)
    0x10 //LSB 配置
    };
    
    P_i2c_transmitData =(uint8_t *) OPT3001_Config_sw_reset;//传输阵列起始地址
    I2C_transmitCounter = OPT3001_Config_SW_RESET 的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    __DELAY_CYCLES (DELAY_10_MS);
    }
    
    Int32_t OPT3001_SingleRead (void)
    {
    
    //uint8_t CDC_Config[2]={0};//测试变量
    uint8_t Lux_Measur1_MSB[2]={0x00、0x00};//电容 MEAS1的 MSB
    //uint32_t luxVal=0;
    
    int32_t Lux_MEAS1 = 0;来自 MEAS1的//24位 Lux 值(32位变量)
    
    uint8_t OPT3001_initMEAS1[3]=
    {
    0x01、//选择配置寄存器地址
    0xC2、//MSB 配置(设置100ms 转换时间、连续转换
    0x10 //LSB 配置
    };
    
    const uint8_t OPT3001_ResultAddr[1]={0x00};//Lux_MEAS1_MSB 寄存器地址
    
    P_i2c_transmitData =(uint8_t *) OPT3001_initMEAS1; //发送阵列起始地址
    I2C_transmitCounter = OPT3001_initMEAS1的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    
    _delay_cycles (delay_10_ms);
    
    P_i2c_transmitData =(uint8_t *) OPT3001_ResultAddr;//传输阵列起始地址
    I2C_transmitCounter = OPT3001_ResultAddr 的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    
    P_i2c_receivedBuffer =(uint8_t *) Lux_Measur1_MSB; //接收阵列起始地址
    I2C_READ_BYTE (OPT3001_ADDRESS、LUX_Meas1_MSB 的大小);//读取两个字节的 lux 数据形式结果寄存器
    LUX_Meas1_MSB[0]= i2c_receivedBuffer[0];
    LUX_Meas1_MSB[1]= i2c_receivedBuffer[1];
    
    LUX_MEAS1 = 0x0FFF &(uint16_t) LUX_Measur1_MSB[0]<< 8 |(uint16_t) LUX_Measur1_MSB[1];
    int8_t exp = lux_Meas1_MSB[0]>4;//指数是前四位
    Lux_MEAS1 = 0.01 * pow (2、exp)* Lux_MEAS1;
    返回 LUX_MEAS1;
    }
    
    int32_t OPT3001_ID (uint8_t opt_ID_TYPE)
    {
    
    uint8_t readid_msb[2]={0x00、0x00};
    
    ///此时已由 opt3001_int()配置;
    uint8_t OPT3001_initMEAS1[3]=
    {
    0x01、//选择配置寄存器地址
    0xC2、//MSB 配置(设置100ms 转换时间、连续转换
    0x10 //LSB 配置
    };
    
    P_i2c_transmitData =(uint8_t *) OPT3001_initMEAS1; //发送阵列起始地址
    I2C_transmitCounter = OPT3001_initMEAS1的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    
    _delay_cycles (delay_10_ms);
    
    P_i2c_transmitData =(uint8_t *) opt_ID_type;//传输阵列起始地址
    I2C_transmitCounter = opt_ID_type 的大小; //加载发送字节计数器
    I2C_WRITE (OPT3001_ADDRESS);
    
    P_i2c_receivedBuffer =(uint8_t *) readid_msb; //接收阵列起始地址
    I2C_READ_BYTE (OPT3001_ADDRESS、sizeof readid_msb);//读取两个字节的 lux 数据形式结果寄存器
    uint32_t readid = 0x0FFF &(uint16_t) readid_msb[0]<< 8 |(uint16_t) readid_msb[1];
    退货读数;
    
    }
    //*********
    //
    ////这是 USCI_B1中断矢量处理例程。
    ////
    *********
    #if defined (__TI_Compiler_version__)|| defined (__IAR_systems_icc_)
    #pragma vector=USCI_B1_vector
    __interrupt
    #elif defined (__GNU__)
    __attribute__(INTERRUPT (USCI_B1_vector)))
    #endif
    void USCI_B1_ISR (void
    )(void)
    开关(_偶数_在范围内(UCB1IV、12)){
    USCI_I2C_UCTXIFG 案例:
    {
    //检查 TX 字节计数器
    IF (i2c_transmitCounter)
    {
    //启动从主设备到从设备的字符发送
    USCI_B_I2C_masterSendMultiByteNext (USCI_B1_BASE、
    *p_i2c_transmitData++
    );
    
    //递增 TX 字节计数器
    I2C_transmitCounter--;
    }
    其他
    {
    //仅启动停止
    USCI_B_I2C_masterSendMultiByteStop (USCI_B1_BASE);
    
    //清除主机中断状态
    USCI_B_I2C_clearInterrupt (USCI_B1_base、
    USCI_B_I2C_Transmit 中断);
    
    //在中断返回时退出 LPM0
    //_BIC_SR_REGISTER_ON_EXIT (LPM0_Bits);不在低功耗模式
    中}
    中断;
    }
    
    USCI_I2C_UCRXIFG 案例:
    {
    //递减 RX 字节计数器
    I2C_receivedCounter--;
    
    if (i2c_receivedCounter)
    {
    if (i2c_receivedCounter = 1)
    {
    //启动接收结束->接收字节与 NAK
    *p_i2c_receivedBuffer++= USCI_B_I2C_masterReceiveMultiByteFinish( USCI_B1_base );
    }
    其他
    {
    //每次接收一个字节
    *p_i2c_receivedBuffer++= USCI_B_I2C_masterReceiveMultiByteNext (USCI_B1_base);
    }
    }
    其他
    {
    //接收最后一个字节
    *p_i2c_receivedBuffer = USCI_B_I2C_masterReceiveMultiByteNext (USCI_B1_base);
    __BIC_SR_REGISTER_ON_EXIT (LPM0_BITS);//不在低功耗模式
    中}
    
    中断;
    }
    }