Jump to content
43oh

canid

Members
  • Content Count

    7
  • Joined

  • Last visited

  • Days Won

    1

Posts posted by canid

  1. I'll be updating soonish, but I'm merging the slave code and trying to do pheripheral selection/config using preprocessing.

     

    peripherals I'm incorporating into the slave code:

    * Digital out:    Relays and TTL,

    * Digital  in:     Switches and TTL,

    * Thermistors: Specific NTC at least.

    * CTs

     

    When I've got that fleshed out, I'll get back to the first master code and rethink the comand protocol.

  2. This is very much in progress, and there's nothing fancy about it, but I wanted to share with you what I'm working on at the moment since I'm back into the 430 again after a while in arm/linux land.

     

    Only the relay stuff is implemented for now and the master is currently just a test which advances the relay selections by push of the s2 button. Criticism, ideas and insults welcome :D

     

    I would like to do various slave firmwares for sensors, etc and I will be incoprorating also a BBB controller at some point.

     

    Code shamefully stolen/modified from TI examples.

     

    Master.c

    //******************************************************************************
    //   MSP430G2x31 - I2C Automation Controller/Sensor, Master
    //
    //   Description: This is the test firmware for the I2C master controller. It
    // currently advances, by action of s2 on the launchpad (falling edge of P1.3),
    // the control word from 0x00 through 0x1111 were each bit is the relay to be
    // (0) opened or (1) closed. It will be updated to reflect the desired control
    // protocol shortly.
    //
    //******************************************************************************
     
    #include <msp430g2231.h>
     
    char MST_Data = 0;                      // Variable for transmitted data
    char SLV_Addr = 0x90;                   // Address is 0x48 << 1 bit + 0 for Write
    int I2C_State = 0;                      // State variable
     
    void main(void) {
        volatile unsigned int i;             // Use volatile to prevent removal
     
        WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog
        if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF) {
            while(1);                          // If calibration constants erased do not load, trap CPU!!
        }
        BCSCTL1 = CALBC1_1MHZ;               // Set DCO
        DCOCTL = CALDCO_1MHZ;
     
        P1OUT = 0xC0;                        // P1.6 & P1.7 Pullups, others to 0
        P1OUT |= BIT3;
        P1REN |= 0xC0;                       // P1.3, P1.6 & P1.7 Pullups
        P1REN |= BIT3;
        P1DIR = 0xFF;
        P1DIR &= ~BIT3;                   // Unused pins as outputs. s2 as input.
        P1IE |= BIT3;                   // Enable P1 interrupt for P1.3
        P2OUT = 0;
        P2DIR = 0xFF;
     
        USICTL0 = USIPE6+USIPE7+USIMST+USISWRST; // Port & USI mode setup
        USICTL1 = USII2C+USIIE;              // Enable I2C mode & USI interrupt
        USICKCTL = USIDIV_3+USISSEL_2+USICKPL; // Setup USI clocks: SCL = SMCLK/8 (~125kHz)
        USICNT |= USIIFGCC;                  // Disable automatic clear control
        USICTL0 &= ~USISWRST;                // Enable USI
        USICTL1 &= ~USIIFG;                  // Clear pending flag
        P1IFG &= ~BIT3;                     // Clear p1.3 interrupt flag.
        _EINT();
     
        while(1) {
            USICTL1 |= USIIFG;                 // Set flag and start communication
            LPM0;                              // CPU off, await USI interrupt
            _NOP();                            // Used for IAR
            for (i = 0; i < 5000; i++);        // Dummy delay between communication cycles
        }
    }
     
    /******************************************************
    // Port1 isr
    ******************************************************/
     
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void) {
        USICTL1 &= ~USIIE;          // Disable I2C interrupt until we finish.
     
        P1IE &= ~BIT3;              // Clear own interrupt until we finish
     
        if(MST_Data < 15) {
            MST_Data++;            // Increment Master data
        } else {
            MST_Data = 0;
        }
        P1OUT &= ~BIT0;
        __delay_cycles(1000000);
        P1OUT |= BIT0;
     
        P1IE |= BIT3;               // Re-enable own interrupt and clear interrupt flag.
        P1IFG &= ~BIT3;
     
        USICTL1 |= USIIE;           // Re-enable I2C interrupt and clear pending flag.
        USICTL1 &= ~USIIFG;
    }
     
    /******************************************************
    // USI isr
    ******************************************************/
    #pragma vector = USI_VECTOR
    __interrupt void USI_TXRX (void) {
        switch(I2C_State) {
            case 0: // Generate Start Condition & send address to slave
                  //P1OUT |= 0x01;           // LED on: sequence start
                USISRL = 0x00;           // Generate Start Condition...
                USICTL0 |= USIGE+USIOE;
                USICTL0 &= ~USIGE;
                USISRL = SLV_Addr;       // ... and transmit address, R/W = 0
                USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, TX Address
                I2C_State = 2;           // Go to next state: receive address (N)Ack
                break;
     
            case 2: // Receive Address Ack/Nack bit
                USICTL0 &= ~USIOE;       // SDA = input
                USICNT |= 0x01;          // Bit counter = 1, receive (N)Ack bit
                I2C_State = 4;           // Go to next state: check (N)Ack
                break;
     
            case 4: // Process Address Ack/Nack & handle data TX
                USICTL0 |= USIOE;        // SDA = output
                if (USISRL & 0x01) {       // If Nack received, send stop
                    USISRL = 0x00;
                    USICNT |=  0x01;       // Bit counter = 1, SCL high, SDA low
                    I2C_State = 10;        // Go to next state: generate Stop
                    //P1OUT |= 0x01;         // Turn on LED: error
                } else { // Ack received, TX data to slave...
                    USISRL = MST_Data;     // Load data byte
                    USICNT |=  0x08;       // Bit counter = 8, start TX
                    I2C_State = 6;         // Go to next state: receive data (N)Ack
                    //P1OUT &= ~0x01;        // Turn off LED
                } break;
     
            case 6: // Receive Data Ack/Nack bit
                USICTL0 &= ~USIOE;       // SDA = input
                USICNT |= 0x01;          // Bit counter = 1, receive (N)Ack bit
                I2C_State = 8;           // Go to next state: check (N)Ack
                break;
     
            case 8: // Process Data Ack/Nack & send Stop
                USICTL0 |= USIOE;
                if (USISRL & 0x01) {       // If Nack received...
                    //P1OUT |= 0x01;         // Turn on LED: error
                } else {                     // Ack received
                    //P1OUT &= ~0x01;        // Turn off LED
                }
                // Send stop...
                USISRL = 0x00;
                USICNT |=  0x01;         // Bit counter = 1, SCL high, SDA low
                I2C_State = 10;          // Go to next state: generate Stop
                break;
     
            case 10:// Generate Stop Condition
                USISRL = 0x0FF;          // USISRL = 1 to release SDA
                USICTL0 |= USIGE;        // Transparent latch enabled
                USICTL0 &= ~(USIGE+USIOE);// Latch/SDA output disabled
                I2C_State = 0;           // Reset state machine for next transmission
                LPM0_EXIT;               // Exit active for next transfer
                break;
        }
        USICTL1 &= ~USIIFG;                  // Clear pending flag
    }
    
    

    Slave.c

    //******************************************************************************
    //   MSP430G2x31 - I2C Automation Controller/Sensor, Slave Node
    //
    //   Description: This is the firmware for the i2c slave controller
    //
    //******************************************************************************
    
    #include <msp430.h>
    
    // peripheral selections
    #define ADC                                // Define if slave needs ADC10
    
    //   Select peripheral type for each pin:
    // RELAY for relay or other digital output such as MOSFET or other TTL control,
    // DIGITAL for digtal input such as TTL sensor, switch, etc.
    // CT for current transformer,
    // NTC for negative temp. coefficient thermistor,
    // PTC for positive temp. coefficient thermistor,
    #define P1_0 RELAY
    #define P1_1 RELAY
    #define P1_2 RELAY
    #define P1_3 RELAY
    #define P1_4 CT
    #define P1_5 NTC
    
    char ownAddr = 0x90;                  // Address is 0x48<<1 for R/W
    int i2cState = 0;                     // State variable
    unsigned char RXData=0;
    
    void main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;            // Stop watchdog
      if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
      {
        while(1);                          // If calibration constants erased
                                           // do not load, trap CPU!!
      }
    
      // Peripherals setup
      // port setup stuff
      #if P1_0 == RELAY
        P1DIR |= BIT0;                        // set pin to output.
      #elif P1_0 == THERM
        P1DIR &= ~BIT0;                        // set pin to input.
        ADC10CTL1 |= INCH0;                    // enable adc chan. 0
      #elif P1_0 == CT
        P1DIR &= ~BIT0;                        // set pin to input.
        ADC10CTL1 |= INCH0;                    // enable adc chan
      #elif P1_0 == ACLK
    
      #elif P1_0 == TA0CLK
    
      #endif
    
      #if P1_1 == RELAY
        P1DIR |= BIT1;                        // set pin to output.
      #elif P1_1 == THERM
        P1DIR &= ~BIT1;                        // set pin to input.
        ADC10CTL1 |= INCH1;                    // enable adc chan.
      #elif P1_1 == CT
        P1DIR &= ~BIT1;                        // set pin to input.
        ADC10CTL1 |= INCH1;                    // enable adc chan.
      #elif P1_1 == TA0
    
      #endif
    
      #if P1_2 == RELAY
          P1DIR |= BIT2;                        // set pin to output.
      #elif P1_2 == THERM
        P1DIR &= ~BIT2;                        // set pin to input.
        ADC10CTL1 |= INCH2;                    // enable adc chan.
      #elif P1_2 == CT
        P1DIR &= ~BIT2;                        // set pin to input.
        ADC10CTL1 |= INCH2;                    // enable adc chan.
      #elif P1_2 == TA0
    
      #endif
    
      #if P1_3 == RELAY
          P1DIR |= BIT3;                        // set pin to output.
      #elif P1_3 == NTC
        P1DIR &= ~BIT3;                        // set pin to input.
        ADC10CTL1 |= INCH3;                    // enable adc chan.
      #elif P1_3 == CT
        P1DIR &= ~BIT3;                        // set pin to input.
        ADC10CTL1 |= INCH3;                    // enable adc chan.
      #elif P1_3 == ADC10CLK
    
      #elif P1_3 == VREFn
    
      #endif
    
      #if P1_4 == RELAY
          P1DIR |= BIT4;                        // set pin to output.
      #elif P1_4 == THERM
        P1DIR &= ~BIT4;                        // set pin to input.
        ADC10CTL1 |= INCH4;                    // enable adc chan.
      #elif P1_4 == CT
        P1DIR &= ~BIT4;                        // set pin to input.
        ADC10CTL1 |= INCH4;                    // enable adc chan.
      #elif P1_4 == SMCLK
    
      #elif P1_4 == VREFp
    
      #endif
    
      #if P1_5 == RELAY
          P1DIR |= BIT5;                        // set pin to output.
      #elif P1_5 == THERM
          P1DIR &= ~BIT5;                        // set pin to input.
          ADC10CTL1 |= INCH5;                    // enable adc chan.
      #elif P1_5 == CT
          P1DIR &= ~BIT5;                        // set pin to input.
          ADC10CTL1 |= INCH5;                    // enable adc chan.
      #elif P1_5 == SCLK
    
      #endif
    
    
      BCSCTL1 = CALBC1_1MHZ;               // Set DCO
      DCOCTL = CALDCO_1MHZ;
    
      P1OUT = 0xC0;                        // P1.6 & P1.7 Pullups
      P1REN |= 0xC0;                       // P1.6 & P1.7 Pullups
      P2OUT = 0;
      P2DIR = 0xFF;
    
      USICTL0 = USIPE6+USIPE7+USISWRST;    // Port & USI mode setup
      USICTL1 = USII2C+USIIE+USISTTIE;     // Enable I2C mode & USI interrupts
      USICKCTL = USICKPL;                  // Setup clock polarity
      USICNT |= USIIFGCC;                  // Disable automatic clear control
      USICTL0 &= ~USISWRST;                // Enable USI
      USICTL1 &= ~USIIFG;                  // Clear pending flag
      _EINT();
    
      #ifdef ADC
        ADC10CTL0 |= ENC + ADC10SC;
      #endif
    
      while(1)
      {
        LPM0;                              // CPU off, await USI interrupt
        _NOP();                            // Used for IAR
      }
    }
    
    //******************************************************************************
    // USI interrupt service routine
    //******************************************************************************
    #pragma vector = USI_VECTOR
    __interrupt void USI_TXRX (void)
    {
      if (USICTL1 & USISTTIFG)             // Start entry?
      {
        P1OUT |= 0x01;                     // LED on: sequence start
        i2cState = 2;                     // Enter 1st state on start
      }
    
      switch(i2cState)
        {
          case 0: // Idle, should not get here
                  break;
    
          case 2: // RX Address
                  USICNT = (USICNT & 0xE0) + 0x08; // Bit counter = 8, RX address
                  USICTL1 &= ~USISTTIFG;   // Clear start flag
                  i2cState = 4;           // Go to next state: check address
                  break;
    
          case 4: // Process Address and send (N)Ack
                  if (USISRL & 0x01)       // If read...
                    ownAddr++;            // Save R/W bit
                  USICTL0 |= USIOE;        // SDA = output
                  if (USISRL == ownAddr)  // Address match?
                  {
                    USISRL = 0x00;         // Send Ack
                    P1OUT &= ~0x01;        // LED off
                    i2cState = 8;         // Go to next state: RX data
                  }
                  else
                  {
                    USISRL = 0xFF;         // Send NAck
                    P1OUT |= 0x01;         // LED on: error
                    i2cState = 6;         // Go to next state: prep for next Start
                  }
                  USICNT |= 0x01;          // Bit counter = 1, send (N)Ack bit
                  break;
    
          case 6: // Prep for Start condition
                  USICTL0 &= ~USIOE;       // SDA = input
                  ownAddr = 0x90;         // Reset slave address
                  i2cState = 0;           // Reset state machine
                  break;
    
          case 8: // Receive data byte
                  USICTL0 &= ~USIOE;       // SDA = input
                  USICNT |=  0x08;         // Bit counter = 8, RX data
                  i2cState = 10;          // Go to next state: Test data and (N)Ack
                  break;
    
          case 10:// Check Data & TX (N)Ack
                  RXData = USISRL;                 // Get RX data
    
                  USICTL0 |= USIOE;        // SDA = output
                  P1OUT = 0x0;
                  if(RXData & BIT0) {
                      P1OUT |= BIT1;
                  } if(RXData & BIT1) {
                      P1OUT |= BIT2;
                  } if(RXData & BIT2) {
                      P1OUT |= BIT3;
                  } if(RXData & BIT3) {
                      P1OUT |= BIT4;
                  } USISRL = 0x00;         // Send Ack
                  P1OUT &= ~0x01;        // LED off
    /*              {
                    USISRL = 0xFF;         // Send NAck
                    P1OUT |= 0x01;         // LED on: error
                  }
    */
                  USICNT |= 0x01;          // Bit counter = 1, send (N)Ack bit
                  i2cState = 6;           // Go to next state: prep for next Start
                  break;
        }
    
      USICTL1 &= ~USIIFG;                  // Clear pending flags
    }
    
    

    And I got lazy and did a fraunchpad version for testing which uses LED 5-8 instead of external relays and the extra voltage level.

    //******************************************************************************
    //  MSP430G2x31 - I2C Relay Controller, Fraunchpad Slave
    //
    //   Description: This is a test version of the slave firmware for conveniently
    // testing using the Fraunchpad and it's user LEDs 5-8 in place of relays.
    //
    //******************************************************************************
     
     
    #include <msp430.h>
     
    unsigned char RXData;
     
    int main(void)
     
    {
     
        WDTCTL = WDTPW + WDTHOLD;
     
        // Init SMCLK = MCLk = ACLK = 1MHz
        CSCTL0_H = 0xA5;
        CSCTL1 |= DCOFSEL0 + DCOFSEL1;          // Set max. DCO setting = 8MHz
        CSCTL2 = SELA_3 + SELS_3 + SELM_3;      // set ACLK = MCLK = DCO
        CSCTL3 = DIVA_3 + DIVS_3 + DIVM_3;      // set all dividers to 1MHz
      
        // Configure Pins for I2C
        P1SEL1 |= BIT6 + BIT7;                  // Pin init
     
        // Configure pins for LEDs 5-8
        P3DIR = BIT4+BIT5+BIT6+BIT7;
     
        // eUSCI configuration
        UCB0CTLW0 |= UCSWRST ;              //Software reset enabled
        UCB0CTLW0 |= UCMODE_3  + UCSYNC;        //I2C mode, sync mode
        UCB0I2COA0 = 0x48 + UCOAEN;         //own address is 0x48 + enable
        UCB0CTLW0 &=~UCSWRST;               //clear reset register
        UCB0IE |=  UCRXIE0;                 //receive interrupt enable
     
        __bis_SR_register(CPUOFF + GIE);        // Enter LPM0 w/ interrupts
        __no_operation();
    }
     
     
     
     
    #pragma vector = USCI_B0_VECTOR
    __interrupt void USCIB0_ISR(void)
     
    {
     
       switch(__even_in_range(UCB0IV,0x1E))
        {
          case 0x00: break;                     // Vector 0: No interrupts break;
          case 0x02: break;                     // Vector 2: ALIFG break;
          case 0x04: break;                     // Vector 4: NACKIFG break;
          case 0x06: break;                     // Vector 6: STTIFG break;
          case 0x08: break;                     // Vector 8: STPIFG break;
          case 0x0a: break;                     // Vector 10: RXIFG3 break;
          case 0x0c: break;                     // Vector 14: TXIFG3 break;
          case 0x0e: break;                     // Vector 16: RXIFG2 break;
          case 0x10: break;                     // Vector 18: TXIFG2 break;
          case 0x12: break;                     // Vector 20: RXIFG1 break;
          case 0x14: break;                     // Vector 22: TXIFG1 break;
          case 0x16:
            RXData = UCB0RXBUF;                 // Get RX data
                    if(RXData & BIT0) {
                        P3OUT |= BIT4;
                    } else P3OUT &= ~BIT4;
                    if(RXData & BIT1) {
                        P3OUT |= BIT5;
                    } else P3OUT &= ~BIT5;
                    if(RXData & BIT2) {
                        P3OUT |= BIT6;
                    } else P3OUT &= ~BIT6;
                    if(RXData & BIT3) {
                        P3OUT |= BIT7;
                    } else P3OUT &= ~BIT7;
            break;                              // Vector 24: RXIFG0 break;
          case 0x18: break;                     // Vector 26: TXIFG0 break;
          case 0x1a: break;                     // Vector 28: BCNTIFG break;
          case 0x1c: break;                     // Vector 30: clock low timeout break;
          case 0x1e: break;                     // Vector 32: 9th bit break;
          default: break;
        }
     
    }
    
  3. I have not been able to fix the borken one. I wanted to update to let everybody know that I was able to replace my Launchpad. I bought two just in case.

     

    In the spirit of community that this forum has shown me, and because it's the Holiday season, I would offer to help out. If somebody else here knows what it's like not to be able to come up with $5 for equipment and needs a launchpad, please let me know. Limited to places that TI will ship.

  4. yes, that was the target side (3.5V). I did not supply it with 5v from the usb side of the tps77301.

     

    i already took some isopropanol and a toothbrush to the board. i gingerly ran a fine pick between all IC pins on the FET side of the board to make sure nothing which might have been missed in the cleaning bridged any pins.

     

    i'm starting to suspect the tps77301 regulator, and getting flaky behavior at the target end. a fraction of the time i plug the board in i get several hertz blinking of the led on p1.0, and corresponding interruption (cutting out) of the PWM the current program generates by p1.6. other times, it flickers very rapidly (~1kHz according to my multimeter), and sometimes stabilizes within a second or so. sometimes the program fails to turn on the outputs at all.

     

    i barely know what i'm doing, so i am of course just speculating.

     

    the voltage requirement for the tusb3410 chip is >3.6v

     

    I am in California, in the US.

  5. I hope reviving older threads is acceptable here, but I wanted to take a moment to say that I encountered nearly the same problem with my launchpad. In my case, i did not supply an over voltage to the target side of the board, but tried to supply from the Vcc on the target side a board which apparently drew more current than the USB port or the launchpad could supply (a gameboy pocket main board, minus the lcd).

     

    this dimmed the leds imediately, and i dicconnected the board within 1 second, but afterward the launchpad would not be recognized. I noticed between the usb connector and D1 what first looked to be scorching, but turned out to be a waxy substance. i cleaned this away and found no traces appearing to be burned. the area which had overheated did not persist in doing so afterward. i probed all the traces running through that area of the board for continuity, then tested the diode, tested all the resistors, tested U4 as per the functional diagram in the datasheet, which i believe checks out. No conclusion on the fault, but i believe it is the USB controller.

     

    I monitored the bus in software with usb trace, and hot plugging showed no negotiation at all, which i suppose might reaffirm this speculation. I will probably replace my launchpad as soon as possible, but $5 is sometimes a lot of money to me, so I do not plan to stop troubleshooting it.

     

    I hope this might offer insight for anybody suffering similar trouble, to have another documented backgroun resulting in this problem. of course it's always possible some debris shorted something as well, as i had the LP out in my metal shop, but it did not present when i first brought it in and resumed using it.

  6. I'm a knifemaker and bowyer from california. I have only a little experience with PIC MCUs and am brand new to the MSP430, but I found the launchpad a hard offer to refuse. I am a hobbyist in electronic engineering and like adding new skills to by set, so I hope to do a lot of learning fast.

     

    I'm glad to find this site.

×
×
  • Create New...