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.

[参考译文] I2C从头开始工作,用于按钮盒

Guru**** 2596205 points
Other Parts Discussed in Thread: MSP430G2553

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/632549/i2c-from-scratch-working-for-pushbutton-case

主题中讨论的其他部件:MSP430G2553

大家好,

我的项目是通过I2C创建4个MSP430G2553 MCU。 一个主控制器3个从属控制器,主控制器询问从属控制器,然后从属控制器响应。 I2C传输后,从属设备将完成其工作(GPIO设置,检查中断等) 主控制器还将检查GPIO的中断。
对于第一个步骤,我想创建一个带有2个启动板的简单代码。 如果按下了WFP 1.3 上的按钮,则Mater将开始向从属设备传输数据。 对于主代码,我使用了的组合  
msp430g2xxS 3_uscib0_i2c_12.c

msp430g2xxS 3_P1_02.c
进行了一些修改

对于从属设备,代码未更改 ,尽管我还想添加一个循环并执行一些操作(主要是GPIO,一个AD转换)
请您"帮我把脚放回地面上!" ? :-)谢谢。

#include <MSP4S.h>

#define NUM_Bytes_TX 3 //有多少字节?
#define NUM_Bytes_RX 2

Int RXByteCtr,RPT_Flag = 0;//在1时启用重复启动
volatile unsigned char RxBuffer[128];//分配128字节的RAM
unsigned char *PTxData;//指向TX数据的指针
unsigned char *PRxData;//指向RX数据的指针
unsigned char TXByteCtr,RX = 0;
unsigned char MSData = 0x55;

void Setup_TX (void);
void Setup_RX (void);
void transmit(void);
接收无效(无效);

无符号char标志=0;

内部主(无效)

WDTCTL = WDTPW + WDTHOLD;//停止WDT


/*mod start*/
P1DIR || BIT0;//将WFP 1.0 设置为输出方向
P1IE |= BIT3;//已启用WFP 1.3 中断
P1IES |= BIT3;// WFP 1.3 高/低边缘
P1REN |= BIT3;//启用SW2上的上拉(WFP 1.3)
P1OUT=0;
P1IFG &=~BIT3;//已清除WFP 1.3 IFG
P1SEL || BIT6 + BIT7;//将I2C引脚分配给USI_B0
P1SEL2|= BIT6 + BIT7;//将I2C引脚分配给USI_B0

/* mod end*/
__bis_sr_register (CPUOFF + GIE);

而(1){

开关(标志)

案例1:

//传输过程
Setup_TX();
RPT_Flag = 0;
RPT_Flag = 1;
Transmit();
while (UCB0CTL1和UCTXSTP);//确保已发送停止条件

//接收过程
Setup_Rx();
receive();
while (UCB0CTL1和UCTXSTP);//确保已发送停止条件
标志=0;
}
中断;
默认:

}
}
}
}


#pragma vector=Port1_vector
__interrupt void Port_1 (void)

P1OUT ^= BIT0;// WFP 1.0 =切换
P1IFG &=~BIT3;//已清除WFP 1.3 IFG
标志=1;
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);
}

//------------------
// USI_B0数据ISR用于移动从I2C从属设备接收的数据
//至MSP430内存。 它的结构可以用于接收
//通过预加载带字节计数的RXByteCtr,可获得任意2个以上的字节。
//------------------
#pragma vector = USCIAB0TX_vector
__interrupt void USCIAB0TX_ISR(void)

如果(RX == 1){//主接收?
RXByteCtr --;// Decrement RX字节计数器
IF (RXByteCtr)

*PRxData++= UCB0RXBUF;//将RX数据移动到PRxData地址
}
否则

IF (RPT_Flag == 0)
UCB0CTL1 || UCTXSTP;//不重复启动:停止条件
IF (RPT_Flag == 1){//如果重复开始:不执行任何操作
RPT_Flag = 0;
}
*PRxData = UCB0RXBUF;//将最终RX数据移至PRxData
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出LPM0
}}

