大家好,
我的项目是通过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();
}