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.

[参考译文] MSP430FR5994:DMA不是由I2C中断触发的

Guru**** 2540720 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1089818/msp430fr5994-dma-not-triggered-by-a-i2c-interrupt

部件号:MSP430FR5994

嘿,社区,

有一段时间我尝试将DMA与我的I2C库集成以提高性能。 作为初始步骤,我只是想在不启用CPU的情况下将接收到的数据直接传输到内存中。因此,我配置了DMA通道4,以便它可以由我的UCB2 -I2C接收中断触发。但问题是DMA不是由该接收中断触发的。 但当我从I2C中断中提供DMAREQ时,它是有效的。我在下面附上了我的代码。 请浏览并告诉我您的建议。

注:我还在上读过Web DMA对I2C通信的贡献不及对SPI和UART的贡献。 因为我正在学习,所以我想自己学习和分析。

代码:

主要c

#include <msp430.h> 
#include <i2c\I2C.h>


/**
 * main.c
 */

#define ADXL_Address    0x53
#define Part_id      0x00
#define Clock_Div    80

#define Power_CTL             0x2D
#define Data_Rate             0x2C
#define Data_Format           0x31

#define X0_Reg                0x32


uint8_t adxl_Power_Ctl_cmd     [TYPE_0_LENGTH] = {0x08};  //
uint8_t adxl_Data_Rate_cmd     [TYPE_0_LENGTH] = {0x08};  // Lower power mode with 25 Hz bandwidth and 12.5Hz ODR   ||0x17 for 6.25hz bandwith and 12.5Hz ODR
uint8_t adxl_Data_Format_cmd   [TYPE_0_LENGTH] = {0x00};  //Range :+-2g INT inver bit is low

#define Power_CTL_value  0x08
#define Data_Rate_value  0x08
#define Data_Format_valu 0x00

int dma_value[10] = {0};
int data[10] = {0};



void DMA_Init()
{
    DMA4CTL    &=~DMAEN;

     DMACTL1    |= DMA4TSEL__UCB2RXIFG0;
//     DMACTL4    &=~DMARMWDIS;
     DMACTL4    |=DMARMWDIS;
     DMA4CTL    &=~DMA4CTL;
     __data20_write_long((uintptr_t) &DMA4SA,(uintptr_t) &UCB2RXBUF);
     __data20_write_long((uintptr_t) &DMA4DA,(uintptr_t)  &dma_value);

     DMA4SZ     = 6;

     DMA4CTL    |=DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__WORD|DMADSTBYTE__WORD|DMALEVEL__EDGE|DMAEN;
}


int main(void)
{
	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
	DMA_Init();
	initGPIO();

    initI2C(ADXL_Address, Clock_Div);
	
	while(1)
	{
//	    I2C_Master_ReadReg(ADXL_Address, Part_id, TYPE_0_LENGTH);
        I2C_Master_WriteReg(ADXL_Address, Data_Rate, adxl_Data_Rate_cmd, TYPE_0_LENGTH);
        I2C_Master_WriteReg(ADXL_Address, Data_Format, adxl_Data_Format_cmd, TYPE_0_LENGTH);
        I2C_Master_WriteReg(ADXL_Address, Power_CTL, adxl_Power_Ctl_cmd, TYPE_0_LENGTH);

        I2C_Master_ReadReg(ADXL_Address, X0_Reg, TYPE_2_LENGTH);


        data[0] = (short)((((unsigned short)dma_value[1]) << 8) | dma_value[0]);
        data[1] = (short)((((unsigned short)dma_value[3]) << 8) | dma_value[2]);
        data[2] = (short)((((unsigned short)dma_value[5]) << 8) | dma_value[4]);

	    __delay_cycles(1000000);
	}
	return 0;
}

I2C.h

/*
 * I2C.h
 *
 *  Created on: 10-Feb-2022
 *      Author: TOSHIBA
 */