Else{//主传输
IF (TXByteCtr)//检查TX字节计数器

UCB0TXBUF = MSData++;//加载TX缓冲区
TXByteCtr -;// Decrement TX字节计数器
}
否则

IF (RPT_Flag == 1){
RPT_Flag = 0;
PTxData =&MSData;// TX数组起始地址
TXByteCtr = NUM_Bytes_TX;//加载TX字节计数器
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);
}
否则{
UCB0CTL1 || UCTXSTP;// I2C停止条件
IFG2 &=~UCB0TXIFG;//清除USI_B0 TX int标志
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);//退出LPM0
}
}
}

}

void Setup_TX (void)
_DINT();
Rx = 0;
IE2 &=~UCB0RXIE;
while (UCB0CTL1和UCTXSTP);//确保已发送停止条件//禁用RX中断
UCB0CTL1 || UCSWRST;//启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSNC;// I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用SMCLK,保持SW重置
UCB0BR0 = 12;// fSCL = SMCLK/12 =~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x48;//从属地址为048h
UCB0CTL1 &=~UCSWRST;//清除软件重置,恢复操作
IE2 |= UCB0TXIE;//启用TX中断
}
void Setup_RX (void)
_DINT();
Rx = 1;
IE2 &=~UCB0TXIE;
UCB0CTL1 || UCSWRST;//启用软件重置
UCB0CTL0 = UCMST + UCMODE_3 + UCSNC;// I2C主控,同步模式
UCB0CTL1 = UCSSEL_2 + UCSWRST;//使用SMCLK,保持SW重置
UCB0BR0 = 12;// fSCL = SMCLK/12 =~100kHz
UCB0BR1 = 0;
UCB0I2CSA = 0x48;//从属地址为048h
UCB0CTL1 &=~UCSWRST;//清除软件重置,恢复操作
IE2 |= UCB0RXIE;//启用RX中断
}
void transmit (void){
PTxData =&MSData;// TX数组起始地址
TXByteCtr = NUM_Bytes_TX;//加载TX字节计数器
while (UCB0CTL1和UCTXSTP);//确保已发送停止条件
UCB0CTL1 || UCTR + UCTXSTT;// I2C TX,启动条件
__bis_sr_register(CPUOFF + GIE);//输入带中断的LPM0
}
作废接收(作废)
PRxData =(unsigned char *)RxBuffer;// RX缓冲区的开始
RXByteCtr = NUM_Bytes_RX-1;//加载RX字节计数器
while (UCB0CTL1和UCTXSTP);//确保已发送停止条件
UCB0CTL1 || UCTXSTT;// I2C启动条件
__bis_sr_register(CPUOFF + GIE);//输入带中断的LPM0
}

从属(未更改)  msp430g2xxS 3_uscib0_i2c_13.c

#include <MSP4S.h>


#define NUM_bytes 2 //有多少字节?
//****请注意,此值需要与中的NUM_Bytes_RX相同
//关联的主代码。 此定义让从属设备知道何时进行
//从RX中断源切换到TX中断源。 这是
//重要,因为中断向量由TX和RX标志共享。

unsigned char *PTxData;//指向TX数据的指针
unsigned char *PRxData;//指向RX数据的指针
volatile unsigned char RxBuffer[128];//分配128字节的RAM
CHAR SLV_Data = 0x11;
volatile unsigned char TXByteCtr,RXByteCtr,RX = 0;
volatile unsigned char RxBuffer[128];//分配128字节的RAM


void USI_slaver_Setup(void);
void Setup_RX (void);
接收无效(无效);

内部主(无效)

WDTCTL = WDTPW + WDTHOLD;//停止WDT

而(1){
USI_SLAVER_SETUP();
}
}

//------------------
// USI_B0数据ISR用于将MSP430内存中的数据移动到
// I2C主控。 TxData指向要传输的下一个字节和TXByteCtr
//跟踪传输的字节数。
//------------------
#pragma vector = USCIAB0TX_vector
__interrupt void USCIAB0TX_ISR(void)

