大家好、
当我尝试从 MPU-9250从器件接收2个或更多字节时、我正在尝试弄清楚为什么我的代码不起作用。 接收一个字节正常工作、Tx 功能也正常工作。
如果我注释掉:
if (i2c.length = 1) { UCB0CTL1 |= UCTXSTP; }
在 ISR 的主器件接收部分、并在读取最后一个字节后置1 UCTXSTP、它就会工作。 根据用户指南、UCTXSTP 应在接收字节时置1。
示例代码也以与我所做的类似的方式执行此操作。 有什么想法吗?
/*
MSP430_i2c.c
*
*创建日期:2019年11月1日
* 作者:Wayne
*
说明:用于 msp430g2553的 I2C 驱动器、使用中断。
*/
#include
#defineSCL_PINBIT6
#defineSDA_PINBIT7
typedef 枚举{
State_Waiting、
状态读取、
State_writing
}MSP430_i2c_state;
typedef 结构{
易失性 MSP430_i2c_state;
unsigned char slave_reg;//第一个从器件寄存器。
unsigned char slave_reg_written;// 0如果从器件寄存器尚未写入。 *
unsigned char *数据;
无符号短长度;
启用无符号字符;
}MSP430_i2c_info;
静态 MSP430_i2c_info i2c ={
.enabled = 0
};
void i2c_enable ()
{
/*初始化 USCI I2C 模块*/
BCSCTL3 |= LFXT1S_2;// VLOCLK (~12KHz)馈送 ACLK (选择 ACLK 源为内部 VLO)
UCB0CTL1 |= UCSWRST | UCSSEL_1;//将 USCI_B 保持在复位状态以进行初始化(设置 UCSWRST)&选择 ACLK
UCB0CTL0 = UCMST | UCMODE_3 | UCSYNC; // I2C 主模式| I2C 模式
UCB0BR0 = 8;//设置 i2c 频率
UCB0BR1 = 0;
P1SEL |= SDA_PIN | SCL_PIN; //配置端口
P1SEL2 |= SDA_PIN | SCL_PIN;
UCB0CTL1 &=~UCSWRST; //释放 USCI_B 以运行(清除 UCSWRST)
IE2 |= UCB0TXIE | UCB0RXIE;//通过 UCxRXIE 和/或 UCxTXIE 启用中断(可选)
int i2c_write (unsigned char SLV_addr、unsigned char reg_addr、unsigned char 长度、unsigned const char 数据
)*
/*填充结构。 *
I2C.state = State_writing;
i2c.slave_reg = reg_addr;
I2c.slave_reg_written = 0;
I2C.data =(unsigned char*) data;
I2c.length =长度;
UCB0I2CSA = SLV_addr; //将从器件地址写入 UCB0I2CSA 寄存器
UCB0CTL0 &=~UCSLA10; // 7位从器件寻址模式
UCB0CTL1 |= UCTR + UCTXSTT; //将 UCTR 设置为 TX 模式+将 UCTXSTT 设置为生成启动条件
while (i2c.state!= State_Waiting)
{//输入带中断的 LPM0 */
_bis_SR_register (CPUOFF + GIE);
I2C.state = State_Waiting;
}
返回0;//此返回无意义。 需要返回一些错误或其他
内容}
int i2c_read (unsigned char slv_addr、unsigned char reg_addr、unsigned char length、unsigned char * data)
{
//填充结构。 */
i2c.state = State_reading;
i2c.slave_reg = reg_addr;
i2c.slave_reg_written = 0;
i2c.data = data;
i2c.length = length;
UCB0I2CSA = SLV_addr;//将从器件地址写入 UCB0I2CSA 寄存器
UCB0CTL0 &=~UCSLA10;// 7位从器件寻址模式
while (UCB0CTL1 & UCTXSTP); //确保停止条件已发送
UCB0CTL1 |= UCTR | UCTXSTT; // I2C 启动条件
while (i2c.state!= State_Waiting)
{//输入 LPM0 w/中断*/
_bis_SR_register (CPUOFF + GIE);
i2c.state = State_Waiting;
}
return 0;
}
#if defined (__TI_Compiler_version_)|| defined (__IAR_ICR_BIAS_COVERS
(void)#BIAS_BIAS_COMPLETE_COMPLETE_COMPLETOR (void)#BIAS_COMPLETE_COMPLETE_COMPLETE_COMPLETE_COMPLETE_COMPLETE_COMPLETE_TRIE_TRIE_INEST_BIST_NOW_#BIST_COMPLETE_COMPLETE_SIONENTS_BIST_INEST_VERS (nLETE)#BIST_COMPLE
#endif
{
if (IFG2 & UCB0RXIFG)//主机接收?
{
i2c.length--;
if (i2c.length)
{
* i2c.data++= UCB0RXBUF;
if (i2c.length = 1)
{
UCB0CTL1 |= UCTXSTP;
}
否则
{
* i2c.data = UCB0RXBUF;
//UCB0CTL1 |= UCB0TXIFG
;= UCB0TXIFG 和~UCB0TXIFG;//清除 TX 中断标志
__BIC_SR_REGISTER_ON_EXIT (CPUOFF); //退出 LPM0
}
否则(IFG2 & UCB0TXIFG)//主机发送?
{
switch (i2c.state)
{
case State_writing:
if (!i2c.slave_reg_writing)
{
i2c.slave_reg_write= 1;//
UCB0TXBUF = i2c.slave_reg;//发送从地址
}
否则(i2c.length)//要发送的数据?
{
char next =* i2c.data;//
i2c.data++;//递增字节
i2c.length-;//递减待发送的数据量
//写入 TXBUF 必须始终是最终操作。 //
UCB0TXBUF = NEXT;
}
否则//没有更多数据要发送?
{
UCB0CTL1 |= UCTXSTP;//生成停止条件。
IFG2 &=~UCB0TXIFG;//清除 Tx 中断标志
__BIC_SR_REGISTER_ON_EXIT (CPUOFF + GIE);
}
break;
case State_reading:
if (!i2c.slave_reg_written)
{
i2c.slave_reg_written = 1;
UCB0TXBUF = i2c.r_rev.rn
);重复启动 RX 模式。 //
UCB0CTL1 &=~UCTR;
UCB0CTL1 |= UCTXSTT;
//如果是单字节,请立即准备 STOP 信号。 //
if (i2c.length ==1)
{
//井,不是立即。 首先、我们需要确保
*已发送启动信号。
//
while (UCB0CTL1 & UCTXSTT);
UCB0CTL1 |= UCTXSTP;
IFG2 &=~UCB0TXIFG;//清除 TX 中断标志
}
中断;
}
}}