#ifndef I2C_I2C_H_
#define I2C_I2C_H_

/*
 * i2c.h
 *
 *  Created on: 09-Oct-2021
 *      Author: TOSHIBA
 */

#ifndef I2C_H_
#define I2C_H_

#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>

//******************************************************************************
// Pin Config ******************************************************************
//******************************************************************************

#define LED_OUT     P1OUT
#define LED_DIR     P1DIR
#define LED0_PIN    BIT0
#define LED1_PIN    BIT1

#define CMD_TYPE_0_SLAVE      0x00
#define CMD_TYPE_1_SLAVE      0x1D
#define CMD_TYPE_2_SLAVE      3

#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] = {'F', '4', '1', '9', '2', 'B'};
//uint8_t MasterType1 [TYPE_1_LENGTH] = { 8, 9};
//uint8_t MasterType0 [TYPE_0_LENGTH] = {0x08};
//uint8_t MasterType3 [TYPE_0_LENGTH] = {0x0A};
//uint8_t MasterType4 [TYPE_0_LENGTH] = {0x03};
//
//
uint8_t SlaveType2 [TYPE_2_LENGTH] = {0};
uint8_t SlaveType1 [TYPE_1_LENGTH] = {0};
uint8_t SlaveType0 [TYPE_0_LENGTH] = {0};
//
//
//uint8_t Power_CTL_value [TYPE_0_LENGTH] = {0x08};
//uint8_t Data_Rate_value [TYPE_0_LENGTH] = {0x0A};
//uint8_t Data_Format_value [TYPE_0_LENGTH] = {0x03};


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;


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 initGPIO();

void initClockTo16MHz();

void initI2C(uint8_t SLAVE_ADDR,uint8_t clk_div);

/* Used to track the state of the software state machine*/
I2C_Mode MasterMode = IDLE_MODE;

/* The Register Address/Command to use*/
uint8_t TransmitRegAddr = 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;



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 */
    UCB2I2CSA = dev_addr;
    UCB2IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
    UCB2IE &= ~UCRXIE;                       // Disable RX interrupt
    UCB2IE |= UCTXIE;                        // Enable TX interrupt

    UCB2CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
    __enable_interrupt();
    __bis_SR_register(LPM0_bits);              // Enter LPM0 w/ interrupts

    return 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 TransmitBuffer
    CopyArray(reg_data, TransmitBuffer, count);

    TXByteCtr = count;
    RXByteCtr = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;

    /* Initialize slave address and interrupts */
    UCB2I2CSA = dev_addr;
    UCB2IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
    UCB2IE &= ~UCRXIE;                       // Disable RX interrupt
    UCB2IE |= UCTXIE;                        // Enable TX interrupt

    UCB2CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
    __enable_interrupt();
    __bis_SR_register(LPM0_bits);              // Enter LPM0 w/ interrupts

    return 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];
    }
}


//******************************************************************************
// Device Initialization *******************************************************
//******************************************************************************


void initGPIO()
{
    // Configure GPIO
    LED_OUT &= ~(LED0_PIN | LED1_PIN); // P1 setup for LED & reset output
    LED_DIR |= (LED0_PIN | LED1_PIN);

    // I2C pins
    P7SEL0 |= BIT0 | BIT1;
    P7SEL1 &= ~(BIT0 | BIT1);

    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;
}

void initClockTo16MHz()
{
    // Configure one FRAM waitstate as required by the device datasheet for MCLK
    // operation beyond 8MHz _before_ configuring the clock system.
    FRCTL0 = FRCTLPW | NWAITS_1;

    // Clock System Setup
    CSCTL0_H = CSKEY_H;                     // Unlock CS registers
    CSCTL1 = DCOFSEL_0;                     // Set DCO to 1MHz

    // Set SMCLK = MCLK = DCO, ACLK = LFXTCLK (VLOCLK if unavailable)
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;

    // Per Device Errata set divider to 4 before changing frequency to
    // prevent out of spec operation from overshoot transient
    CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4;   // Set all corresponding clk sources to divide by 4 for errata
    CSCTL1 = DCOFSEL_4 | DCORSEL;           // Set DCO to 16MHz

    // Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
    __delay_cycles(60);
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;   // Set all dividers to 1 for 16MHz operation
    CSCTL0_H = 0;                           // Lock CS registers
}

