MSP430G2553 I2C problem
Leonarnhy
Posts: 1
Hello! Firstly,I want to apologize for my confused and interminable description here. Please take your time to read it.
I am having a tough time to get the I2C to work. I use MSP430G2553 as a master and want to control my DSP.
I need to send about 40 messages to reboot the DSP.
Each message consists of:
1- Start bit
2- Slave Address + write bit
3- Register + Data (data can be between 1 byte t0 500 bytes )
4- Stop bit
The master starts to send the first message successfully to the DSP. Please see below.
The DSP acknowledges to each byte which is received from the master.
My problem is that the master doesn’t send the next message. I have tried different options (different interrupt implementation), but the best case is that the MSP430g2553 go to sleep just after the TX interrupt is completed. Please see the code below.
What do I miss for getting I2c to work? Can anybody help me with this?
/*
* ======== Standard MSP430 includes ========
*/
#include <msp430.h>
/*
* ======== Grace related includes ========
*/
#include <ti/mcu/msp430/Grace.h>
#include "Beep_export_IC_1.h" // DSP header file
/* DSP defines */
#define DSP_ADDR 0x38 // DSP address
#define DSP_register_length 2
//MCU data definition
// iic
void iic_init(void);
void iic_tx_init(void);
void iic_rx_init(void);
void start_TX(void);
void start_RX(void);
void Prepare_DSP_Data_to_send(unsigned char * reg_addr, int length, unsigned char * buf);
// iic
unsigned char *PTxData; // Pointer to TX data
unsigned char TXByteCtr;
unsigned char *PRxData; // Pointer to RX data
unsigned char RXByteCtr;
volatile unsigned char RxBuffer[3]; // Allocate 3 byte of RAM
/*
* ======== main ========
*/
void main(void)
{ Grace_init(); // Activate Grace-generated configuration
__enable_interrupt(); // Set global interrupt enable
while (1)
{ default_download_IC_1(); // This function includes all DSP messages, } }
void iic_tx_init()
{ UCB0I2CSA = DSP_ADDR;
UCB0I2CIE |= UCB0TXIE; // Enable TX interrupt}
void iic_rx_init(void)
{UCB0I2CIE |= UCB0RXIE; // enable RX interrupt}
void Prepare_DSP_Data_to_send(unsigned char * reg_addr, int length, unsigned char * buf)
{ PTxData = reg_addr;
int ZZ = 0;
for (ZZ = 0; ZZ < length ; ZZ++)
{PTxData [2 + ZZ]=buf [ZZ];}
TXByteCtr = (length + 2);
iic_tx_init();
__delay_cycles(10000);
start_TX();
__delay_cycles(200000);
}
// iic start transmitting
void start_TX(void)
{
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
// __no_operation(); // Remain in LPM0 until all data
// is TX'd
UCB0CTL1 |= UCTXSTP; // I2C stop condition
// while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
// iic restart and receive
void start_RX(void)
{
while (UCB0CTL1 & UCTXSTP); // wait for stop
UCB0CTL1 &= ~UCTR; // restart, set as receiver
UCB0CTL1 |= UCTXSTT; // start condition
__bis_SR_register(LPM0_bits + GIE);
while (UCB0CTL1 & UCTXSTP);
}
the Interrupts function:
/*
* This file is automatically generated and does not require a license
*
* ==== WARNING: CHANGES TO THIS GENERATED FILE WILL BE OVERWRITTEN ====
*
* To make changes to the generated code, use the space between existing
* "USER CODE START (section: <name>)"
* and
* "USER CODE END (section: <name>)"
* comments, where <name> is a single word identifying the section.
* Only these sections will be preserved.
*
* Do not move these sections within this file or change the START and
* END comments in any way.
* ==== ALL OTHER CHANGES WILL BE OVERWRITTEN WHEN IT IS REGENERATED ====
*
* This file was generated from
* C:/ti/grace_2_00_01_65/packages/ti/mcu/msp430/csl/interrupt_vectors/InterruptVectors_init.xdt
*/
#include <msp430.h>
/* USER CODE START (section: InterruptVectors_init_c_prologue) */
extern unsigned char *PTxData; // Pointer to TX data
extern unsigned char TXByteCtr;
extern unsigned char *PRxData; // Pointer to RX data
extern unsigned char RXByteCtr;
/* USER CODE END (section: InterruptVectors_init_c_prologue) */
/*
* ======== InterruptVectors_graceInit ========
void InterruptVectors_graceInit(void)
{}
/* Interrupt Function Prototypes */
* ======== USCI A0/B0 TX Interrupt Handler Generation ========
* Here are several important notes on using USCI_A0/B0 TX interrupt Handler:
* 1. User could use the following code as a template to service the interrupt
* handler. Just simply copy and paste it into your user definable code
* section.
* For UART and SPI configuration:
if (IFG2 & UCA0TXIFG) {
}
else if (IFG2 & UCB0TXIFG) {
}
* For I2C configuration:
if (IFG2 & UCA0/B0TXIFG) {
}
else if (IFG2 & UCA0/B0RXIFG) {
}
* 2. User could also exit from low power mode and continue with main
* program execution by using the following instruction before exiting
* this interrupt handler.
*
* __bic_SR_register_on_exit(LPMx_bits);
*/
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR_HOOK(void)
{
/* USER CODE START (section: USCI0TX_ISR_HOOK) */
if (TXByteCtr) // Check TX byte counter
UCB0TXBUF = *PTxData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter}
else { UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag }
/* USER CODE END (section: USCI0TX_ISR_HOOK) */}
/*
* ======== USCI A0/B0 RX Interrupt Handler Generation ========
*
* Here are several important notes on using USCI_A0/B0 RX interrupt Handler:
* 1. User could use the following code as a template to service the interrupt
* handler. Just simply copy and paste it into your user definable code
* section.
* For UART and SPI configuration:
if (IFG2 & UCA0RXIFG) {}
else if (IFG2 & UCB0RXIFG) {}
* For I2C configuration:
if (UCB0STAT & UCSTTIFG) {}
else if (UCB0STAT & UCSTPIFG) {}
else if (UCB0STAT & UCNACKIFG) {}
else if (UCB0STAT & UCALIFG) {}
* 2. User could also exit from low power mode and continue with main
* program execution by using the following instruction before exiting
* this interrupt handler.
* __bic_SR_register_on_exit(LPMx_bits);
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR_HOOK(void)
{ /* USER CODE START (section: USCI0RX_ISR_HOOK) */
RXByteCtr--; // Decrement RX byte counter
if (RXByteCtr)
{P1OUT ^= 0x10;
*PRxData++ = UCB0RXBUF; // Move RX data to address PRxData
if (RXByteCtr == 1) // Only one byte left?
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition}
else
{ *PRxData = UCB0RXBUF; // Move final RX data to PRxData }
/* USER CODE END (section: USCI0RX_ISR_HOOK) */}
To be honest, this spent me much time to do. Anyway, thanks for your patience.
I am having a tough time to get the I2C to work. I use MSP430G2553 as a master and want to control my DSP.
I need to send about 40 messages to reboot the DSP.
Each message consists of:
1- Start bit
2- Slave Address + write bit
3- Register + Data (data can be between 1 byte t0 500 bytes )
4- Stop bit
The master starts to send the first message successfully to the DSP. Please see below.
The DSP acknowledges to each byte which is received from the master.
My problem is that the master doesn’t send the next message. I have tried different options (different interrupt implementation), but the best case is that the MSP430g2553 go to sleep just after the TX interrupt is completed. Please see the code below.
What do I miss for getting I2c to work? Can anybody help me with this?
/*
* ======== Standard MSP430 includes ========
*/
#include <msp430.h>
/*
* ======== Grace related includes ========
*/
#include <ti/mcu/msp430/Grace.h>
#include "Beep_export_IC_1.h" // DSP header file
/* DSP defines */
#define DSP_ADDR 0x38 // DSP address
#define DSP_register_length 2
//MCU data definition
// iic
void iic_init(void);
void iic_tx_init(void);
void iic_rx_init(void);
void start_TX(void);
void start_RX(void);
void Prepare_DSP_Data_to_send(unsigned char * reg_addr, int length, unsigned char * buf);
// iic
unsigned char *PTxData; // Pointer to TX data
unsigned char TXByteCtr;
unsigned char *PRxData; // Pointer to RX data
unsigned char RXByteCtr;
volatile unsigned char RxBuffer[3]; // Allocate 3 byte of RAM
/*
* ======== main ========
*/
void main(void)
{ Grace_init(); // Activate Grace-generated configuration
__enable_interrupt(); // Set global interrupt enable
while (1)
{ default_download_IC_1(); // This function includes all DSP messages, } }
void iic_tx_init()
{ UCB0I2CSA = DSP_ADDR;
UCB0I2CIE |= UCB0TXIE; // Enable TX interrupt}
void iic_rx_init(void)
{UCB0I2CIE |= UCB0RXIE; // enable RX interrupt}
void Prepare_DSP_Data_to_send(unsigned char * reg_addr, int length, unsigned char * buf)
{ PTxData = reg_addr;
int ZZ = 0;
for (ZZ = 0; ZZ < length ; ZZ++)
{PTxData [2 + ZZ]=buf [ZZ];}
TXByteCtr = (length + 2);
iic_tx_init();
__delay_cycles(10000);
start_TX();
__delay_cycles(200000);
}
// iic start transmitting
void start_TX(void)
{
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0, enable interrupts
// __no_operation(); // Remain in LPM0 until all data
// is TX'd
UCB0CTL1 |= UCTXSTP; // I2C stop condition
// while (UCB0CTL1 & UCTXSTP); // Ensure stop condition got sent
}
// iic restart and receive
void start_RX(void)
{
while (UCB0CTL1 & UCTXSTP); // wait for stop
UCB0CTL1 &= ~UCTR; // restart, set as receiver
UCB0CTL1 |= UCTXSTT; // start condition
__bis_SR_register(LPM0_bits + GIE);
while (UCB0CTL1 & UCTXSTP);
}
the Interrupts function:
/*
* This file is automatically generated and does not require a license
*
* ==== WARNING: CHANGES TO THIS GENERATED FILE WILL BE OVERWRITTEN ====
*
* To make changes to the generated code, use the space between existing
* "USER CODE START (section: <name>)"
* and
* "USER CODE END (section: <name>)"
* comments, where <name> is a single word identifying the section.
* Only these sections will be preserved.
*
* Do not move these sections within this file or change the START and
* END comments in any way.
* ==== ALL OTHER CHANGES WILL BE OVERWRITTEN WHEN IT IS REGENERATED ====
*
* This file was generated from
* C:/ti/grace_2_00_01_65/packages/ti/mcu/msp430/csl/interrupt_vectors/InterruptVectors_init.xdt
*/
#include <msp430.h>
/* USER CODE START (section: InterruptVectors_init_c_prologue) */
extern unsigned char *PTxData; // Pointer to TX data
extern unsigned char TXByteCtr;
extern unsigned char *PRxData; // Pointer to RX data
extern unsigned char RXByteCtr;
/* USER CODE END (section: InterruptVectors_init_c_prologue) */
/*
* ======== InterruptVectors_graceInit ========
void InterruptVectors_graceInit(void)
{}
/* Interrupt Function Prototypes */
* ======== USCI A0/B0 TX Interrupt Handler Generation ========
* Here are several important notes on using USCI_A0/B0 TX interrupt Handler:
* 1. User could use the following code as a template to service the interrupt
* handler. Just simply copy and paste it into your user definable code
* section.
* For UART and SPI configuration:
if (IFG2 & UCA0TXIFG) {
}
else if (IFG2 & UCB0TXIFG) {
}
* For I2C configuration:
if (IFG2 & UCA0/B0TXIFG) {
}
else if (IFG2 & UCA0/B0RXIFG) {
}
* 2. User could also exit from low power mode and continue with main
* program execution by using the following instruction before exiting
* this interrupt handler.
*
* __bic_SR_register_on_exit(LPMx_bits);
*/
#pragma vector=USCIAB0TX_VECTOR
__interrupt void USCI0TX_ISR_HOOK(void)
{
/* USER CODE START (section: USCI0TX_ISR_HOOK) */
if (TXByteCtr) // Check TX byte counter
UCB0TXBUF = *PTxData++; // Load TX buffer
TXByteCtr--; // Decrement TX byte counter}
else { UCB0CTL1 |= UCTXSTP; // I2C stop condition
IFG2 &= ~UCB0TXIFG; // Clear USCI_B0 TX int flag }
/* USER CODE END (section: USCI0TX_ISR_HOOK) */}
/*
* ======== USCI A0/B0 RX Interrupt Handler Generation ========
*
* Here are several important notes on using USCI_A0/B0 RX interrupt Handler:
* 1. User could use the following code as a template to service the interrupt
* handler. Just simply copy and paste it into your user definable code
* section.
* For UART and SPI configuration:
if (IFG2 & UCA0RXIFG) {}
else if (IFG2 & UCB0RXIFG) {}
* For I2C configuration:
if (UCB0STAT & UCSTTIFG) {}
else if (UCB0STAT & UCSTPIFG) {}
else if (UCB0STAT & UCNACKIFG) {}
else if (UCB0STAT & UCALIFG) {}
* 2. User could also exit from low power mode and continue with main
* program execution by using the following instruction before exiting
* this interrupt handler.
* __bic_SR_register_on_exit(LPMx_bits);
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR_HOOK(void)
{ /* USER CODE START (section: USCI0RX_ISR_HOOK) */
RXByteCtr--; // Decrement RX byte counter
if (RXByteCtr)
{P1OUT ^= 0x10;
*PRxData++ = UCB0RXBUF; // Move RX data to address PRxData
if (RXByteCtr == 1) // Only one byte left?
UCB0CTL1 |= UCTXSTP; // Generate I2C stop condition}
else
{ *PRxData = UCB0RXBUF; // Move final RX data to PRxData }
/* USER CODE END (section: USCI0RX_ISR_HOOK) */}
To be honest, this spent me much time to do. Anyway, thanks for your patience.
Comments
http://e2e.ti.com/support/microcontrollers/msp430/f/166
Though I can not really tell due to you not using [ code ] brackets:
G2553 have USCI, don't use i2c examples for the much simpler USI