Other Parts Discussed in Thread: CC2541
尊敬的读者:
目前、我正在从事一个同时需要 I2C 功能和 BLE 功能的项目。 CC2541支持这些功能、因此这很好。
情况
- 我能够 使用 I2C 协议写入 PCA9635 LEDdriver 模块的寄存器。
- 我能够使用 BLE 连接到器件、我有恒定的传入数据流(每350ms 一次)。
目标
- 能够实现稳定(连续)的 BLE 连接、并且能够不时(不太频繁)向 LEDdriver 写入数据。
问题
- 使用 I2C 写入寄存器时、器件停止广播其配置文件(在 lightBlue 应用中不再可见)。 因此、BLE 和 I2C 都可以单独工作、但将它们一起使用可以解决问题。
结果
- 将全局中断使能位设置为0会破坏 BLE 连接。 发现此问题后、解释相当简单、因为 BLE 需要中断才能工作。
- 在 BLE 软件开发人员指南中、我发现应用的处理时间(I2C)可能最多需要2ms。 (第7.6.2节:限制 BLE 活动期间的应用处理)。 我可以轻松测量事件的时间吗? 由于 BLE 的中断具有最高优先级(对吧?)、连接如何中断。 我希望 I2C 通信会中断、而不是 BLE 广播。
- 向 I2CDATA 寄存器写入0x00或0x01时、器件在 lightBlue 应用中仍然可见、因此 BLE 似乎仍然工作。 将0xAA 写入 I2cData (从而写入 LED 驱动器)时、器件会在 lightBlue 应用中消失。 考虑到这一点、假设这是一个时序问题:向 I2cData 这样的寄存器写入更多1是否需要更长时间?
所以我的问题是、这个问题的原因是什么、如何解决呢?
我用于写入 I2C 数据的 I2C 函数为:
typedef 枚举
{
// HAL_I2C_MASTER 模式时钟频率。
i2cClock_123KHZ = 0x00、
i2cClock_144KHZ = 0x01、
i2cClock_165KHZ = 0x02、
i2cClock_197KHZ = 0x03、
i2cClock_33KHZ = 0x80、
i2cClock_267KHZ = 0x81、
i2cClock_533KHZ = 0x82
} i2cClock_t;
空 HalI2CInit (i2cClock_t 时钟速率)
{
//设置上拉引脚。
I2CWC = 0x0C;// 0000 1100
//重置 I2C 配置
I2CCFG = 0x00;// 0000 0000
//设置 I2C 时钟速率
I2C_CLOCK_RATE (时钟速率);
//启用全局中断(IEN0.EA = 1)
IEN0 |= 0x80;// 1000 0000
//启用中断(P2IE = 1)
IEN2 |= 0x02;// 0000 0010
//启用 I2C (ENS1 = 1)
I2C_ENABLE();
}
空 HalI2CDisable (空)
{
//通过删除时钟信号来停止通信
I2C_STOP();
//禁用时钟信号
I2C_disable();
//禁用中断(P2IE = 0)
IEN2 &= 0xFD;// 1111 1101
//不要禁用全局中断,因为这会破坏 BLE 功能。
//禁用全局中断(IEN0.EA = 0)
// IEN0 &= 0x7F;// 0111 1111
}
void setLEDOUTPUT0 (uint8寄存器 LEDOUT0)
{
HalI2CInit (i2cClock_33KHZ);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//设置 LEDOUTPUT 0 - 3
//通过发送起始位来启动通信(STA = 1)
// 1:清除 SI 位(到0)(中断标志)
I2CCFG &= 0xF7;// 1111 0111
// 2:设置起始位(设为1)
I2CCFG |= 0x20;// 0010 0000
// 3:等待 SI 位被置位(设为1)(中断标志)
while (((I2CCFG & 0x08)= 0);// 0000 1000
// 4:未设置起始位(至0)
I2CCFG &= 0xDF;// 1101 1111
//发送设备地址并通知写入
if (I2CSTAT = 0x08)//如果一个 START 条件已经被发送(应该)
{
// 1:将器件地址和 R/W 加载到 I2C 数据寄存器中
I2cData =((0x00 << 1)| 0x00);// 0x00 =写入
// 2:清除 SI 位(到0)(中断标志)
I2CCFG &= 0xF7;// 1111 0111
// 3:等待 SI 位被置位(设为1)(中断标志)
while (((I2CCFG & 0x08)= 0);// 0000 1000
}
//将数据字节发送到设备
// 1:检查器件(从器件)是否已确认请求。
如果(I2CSTAT = 0x18)//如果器件地址和写入位已经发送,则接收到 ACK。
{
//发送字节
// 1:将 dataByte 加载到 I2C 数据寄存器中
I2cData = 0x14;//dataByte;
// 2:清除 SI 位(到0)(中断标志)
I2CCFG &= 0xF7;// 1111 0111
// 3:等待 SI 位被置位(设为1)(中断标志)
while (((I2CCFG & 0x08)= 0);// 0000 1000
}
//将数据字节发送到设备
// 1:检查器件(从器件)是否已确认请求。
如果(I2CSTAT = 0x28)//如果器件地址和写入位已经发送,则接收到 ACK。
{
//发送字节
// 1:将 dataByte 加载到 I2C 数据寄存器中
I2cData =寄存器 LEDOUT0;//0xAA;//dataByte;
// 2:清除 SI 位(到0)(中断标志)
I2CCFG &= 0xF7;// 1111 0111
// 3:等待 SI 位被置位(设为1)(中断标志)
while (((I2CCFG & 0x08)= 0);// 0000 1000
}
//通过设置停止位(STO = 1)停止通信
HalI2CDisable();
返回;
}