void initI2C(uint8_t SLAVE_ADDR,uint8_t clk_div)
{
    UCB2CTLW0 = UCSWRST;                      // Enable SW reset
    UCB2CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
    UCB2BRW = 10;                            // fSCL = SMCLK/160 = ~100kHz
    UCB2I2CSA = SLAVE_ADDR;                   // Slave Address
    UCB2CTLW0 &= ~UCSWRST;                    // Clear SW reset, resume operation
    UCB2IE |= UCNACKIE;
}


#endif /* I2C_H_ */


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B2_VECTOR))) USCI_B2_ISR (void)
#else
#error Compiler not supported!
#endif
{
  //Must read from UCB2RXBUF
  uint8_t rx_val = 0;
  switch(__even_in_range(UCB2IV, USCI_I2C_UCBIT9IFG))
  {
    case USCI_NONE:          break;         // Vector 0: No interrupts
    case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG
    case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
      break;
    case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
    case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG
    case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
    case USCI_I2C_UCTXIFG3:  break;         // Vector 12: TXIFG3
    case USCI_I2C_UCRXIFG2:  break;         // Vector 14: RXIFG2
    case USCI_I2C_UCTXIFG2:  break;         // Vector 16: TXIFG2
    case USCI_I2C_UCRXIFG1:  break;         // Vector 18: RXIFG1
    case USCI_I2C_UCTXIFG1:  break;         // Vector 20: TXIFG1
    case USCI_I2C_UCRXIFG0:                 // Vector 22: RXIFG0
//        rx_val = UCB2RXBUF;
        DMA4CTL |=DMAREQ;
        if (RXByteCtr)
        {
//          ReceiveBuffer[ReceiveIndex++] = rx_val;
          RXByteCtr--;
        }

        if (RXByteCtr == 1)
        {
          UCB2CTLW0 |= UCTXSTP;
        }
        else if (RXByteCtr == 0)
        {
          UCB2IE &= ~UCRXIE;
          MasterMode = IDLE_MODE;
          __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
        }
        break;
    case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
        switch (MasterMode)
        {
          case TX_REG_ADDRESS_MODE:
              UCB2TXBUF = TransmitRegAddr;
              if (RXByteCtr)
                  MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
              else
                  MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
              break;

          case SWITCH_TO_RX_MODE:
              UCB2IE |= UCRXIE;              // Enable RX interrupt
              UCB2IE &= ~UCTXIE;             // Disable TX interrupt
              UCB2CTLW0 &= ~UCTR;            // Switch to receiver
              MasterMode = RX_DATA_MODE;    // State state is to receive data
              UCB2CTLW0 |= UCTXSTT;          // Send repeated start
              if (RXByteCtr == 1)
              {
                  //Must send stop since this is the N-1 byte
                  while((UCB2CTLW0 & UCTXSTT));
                  UCB2CTLW0 |= UCTXSTP;      // Send stop condition
              }
              break;

          case TX_DATA_MODE:
              if (TXByteCtr)
              {
                  UCB2TXBUF = TransmitBuffer[TransmitIndex++];
                  TXByteCtr--;
              }
              else
              {
                  //Done with transmission
                  UCB2CTLW0 |= UCTXSTP;     // Send stop condition
                  MasterMode = IDLE_MODE;
                  UCB2IE &= ~UCTXIE;                       // disable TX interrupt
                  __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
              }
              break;

          default:
              __no_operation();
              break;
        }
        break;
    default: break;
  }
}


