Jump to content

canid

Members
  • Content Count

    7
  • Joined

  • Last visited

  • Days Won

    1
  1. canid

    I2C multi-slave automation project.

    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 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. canid

    Launchpad

    For anybody who missed my comment here i thought i would post it here. I was able to replace my borked LP and am able to offer one to the next person who needs one but can not afford it. $4.30 isn't a lot of money to most of us, but sometimes things are rough.
  4. canid

    Big problem with my Launchpad

    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.
  5. canid

    Big problem with my Launchpad

    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.
  6. canid

    Big problem with my Launchpad

    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.
  7. canid

    Hello from California

    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.
×