IF (RX == 0){ UCB0TXBUF = SLV_DATA+;//在地址PTxData传输数据
TXByteCtr ++;//增量TX字节计数器
}
IF (RX == 1){*PRxData++= UCB0RXBUF;//将RX数据移动到地址PRxData
RXByteCtr ++;//增加RX字节计数


IF (RXByteCtr >= NUM_Bytes){//收到足够的字节以进行切换
Rx = 0;//至TX?
IE2 &=~UCB0RXIE;
IE2 |= UCB0TXIE;
RXByteCtr = 0;
}
}
}

//------------------
// USI_B0状态ISR用于从LPM0唤醒CPU,以便执行此操作
//传输数据后,在主程序中进行处理。 LPM0为
//仅在实际数据出现(重新)启动或停止条件时退出
//已传输。
//------------------
#pragma vector = USCIAB0RX_vector
__interrupt void USCIAB0RX_ISR(void)

IF (RX == 0){ UCB0STAT &=~(UCSTPIFG + UCSTIFG);//清除中断标志
IF (TXByteCtr)//检查TX字节计数器
__BIC_SR_REGISTER_ON_EXIT (CPUOFF);//如果数据为,则退出LPM0
}//已传输
IF (RX == 1){UCB0STAT &=~(UCSTPIFG + UCSTIFG);//清除中断标志
}
}
void Setup_RX (void){
_DINT();
Rx = 1;
IE2 &=~UCB0TXIE;//禁用TX中断
UCB0CTL1 || UCSWRST;//启用软件重置
UCB0CTL0 = UCMODE_3 + UCSYNC;// I2C从属,同步模式
UCB0I2COA = 0x48;//自有地址为048h
UCB0CTL1 &=~UCSWRST;//清除软件重置,恢复操作
UCB0I2CIE || UCSTPIE + UCSTTIE;//启用STT和STP中断
IE2 |= UCB0RXIE;//启用RX中断

}

作废接收(作废)
PRxData =(unsigned char *)RxBuffer;// RX缓冲区的开始
RXByteCtr = 0;//清除RX字节计数
TXByteCtr = 0;
__bis_sr_register(CPUOFF + GIE);//输入带中断的LPM0
//保留在LPM0中,直到主控
//完成TX
}
void USI_slaver_Setup(void){
P1SEL || BIT6 + BIT7;//将I2C引脚分配给USI_B0
P1SEL2|= BIT6 + BIT7;//将I2C引脚分配给USI_B0
Setup_Rx();
receive();
}

 

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

    请您解释一下哪些功能不起作用? 您是否看到正在到达按钮的ISR。 如果是,您是否看到主控启动I2C事务?

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

    此问题是否已解决? 如果很快没有响应,则线程将由于不活动而关闭。

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

    您好,还没有。

    很抱歉我的回复太晚了,我正在忙于其他项目。 不管怎样,我的问题如下:
    ——主控制器似乎可以正确发送数据,我已经通过调试和使用示波器和逻辑分析器对其进行了检查,但是从控制器似乎根本没有响应或做任何事情。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的,我看到ISR正在到达按钮。 是的,我看到师父的印心,但似乎没有完成。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好,

    我知道您说主设备正在正确发送数据,但如果默认的从属设备代码未接收到数据,则可能不是这样。 具体来说,为什么要在主while循环之前添加__bis_sr_register (CPUOFF + GIE)行? 这将使CPU进入休眠状态,因此While循环中的初始化可能无法正确执行(或根本无法执行)。 尝试删除此项,看看是否可以解决问题。

    如果没有,我建议您首先尝试使用默认主控和默认salve (不添加按钮代码和其他逻辑),看看您是否可以获得任何I2C通信。 如果不是,则您的硬件设置可能是您的问题。 有关调试串行通信的帮助,请参见本指南:www.ti.com/lit/an/slaa734/slaa734.pdf

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

    此问题是否已解决? 如果是,请标记为已回答。

    此致,
    Nathan