Jump to content
43oh

Rickta59

Members
  • Content Count

    1,135
  • Joined

  • Last visited

  • Days Won

    71

Reputation Activity

  1. Like
    Rickta59 reacted to SugarAddict in $4.30 LCD Booster - Sold Out   
    Ok, so... things are a little weird around here, I'm not 100% sure when I'll get all of this together and to B#, I'm dropping an offer a house so all that (closing, moving, yadda yadda) might interrupt... BUT here's a nice pic with the finished mounting spacer that I picked up 100 of today (The clips hold, but I'm still a little iffy about needing something on the top holding the male connector in, users could always just super glue the thing together :mrgreen: )
     

  2. Like
    Rickta59 reacted to RobG in Serial EEPROM   
    I just got my hands on 24LC32A serial EEPROM and here is how I got it work with my LaunchPad.
    There's really nothing special about it, just I2C functions. I was going to use TI's examples for I2C, but some of them are horrible and decided to write my own functions. This is my first stab at I2C so expect improved version of the code pretty soon.
    Also, I did not use USI since 24LC32A can be clocked @400kHz @3.6V and bit banging seemed to be the right and easiest way to do it. External pull up should be between 2k-10k, suggested is lower value for 400kHz, but I am using 10k and it's working fine.
     

     
    The code below provides functions to read and write chars and ints.
    More functions to come later.
    You can remove optional functions and leave the required ones and the ones you will use.
     

    #include // required #define SCL BIT6 #define SDA BIT7 #define READ 0xA1 #define WRITE 0xA0 #define FAILURE -1 #define SUCCESS 0 // required void sendByte(void); void receiveByte(void); void sendAck(void); void receiveAck(void); void start(void); void stop(void); // required unsigned char txData = 0; unsigned char rxData = 0; unsigned char ackFlag = 0; unsigned char bitCounter = 0; unsigned int address = 0; // 12 bit address, upper 4 bits should be 0s. // optional int writeChar(void); int readChar(void); int readCurrentChar(void); int writeInt(void); int readInt(void); // optional unsigned char charData = 0; unsigned int intData = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; P1OUT |= SCL; P1DIR |= SCL; while(1) { address = 0; // set address to 0 readInt(); // read int from address 0 (2 bytes) //handle failure, readInt will return FAILURE or SUCCESS, check before using intData, it might be corrupted _delay_cycles(1000000); // delay for testing intData = 0xABCD; // set intData, we will save it writeInt(); // write intData to address 0 (2 bytes) //handle failure _delay_cycles(1000000); readCurrentChar(); // read char to charData from the current address, since we wrote 2 bytes starting @ address 0, internal address counter of 24LC32A now points to address 2 //handle failure _delay_cycles(1000000); address = 2; // set address to 2 readChar(); // read char (1 byte) from address 2 //handle failure _delay_cycles(1000000); charData = 0xEF; writeChar(); // write char to address 2 //handle failure // since the writeChar might take a while, we are can do acknowledge polling to see if the EEPROM is ready. // this is not the best way because if the nack is a result of something else than busy, we will have an infinite loop. while(readCurrentChar()) {} _delay_cycles(1000000); } } // optional int readCurrentChar(void) { start(); txData = READ; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; receiveByte(); ackFlag = 0; sendAck(); stop(); charData = rxData; return SUCCESS; } // optional int readChar(void) { start(); txData = WRITE; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address >> 8; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address; sendByte(); receiveAck(); start(); txData = READ; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; receiveByte(); ackFlag = 0; sendAck(); charData = rxData; stop(); return SUCCESS; } // optional int writeChar(void) { start(); txData = WRITE; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address >> 8; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = charData; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; stop(); return SUCCESS; } // optional int readInt(void) { start(); txData = WRITE; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address >> 8; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address; sendByte(); receiveAck(); start(); txData = READ; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; receiveByte(); ackFlag = 1; sendAck(); intData = rxData; intData <<= 8; receiveByte(); ackFlag = 0; sendAck(); intData |= rxData; stop(); return SUCCESS; } // optional int writeInt(void) { start(); txData = WRITE; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address >> 8; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = address; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = intData >> 8; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; txData = intData; sendByte(); receiveAck(); if(!ackFlag) return FAILURE; stop(); return SUCCESS; } // required // send byte to slave void sendByte(void) { P1DIR |= SDA; bitCounter = 0; while(bitCounter < 8) { (txData & BIT7) ? (P1OUT |= SDA) : (P1OUT &= ~SDA); P1OUT |= SCL; txData <<= 1; bitCounter++; P1OUT &= ~SCL; } P1OUT |= SDA; P1DIR &= ~SDA; } // required // receive byte from slave void receiveByte(void) { bitCounter = 0; while(bitCounter < 8) { P1OUT |= SCL; rxData <<= 1; bitCounter++; if(P1IN & SDA) { rxData |= BIT0; } P1OUT &= ~SCL; } } // required // send master's ACK void sendAck(void) { P1DIR |= SDA; (ackFlag) ? (P1OUT &= ~SDA) : (P1OUT |= SDA); P1OUT |= SCL; P1OUT &= ~SCL; P1OUT |= SDA; P1DIR &= ~SDA; } // required // receive slave's ACK void receiveAck(void) { P1OUT |= SCL; (P1IN & SDA) ? (ackFlag = 0) : (ackFlag = 1); P1OUT &= ~SCL; } // required // start condition void start(void) { P1OUT |= SCL; P1DIR |= SDA; P1OUT &= ~SDA; P1OUT &= ~SCL; P1OUT |= SDA; P1DIR &= ~SDA; } // required // stop condition void stop(void) { P1DIR |= SDA; P1OUT &= ~SDA; P1OUT |= SCL; P1OUT |= SDA; P1DIR &= ~SDA; }
  3. Like
    Rickta59 reacted to pabigot in GPIO abstraction layer   
    The only thing to watch out for is that the structures you're using don't have a volatile qualifier on the peripheral registers, which is why this happens:
    Because they're not volatile, the compiler is free to optimize the bejeezus out of the code, possibly reordering and eliminating some assignments if it sees a subsequent assignment to the same variable with no intervening read. With some registers, putting both bit sets into a single operation would result in very wrong behavior. E.g., a sequence I wrote earlier today:

    UCB0CTL1 |= UCSWRST; UCB0CTL1 &= ~UCSWRST; might very well be completely eliminated, resulting in corrupted I2C reads.
     
    I suspect this could result in some very difficult to understand bugs. You can avoid the problem by adding volatile qualifiers in the structure declarations, though of course you'll lose the corresponding performance. However, the readability/simplicity would remain.
  4. Like
    Rickta59 got a reaction from larsie in Switch between I2C and SPI on same pins?   
    Might be easier just to snag the software only SPI implementation from bad apple project. You can run that on any pin.
     
    -rick
  5. Like
    Rickta59 reacted to jsolarski in I will back back soon   
    No Job yet but I think I have some of my spark back
     
     
    Starting a New MSP430 based robot with differential steering and pingpong balls for cheap casters lol.....

     
     
    @RobG I wish I was better at java, but PHP is my strong point. Thanks for the offer
     
     
     
    I do have to thank this forum for bing so great!
    Now time to catch up on about 26 pages of new posts lol
  6. Like
    Rickta59 got a reaction from zborgerd in GPIO abstraction layer   
    [EDIT: This code concept has evolved into "fabooh" find it here on github https://github.com/RickKimball/msp430_code/tree/master/fabooh ]
     
    I've been experimenting with msp430-gcc uniarch trying out different approaches to implement a fast GPIO abstraction layer that hides some of the bitmask gymnastics we all seem to do when programming the msp430. I think I've come up with a reasonable approach and I'm hoping for some feedback from all of you.
     
    Normally to access the gpio ports on the msp430 with 'C', you use a bit ANDing (P1OUT & BIT4) and ORing ( P1OUT | BIT1 ) style of programming to read and write the bits. In the Arduino world, they hide all the bit magic using digitalRead and digitalWrite. The downside, at least on the Arduino, is those instructions aren't very efficient. However, reading code written for the Arduino API does seem somewhat more understandable than a bunch of ANDs and ORs.
     
    I want to make my code more readable, but I didn't want to sacrifice efficiency. After rejecting a few different methods, such as macros and functions with port tables, I came up with a C++ template that can be used to hide most of the bit mask programming and still manages to be reasonably efficient.
     
    Here is an example of toggling some leds on and off using a timer:
    /** * gpiotest.cpp - experimental c++ template based gpio abstraction * * author: rick@kimballsoftware.com * * 2012-01-14 - this version is about 168 bytes using msp430-gcc -Os */ #include #include #include "gpio.h" GPIO<0> LED1; // P1.0 GPIO<6> LED2; // P1.6 /** * millis - access to milliseconds since startup * * Note: because the value is stored in a 16 bit int, * it rolls over every 65536 milliseconds or 65.536 seconds */ static uint16_t millis; int main(void) { WDTCTL = WDT_MDLY_0_5; // Configure Watchdog as .5 second interval timer // use default ~1.024 MHz DCO clock digitalWrite(LED1,HIGH); digitalWrite(LED2,LOW); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); IE1 |= WDTIE; // Enable WDT interrupt while(1) { // Go to sleep until the Watchdog wakes us _BIS_SR(LPM0_bits + GIE); // The WDT_INTERVAL_ISR brings the CPU out of sleep mode // and we end up here, every 8 seconds or so if ( millis % 8192 == 0 ) { volatile int i=0; i=i; } } return 0; } /** * WDT_INTERVAL_ISR -Watchdog Timer ISR handler * * Note: assumes MCLK is 1.024MHz and we are using the * WatchDog Interval timer mode of WDT_MDLY_0_5 */ #ifdef __GNUC__ __attribute__( (interrupt (WDT_VECTOR)) ) #else #pragma vector = WDT_VECTOR __interrupt #endif void WDT_INTERVAL_ISR(void) { static uint8_t _500uSCount= 0; // count each .5mSec tick // every 2 ticks update the millis counter if ( (++_500uSCount % 2) == 0) { millis++; if ( millis % 64 == 0) { // toggle every 64 mSec, uses power of 2 value for smaller code LED1.toggle(); // our 2 leds are out of sync LED2.toggle(); // one is on when the other is off _BIC_SR_IRQ(LPM0_bits); // leave the ISR and exit sleep mode } } } To use the code you include "gpio.h" .. this declares the GPIO template and provides accessor functions for reading / writing and configuring the ports and pins. 
    To use the launchpad leds, just create an instance of the GPIO object for each pin:
    GPIO<0> LED1; // P1.0 GPIO<6> LED2; // P1.6This gives you an object that allows you to manipulate the pin values. You can do things like LED1.setHigh() or LED1.setLow() to toggle that pin HIGH and LOW. LED1.setHigh() is doing a P1OUT |= BIT0; under the covers. LED1.setLow does a P1OUT &= ~BIT0. 
    To use the pin as output you need to configure it. Normally you would do a P1SEL |= BIT0; to make it an output pin. With the gpio.h you can just use LED1.configureAsOutput(). As an example of how we can be more Arduino like, I provided a macro so you can also use "pinMode(LED1, OUTPUT)" instead.
     
    Because we are using c++ templates, the compiler is very efficient at optimizing the code. In the example, I use two 'C' statements to set the pin modes. However the compilers optimizes it down to a single msp430 instruction.
    pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); c04c: f2 d0 41 00 bis.b #65, &0x0022 ;#0x0041 c050: 22 00 In fact, the example code is only 168 bytes of msp430 object code. This seems very reasonable to me for readable C code. Using C++ templates with structures has another advantage over traditional C++ classes done Arduino style. if you don't use a function you don't incur any overhead. The compiler only generates object code for the functions you use. This allows you to create all the various helper methods you might want and not end up with giant code bloat. 
    I've concentrated on making the experiment work with the msp430g2553 and msp430g2231. However it should be fine with any of the 'G' series of chips. You need to look at the way the GPIO structure is laid out and make sure it maps to the special memory areas for your chip.
     
    This isn't a finished work, it is just a starting point for those hoping for some GPIO abstraction that that still yields efficient code. Take a look at the gpio.h and the sample code and tell me what you think. It should compile with both CCS and msp430-gcc ( although I haven't tried CCS )
     
    You can find the latest version of the code here:
     
    https://gist.github.com/1597239
     
    It has the following files:
     
    gpiotest.cpp - is the sample program
    gpio.h - the GPIO template declaration
     
    [Edited 1/28/2012] updated code with more implementation methods
     
    -rick
  7. Like
    Rickta59 got a reaction from YanuarPrijadi in Interface 23K256 SPI RAM with USI SPI   
    I came across the Microchip 23K256 Serial RAM device a while back. It seems to fit the bill
    when you need more RAM but don't want to spend a lot of money to get it. These chips are
    inexpensive, (about $1,50 at time of this post 06/05/2011) and hold 32K worth of data. You access
    the memory using SPI. You can even put multiple 23K256 devices on your SPI bus and get
    even more buffer space.
     
    The arduino world already has a couple of libraries to access these devices. I adapted
    one of these to work with both CCS and the uniarch compiler.
     
    I used GRACE to help me configure the msp430g2452 USI in SPI Mode 1. This code might be
    also be useful as a starting point for any SPI Mode 1 device. This code is written for the USI
    device. It would be nice to have a USCI version that would work with the g2553 chip.
     
    Typical use for this device might be to buffer UART received data that is larger than the 128 bytes
    of SRAM available on the smaller G series chips.
     
    You might want to verify the pin setup, I think I have it correct, however you should always verify.
    One interesting item of note is my use of one of the GPIO pins to power the device. You may or
    may not want to use that in your setup. According to the datasheet the 23K256 uses somewhere
    between 2-10mA of power based on how fast you interface with it. I think the G series should
    handle that but I'm not 100% sure. Please comment if you know.
     
    https://gist.github.com/1009412
     

    /** * testspi23K256.c - Interface Microchip 23K256 Serial RAM chip with MSP430G2452 USI SPI * * This code snippet show you how to configure the USI SPI in SPI Mode 1 to communicate with * the 23K256 chip at 4MHz. It takes about 98uSecs to write a single byte and 32K takes * about 100ms. * * msp430g2452 - http://focus.ti.com/docs/prod/folders/print/msp430g2452.html * 23K256 - http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en539039 * * Pin Connections: * * MSP430 SCLK P1.5 -> PIN 6(SCK) 23K256 * MSP430 MISO P1.7 -> PIN 2(SO) 23K256 * MSP430 MOSI P1.6 -> PIN 5(SI) 23K256 * MSP430 GPIO P1.1 -> PIN 1(CS) 23K256 * MSP430 GPIO P1.4 -> PIN 8(VCC) 23K256 * * 23K256 PIN 7 Pullup resistor * 23K256 PIN 8 Pulldown resistor * * Linux build: * * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -c testspi23K256.c * $ msp430-gcc -mmcu=msp430g2452 -O3 -g -Wall -I. -o ./testspi23K256.elf ./testspi23K256.o -Wl,-Map,./testspi23K256.map * $ msp430-objdump -Sww ./testspi23K256.elf >./testspi23K256.lss * $ msp430-size ./testspi23K256.elf * $ mspdebug -q --force-reset rf2500 "erase" "prog ./testspi23K256.elf" * * This code was inspired from this code: * * http://sourceforge.net/projects/mysudoku/files/ * http://hackaday.com/2009/03/02/parts-32kb-spi-sram-memory-23k256/ * */ #include #include enum { POWER_PIN = BIT4, // we power the 23K256 chip from one of our GPIO pins SS_PIN = BIT1, // CS , active low DEBUG_PIN = BIT0, // toggle on and off marking time to write DUMMY_BYTE = 0xFF // byte we send when we just want to read slave data }; static inline uint8_t RWData(volatile uint8_t value); void loop(); #define powerOn P1OUT |= POWER_PIN #define powerOff P1OUT &= ~POWER_PIN #define ssSelect P1OUT &= ~SS_PIN #define ssDeselect P1OUT |= SS_PIN #define delay_1ms __delay_cycles(16000) #define SR_WRITE_STATUS 0x01 #define SR_WRITE 0x02 #define SR_READ 0x03 #define SR_READ_STATUS 0x05 // 23K256 Serial Ram functions uint8_t SR_getMode(void) { ssSelect; RWData(SR_READ_STATUS); // 0x05 uint8_t mode = RWData(DUMMY_BYTE); ssDeselect; return mode; } void SR_setMode(uint8_t mode) { ssSelect; RWData(SR_WRITE_STATUS); // 0x01 RWData(mode); ssDeselect; } static inline void SR_writestream(uint16_t addr) { ssDeselect; // deselect if we are active ssSelect; RWData(0x02); RWData(addr >> 8); RWData(addr); } static inline void SR_readstream(uint16_t addr) { ssDeselect; ssSelect; RWData(0x03); RWData(addr >> 8); RWData(addr); } static inline uint8_t RWData(volatile uint8_t value) { USISRL = value; USICNT = 8; // initialize bit count, start transfer/read __delay_cycles(0); while (!(USIIFG & USICTL1)) ; // wait for SPI flag to trip return USISRL; } /** * main */ int main() { // kill the watchdog timer WDTCTL = WDTPW + WDTHOLD; // configure DCO clock to 16MHz BCSCTL2 = SELM_0 + DIVM_0 + DIVS_0; if (CALBC1_16MHZ != 0xFF) { DCOCTL = 0x00; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; } BCSCTL1 |= XT2OFF + DIVA_0; BCSCTL3 = XT2S_0 + LFXT1S_2 + XCAP_1; // configure GPIO P1OUT = POWER_PIN; P1DIR = SS_PIN + POWER_PIN + DEBUG_PIN; // configure USI - SPI Mode 1 @ 4MHz, clocked off SMCLK USICTL0 |= USISWRST; USICTL0 = USIPE7 + USIPE6 + USIPE5 + USIMST + USIOE + USISWRST; USICTL1 |= USICKPH; USICKCTL = USIDIV_1 + USISSEL_2; /* Enable USI */ USICTL0 &= ~USISWRST; __enable_interrupt(); // Set global interrupt enable // toggle the power for the 23K256 powerOff; delay_1ms; powerOn; ssDeselect; delay_1ms; while (1) { uint8_t chipMode; // make sure there is a 23K256 chip and that // is wired properly and in sequential mode chipMode = SR_getMode(); if (chipMode != 0x41) { SR_setMode(0x41); } else { while (1) { loop(); } } } } #define BYTES_TO_STREAM 32768 // should be less <= 32768 #define PATTERN_BYTE_VALUE 0x55 /** * loop - write a test pattern and read it back */ void loop() { volatile uint16_t i; volatile uint8_t storedValue = 0; P1OUT |= DEBUG_PIN; // mark start of write for measurement with oscope SR_writestream(0); // start writing at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { RWData(PATTERN_BYTE_VALUE); } P1OUT &= ~DEBUG_PIN; // mark end of write for measurement with oscope // verify the bytes we wrote were stored and retreived properly SR_readstream(0); // start reading at address 0 for (i = 0; i < BYTES_TO_STREAM; ++i) { storedValue = RWData(DUMMY_BYTE); // verify our test pattern if (storedValue != PATTERN_BYTE_VALUE) { // if values aren't the same an error occurred, // turn off all leds, then sit and spin P1OUT &= ~BIT6; P1OUT &= ~DEBUG_PIN; while (1) { ; } } } }
  8. Like
    Rickta59 reacted to krzyk2 in Useful bit and performance tips   
    I found this on Hacker News, looks like at least some of those could be used in MSP430 to speed things up when dealing with ints and bits.
    http://www.graphics.stanford.edu/~seander/bithacks.html
     
    The other one is msp430-gcc specific performance tips and already appeared on the forum, but probably now everyone is aware of it so.
    http://mspgcc.sourceforge.net/manual/c1408.html
  9. Like
    Rickta59 reacted to krzyk2 in Dallas/Maxim One Wire Library   
    Thanks to pointers from Rickta59 here's code tuned to work in msp430-gcc.
    I've used it in my project to read temperature from DS sensor and it works correctly.
    dow.zip
  10. Like
    Rickta59 reacted to nobody in Launchpad Pin1.3 problem   
    Small warning for those who do not read manuals:
     
    TI produces for us a very good kit at a very competitive price. But no thing is not entirely perfect.
     
    Into this kit is pin P1.3 connected to button S2. OK, no problem. But for debouncing button, RC combination C34/R24 is also attached to P1.3.
     
    And here's the problem. C34/R24 is not detachable. Still not problem to us? Look to the simple sample code:

    #include "io430.h" #include "intrinsics.h" const unsigned char FONT[] = { 0x00, 0x06, 0x22, 0x00, 0x6D, 0x00, 0x00, 0x20, 0x39, 0x0F, 0x00, 0x70, 0x08, 0x40, 0x00, 0x52, 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x48, 0x48, 0x39, 0x48, 0x0F, 0x53, 0x00, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x6F, 0x76, 0x30, 0x1E, 0x76, 0x38, 0x15, 0x54, 0x3F, 0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x1C, 0x2A, 0x76, 0x6E, 0x5B, 0x39, 0x64, 0x0F, 0x23, 0x08, 0x20, 0x77, 0x7C, 0x58, 0x5E, 0x79, 0x71, 0x6F, 0x74, 0x04, 0x1E, 0x76, 0x18, 0x15, 0x54, 0x5C, 0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x1C, 0x2A, 0x76, 0x6E, 0x5B, 0x39, 0x30, 0x0F, 0x40, 0x00 }; // ASCII table [0x20 - 0xFF] /********************************************************************************************/ /* Test - minimalize power consumption of MSP430G2211 */ /* */ /* I use one character from the display LCD-S301C31TR, connected to port 1 */ /* P1.0 = Seg.A1, P1.1 = Seg.B1, P1.2 = Seg.C1, P1.3 = Seg.D1, */ /* P1.4 = Seg.E1, P1.5 = Seg.F1, P1.6 = Seg.G1, P1.7 = COM */ /* */ /* Power consumption is 76uA/3.5V, 65uA/3V, 33uA/1.5V (problem is RC of P1.3) */ /* Without P1.3 power consumption is 3.2uA/3.5V, 2.7uA/3V, 1.35uA/1.5V */ /********************************************************************************************/ int main( void ) { unsigned int i, j; WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer to prevent time out reset BCSCTL3 |= LFXT1S1; // VLOCLK enable (my VLOCLK worked at ~~10kHz) TACCR0 = 50u - 1u; // 10kHz/200Hz = 50 - interrupt every 5msec (200Hz) TACTL |= TASSEL_1 + ID_0 + MC_1; // Timer A clock source select: 1 - ACLK = VLOCLK // Timer A input divider: 0 - /1 // Timer A mode control: 1 - Up to CCR0 TACCTL0 = CCIE; // Capture/compare interrupt enable __enable_interrupt(); //P1DIR = 0xFF; // Set all P1 to output direction // - alternative - P1DIR = 0xFF - BIT3; // Set all P1 to output direction (without P1.3) for(; // Never ending story { for(i=0; i<(128-32); i++) // Browse ASCII table chars [0x20 - 0xFF] { for(j=0; j<100; j++) // Any character displayed 0.5 sec { if(P1IN & BIT7) P1OUT = FONT[i]; else P1OUT = ~FONT[i]; __bis_SR_register(LPM3_bits); // ZZZZZZZZZzzzzzzz.......... // CPU, MCLK, SMCLK, DCO are disabled, ACLK are active } } } } #pragma vector = TIMERA0_VECTOR // Timer A CC0 __interrupt void DELAY(void) { __bic_SR_register_on_exit(LPM3_bits); // WAKE UP, BABY !!! }
     
    OK. The problem is here, what is the solution?
     
    1) Do not use P1.3 (not good, this small cheap chips have a few pins ...)
    2) Move your lovely chip out of the Launchpad to Breadboard. Thanks to SpyBiWire you need only four wires ...
    3) Simply ignore this problem
    4) Modify your Launchpad to fix this issue
     
    Modify. But how?
     
    My suggestion is: break the route from C34/R24 to pin P1.3 of IC1 socket. Remove pinheader J5. Drill two new holes between S2 and J5. Solder a new, six-pin header at location J5. Use two new pins on the pinheader for detachable connection from C34/R24 to button S2. Route S2 to P1.3.
     
    And that is all. End of story.
  11. Like
    Rickta59 reacted to SugarAddict in F5529 Breakout Dev Board (Now with pics!)   
    And now that parts finally showed up (yay for china ordering...) here's two pics of a fully pop'd one. I will be sending 3 of these to the store for BH at some time in the future... might send him the blank boards I will have leftover as well. oh! and I'll attach the Eagle sch/brd here as well...
     
    5529-Dev-v2-2.brd
    5529-Dev-v2-2.sch
     


     
    Motherboard standoffs, gotta love'm!
  12. Like
    Rickta59 reacted to username in Using a Relay with the MSP430, help?   
    Yes that is correct. LSD(Low side driver) meaning a transistor between GND and load. A HSD (high side driver) would be a transistor between power and the load.
     
    As for usage of a mosfet, versus a BJT.... well you saw my flop in the IRC.... Ultimately, which to use depends on your application and as far as us hobbyists are concerned, it generally comes down to personal preference. The reason being you can commonly make either work. I personally prefer mosfets because they do not require a constant current to be applied at the gate in order to be turned on. Hook them up directly to the msp430 and not worry about current consumption. (provided i'm not pwming at a fast frequency)
     
    Regarding the protection diode, I take back what I said. As a rule of thumb it is probably best to have one in your circuit when dealing with inductive loads.
     
    Here is an excellent video regarding them:
  13. Like
    Rickta59 reacted to g5pw in mspgcc available under MacPorts   
    Hello fellow msp430-ers!
    I was just dropping by to let you know that I finally completed the portfiles for the mspgcc tolchain (Of course this applies only to Mac OS X users)! The version is the LTS one (20110706). Soon (matter of hours I think) will be available the 20111224 version too!
    Feel free to contact me if you have some trouble, I tested it and it should work Mind that the latest version will break some code (or at least OpenChronos firmware didn't compile for me without some modifications).
     

    Oh, and can I just add that OpenChronos development is continuing on Gitorious! Feel free to drop by and comment!

  14. Like
    Rickta59 got a reaction from Alan in mspgcc output binary sizes   
    You could try:
     

    msp430-gcc -Os -g -fdata-sections -ffunction-sections -Wl,--gc-sections file1.c functionLib.c -o out.elf
     
    -rick
  15. Like
    Rickta59 got a reaction from Alan in mspgcc output binary sizes   
    I tried this code and it works with the EXTRAFLAGS. I ended up with a different size elf file than you though:
     

    Erasing... Programming... Writing 250 bytes to c000 [section]... Writing 32 bytes to ffe0 [section]... $ make rm -f *.elf msp430-gcc -Wall -g -L/usr/msp430/lib/ldscripts/msp430g2553/ -I /usr/msp430/include -Os -fdata-sections -ffunction-sections -Wl,--gc-sections -mmcu=msp430g2553 -o clock.elf main.c $ msp430-size clock.elf text data bss dec hex filename 282 0 3 285 11d clock.elf $
     
    I'm using the 20110706 msp430-gcc with all the patches applied. It is funny that you are getting a different size clock.elf. You might want to check your path and make sure you are getting the correct msp430-gcc.
     
    Do you have a 32.768kHz XTAL soldered on your Launchpad? I ran this test with a msp430g2553 chip on a bread board, I just plopped a watch crystal in there without any capacitors and it worked. Without the crystal, both leds are pegged on and don't flash at all. I would expect that based on your NMI_RESET code.
     
    -rick
  16. Like
    Rickta59 reacted to oPossum in DIP package breadboard breakout   
    This is a breakout board for 20 pin DIP package MSP430. It is intended to plug in to a solderless breadboard.
     
    Dimensions are 50.0 mm x 24.6 mm, so two will fit on a 50 x 50 mm panel.
     
    It is SIL style rather than the more common DIL style so that all the pins can be clearly labeled and logically ordered. This style also allows 4 of the 5 holes in a column be be used. Can be used with straight or right angle header strip.
     
    The circuit is minimalist with just a bypass cap and resistor on /Reset. Optional xtal and power LED.
     
    Provision for 50 mil and/or 100 mil program/debug/UART headers. Selectable soft or hard UART configuration.
     
    In addition to the 18 pin header on the bottom, there is an optional 2 pin header that connects to the power rails of the breadboard.
     

    dip_breadboard.brd
    dip_breadboard.sch
  17. Like
    Rickta59 got a reaction from krzyk2 in Digital Picture Frame Thermometer   
    I had already fixed up the serial.asm here:
    http://www.43oh.com/forum/viewtopic.php?f=10&t=1727#p12116
     
    there are some hints on that post regarding what needs to be changed.
     
    -rick
  18. Like
    Rickta59 got a reaction from DecebaL in Software async serial tx/rx without timer   
    Here is an msp430-gcc port of serial.S. Only some minor changes required:
     
    renamed from serial.asm to serial.S
    changed header inclusion, .cdecls to #include
    added ':' to all labels
    changed .bss directives to .lcomm
    changed .def directives to .global
    fixed argument registers CCS using R12-R15 for arg1-arg4, GCC uses R15-R12 for arg1-arg4
    reworked temp registers because of argument register reorder
    changed OR asm statements to BIS statements
     

    ; serial.S - gcc port of serial.asm #include ;------------------------------------------------------------------------------- ; --- define PC,SP,SR gcc only knows about registers --- #define PC r0 #define SP r1 #define SR r2 #define ARG1 R15 #define ARG2 R14 #define ARG3 R13 #define ARG4 R12 .lcomm in_bit_mask, 2 ; Serial in pin .lcomm out_bit_mask, 2 ; Serial out pin .lcomm bit_dur, 2 ; Bit duration in cycles .lcomm half_dur, 2 ; Half bit duration in cycles ; .text ; .global serial_setup ; void serial_setup(unsigned out_mask, unsigned in_mask, unsigned bit_duration); .global putc ; void putc(unsigned c); .global puts ; void puts(char *s); .global getc ; unsigned getc(void); ; .p2align 1,0 ; align on a word boundary serial_setup: ; - Setup serial I/O bitmasks and bit duration (32 minimum) mov ARG1, &out_bit_mask ; Save serial output bitmask mov ARG2, &in_bit_mask ; Save serial input bitmask bis ARG1, &P1DIR ; Setup output pin bis ARG1, &P1OUT ; bic ARG2, &P1DIR ; Setup input pin bis ARG2, ARG1 ; bic ARG1, &P1SEL ; Setup peripheral select mov ARG3, ARG1 ; sub #16, ARG3 ; Adjust count for loop overhead rla ARG3 ; Multiply by 2 because NOP is two bytes mov ARG3, &bit_dur ; Save bit duration sub #32, ARG1 ; Adjust count for loop overhead mov ARG1, &half_dur ; Save half bit duration ret ; Return ; ; - Send a single char putc: ; Char to tx in R15 ; R12, R13, R14, R15 trashed mov &out_bit_mask, R12 ; Serial output bitmask mov &bit_dur, R14 ; Bit duration bis #0x0300, ARG1 ; Add Stop bit(s) to tx char jmp bit_low ; Send start bit... ; tx_bit: mov R14, R13 ; Get bit duration tx_delay: nop ; 4 cycle loop sub #8, R13 ; jc tx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; rra ARG1 ; Get bit to tx, test for zero jc bit_high ; If high... bit_low: bic.b R12, &P1OUT ; Send zero bit jmp tx_bit ; Next bit... bit_high: bis.b R12, &P1OUT ; Send one bit jnz tx_bit ; If tx data is not zero, then there are more bits to send... ; ret ; Return when all bits sent ; ; ; - Send a NULL terminated string puts: ; Tx string using putc push R11 ; mov ARG1, R11 ; String pointer in R15, copy to R11 putsloop: ; mov.b @R11+, ARG1 ; Get a byte, inc pointer tst.b ARG1 ; Test if end of string jz putsx ; Yes, exit... call #putc ; Call putc jmp putsloop ; putsx: pop R11 ; ret ; ; getc: ; - Get a char mov &bit_dur, R14 ; Bit duration mov &in_bit_mask, R13 ; Input bitmask mov #0x01FF, ARG1 ; 9 bits - 8 data + stop ; rx_start: ; Wait for start bit mov &P1IN, R12 ; Get serial input and R13, R12 ; Mask and test bit jc rx_start ; Wait for low... ; mov &half_dur, R13 ; Wait for 1/2 bit time ; rx_delay: nop ; Bit delay sub #8, R13 ; jc rx_delay ; subc R13, PC ; 0 to 3 cycle delay nop ; 3 nop ; 2 nop ; 1 ; mov &P1IN, R12 ; Get serial input and &in_bit_mask, R12 ; rrc ARG1 ; Shift in a bit ; mov R14, R13 ; Setup bit timer jc rx_delay ; Next bit... ; rla ARG1 ; Move stop bit to carry swpb ARG1 ; Move rx byte to lower byte, start bit in msb ret ; Return with rx char and start bit in R15, stop bit in carry
     
    -rick
  19. Like
    Rickta59 reacted to gordon in Eclipse plugin for mspdebug and msp430-gcc   
    This is just cosmetics (AFAICT), but use MSPDebug from git (fixed in 66368ce) to make it go away.
  20. Like
    Rickta59 got a reaction from Tribes in Full-duplex software UART for launchpad   
    So this code snippet springs forth from my desire to use a terminal emulator ( I like putty best ) with my launchpad via the built-in COM port. Simple I think, someone must have already done this by now, no? Well, trying to find a working example for the launchpad led me down a lot of dead ends with nothing that worked well. I did find examples that were half-duplex and ones that required more Timer features than you find on the msp430g2231. Unfortunately, none of them fit my requirements.
     
    My goal was to find something that would allow me to use higher DCO clock speeds such as 16MHZ. I also wanted to be able to run reliably with 115k baud rates, so that I can connect a serial to TCP proxy and make my launchpad web enabled.
     
    I've implemented something here that meets both of those goals. Well sort of. I discovered that the COM port on the launchpad will only work up to 9600 baud. However, you can disconnect the jumpers and plug your RX/TX lines into an FT232RL device and get higher speeds. It also works well if your goal is to interface to some other device via TTL level RS232, say a GPS device.
     
    You can find the code here:
     
    https://github.com/RickKimball/msp430softserial
     
    Because everything is better with pictures, I took a snapshot of the RX line receiving the character 'U' at 9600 baud. 'U' is unique in that it forms a perfect clock wave 0 10101010 1 when you add the stop and start bits. The green line is the RX line, the red line is me toggling a debug pin inside of the RX ISR routine. I used a program called Soundcard Oscilloscope that helped me dial in the proper timing so that I was sampling in the center of each data bit. http://www.zeitnitz.de/Christian/scope_en
     

     
    In the picture above, you'll notice that the first red crossing takes longer than the other samplings, that is because we just ignore the value of the start bit and start sampling in the center of the first data bit.
     
    To use and test the code, download it from github and bring it into CCS. Once it is running figure out which COM port your launchpad is using and connect to it with a terminal emulator like putty or minicom using 9600 baud. The default configuration expects you to have soldered a 32.768k crystal to the launchpad board. It uses the crystal to calibrate the DCO for a higher MHZ speed. Don't worry, I don't write it to flash, I just calibrate it and use it. However, you can edit the config.h to modify the baud rate and MCLK speed. You can even run it at the default MCLK speed. See the config.h file comments for more information.
     
    I think I've commented the code fairly well. However, this is actually my first published project with the MSP430 launchpad so comments are welcome. So enjoy!
     
    -rick
  21. Like
    Rickta59 reacted to Madox in OddBot Launchpad (Mecanum Wheel Rover via Wii Nunchuk)   
    Just a small mini project for me to familiarise myself with the Launchpad.
     
    This uses a Wii Wireless Nunchuk to drive a set of Mecanum Wheels using the msp430g2231.
     
    *wow at 43oh spam restrictions*
     
    I suppose I'll link to the Google Code then
    http://code.google.com/p/madox/source/b ... -launchpad
  22. Like
    Rickta59 got a reaction from wilywyrm in Help with hardware UART   
    The easiest way to deal with the baud rate registers is to use this page:
     
    http://mspgcc.sourceforge.net/baudrate.html
     
    http://mspgcc.sourceforge.net/cgi-bin/msp-uart.pl?clock=32768&baud=9600&submit=calculate
    Seems to yield:
     
    UBR00=0x03; UBR10=0x00; UMCTL0=0x29; /* uart0 32768Hz 9637bps */
     
    I haven't tried the setting above so I can't vouch for it. I'm still trying to understand the proper way to use these registers also.
    I've looked at the msp-uart.pl perl code and compared it to another site on the net that uses an Excel spreadsheet
    and they produce different results and use different algorithms. If you can set your MCU_FREQ to be a multiple
    of the baud rate you want to use you can ignore all the modulation. Using a 1.2288 Mhz clock frequency the cycle count between bits would be an even multiple of 9600 so the UBR00 would be 1228800/9600 = 128.
     
    -rick
  23. Like
    Rickta59 got a reaction from wilywyrm in Help with hardware UART   
    Just start by sitting in a loop waiting for a request. Once you receive something you can start sending back your position data.
     
    This seems to work:
     
    main.cpp

    /** * main.cpp - swserial/timerserial/usciserial Serial Asynch test driver. * * To test: use putty and connect to /dev/ttyACM0 at 9600 Baud * */ #include #include #include "serial.h" #define MCLK_FREQ 16000000UL /* run @16MHz */ /** * typedef Serial - start of a simple serial wrapper class */ typedef struct { /** * begin() - initialize serial port, sets registers, port direction, and * alternative port features as required by implementing serial routines. * Depending on the implementing method, you may not be able to use * arbitrary rx/tx pins the software only implementation is the only * version capable of using any arbitrary pin. * * baudRate - bits/sec default: 9600 * rxPin - receive pin default: 1 (P1.1) ( g2553 defaults ) * txPin - transmit pin default: 2 (P1.2) */ static void begin(uint32_t baud = 9600, int rxPin = 1, int txPin = 2) { init_serial(1 << txPin, 1 << rxPin, MCLK_FREQ / baud, (MCLK_FREQ / baud) >> 8); } /** * puts - writes the string s to the serial output stream without a trailing * newline character. Note: this differs from the ISO standard puts() * function which appends a newline character. ` */ static void puts(register const char *s) { while(*s) { putchar(*s++); } } } serial_t; static serial_t Serial; static void initMCLK() { #ifdef __MSP430FR5739 CSCTL0_H = 0xA5; // CS_KEY CSCTL1 |= DCOFSEL0 + DCOFSEL1; // Set max. DCO setting CSCTL2 = SELA_3 + SELS_3 + SELM_3; // set ACLK = MCLK = DCO CSCTL3 = DIVA_0 + DIVS_0 + DIVM_0; // set all dividers #else // Use 16MHz DCO factory calibration DCOCTL = 0; BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; #endif } int main(void) { WDTCTL = WDTPW | WDTHOLD; /* Disable watchdog */ initMCLK(); // configure serial device using defaults Serial.begin(9600); //__eint(); // we enable interrupts after user setup() to give them a chance to customize // if you are using an FTDI or other reasonable USB-serial chip you can output // serial data at reset. If you want to use the Launchpad /dev/ttyACM0 you have // to wait for a request before spewing. #if 0 printf("\rWelcome to msp430 uNix! %s %s %d, %d:%d %s\r\nlogin: ", "Fri", "Oct", 9, 11, 25, "AM"); Serial.puts("\r\n# "); #endif int c; int nCharCnt = 0; for (; { c = getchar(); // do some minimum line control to handle backspace if ( c != 127 ) { putchar(c); nCharCnt++; } else { if (nCharCnt > 0) { putchar(c); --nCharCnt; } } // append newline on CR if ( c == '\r' ) { Serial.puts("\n# "); nCharCnt = 0; } // restart processor on CTRL-D if ( c == 0x04 /*CTRL-D*/ ) { WDTCTL = WDTHOLD; // restart by setting the WDTCTL without a password } } return 0; }
     
    usci_serial.c

    /* * usci_serial.c - USCI implementations of init_serial(), getchar(), putchar() and puts() * * Created on: Oct 30, 2011 * Author: kimballr - rick@kimballsoftware.com */ #include #include #include "serial.h" /** * init_serial(txPinMask, rxPinMask, bitDuration, durMod) * * Really simple use of the hardware UART so that it will be * compatible with the our simple software ones. We setup the * hardware UART using the pins and bit duration provided. * * This code doesn't use any interrupts. Just simple polling * to decide when to receive or transmit. * */ void init_serial(int txPinMask, int rxPinMask, unsigned duration, unsigned durmod) { // Use UART defaults for most things. // LSB // 8-N-1 ( 8 bit, NO parity, 1 Stop bit) UCA0CTL1 |= UCSSEL_2; // use SMCLK as source for USCI clock UCA0BR0 = duration; // bit duration is MCLK/BAUD UCA0BR1 = durmod; // (MCLK/BAUD) >> 8 #ifdef __MSP430FR5739 P2SEL1 |= BIT0 | BIT1; P2SEL0 &= ~(BIT0 | BIT1); #else P1SEL = rxPinMask | txPinMask; // P1.1=RXD, P1.2=TXD P1SEL2 = rxPinMask | txPinMask; // P1.1=RXD, P1.2=TXD #endif UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine } /** * int getchar() - read next char from serial port rx pin * * */ int getchar(void) { // sit and spin waiting for baudot heh I make myself laugh while (!(UC0IFG & UCA0RXIFG)) { ; // busywait until USCI_A0 RX buffer is ready } return UCA0RXBUF; // return RXed character } /** * putchar(int c) - write char to serial port * */ int putchar(int c) { // make sure previous character has been sent // before trying to send another character while (!(UC0IFG & UCA0TXIFG)) { ; // busywait until USCIA0TX buffer is ready } UCA0TXBUF = (uint8_t) c; // TX character return 0; }
     
    serial.h

    //------------------------------------------------------------------------ // serial.h - function declarations for compact asm serial routines //------------------------------------------------------------------------ #ifdef __cplusplus extern "C" { #endif void init_serial(int txPinMask, int rxPinMask, unsigned duration, unsigned durMod); int getchar(void); int putchar(int); #ifdef __cplusplus } /* extern "C" */ #endif
     
    To compile just use:
     

    msp430-gcc -O0 -g -mmcu=msp430g2553 main.cpp usci_serial.c -o main.elf
  24. Like
    Rickta59 got a reaction from wilywyrm in Help with hardware UART   
    If you do that on a linux box, it is going to overflow the serial ACM buffer and the kill the port. It will just be dead.
    On linux, you should be waiting till you receive something before you start spewing.
  25. Like
    Rickta59 reacted to pabigot in mspgcc-based test/demo environment   
    Impolitely following up on my own post: one of the best things about test430 is scripts/ez430, which allows you to monitor serial output from the launchpad using the USB HID interface, bypassing all the problems with Linux tty-style serial support of the TUSB3410. You can even leave this running in one window while you're using mspdebug to program the board in another. You will need the latest Python USB bindings; information is in the README.
×
×
  • Create New...