#endif /* I2C_I2C_H_ */

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

    > UCB2IE |= UCRXIE;//启用RX中断

    启用Rx中断将阻止其触发DMA [参考用户指南(SLAU367P)表11-2]。 如果您使用 的是DMA4TSLE__UCB2RXIFG0,则需要删除此行。

    -------------------

    主动提供:  

    > DMA4CTL |=DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__WORD|DMADSTBYTE__WORD|DMALEVEL__EDGE|DMAEN;

    UCB2RXBUF (有效)是一个字节,您(大概)也想将字节写入内存。 请尝试:

    > DMA4CTL |=DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__byte|DMADSTBYTE__byte|DMALEVEL__EDGE|DMAEN;

    --------

    我不知道与您提到的UART/SPI进行比较的背景。 通常,DMA对短传输的收益较低,因为您必须摊销设置DMA的成本,但DMA对任何使用都能获得相同的收益(中断较少,因此通常更快,无人值守的操作)。

    [编辑:还要考虑使用USASTP(=2)[参考用户指南第32.3 节. 8.2 ]。 如果没有它,您很有可能会读取太多的一个字节,这将使您的DMA (更不用说您的数据)丢失。]

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

    嗨,Bruce,

    我尝试通过禁用 UCB2IE |= UCRXIE来解决问题。  但是一旦我禁用了UCRXIE,我从传感器得到了响应,但它仍然没有触发DMA。它只是卡在LPM0模式中。

    它浏览了表,并被告知“当eUSSCI_Bx接收到新数据时,将触发传输。 传输开始时,UCBxRXIFG会自动重置。 如果设置了UCBxRXIE,UCBxRXIFG不会触发传输。"所以我尝试启用UCRXIE,并注释掉整个RXIFG0部分,但仍然得到相同的结果。

    我已附上修改的代码:

    I2C.h

    /*
     * I2C.h
     *
     *  Created on: 10-Feb-2022
     *      Author: TOSHIBA
     */
    
    #ifndef I2C_I2C_H_
    #define I2C_I2C_H_
    
    /*
     * i2c.h
     *
     *  Created on: 09-Oct-2021
     *      Author: TOSHIBA
     */
    
    #ifndef I2C_H_
    #define I2C_H_
    
    #include <msp430.h>
    #include <stdint.h>
    #include <stdbool.h>
    
    //******************************************************************************
    // Pin Config ******************************************************************
    //******************************************************************************
    
    #define LED_OUT     P1OUT
    #define LED_DIR     P1DIR
    #define LED0_PIN    BIT0
    #define LED1_PIN    BIT1
    
    #define CMD_TYPE_0_SLAVE      0x00
    #define CMD_TYPE_1_SLAVE      0x1D
    #define CMD_TYPE_2_SLAVE      3
    
    #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] = {'F', '4', '1', '9', '2', 'B'};
    //uint8_t MasterType1 [TYPE_1_LENGTH] = { 8, 9};
    //uint8_t MasterType0 [TYPE_0_LENGTH] = {0x08};
    //uint8_t MasterType3 [TYPE_0_LENGTH] = {0x0A};
    //uint8_t MasterType4 [TYPE_0_LENGTH] = {0x03};
    //
    //
    uint8_t SlaveType2 [TYPE_2_LENGTH] = {0};
    uint8_t SlaveType1 [TYPE_1_LENGTH] = {0};
    uint8_t SlaveType0 [TYPE_0_LENGTH] = {0};
    //
    //
    //uint8_t Power_CTL_value [TYPE_0_LENGTH] = {0x08};
    //uint8_t Data_Rate_value [TYPE_0_LENGTH] = {0x0A};
    //uint8_t Data_Format_value [TYPE_0_LENGTH] = {0x03};
    
    
    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;
    
    
    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 initGPIO();
    
    void initClockTo16MHz();
    
    void initI2C(uint8_t SLAVE_ADDR,uint8_t clk_div);
    
    /* Used to track the state of the software state machine*/
    I2C_Mode MasterMode = IDLE_MODE;
    
    /* The Register Address/Command to use*/
    uint8_t TransmitRegAddr = 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;
    
    
    
    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 */
        UCB2I2CSA = dev_addr;
        UCB2IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB2IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB2IE |= UCTXIE;                        // Enable TX interrupt
    
        UCB2CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __enable_interrupt();
        __bis_SR_register(LPM0_bits);              // Enter LPM0 w/ interrupts
    
        return 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 TransmitBuffer
        CopyArray(reg_data, TransmitBuffer, count);
    
        TXByteCtr = count;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
    
        /* Initialize slave address and interrupts */
        UCB2I2CSA = dev_addr;
        UCB2IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB2IE &= ~UCRXIE;                       // Disable RX interrupt
        UCB2IE |= UCTXIE;                        // Enable TX interrupt
    
        UCB2CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition
        __enable_interrupt();
        __bis_SR_register(LPM0_bits);              // Enter LPM0 w/ interrupts
    
        return 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];
        }
    }
    
    
    //******************************************************************************
    // Device Initialization *******************************************************
    //******************************************************************************
    
    
    void initGPIO()
    {
        // Configure GPIO
        LED_OUT &= ~(LED0_PIN | LED1_PIN); // P1 setup for LED & reset output
        LED_DIR |= (LED0_PIN | LED1_PIN);
    
        // I2C pins
        P7SEL0 |= BIT0 | BIT1;
        P7SEL1 &= ~(BIT0 | BIT1);
    
        // Disable the GPIO power-on default high-impedance mode to activate
        // previously configured port settings
        PM5CTL0 &= ~LOCKLPM5;
    }
    
    void initClockTo16MHz()
    {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRCTL0 = FRCTLPW | NWAITS_1;
    
        // Clock System Setup
        CSCTL0_H = CSKEY_H;                     // Unlock CS registers
        CSCTL1 = DCOFSEL_0;                     // Set DCO to 1MHz
    
        // Set SMCLK = MCLK = DCO, ACLK = LFXTCLK (VLOCLK if unavailable)
        CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;
    
        // Per Device Errata set divider to 4 before changing frequency to
        // prevent out of spec operation from overshoot transient
        CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4;   // Set all corresponding clk sources to divide by 4 for errata
        CSCTL1 = DCOFSEL_4 | DCORSEL;           // Set DCO to 16MHz
    
        // Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz))
        __delay_cycles(60);
        CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;   // Set all dividers to 1 for 16MHz operation
        CSCTL0_H = 0;                           // Lock CS registers
    }
    
    void initI2C(uint8_t SLAVE_ADDR,uint8_t clk_div)
    {
        UCB2CTLW0 = UCSWRST;                      // Enable SW reset
        UCB2CTLW0 |= UCMODE_3 | UCMST | UCSSEL__SMCLK | UCSYNC; // I2C master mode, SMCLK
        UCB2BRW = 10;                            // fSCL = SMCLK/160 = ~100kHz
        UCB2I2CSA = SLAVE_ADDR;                   // Slave Address
        UCB2CTLW0 &= ~UCSWRST;                    // Clear SW reset, resume operation
        UCB2IE |= UCNACKIE;
    }
    
    
    #endif /* I2C_H_ */
    
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B2_VECTOR
    __interrupt void USCI_B2_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B2_VECTOR))) USCI_B2_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      //Must read from UCB2RXBUF
      uint8_t rx_val = 0;
      switch(__even_in_range(UCB2IV, USCI_I2C_UCBIT9IFG))
      {
        case USCI_NONE:          break;         // Vector 0: No interrupts
        case USCI_I2C_UCALIFG:   break;         // Vector 2: ALIFG
        case USCI_I2C_UCNACKIFG:                // Vector 4: NACKIFG
          break;
        case USCI_I2C_UCSTTIFG:  break;         // Vector 6: STTIFG
        case USCI_I2C_UCSTPIFG:  break;         // Vector 8: STPIFG
        case USCI_I2C_UCRXIFG3:  break;         // Vector 10: RXIFG3
        case USCI_I2C_UCTXIFG3:  break;         // Vector 12: TXIFG3
        case USCI_I2C_UCRXIFG2:  break;         // Vector 14: RXIFG2
        case USCI_I2C_UCTXIFG2:  break;         // Vector 16: TXIFG2
        case USCI_I2C_UCRXIFG1:  break;         // Vector 18: RXIFG1
        case USCI_I2C_UCTXIFG1:  break;         // Vector 20: TXIFG1
    //    case USCI_I2C_UCRXIFG0:                 // Vector 22: RXIFG0
    //////        rx_val = UCB2RXBUF;
    ////        DMA4CTL |=DMAREQ;
    ////        if (RXByteCtr)
    ////        {
    //////          ReceiveBuffer[ReceiveIndex++] = rx_val;
    ////          RXByteCtr--;
    ////        }
    ////
    ////        if (RXByteCtr == 1)
    ////        {
    ////          UCB2CTLW0 |= UCTXSTP;
    ////        }
    ////        else if (RXByteCtr == 0)
    ////        {
    ////          UCB2IE &= ~UCRXIE;
    ////          MasterMode = IDLE_MODE;
    ////          __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
    ////        }
    //        break;
        case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
            switch (MasterMode)
            {
              case TX_REG_ADDRESS_MODE:
                  UCB2TXBUF = TransmitRegAddr;
                  if (RXByteCtr)
                      MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
                  else
                      MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
                  break;
    
              case SWITCH_TO_RX_MODE:
    //              UCB2IE |= UCRXIE;              // Enable RX interrupt
                  UCB2IE &= ~UCTXIE;             // Disable TX interrupt
                  UCB2CTLW0 &= ~UCTR;            // Switch to receiver
                  MasterMode = RX_DATA_MODE;    // State state is to receive data
                  UCB2CTLW0 |= UCTXSTT;          // Send repeated start
                  if (RXByteCtr == 1)
                  {
                      //Must send stop since this is the N-1 byte
                      while((UCB2CTLW0 & UCTXSTT));
                      UCB2CTLW0 |= UCTXSTP;      // Send stop condition
                  }
                  break;
    
              case TX_DATA_MODE:
                  if (TXByteCtr)
                  {
                      UCB2TXBUF = TransmitBuffer[TransmitIndex++];
                      TXByteCtr--;
                  }
                  else
                  {
                      //Done with transmission
                      UCB2CTLW0 |= UCTXSTP;     // Send stop condition
                      MasterMode = IDLE_MODE;
                      UCB2IE &= ~UCTXIE;                       // disable TX interrupt
                      __bic_SR_register_on_exit(CPUOFF);      // Exit LPM0
                  }
                  break;
    
              default:
                  __no_operation();
                  break;
            }
            break;
        default: break;
      }
    }
    
    
    #endif /* I2C_I2C_H_ */
    

    主要c

    #include <msp430.h> 
    #include <i2c\I2C.h>
    
    
    /**
     * main.c
     */
    
    #define ADXL_Address    0x53
    #define Part_id      0x00
    #define Clock_Div    80
    
    #define Power_CTL             0x2D
    #define Data_Rate             0x2C
    #define Data_Format           0x31
    
    #define X0_Reg                0x32
    
    
    uint8_t adxl_Power_Ctl_cmd     [TYPE_0_LENGTH] = {0x08};  //
    uint8_t adxl_Data_Rate_cmd     [TYPE_0_LENGTH] = {0x08};  // Lower power mode with 25 Hz bandwidth and 12.5Hz ODR   ||0x17 for 6.25hz bandwith and 12.5Hz ODR
    uint8_t adxl_Data_Format_cmd   [TYPE_0_LENGTH] = {0x00};  //Range :+-2g INT inver bit is low
    
    #define Power_CTL_value  0x08
    #define Data_Rate_value  0x08
    #define Data_Format_valu 0x00
    
    int dma_value[10] = {0};
    int data[10] = {0};
    
    
    
    void DMA_Init()
    {
        DMA4CTL    &=~DMAEN;
    
         DMACTL1    |= DMA4TSEL__UCB2RXIFG0;
    //     DMACTL4    &=~DMARMWDIS;
         DMACTL4    |=DMARMWDIS;
         DMA4CTL    &=~DMA4CTL;
         __data20_write_long((uintptr_t) &DMA4SA,(uintptr_t) &UCB2RXBUF);
         __data20_write_long((uintptr_t) &DMA4DA,(uintptr_t)  &dma_value);
    
         DMA4SZ     = 6;
         DMA4CTL &= ~DMAIFG;
         DMA4CTL    |=DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__BYTE|DMADSTBYTE__BYTE|DMALEVEL__EDGE|DMAIE|DMAEN;
    }
    
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	DMA_Init();
    	initGPIO();
    
        initI2C(ADXL_Address, Clock_Div);
    	
    	while(1)
    	{
    	    I2C_Master_ReadReg(ADXL_Address, Part_id, TYPE_0_LENGTH);
            I2C_Master_WriteReg(ADXL_Address, Data_Rate, adxl_Data_Rate_cmd, TYPE_0_LENGTH);
            I2C_Master_WriteReg(ADXL_Address, Data_Format, adxl_Data_Format_cmd, TYPE_0_LENGTH);
            I2C_Master_WriteReg(ADXL_Address, Power_CTL, adxl_Power_Ctl_cmd, TYPE_0_LENGTH);
    
            I2C_Master_ReadReg(ADXL_Address, X0_Reg, TYPE_2_LENGTH);
    
    
            data[0] = (short)((((unsigned short)dma_value[1]) << 8) | dma_value[0]);
            data[1] = (short)((((unsigned short)dma_value[3]) << 8) | dma_value[2]);
            data[2] = (short)((((unsigned short)dma_value[5]) << 8) | dma_value[4]);
    
    	    __delay_cycles(1000000);
    	}
    	return 0;
    }
    
    
    //------------------------------------------------------------------------------
    // DMA Interrupt Service Routine
    //------------------------------------------------------------------------------
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=DMA_VECTOR
    __interrupt void DMA_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(DMAIV,16))
      {
        case 0: break;
        case 2:                                 // DMA0IFG = DMA Channel
            break;
        case 4: break;                          // DMA1IFG = DMA Channel 1
        case 6: break;                          // DMA2IFG = DMA Channel 2
        case 8: break;                          // DMA3IFG = DMA Channel 3
        case 10:
            P1OUT ^= BIT0;                        // Toggle P1.0 - PLACE BREAKPOINT HERE AND CHECK DMA_DST VARIABLE
            break;                         // DMA4IFG = DMA Channel 4
        case 12: break;                         // DMA5IFG = DMA Channel 5
        case 14: break;                         // DMA6IFG = DMA Channel 6
        case 16: break;                         // DMA7IFG = DMA Channel 7
        default: break;
      }
    }
    

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

    >DMACTL1 |= DMA4Tsel__UCB2RXIFG0;
    DMA4TSEL位于DMACTL2中。 [参考UG表11-7]。 尝试:

    >DMACTL2 |= DMA4Tsel__UCB2RXIFG0;

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

    嗨,Bruce,

    感谢你的帮助。 它真的很有效。 感谢您提供以下提示。 刚才我遇到了这个问题。

    [403.5409万[编辑:还要考虑使用USASTP=2 8.2 用户指南[参考][Users.Users][参考32.3。 如果没有它,您很有可能会读取过多的字节,这将使您的DMA (更不用说您的数据)丢失。]