Part Number:MSP430G2553Other Parts Discussed in Thread:MSP-EXP430G2, MSP430F5438A,
使用官方例程 msp430g2xx3_usci_i2c_standard_slave.c 代码 板子为官方 msp-exp430g2 时 无响应,连I2C起始 中断都不进入,测量P1.6 P1.7电压波形一切正常!有人用过MSP430 硬件I2C从机模式吗?之前试过MSP430F5438A,使用官方例程也没成功.附上官方例程代码
//******************************************************************************
// MSP430G2xx3 Demo – USCI_B0, I2C Slave multiple byte TX/RX
//
// Description: I2C master communicates to I2C slave sending and receiving
// 3 different messages of different length. (This is the slave code). The
// slave will be in LPM0 mode, waiting for the master to initiate the
// communication. The slave will send/receive bytes based on the master's
// request. The slave will handle I2C bytes sent/received using the
// I2C interrupt.
// ACLK = NA, MCLK = SMCLK = DCO 16MHz.
//
//
// MSP430G2553 3.3V
// —————– /|\ /|\
// /|\ | | | 4.7k
// | | | 4.7k |
// —|RST | | |
// | | | |
// | P1.6|—|—+- I2C Clock (UCB0SCL)
// | | |
// | P1.7|—+—– I2C Data (UCB0SDA)
// | |
// | |
//
// Nima Eskandari
// Texas Instruments Inc.
// April 2017
// Built with CCS V7.0
//******************************************************************************
#include <msp430.h>#include <stdint.h>
//******************************************************************************
// Example Commands ************************************************************
//******************************************************************************
#define SLAVE_ADDR 0x48
/* CMD_TYPE_X_SLAVE are example commands the master sends to the slave.
* The slave will send example SlaveTypeX buffers in response.
*
* CMD_TYPE_X_MASTER are example commands the master sends to the slave.
* The slave will initialize itself to receive MasterTypeX example buffers.
* */
#define CMD_TYPE_0_SLAVE 0
#define CMD_TYPE_1_SLAVE 1
#define CMD_TYPE_2_SLAVE 2
#define CMD_TYPE_0_MASTER 3
#define CMD_TYPE_1_MASTER 4
#define CMD_TYPE_2_MASTER 5
#define TYPE_0_LENGTH 1
#define TYPE_1_LENGTH 2
#define TYPE_2_LENGTH 6
#define MAX_BUFFER_SIZE 20
/* MasterTypeX are example buffers initialized in the master, they will be
* sent by the master to the slave.
* SlaveTypeX are example buffers initialized in the slave, they will be
* sent by the slave to the master.
* */
uint8_t MasterType2 [TYPE_2_LENGTH] = {0};
uint8_t MasterType1 [TYPE_1_LENGTH] = { 0, 0};
uint8_t MasterType0 [TYPE_0_LENGTH] = { 0};
uint8_t SlaveType2 [TYPE_2_LENGTH] = {'A', 'B', 'C', 'D', '1', '2'};
uint8_t SlaveType1 [TYPE_1_LENGTH] = {15, 16};
uint8_t SlaveType0 [TYPE_0_LENGTH] = {12};
//******************************************************************************
// General I2C State Machine ***************************************************
//******************************************************************************
typedef enum I2C_ModeEnum{
IDLE_MODE,
NACK_MODE,
TX_REG_ADDRESS_MODE,
RX_REG_ADDRESS_MODE,
TX_DATA_MODE,
RX_DATA_MODE,
SWITCH_TO_RX_MODE,
SWITHC_TO_TX_MODE,
TIMEOUT_MODE
} I2C_Mode;
/* Used to track the state of the software state machine*/
I2C_Mode SlaveMode = RX_REG_ADDRESS_MODE;
/* The Register Address/Command to use*/
uint8_t ReceiveRegAddr = 0;
/* ReceiveBuffer: Buffer used to receive data in the ISR
* RXByteCtr: Number of bytes left to receive
* ReceiveIndex: The index of the next byte to be received in ReceiveBuffer
* TransmitBuffer: Buffer used to transmit data in the ISR
* TXByteCtr: Number of bytes left to transfer
* TransmitIndex: The index of the next byte to be transmitted in TransmitBuffer
* */
uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t RXByteCtr = 0;
uint8_t ReceiveIndex = 0;
uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0};
uint8_t TXByteCtr = 0;
uint8_t TransmitIndex = 0;
/* Initialized the software state machine according to the received cmd
*
* cmd: The command/register address received
* */
void I2C_Slave_ProcessCMD(uint8_t cmd);
/* The transaction between the slave and master is completed. Uses cmd
* to do post transaction operations. (Place data from ReceiveBuffer
* to the corresponding buffer based in the last received cmd)
*
* cmd: The command/register address corresponding to the completed
* transaction
*/
void I2C_Slave_TransactionDone(uint8_t cmd);
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);
void I2C_Slave_ProcessCMD(uint8_t cmd)
{
ReceiveIndex = 0;
TransmitIndex = 0;
RXByteCtr = 0;
TXByteCtr = 0;
switch (cmd)
{
case (CMD_TYPE_0_SLAVE): //Send slave device id (This device's id)
SlaveMode = TX_DATA_MODE;
TXByteCtr = TYPE_0_LENGTH;
//Fill out the TransmitBuffer
CopyArray(SlaveType0, TransmitBuffer, TYPE_0_LENGTH);
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
break;
case (CMD_TYPE_1_SLAVE): //Send slave device time (This device's time)
SlaveMode = TX_DATA_MODE;
TXByteCtr = TYPE_1_LENGTH;
//Fill out the TransmitBuffer
CopyArray(SlaveType1, TransmitBuffer, TYPE_1_LENGTH);
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
break;
case (CMD_TYPE_2_SLAVE): //Send slave device location (This device's location)
SlaveMode = TX_DATA_MODE;
TXByteCtr = TYPE_2_LENGTH;
//Fill out the TransmitBuffer
CopyArray(SlaveType2, TransmitBuffer, TYPE_2_LENGTH);
IE2 &= ~UCB0RXIE; // Disable RX interrupt
IE2 |= UCB0TXIE; // Enable TX interrupt
break;
case (CMD_TYPE_0_MASTER):
SlaveMode = RX_DATA_MODE;
RXByteCtr = TYPE_0_LENGTH;
IE2 &= ~UCB0TXIE; // Disable RX interrupt
IE2 |= UCB0RXIE; // Enable TX interrupt
break;
case (CMD_TYPE_1_MASTER):
SlaveMode = RX_DATA_MODE;
RXByteCtr = TYPE_1_LENGTH;
IE2 &= ~UCB0TXIE; // Disable RX interrupt
IE2 |= UCB0RXIE; // Enable TX interrupt
break;
case (CMD_TYPE_2_MASTER):
SlaveMode = RX_DATA_MODE;
RXByteCtr = TYPE_2_LENGTH;
IE2 &= ~UCB0TXIE; // Disable RX interrupt
IE2 |= UCB0RXIE; // Enable TX interrupt
break;
default:
__no_operation();
break;
}
}
void I2C_Slave_TransactionDone(uint8_t cmd)
{
switch (cmd)
{
case (CMD_TYPE_0_SLAVE): //Slave device id was sent(This device's id)
break;
case (CMD_TYPE_1_SLAVE): //Slave device time was sent(This device's time)
break;
case (CMD_TYPE_2_SLAVE): //Send slave device location (This device's location)
break;
case (CMD_TYPE_0_MASTER):
CopyArray(ReceiveBuffer, MasterType0, TYPE_0_LENGTH);
break;
case (CMD_TYPE_1_MASTER):
CopyArray(ReceiveBuffer, MasterType1, TYPE_1_LENGTH);
break;
case (CMD_TYPE_2_MASTER):
CopyArray(ReceiveBuffer, MasterType2, TYPE_2_LENGTH);
break;
default:
__no_operation();
break;
}
}
void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count)
{
uint8_t copyIndex = 0;
for (copyIndex = 0; copyIndex < count; copyIndex++)
{
dest[copyIndex] = source[copyIndex];
}
}
//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************
void initClockTo16MHz()
{
if (CALBC1_16MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_16MHZ; // Set DCO
DCOCTL = CALDCO_16MHZ;
}
void initGPIO()
{
P1SEL |= BIT6 + BIT7; // Assign I2C pins to USCI_B0
P1SEL2|= BIT6 + BIT7; // Assign I2C pins to USCI_B0
}
void initI2C()
{
UCB0CTL1 |= UCSWRST; // Enable SW reset
UCB0CTL0 = UCMODE_3 + UCSYNC; // I2C Slave, synchronous mode
UCB0I2COA = SLAVE_ADDR; // Own Address
UCB0CTL1 &= ~UCSWRST; // Clear SW reset, resume operation
UCB0I2CIE |= UCSTPIE + UCSTTIE; // Enable STT and STP interrupt
IE2 |= UCB0RXIE; // Enable RX interrupt
}
//******************************************************************************
// Main ************************************************************************
// Enters LPM0 and waits for I2C interrupts. The data sent from the master is *
// then interpreted and the device will respond accordingly *
//******************************************************************************
int main(void) {
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
initClockTo16MHz();
initGPIO();
initI2C();
__bis_SR_register(LPM0_bits + GIE);
return 0;
}
//******************************************************************************
// I2C Interrupt For Received and Transmitted Data******************************
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void)
#else
#error Compiler not supported!
#endif
{
if (IFG2 & UCB0RXIFG) // Receive Data Interrupt
{
//Must read from UCB0RXBUF
uint8_t rx_val = UCB0RXBUF;
switch (SlaveMode)
{
case (RX_REG_ADDRESS_MODE):
ReceiveRegAddr = rx_val;
I2C_Slave_ProcessCMD(ReceiveRegAddr);
break;
case (RX_DATA_MODE):
ReceiveBuffer[ReceiveIndex++] = rx_val;
RXByteCtr–;
if (RXByteCtr == 0)
{
//Done Receiving MSG
SlaveMode = RX_REG_ADDRESS_MODE;
IE2 &= ~(UCB0TXIE);
IE2 |= UCB0RXIE; // Enable RX interrupt
I2C_Slave_TransactionDone(ReceiveRegAddr);
}
break;
default:
__no_operation();
break;
}
}
else if (IFG2 & UCB0TXIFG) // Transmit Data Interrupt
{
//Must write to UCB0TXBUF
switch (SlaveMode)
{
case (TX_DATA_MODE):
UCB0TXBUF = TransmitBuffer[TransmitIndex++];
TXByteCtr–;
if (TXByteCtr == 0)
{
//Done Transmitting MSG
SlaveMode = RX_REG_ADDRESS_MODE;
IE2 &= ~(UCB0TXIE);
IE2 |= UCB0RXIE; // Enable RX interrupt
I2C_Slave_TransactionDone(ReceiveRegAddr);
}
break;
default:
__no_operation();
break;
}
}
}
//******************************************************************************
// I2C Interrupt For Start, Restart, Nack, Stop ********************************
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void)
#else
#error Compiler not supported!
#endif
{
//仿真挂断点连这里都跳不进来
if (UCB0STAT & UCSTPIFG) //Stop or NACK Interrupt
{
UCB0STAT &=
~(UCSTTIFG + UCSTPIFG + UCNACKIFG); //Clear START/STOP/NACK Flags
}
if (UCB0STAT & UCSTTIFG)
{
UCB0STAT &= ~(UCSTTIFG); //Clear START Flags
}
}
Susan Yang:
请问您现在使用的主从机均是开发板?是否有按照例程说明上拉 4.7k 电阻?
,
user6352220:
主机端为电脑+CH341T(内置上拉电阻),I2C器件地址(0x7f)核对无问题,另外电脑端和别人的产品通讯是正常的,产品使用的芯片也是G2553
,
Susan Yang:
下面我附上的文件中,主从有两种通信方式。
g2553_i2c_slave.c 设备正在等待主设备与其通信。然后它将执行 6 个命令之一。
fr5529_i2c_master.c 设备将发送三个消息,并要求读取三个消息。消息长度不同。
使用的引脚是 fr5529 上的 P2.0 和 P2.1。MSP430G2553 上的 P1.6 和 P1.7。
它们都将以 16 MHz 运行。使用的 I2C 上拉电阻是 10k 欧姆电阻。
#include <msp430.h>#include <stdint.h> #include <stdbool.h>#define SLAVE_ADDR0x48#define CMD_TYPE_0_SLAVE0 #define CMD_TYPE_1_SLAVE1 #define CMD_TYPE_2_SLAVE2#define CMD_TYPE_0_MASTER3 #define CMD_TYPE_1_MASTER4 #define CMD_TYPE_2_MASTER5#define TYPE_0_LENGTH1 #define TYPE_1_LENGTH2 #define TYPE_2_LENGTH6#define MAX_BUFFER_SIZE20typedef enum I2C_ModeEnum{IDLE_MODE,NACK_MODE,TX_REG_ADDRESS_MODE,RX_REG_ADDRESS_MODE,TX_DATA_MODE,RX_DATA_MODE,SWITCH_TO_RX_MODE,SWITHC_TO_TX_MODE,TIMEOUT_MODE } I2C_Mode;uint8_t MasterType2 [TYPE_2_LENGTH] = {'F', '4', '1', '9', '2', 'B'}; uint8_t MasterType1 [TYPE_1_LENGTH] = { 8, 9}; uint8_t MasterType0 [TYPE_0_LENGTH] = { 11};uint8_t SlaveType2 [TYPE_2_LENGTH] = {0}; uint8_t SlaveType1 [TYPE_1_LENGTH] = {0}; uint8_t SlaveType0 [TYPE_0_LENGTH] = {0};I2C_Mode MasterMode = IDLE_MODE;uint8_t TransmitRegAddr = 0;uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t RXByteCtr = 0; uint8_t ReceiveIndex = 0; uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t TXByteCtr = 0; uint8_t TransmitIndex = 0;/* I2C Write and Read Functions */ I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count); I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count); void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);void initClockTo16MHz() {UCSCTL3 |= SELREF_2;// Set DCO FLL reference = REFOUCSCTL4 |= SELA_2;// Set ACLK = REFO__bis_SR_register(SCG0);// Disable the FLL control loopUCSCTL0 = 0x0000;// Set lowest possible DCOx, MODxUCSCTL1 = DCORSEL_5;// Select DCO range 16MHz operationUCSCTL2 = FLLD_0 + 487;// Set DCO Multiplier for 16MHz// (N + 1) * FLLRef = Fdco// (487 + 1) * 32768 = 16MHz// Set FLL Div = fDCOCLK__bic_SR_register(SCG0);// Enable the FLL control loop// Worst-case settling time for the DCO when the DCO range bits have been// changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx// UG for optimization.// 32 x 32 x 16 MHz / 32,768 Hz = 500000 = MCLK cycles for DCO to settle__delay_cycles(500000);//// Loop until XT1,XT2 & DCO fault flag is cleareddo{UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flagsSFRIFG1 &= ~OFIFG;// Clear fault flags}while (SFRIFG1&OFIFG);// Test oscillator fault flag }uint16_t setVCoreUp(uint8_t level){uint32_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;//The code flow for increasing the Vcore has been altered to work around//the erratum FLASH37.//Please refer to the Errata sheet to know if a specific device is affected//DO NOT ALTER THIS FUNCTION//Open PMM registers for write accessPMMCTL0_H = 0xA5;//Disable dedicated Interrupts//Backup all registersPMMRIE_backup = PMMRIE;PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |SVSLPE | SVMHVLRIE | SVMHIE |SVSMHDLYIE | SVMLVLRIE | SVMLIE |SVSMLDLYIE);SVSMHCTL_backup = SVSMHCTL;SVSMLCTL_backup = SVSMLCTL;//Clear flagsPMMIFG = 0;//Set SVM highside to new level and check if a VCore increase is possibleSVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);//Wait until SVM highside is settledwhile((PMMIFG & SVSMHDLYIFG) == 0){;}//Clear flagPMMIFG &= ~SVSMHDLYIFG;//Check if a VCore increase is possibleif((PMMIFG & SVMHIFG) == SVMHIFG){//-> Vcc is too low for a Vcore increase//recover the previous settingsPMMIFG &= ~SVSMHDLYIFG;SVSMHCTL = SVSMHCTL_backup;//Wait until SVM highside is settledwhile((PMMIFG & SVSMHDLYIFG) == 0){;}//Clear all FlagsPMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |SVMLVLRIFG | SVMLIFG |SVSMLDLYIFG);//Restore PMM interrupt enable registerPMMRIE = PMMRIE_backup;//Lock PMM registers for write accessPMMCTL0_H = 0x00;//return: voltage not setreturn false;}//Set also SVS highside to new level//Vcc is high enough for a Vcore increaseSVSMHCTL |= (SVSHRVL0 * level);//Wait until SVM highside is settledwhile((PMMIFG & SVSMHDLYIFG) == 0){;}//Clear flagPMMIFG &= ~SVSMHDLYIFG;//Set VCore to new levelPMMCTL0_L = PMMCOREV0 * level;//Set SVM, SVS low side to new levelSVSMLCTL = SVMLE | (SVSMLRRL0 * level) |SVSLE | (SVSLRVL0 * level);//Wait until SVM, SVS low side is settledwhile((PMMIFG & SVSMLDLYIFG) == 0){;}//Clear flagPMMIFG &= ~SVSMLDLYIFG;//SVS, SVM core and high side are now set to protect for the new core level//Restore Low side settings//Clear all other bits _except_ level settingsSVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 +SVSMLRRL1 + SVSMLRRL2);//Clear level settings in the backup register,keep all other bitsSVSMLCTL_backup &=~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);//Restore low-side SVS monitor settingsSVSMLCTL |= SVSMLCTL_backup;//Restore High side settings//Clear all other bits except level settingsSVSMHCTL &= (SVSHRVL0 + SVSHRVL1 +SVSMHRRL0 + SVSMHRRL1 +SVSMHRRL2);//Clear level settings in the backup register,keep all other bitsSVSMHCTL_backup &=~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);//Restore backupSVSMHCTL |= SVSMHCTL_backup;//Wait until high side, low side settledwhile(((PMMIFG & SVSMLDLYIFG) == 0) &&((PMMIFG & SVSMHDLYIFG) == 0)){;}//Clear all FlagsPMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);//Restore PMM interrupt enable registerPMMRIE = PMMRIE_backup;//Lock PMM registers for write accessPMMCTL0_H = 0x00;return true; }bool increaseVCoreToLevel2() {uint8_t level = 2;uint8_t actlevel;bool status = true;//Set Mask for Max. levellevel &= PMMCOREV_3;//Get actual VCoreactlevel = PMMCTL0 & PMMCOREV_3;//step by step increase or decreasewhile((level != actlevel) && (status == true)){if(level > actlevel){status = setVCoreUp(++actlevel);}}return (status); }void initGPIO() {//LEDsP1OUT = 0x00;// P1 setup for LED & reset outputP1DIR |= BIT0;P4DIR |= BIT7;P4OUT &= ~(BIT7);//I2C PinsP3SEL |= BIT0 + BIT1;// P3.0,1 option select}void initI2C() {UCB0CTL1 |= UCSWRST;// Enable SW resetUCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;// I2C Master, synchronous modeUCB0CTL1 = UCSSEL_2 + UCSWRST;// Use SMCLK, keep SW resetUCB0BR0 = 192;// fSCL = SMCLK/12 = ~100kHzUCB0BR1 = 0;UCB0I2CSA = 0x48;// Slave Address is 048hUCB0CTL1 &= ~UCSWRST;// Clear SW reset, resume operationUCB0IE |= UCNACKIE; }int main(void) {WDTCTL = WDTPW | WDTHOLD;// Stop watchdog timerincreaseVCoreToLevel2();initClockTo16MHz();initGPIO();initI2C();I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_0_MASTER, MasterType0, TYPE_0_LENGTH);I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_1_MASTER, MasterType1, TYPE_1_LENGTH);I2C_Master_WriteReg(SLAVE_ADDR, CMD_TYPE_2_MASTER, MasterType2, TYPE_2_LENGTH);I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_0_SLAVE, TYPE_0_LENGTH);CopyArray(ReceiveBuffer, SlaveType0, TYPE_0_LENGTH);I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_1_SLAVE, TYPE_1_LENGTH);CopyArray(ReceiveBuffer, SlaveType1, TYPE_1_LENGTH);I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_2_SLAVE, TYPE_2_LENGTH);CopyArray(ReceiveBuffer, SlaveType2, TYPE_2_LENGTH);__bis_SR_register(LPM0_bits + GIE);return 0; }#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif {//Must read from UCB0RXBUFuint8_t rx_val = 0;switch(__even_in_range(UCB0IV,0xC)){case USCI_NONE:break;// Vector 0 - no interruptcase USCI_I2C_UCALIFG:break;// Interrupt Vector: I2C Mode: UCALIFGcase USCI_I2C_UCNACKIFG:break;// Interrupt Vector: I2C Mode: UCNACKIFGcase USCI_I2C_UCSTTIFG:break;// Interrupt Vector: I2C Mode: UCSTTIFGcase USCI_I2C_UCSTPIFG:break;// Interrupt Vector: I2C Mode: UCSTPIFGcase USCI_I2C_UCRXIFG:rx_val = UCB0RXBUF;if (RXByteCtr){ReceiveBuffer[ReceiveIndex++] = rx_val;RXByteCtr--;}if (RXByteCtr == 1){UCB0CTL1 |= UCTXSTP;}else if (RXByteCtr == 0){UCB0IE &= ~UCRXIE;MasterMode = IDLE_MODE;__bic_SR_register_on_exit(CPUOFF);// Exit LPM0}break;// Interrupt Vector: I2C Mode: UCRXIFGcase USCI_I2C_UCTXIFG:switch (MasterMode){case TX_REG_ADDRESS_MODE:UCB0TXBUF = TransmitRegAddr;if (RXByteCtr)MasterMode = SWITCH_TO_RX_MODE;// Need to start receiving nowelseMasterMode = TX_DATA_MODE;// Continue to transmision with the data in Transmit Bufferbreak;case SWITCH_TO_RX_MODE:UCB0IE |= UCRXIE;// Enable RX interruptUCB0IE &= ~UCTXIE;// Disable TX interruptUCB0CTL1 &= ~UCTR;// Switch to receiverMasterMode = RX_DATA_MODE;// State state is to receive dataUCB0CTL1 |= UCTXSTT;// Send repeated startif (RXByteCtr == 1){//Must send stop since this is the N-1 bytewhile((UCB0CTL1 & UCTXSTT));UCB0CTL1 |= UCTXSTP;// Send stop condition}break;case TX_DATA_MODE:if (TXByteCtr){UCB0TXBUF = TransmitBuffer[TransmitIndex++];TXByteCtr--;}else{//Done with transmissionUCB0CTL1 |= UCTXSTP;// Send stop conditionMasterMode = IDLE_MODE;UCB0IE &= ~UCTXIE;// disable TX interrupt//IFG2 &= ~(UCB0TXIFG);__bic_SR_register_on_exit(CPUOFF);// Exit LPM0}break;default:__no_operation();break;}break;// Interrupt Vector: I2C Mode: UCTXIFGdefault: break;} }I2C_Mode I2C_Master_ReadReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t count) {/* Initialize state machine */MasterMode = TX_REG_ADDRESS_MODE;TransmitRegAddr = reg_addr;RXByteCtr = count;TXByteCtr = 0;ReceiveIndex = 0;TransmitIndex = 0;/* Initialize slave address and interrupts */UCB0I2CSA = dev_addr;UCB0IFG &= ~(UCTXIFG + UCRXIFG);// Clear any pending interruptsUCB0IE &= ~UCRXIE;// Disable RX interruptUCB0IE |= UCTXIE;// Enable TX interruptUCB0CTL1 |= UCTR + UCTXSTT;// I2C TX, start condition__bis_SR_register(LPM0_bits + GIE);// Enter LPM0 w/ interruptsreturn MasterMode;}I2C_Mode I2C_Master_WriteReg(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t count) {/* Initialize state machine */MasterMode = TX_REG_ADDRESS_MODE;TransmitRegAddr = reg_addr;//Copy register data to TransmitBufferCopyArray(reg_data, TransmitBuffer, count);TXByteCtr = count;RXByteCtr = 0;ReceiveIndex = 0;TransmitIndex = 0;/* Initialize slave address and interrupts */UCB0I2CSA = dev_addr;UCB0IFG &= ~(UCTXIFG + UCRXIFG);// Clear any pending interruptsUCB0IE &= ~UCRXIE;// Disable RX interruptUCB0IE |= UCTXIE;// Enable TX interruptUCB0CTL1 |= UCTR + UCTXSTT;// I2C TX, start condition__bis_SR_register(LPM0_bits + GIE);// Enter LPM0 w/ interruptsreturn MasterMode; }void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) {uint8_t copyIndex = 0;for (copyIndex = 0; copyIndex < count; copyIndex++){dest[copyIndex] = source[copyIndex];} }#include <msp430.h>#include <stdint.h>#define SLAVE_ADDR0x48#define CMD_TYPE_0_SLAVE0 #define CMD_TYPE_1_SLAVE1 #define CMD_TYPE_2_SLAVE2#define CMD_TYPE_0_MASTER3 #define CMD_TYPE_1_MASTER4 #define CMD_TYPE_2_MASTER5#define TYPE_0_LENGTH1 #define TYPE_1_LENGTH2 #define TYPE_2_LENGTH6#define MAX_BUFFER_SIZE20typedef enum I2C_ModeEnum{IDLE_MODE,NACK_MODE,TX_REG_ADDRESS_MODE,RX_REG_ADDRESS_MODE,TX_DATA_MODE,RX_DATA_MODE,SWITCH_TO_RX_MODE,SWITHC_TO_TX_MODE,TIMEOUT_MODE } I2C_Mode;uint8_t MasterType2 [TYPE_2_LENGTH] = {0}; uint8_t MasterType1 [TYPE_1_LENGTH] = { 0, 0}; uint8_t MasterType0 [TYPE_0_LENGTH] = { 0};uint8_t SlaveType2 [TYPE_2_LENGTH] = {'A', 'B', 'C', 'D', '1', '2'}; uint8_t SlaveType1 [TYPE_1_LENGTH] = {15, 16}; uint8_t SlaveType0 [TYPE_0_LENGTH] = {12};I2C_Mode SlaveMode = RX_REG_ADDRESS_MODE;uint8_t ReceiveRegAddr = 0;uint8_t ReceiveBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t RXByteCtr = 0; uint8_t ReceiveIndex = 0; uint8_t TransmitBuffer[MAX_BUFFER_SIZE] = {0}; uint8_t TXByteCtr = 0; uint8_t TransmitIndex = 0;void initClockTo16MHz() {if (CALBC1_16MHZ==0xFF)// If calibration constant erased{while(1);// do not load, trap CPU!!}DCOCTL = 0;// Select lowest DCOx and MODx settingsBCSCTL1 = CALBC1_16MHZ;// Set DCODCOCTL = CALDCO_16MHZ; }void initGPIO() {P1SEL |= BIT6 + BIT7;// Assign I2C pins to USCI_B0P1SEL2|= BIT6 + BIT7;// Assign I2C pins to USCI_B0 }void initI2C() {UCB0CTL1 |= UCSWRST;// Enable SW resetUCB0CTL0 = UCMODE_3 + UCSYNC;// I2C Slave, synchronous modeUCB0I2COA = 0x48;// Own Address is 048hUCB0CTL1 &= ~UCSWRST;// Clear SW reset, resume operationUCB0I2CIE |= UCSTPIE + UCSTTIE;// Enable STT and STP interruptIE2 |= UCB0RXIE;// Enable RX interrupt }inline void I2C_Slave_ProcessCMD(uint8_t cmd); inline void I2C_Slave_TransactionDone(uint8_t cmd); inline void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count);int main(void) {WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timerinitClockTo16MHz();initGPIO();initI2C();__bis_SR_register(LPM0_bits + GIE);return 0; }//------------------------------------------------------------------------------ // The USCI_B0 data ISR is used to move data from MSP430 memory to the // I2C master. PTxData points to the next byte to be transmitted, and TXByteCtr // keeps track of the number of bytes transmitted. //------------------------------------------------------------------------------ #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCIAB0TX_VECTOR __interrupt void USCIAB0TX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR (void) #else #error Compiler not supported! #endif {if (IFG2 & UCB0RXIFG)// Receive Data Interrupt{//Must read from UCB0RXBUFuint8_t rx_val = UCB0RXBUF;switch (SlaveMode){case (RX_REG_ADDRESS_MODE):ReceiveRegAddr = rx_val;I2C_Slave_ProcessCMD(ReceiveRegAddr);break;case (RX_DATA_MODE):ReceiveBuffer[ReceiveIndex++] = rx_val;RXByteCtr--;if (RXByteCtr == 0){//Done Receiving MSGSlaveMode = RX_REG_ADDRESS_MODE;IE2 &= ~(UCB0TXIE);IE2 |= UCB0RXIE;// Enable RX interruptI2C_Slave_TransactionDone(ReceiveRegAddr);}break;default:_no_operation();break;}}else if (IFG2 & UCB0TXIFG)// Transmit Data Interrupt{//Must write to UCB0TXBUFswitch (SlaveMode){case (TX_DATA_MODE):UCB0TXBUF = TransmitBuffer[TransmitIndex++];TXByteCtr--;if (TXByteCtr == 0){//Done Transmitting MSGSlaveMode = RX_REG_ADDRESS_MODE;IE2 &= ~(UCB0TXIE);IE2 |= UCB0RXIE;// Enable RX interruptI2C_Slave_TransactionDone(ReceiveRegAddr);}break;default:_no_operation();break;}} }//------------------------------------------------------------------------------ // The USCI_B0 state ISR is used to wake up the CPU from LPM0 in order to do // processing in the main program after data has been transmitted. LPM0 is // only exit in case of a (re-)start or stop condition when actual data // was transmitted. //------------------------------------------------------------------------------ #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCIAB0RX_VECTOR __interrupt void USCIAB0RX_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCIAB0RX_VECTOR))) USCIAB0RX_ISR (void) #else #error Compiler not supported! #endif {if (UCB0STAT & UCSTPIFG)//Stop or NACK Interrupt{UCB0STAT &=~(UCSTTIFG + UCSTPIFG + UCNACKIFG);//Clear START/STOP/NACK Flags}if (UCB0STAT & UCSTTIFG){UCB0STAT &= ~(UCSTTIFG);//Clear START Flags} }inline void I2C_Slave_ProcessCMD(uint8_t cmd) {ReceiveIndex = 0;TransmitIndex = 0;RXByteCtr = 0;TXByteCtr = 0;switch (cmd){case (CMD_TYPE_0_SLAVE)://Send slave device id (This device's id)SlaveMode = TX_DATA_MODE;TXByteCtr = TYPE_0_LENGTH;//Fill out the TransmitBufferCopyArray(SlaveType0, TransmitBuffer, TYPE_0_LENGTH);IE2 &= ~UCB0RXIE;// Disable RX interruptIE2 |= UCB0TXIE;// Enable TX interruptbreak;case (CMD_TYPE_1_SLAVE)://Send slave device time (This device's time)SlaveMode = TX_DATA_MODE;TXByteCtr = TYPE_1_LENGTH;//Fill out the TransmitBufferCopyArray(SlaveType1, TransmitBuffer, TYPE_1_LENGTH);IE2 &= ~UCB0RXIE;// Disable RX interruptIE2 |= UCB0TXIE;// Enable TX interruptbreak;case (CMD_TYPE_2_SLAVE)://Send slave device location (This device's location)SlaveMode = TX_DATA_MODE;TXByteCtr = TYPE_2_LENGTH;//Fill out the TransmitBufferCopyArray(SlaveType2, TransmitBuffer, TYPE_2_LENGTH);IE2 &= ~UCB0RXIE;// Disable RX interruptIE2 |= UCB0TXIE;// Enable TX interruptbreak;case (CMD_TYPE_0_MASTER):SlaveMode = RX_DATA_MODE;RXByteCtr = TYPE_0_LENGTH;IE2 &= ~UCB0TXIE;// Disable RX interruptIE2 |= UCB0RXIE;// Enable TX interruptbreak;case (CMD_TYPE_1_MASTER):SlaveMode = RX_DATA_MODE;RXByteCtr = TYPE_1_LENGTH;IE2 &= ~UCB0TXIE;// Disable RX interruptIE2 |= UCB0RXIE;// Enable TX interruptbreak;case (CMD_TYPE_2_MASTER):SlaveMode = RX_DATA_MODE;RXByteCtr = TYPE_2_LENGTH;IE2 &= ~UCB0TXIE;// Disable RX interruptIE2 |= UCB0RXIE;// Enable TX interruptbreak;default:_no_operation();break;} }inline void I2C_Slave_TransactionDone(uint8_t cmd) {switch (cmd){case (CMD_TYPE_0_SLAVE)://Slave device id was sent(This device's id)break;case (CMD_TYPE_1_SLAVE)://Slave device time was sent(This device's time)break;case (CMD_TYPE_2_SLAVE)://Send slave device location (This device's location)break;case (CMD_TYPE_0_MASTER):CopyArray(ReceiveBuffer, MasterType0, TYPE_0_LENGTH);break;case (CMD_TYPE_1_MASTER):CopyArray(ReceiveBuffer, MasterType1, TYPE_1_LENGTH);break;case (CMD_TYPE_2_MASTER):CopyArray(ReceiveBuffer, MasterType2, TYPE_2_LENGTH);break;default:_no_operation();break;} }inline void CopyArray(uint8_t *source, uint8_t *dest, uint8_t count) {uint8_t copyIndex = 0;for (copyIndex = 0; copyIndex < count; copyIndex++){dest[copyIndex] = source[copyIndex];} }
,
Susan Yang:
您可以对照上面的程序先看一下,后续您上传代码的话,请您使用回复框下的“插入–>代码”来粘贴您的代码,以便于阅读