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.

[参考译文] 将 Johnson He 和#39的 UART 连接到 I2C 桥接应用用于 DAC

Guru**** 2555870 points
Other Parts Discussed in Thread: MSP430FR2355

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1163671/using-johnson-he-s-uart-to-i2c-bridge-application-for-a-dac

主题中讨论的其他器件:MSP430FR2355

大家好、


我使用 MSP430FR2355控制器。 我正在使用 Johnson He 的 UART 转 I2C 桥接应用。 在应用中、我成功控制了 EEPROM。 是否有人知道该应用程序是否可用于所有 I2C 器件、因为我想通过 UART 帧控制具有 I2C 接口的 DAC。 我将以下 UART_Frame 发送到我的 DAC 进行测试(0x53 (I2cStart) 0xC0 (从器件地址+ RW 位) 0x03 (字节数) 0x60 0xD0 0x40 0x50 (停止 I2C))。
写入命令和从机地址被成功识别、但是要发送的3个字节包含错误的值、有人知道原因是什么吗? 我的 DAC 是 MCP4726。
我注意到、如果您发送了一次无效的 UART 帧、之后就不能发送有效的帧。 是否有人知道如何解决此问题、因为可能会发生一个无效的帧出现、UART_TO_I2C 桥仍应工作。

感谢你的帮助。

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

    Markus、您好!

    这应该是可行的、并且您描述的命令结构看起来是正确的。  

    您是否更改了任何内部寄存器的设置、是否也可以使用逻辑分析仪探测 UART 线?  

    此致、
    Brandon Fisher

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

    您好、Brandon、
    感谢您的回答、我必须将 I2C 时钟频率设置为50kHz 才能使其正常工作。 您是否知道我必须在源代码中进行哪些更改、以便它通过 I2C 连续发送数据2次? 因为我有2个 DAC 具有我使用芯片选择更改的相同地址。 因此两个 DAC 获得相同的值、即 I2C 必须连续发送两次相同的数据。

    谢谢你

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

    这是 quellcode  

    //  Johnson He
    //  Texas Instruments Inc.
    //  June. 2019
    //  Built with IAR Embedded Workbench v7.12.1 & Code Composer Studio v9.0.1
    //******************************************************************************
    #include <msp430.h>
    
    // Define parameters
    #define FRAM_ADDR 0xFD00                 // Internal FRAM address for store register
    #define I2C_TO_UART_BUFF_SIZE 100        // BUFF_SIZE Can be modified if needed
    #define UART_TO_I2C_BUFF_SIZE 100        // BUFF_SIZE Can be modified if needed
    
    // Declare global variables
    #if defined (__TI_COMPILER_VERSION__)
             unsigned int  i;                                         // for cycle
             char i2c_to_uart_data_buff[I2C_TO_UART_BUFF_SIZE];       // Buff
             char uart_to_i2c_data_buff[UART_TO_I2C_BUFF_SIZE];       // Buff
             unsigned char data_cnt;                                  // Used to data counter
    volatile unsigned char uart_cmd ;                                 // Identify "S" "P"  S:0x53 P:0x50
    volatile unsigned char i2c_send_cmd;                              // 1:Read 0:Write
    volatile unsigned int  i2c_send_length1;                          // I2C send length
    volatile unsigned int  i2c_send_length2;                          // I2C send length
    volatile unsigned char i2c_send_cnt;                              // Used to I2C send data counter
    volatile unsigned char i2c_recv_cnt;                              // Used to I2C recv data counter
    volatile unsigned char uart_send_cnt;                             // Used to UART send data counter
    volatile unsigned int  uart_baud;                                 // UART baud
    volatile unsigned int  i2c_speed;                                 // I2C clock
    
    #elif defined (__IAR_SYSTEMS_ICC__)
    __no_init          unsigned int  i;                                    // for cycle
    __no_init          char i2c_to_uart_data_buff[I2C_TO_UART_BUFF_SIZE];  // Buff
    __no_init          char uart_to_i2c_data_buff[UART_TO_I2C_BUFF_SIZE];  // Buff
    __no_init          unsigned char data_cnt;                             // Used to data counter
    __no_init volatile unsigned char uart_cmd ;                            // Identify "S" "P"  S:0x53 P:0x50
    __no_init volatile unsigned char i2c_send_cmd;                         // 1:Read 0:Write
    __no_init volatile unsigned int  i2c_send_length1;                     // I2C send length
    __no_init volatile unsigned int  i2c_send_length2;                     // I2C send length
    __no_init volatile unsigned char i2c_send_cnt;                         // Used to I2C send data counter
    __no_init volatile unsigned char i2c_recv_cnt;                         // Used to I2C recv data counter
    __no_init volatile unsigned char uart_send_cnt;                        // Used to UART send data counter
    __no_init volatile unsigned int  uart_baud;                            // UART baud
    __no_init volatile unsigned int  i2c_speed;                            // I2C clock
    #endif
    
    void Bridge(void);
    
    // Main Functions
    int main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;                              // stop watchdog timer
        FRCTL0 = FRCTLPW | NWAITS_1;                           // Configure one FRAM waitstate as
                                                               // required by the device datasheet for
                                                               // MCLK operation beyond 8MHz _before_
                                                               // configuring the clock system
        __bis_SR_register(SCG0);                               // Disable FLL
        CSCTL3 |= SELREF__REFOCLK;                             // Set REFO as FLL reference source
        CSCTL0 = 0;                                            // clear DCO and MOD registers
        CSCTL1 &= ~(DCORSEL_7);                                // Clear DCO frequency select bits first
        CSCTL1 |= DCORSEL_5;                                   // Set DCO = 16MHz
        CSCTL2 = FLLD_0 + 487;                                 // DCOCLKDIV = 16MHz
        __delay_cycles(3);                                     // Wait
        __bic_SR_register(SCG0);                               // Enable FLL
        while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1));             // FLL locked
    
        CSCTL4 = SELMS__DCOCLKDIV | SELA__REFOCLK;             // Set default REFO (~32768Hz)
                                                               // as ACLK source, ACLK = 32768Hz
                                                               // Default DCOCLKDIV as MCLK
                                                               // and SMCLK source
    
        PM5CTL0 &= ~LOCKLPM5;                                  // Disable GPIO power-on default
                                                               // high-impedance mode
    
        // Read data from FRAM used to UART baud and I2C clock
        uart_baud = *(unsigned int*) FRAM_ADDR;                // UART baud address, 16 bits
        i2c_speed = *(unsigned int*) (FRAM_ADDR + 2);          // I2C clock address, 16 bits
    
        // Initialize hardware I2C pins
        P1SEL0 |= BIT2 | BIT3 | BIT6 | BIT7;                   // I2C and UART pins
    
        // Configure eUSCI_1 UART module
        UCA0CTLW0 |= UCSWRST;                                  // Software reset enabled
        UCA0CTLW0 |= UCSSEL_2;                                 // set SMCLK as BRCLK
        UCA0BRW = (uart_baud == 0xffff) ? 0x008A : uart_baud;  // baud = INT(16000000/uart_baud), default : 115200
        UCA0CTLW0 &= ~UCSWRST;                                 // Initialize eUSCI
        UCA0IE |= UCRXIE;                                      // Enable USCI_A0 RX interrupt
    
        // Configure eUSCI_B I2C module
        UCB0CTLW0 |= UCSWRST;                                  // Software reset enabled
        UCB0CTLW0 |= UCMODE_3 | UCMST | UCSYNC;                // I2C mode, Master mode, sync
        UCB0CTLW1 |= UCASTP_1;                                 // No automatic stop generated
        UCB0BRW = (i2c_speed == 0xffff) ? 0x00A0 : i2c_speed;  // Bit rate clock = SMCLK/i2c_speed,default : 100KHz
        UCB0CTLW0 &= ~UCSWRST;                                 // Initialize eUSCI
        UCB0IE |= UCRXIE | UCTXIE0 | UCBCNTIE | UCSTPIE | UCNACKIE;       // Enable USCI_B0 RX TX CNT interrupt
    
        // Enable global interrupts and enter LPM0
        __bis_SR_register(LPM0_bits + GIE);
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
          if(uart_cmd == 0)
          {
             uart_to_i2c_data_buff[0] = UCA0RXBUF;
             data_cnt = 0;
             switch (UCA0RXBUF)
             {
             case 0x53: uart_cmd = 1; break;     // I2C Write/Read/Repeated_Write/Repeated_Read mode
             case 0x52: uart_cmd = 2; break;     // Read internal register mode
             case 0x57: uart_cmd = 3; break;     // Write internal register mode
             default:   uart_cmd = 0; break;     // don't care
             }
          }
          else
          {
              Bridge();                          // bridge function
          }
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCIB0_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
      {
        case USCI_I2C_UCRXIFG0:                       // Vector 22: RXIFG0
             i2c_to_uart_data_buff[i2c_recv_cnt] = UCB0RXBUF;
             i2c_recv_cnt ++;
             break;
        case USCI_I2C_UCNACKIFG:
             uart_cmd = 0;
             UCB0CTLW0 |= UCTXSTP;
             break;         // Vector 4: NACKIFG
        case USCI_I2C_UCTXIFG0:                       // Vector 24: TXIFG0
             UCB0TXBUF = uart_to_i2c_data_buff[i2c_send_cnt++]; // Send data by I2C
             break;
        case USCI_I2C_UCSTPIFG:                       // Vector 8: STPIFG
             UCB0IFG &= ~UCSTPIFG;                    // Clear stop condition int flag
             while(i2c_recv_cnt--)
             {
                 while(!(UCA0IFG&UCTXIFG));           // Wait UCA0 free
                 UCA0TXBUF = i2c_to_uart_data_buff[uart_send_cnt++];
             }
             uart_send_cnt = 0;
             i2c_recv_cnt = 0;
             break;
        case USCI_I2C_UCBCNTIFG:                      // Vector 26: BCNTIFG
             if(i2c_send_length2 == 0)
             {
                 UCB0CTLW0 |= UCTXSTP;                // Send STOP Bit
                 i2c_send_cmd = 0;
                 i2c_send_cnt = 0;
             }
             else
             {
                 if(i2c_send_cmd == 3)
                 {
                     UCB0CTLW0 &= ~UCTR;                                                  // Receiver/Read
                 }
                 else if(i2c_send_cmd == 4)
                 {
                     UCB0CTLW0 |= UCTR;                                                   // Transmitter/Write
                     i2c_send_cnt = i2c_send_length1 + 7;
                 }
                 UCB0I2CSA = (uart_to_i2c_data_buff[i2c_send_length1 + 4] & 0xfe) >> 1;   // Slave address
                 UCB0TBCNT = i2c_send_length2;                                            // I2C write length
                 UCB0TXBUF = uart_to_i2c_data_buff[i2c_send_length1 + 6];                 // I2C send data
                 UCB0CTL1 |= UCTXSTT;                                                     // I2C start condition
                 i2c_send_length2 = 0;
             }
             break;
      }
    }
    
    void Bridge(void)
    {
        switch(uart_cmd)
        {
        case 1:    // I2C Write/Read/Repeated_Write/Repeated_Read
               data_cnt ++ ;
               uart_to_i2c_data_buff[data_cnt] = UCA0RXBUF;
               i2c_send_cmd = (i2c_send_cmd == 0) ? (((UCA0RXBUF & 0x01) == 1) ? 1 : 2) : i2c_send_cmd; // 1:Read 2:Write/Repeated Write/Repeated Read
               switch(i2c_send_cmd)
               {
               // Read cmd
               case 1:
               if(data_cnt == 3)
               {
                   i2c_send_length1 = uart_to_i2c_data_buff[2];                   // Get read data length
                   if(uart_to_i2c_data_buff[3] == 0x50)
                   {
                       uart_cmd = 0;                                              // Exit cmd
                       i2c_send_length2 = 0;
                       data_cnt = 0;
                       UCB0CTLW0 &= ~UCTR;                                        // Receiver/Read
                       UCB0I2CSA = (uart_to_i2c_data_buff[1] & 0xfe) >> 1;        // Slave address
                       UCB0TBCNT = i2c_send_length1;                              // I2C read length
                       UCB0CTL1 |= UCTXSTT;                                       // I2C start condition
                   }
               }
               break;
    
               // Write cmd
               case 2:
               if((data_cnt > 2) && (data_cnt == uart_to_i2c_data_buff[2] + 3))
               {
                   i2c_send_length1 = uart_to_i2c_data_buff[2];                   // Get write data length
                   if(uart_to_i2c_data_buff[i2c_send_length1 + 3] == 0x50)
                   {
                       uart_cmd = 0;                                              // Exit cmd
                       i2c_send_length2 = 0;
                       data_cnt = 0;
                       UCB0CTLW0 |= UCTR;                                         // Transmitter/Write
                       UCB0I2CSA = (uart_to_i2c_data_buff[1] & 0xfe) >> 1;        // Slave address
                       UCB0TBCNT = i2c_send_length1;                              // I2C write length
                       UCB0CTL1 |= UCTXSTT;                                       // I2C start condition
                       i2c_send_cnt = 3;
                   }
                   else if(uart_to_i2c_data_buff[i2c_send_length1 + 3] == 0x53)
                   {
                       i2c_send_cmd = 3;                                          // Enter Repeated Read mode
                   }
               }
               break;
    
               // Repeated Read cmd
               case 3:
               if(data_cnt == i2c_send_length1 + 6)
               {
                   if((uart_to_i2c_data_buff[i2c_send_length1 + 4] & 0x01) == 0)
                   {
                       i2c_send_cmd = 4;                                          // Enter Repeated Write mode
                       i2c_send_length2 = uart_to_i2c_data_buff[i2c_send_length1 + 5];
                   }
                   else if(uart_to_i2c_data_buff[i2c_send_length1 + 6] == 0x50)
                   {
                       uart_cmd = 0;                                              // Exit cmd
                       i2c_send_length2 = uart_to_i2c_data_buff[i2c_send_length1 + 5];
                       data_cnt = 0;
                       UCB0CTLW0 |= UCTR;                                         // Transmitter/Write
                       UCB0I2CSA = (uart_to_i2c_data_buff[1] & 0xfe) >> 1;        // Slave address
                       UCB0TBCNT = i2c_send_length1;                              // I2C write length
                       UCB0CTL1 |= UCTXSTT;                                       // I2C start condition
                       i2c_send_cnt = 3;
                   }
               }
               break;
    
               // Repeated Write cmd
               case 4:
               if(data_cnt == i2c_send_length1 + i2c_send_length2 + 6)
               {
                   if(uart_to_i2c_data_buff[i2c_send_length1 + i2c_send_length2 + 6] == 0x50)
                   {
                        uart_cmd = 0;                                             // Exit cmd
                        data_cnt = 0;
                        UCB0CTLW0 |= UCTR;                                        // Transmitter/Write
                        UCB0I2CSA = (uart_to_i2c_data_buff[1] & 0xfe) >> 1;       // Slave address
                        UCB0TBCNT = i2c_send_length1;                             // I2C write length
                        UCB0CTL1 |= UCTXSTT;                                      // I2C start condition
                        i2c_send_cnt = 3;
                   }
               }
               break;
    
               default: break;
               }
               break;
        case 2:    // Read internal register
              data_cnt ++ ;
              uart_to_i2c_data_buff[data_cnt] = UCA0RXBUF;
              if(uart_to_i2c_data_buff[data_cnt] == 0x50)      // STOP
              {
                  for(i=1;i<data_cnt;i++)
                      {
                      while(!(UCA0IFG&UCTXIFG));
                      UCA0TXBUF = *(unsigned char *)(FRAM_ADDR + uart_to_i2c_data_buff[i]);     // Output value of internal register
                      }
                  uart_cmd = 0;    // Exit cmd
              }
            break;
        case 3:    // Write internal register
               data_cnt ++ ;
               uart_to_i2c_data_buff[data_cnt] = UCA0RXBUF;
               if((data_cnt % 2 == 1) && (uart_to_i2c_data_buff[data_cnt] == 0x50))   // STOP
               {
                   SYSCFG0 = FRWPPW;
                   for(i=1;i<data_cnt;i+=2)
                       {
                       *(unsigned char *)(FRAM_ADDR + uart_to_i2c_data_buff[i]) = uart_to_i2c_data_buff[i+1];  // Write value of internal register
                       }
                   SYSCFG0 = FRWPPW | PFWP;
                   UCA0CTLW0 |= UCSWRST;
                   UCA0BRW = (*(unsigned int*) FRAM_ADDR == 0xffff) ? 0x008A : *(unsigned int*) FRAM_ADDR;     // Set UART baud
                   UCA0CTLW0 &= ~UCSWRST;
                   UCA0IE |= UCRXIE;
                   UCB0CTLW0 |= UCSWRST;
                   UCB0BRW = (*(unsigned int*)(FRAM_ADDR + 2) == 0xffff) ? 0x00A0 : *(unsigned int*) (FRAM_ADDR + 2);  // Set I2C clock
                   UCB0CTLW0 &= ~UCSWRST;
                   UCB0IE |= UCRXIE | UCTXIE0 | UCBCNTIE | UCSTPIE;
                   uart_cmd = 0;   // Exit cmd
               }
            break;
        default : break;
        }
    }
    

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

    Markus、您好!

    这是处理这种情况的最佳方法吗、您是否总是想将相同的信息写入两个 DAC?  

    如果在 UART 控制器侧处理芯片选择引脚、则可能还需要在该侧处理两次发送消息(即发送 UART 数据包两次)。 否则、您可能会在此处遇到同步问题。  例如、MSP430可能会在芯片选择改变之前发送第二个 I2C 数据包。  

    此致、
    Brandon Fisher

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

    您好、Brandon、


    微控制器将 UART 帧发送到 MSP430。 这应通过桥将 UART 帧发送到 I2C。 但是、UART 帧应从 MSP 发送2次到 I2C、因为我有6个 DAC、每个 DAC 分为3至3个、并通过 CHIPselect 进行控制。 DAC A0 A1 A2 (芯片选择高电平)。DAC A0 A1 A2 (芯片选择低电平)。 始终具有两个相同的地址。 这意味着控制器向 MSP 发送一次、而 MSP 再向 I2C 发送2次、一次是芯片选择高电平、一次是芯片选择低电平、因此始终写入2个 DAC、即 A0 A0、A1 A1或 A2。 在任何情况下、MSP 都应发送芯片选择信号。
    在源代码中是否有一种简单的方法来实现此目的、您是否知道我必须在此处进行哪些更改?
    感谢你的帮助

    此致、

    Markus Jo