Jump to content

timotet

Members
  • Content Count

    223
  • Joined

  • Last visited

  • Days Won

    1

Reputation Activity

  1. Like
    timotet reacted to pabigot in Timer initialization and external oscillator problem   
    You may be selecting the source before it stabilizes, causing it to fall back to an alternative source. Make sure XT2OFFG is clear in UCSCTL7. The TI example program msp430x54x_UCS_8 from the 5418 example programs shows how to configure for XT2 and includes the loop below; there's probably an equivalent one for your chip in the code examples available at http://www.ti.com/product/msp430f5510#toolssoftware.
     

    // Loop until XT1,XT2 & DCO stabilizes do { UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags }while (SFRIFG1&OFIFG); // Test oscillator fault flag UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to expected frequency UCSCTL4 |= SELS_5 + SELM_5; // SMCLK=MCLK=XT2
  2. Like
    timotet reacted to oPossum in Dallas/Maxim One Wire Library   
    Here is a basic library for 1-wire communication. It works with CPU frequency of 1 MHz or higher. Carefully crafted assembly code is used to allow operation over a wide CPU clock frequency range.
     
    There are only two functions. One for setup and the other for all communication tasks.
     

    // one_wire.h void one_wire_setup(volatile unsigned char *dir, volatile unsigned char *in, unsigned bitmask, unsigned mhz); int owex(int data, unsigned bits);
     
    The library is initialized by a call to one_wire_setup(). The arguments specify the I/O pin and clock frequency.
    An example for P1.4 at 16 MHz...
     
    one_wire_setup(&P1DIR, &P1IN, 0x10, 16);
     
    The setup function can be called repeatedly to allow communication on more than one I/O pin.
     
    The owex() [One Wire EXchange] function does bus reset, tx and rx.
     
    To reset the bus and detect if any devices are present, just call it with a bit count of zero....
     
    p = owex(0, 0);
     
    The returned value will be -1 (0xFFFF) if any devices are detected, or 0 if none are detected.
     
    To send data...
     
    owex(0xCC, 8); // Skip ROM command
     
    The returned value should match the data sent, if it does not then there is a bus problem.
     
    To receive data, use -1 (0xFFFF) for the tx data value...
     
    d = owex(-1, 8); // Get 8 bits
     
    1 to 16 bits can be sent/received at once.
     
    This is the core code...

    .def owex ; int owex(int data, unsigned bit_count) .def owdport .def owiport .def owbit .def owtiming .bss owdport, 2 ; Direction port .bss owiport, 2 ; Input port .bss owbit, 2 ; Port bitmask .bss owtiming, 0 ; Timing array .bss owda, 2 ; 28 Zero .bss owdb, 2 ; 33 .bss owdc, 2 ; 39 .bss owdd, 2 ; 7 One .bss owde, 2 ; 8 .bss owdf, 2 ; 85 .bss owdg, 2 ; 500 Reset .bss owdh, 2 ; 50 .bss owdi, 2 ; 450 owex ; tst R13 ; Reset? jeq owrst ; Yes... push R11 ; Save R11, R13 push R13 ; clr R13 ; Clear bit count ; owloop ; --- Tx/Rx bit loop rra R12 ; Get tx bit jc owone ; If one... ; ; - Send and verify zero mov &owda, R15 ; nop ; mov &owdport, R14 ; Bus low bis.b &owbit, 0(R14) ; ; call #owdelay ; Delay 28 us ; mov &owiport, R14 ; Sample bus mov.b @R14, R14 ; bit &owbit, R14 ; rrc R11 ; ; mov &owdb, R15 ; Delay 33 us call #owdelay ; ; mov &owdc, R15 ; mov &owdport, R14 ; Bus open bic.b &owbit, 0(R14) ; ; jmp ownext ; Delay 39 us ; owone ; - Send one and read bit mov &owdd, R15 ; tst R15 ; mov &owdport, R14 ; Bus low bis.b &owbit, 0(R14) ; ; jn owoneo ; Delay 7 us owdlyd ; sub #8, R15 ; nop ; jc owdlyd ; subc R15, PC ; nop ; nop ; nop ; owoneo ; bic.b &owbit, 0(R14) ; Bus open ; jc owones ; Delay 8 us mov &owde, R15 ; owdlye ; sub #8, R15 ; nop ; jc owdlye ; subc R15, PC ; nop ; nop ; nop ; owones ; mov &owiport, R14 ; Sample bus mov.b @R14, R14 ; bit &owbit, R14 ; rrc R11 ; ; mov &owdf, R15 ; Delay 85 us ownext ; call #owdelay ; ; - Next bit inc R13 ; Increment bit count cmp R13, 0(SP) ; Compare bit count jne owloop ; Loop if not done... owrxa ; - Align rx data cmp #16, R13 ; Rx data aligned? jeq owrex ; Yes.. rra R11 ; Shift in a zero bit inc R13 ; Inc bit count jmp owrxa ; Next bit... owrex ; mov R11, R12 ; Get rx data to R12 pop R13 ; Restore R11, R13 pop R11 ; ret ; Return ; ; owrst ; - Reset and presence detect mov &owdport, R14 ; Bus low bis.b &owbit, 0(R14) ; ; mov &owdg, R15 ; Delay 500 us call #owdelay ; ; bic.b &owbit, 0(R14) ; Bus open ; mov &owdh, R15 ; Delay 50 us call #owdelay ; ; mov &owiport, R14 ; Sample bus mov.b @R14, R14 ; bit &owbit, R14 ; subc R12, R12 ; ; mov &owdi, R15 ; Delay 450 us ;jmp owdelay ; and return ; owdelay ; sub #8, R15 ; nop ; jc owdelay ; subc R15, PC ; nop ; nop ; nop ; ret ; ; .end ;
     
    Demo program to read DS1820/1822 temperature sensor is included in zip file.
    one_wire.zip
  3. Like
    timotet reacted to oPossum in Converting binary to decimal (BCD)   
    send((seconds >> 4) + '0'); send((seconds & 0x0F) + '0');
  4. Like
    timotet reacted to RobG in Converting binary to decimal (BCD)   
    Here's what you need to do, you have to get digits from nibbles:
    int digit = (seconds >> 4) + 0x30;
    send(digit);
    digit = (seconds & 0x0F) + 0x30;
    send(digit);
     
    Repeat same for minutes and hours.
    Basically, all variables are already BCD encoded meaning nibbles are between 0-9, no binary to BCD is necessary.
  5. Like
    timotet reacted to xpg in MSP430 Toolbox   
    Hello fellow 430'ers,

    I have been tinkering with this small project for a while, but think it's time to show it to the world. The MSP430 Toolbox has been inspired by various projects like the Bus Pirate, NJC's LaunchScope, and many others. The basic idea is to make a set of usable tools for MCU development, using the Launchpad and as few other components as possible. Also, rather than providing only the MCU side, I've created a small PC-program, which should make it easier to use the toolbox.
    Currently, I have implemented two "tools": A raw digital capturer, and an SPI spy which uses the USI for single-channel capturing. As always, capture frequency is limited by the UART/USB speeds, making an FTDI UART/USB chip much more fun than the Launchpad's UART/USB converter. I have implemented a "high-frequency" mode, which captures to RAM instead. But currently, it's limited to 50 8-bit samples (side note: the Fraunchpad might be fun to play with in this regard).

    Besides the two "tools", which are meant for capturing only, there is an interactive mode that can be used to send/receive via USI-SPI and simply control of the digital I/O on the Launchpad.

    The PC application is written in C# and uses Gtk, which means that it should run on both Linux and Windows. However, only Linux has been tested. It has some rough edges, but works okay . Currently, Monodevelop is required to compile the application.

    Well, on to some demonstration. First video shows the Launchpad connected to an ATMega, which has been loaded with a simply blinky program:




    Next video shows avrdude being used to program an ATMega (with the program seen in the first video):



    Source code for MSP430 firmware is available via git:

    Please take a look at config.h in order to configure MCU speed and UART baudrate.

    Source code for MSP430 PC client is available via git:
    git://gitorious.org/msp430-toolbox/msp4 ... client.git

    The patch required for AVRDUDE to work with the msp430 toolbox can be found here: http://xpg.dk/files/File/msp430/avrdude-msp430toolbox.patch.

    Questions and comments are more than welcome,
    Paul
  6. Like
    timotet reacted to RobG in Converting binary to decimal (BCD)   
    Those are the final versions, the ones I will be using from now on I guess. The C's ease of use (relative ,), and the speed of asm.
    The first one uses only 50 clock cycles, the second one 83, and the third one between 109 and 123.
     
    The first one takes up to 12 bit number and returns 4 digit packed BCD.
     
    The second one takes up to 12 bit number and a pointer to char array which is then populated with 4 digit BCD result, MSD in the first element.
     
    The third one is just like the second, but it maps digits to ASCII characters and blanks leading zeros (returns space instead of 0.)
    This one is perfect for use with HD44780 LCD displays.
    You feed it binary number (might be output from ADC) and you get an array of chars ready to be sent to the LCD.
    For example, number 1234 will be returned as {"0x31",0x32","0x33","0x34"}, then all you need to do is set the address on the display and send elements one by one. Display will look like "1234."
    If the number is smaller, 12 for example, leading digits will be blanked {"0x20",0x20","0x31","0x32"} and the display will look like " 12", meaning you don't have to mess around with positioning.
     
    First one, binary to packed bcd

    unsigned int bcd = binaryToPackedBCD(1234); unsigned int binaryToPackedBCD(unsigned int n) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov R14, R12"); return n; }
     
    Second one, binary to array (unpacked)

    unsigned char bcd[4] = {0,0,0,0}; binaryToUnpackedBCD(1234, bcd); void binaryToUnpackedBCD(unsigned int n, unsigned char * digits) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov.b R14, 3(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 1(R13)"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" mov.b R14, 0(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); return; }
     
    Third one, binary to ASCII or HD44780

    unsigned char chars[4] = {0,0,0,0}; binaryToASCII(780, chars); void binaryToASCII(unsigned int n, unsigned char * characters) { __asm(" clr R14"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" rla R12"); __asm(" dadd R14, R14"); __asm(" mov.b R14, 3(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 1(R13)"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" rra R14"); __asm(" mov.b R14, 0(R13)"); __asm(" swpb R14"); __asm(" mov.b R14, 2(R13)"); __asm(" and #0x0F0F, 0(R13)"); __asm(" and #0x0F0F, 2(R13)"); __asm(" add.b #0x30, 3(R13)"); __asm(" tst.b 0(R13)"); __asm(" jnz l1"); __asm(" mov.b #0x20, 0(R13)"); __asm(" tst.b 1(R13)"); __asm(" jnz l2"); __asm(" mov.b #0x20, 1(R13)"); __asm(" tst.b 2(R13)"); __asm(" jnz l3"); __asm(" mov.b #0x20, 2(R13)"); __asm(" jmp l4"); __asm("l1:"); __asm(" add.b #0x30, 0(R13)"); __asm("l2:"); __asm(" add.b #0x30, 1(R13)"); __asm("l3:"); __asm(" add.b #0x30, 2(R13)"); __asm("l4:"); return; }
  7. Like
    timotet reacted to RobG in I've got the power   
    I want to share some of the ways I am powering my projects and see if there are any other interesting ones that you could suggest.
     
    Phone and computer accessory supplies, many of us have lots of them laying around. The best kind are the switchers, like the one from Zip drive (see picture.) Unlike the kind with transformer, they are light and small, and usually can be altered to output different voltage. I usually take them apart, but sometimes leave them in the case and remove line blades.
     
    If you don't have any, this one on ebay is only $3.15 including s/h. It's small, 5V 2A, and you can get 3.6V by adding two diodes in series.
     
    Another supply worth mentioning is this one, it's larger and more expensive, $8.88 (incl. s/h,) but it's much better quality.
     
    If you have a supply but need to lower the voltage (for example you need 12V and 3.6V,) consider using DC-DC converter, like this one. At $0.79, it's a steal.
    The same module is also available on ebay, 5pcs for $6, but they are used, pulled from equipment.
     


  8. Like
    timotet reacted to B.Noll in ADC10 TestCode   
    While searching an ADC samplecode for the g2231 I found one that made use of the floating point lib to get an accurate reading of the ADC return value. As the g2231 is a 2k chip that is a silly thing to do.
     
    The goal for the code was to get an accuracy that is similar to a 4 digit DMM. Ok, let's think about this. When using the internal reference (2.5V) the resolution we can get is 2.5V / 1024 = 0.002441 Volt. We can see that the last digit will jump because 10 BIT is not enough. Ok, let's try the 2nd reference with 1.5V / 1024 = 0.001468. Not to bad but still not good enough. Also I'de like to have a range from 0-2.5 V.
     
    By testing the code I mentioned before a constant had been used to make the reading look accurate, however, as there was only one constant in use to correct the ADC the result was quite poor compared to a DMM. As we all know in real life there is no perfect ADC and if we only have the linear errors in mind we will find at least an offset and a gain error.
     
    So the problem to solve looked like:
    - avoid floating point
    - get the accuracy of floating point
    - correct the ADC errors
    - get more then 10 BIT out of the g2231
     
    The following code will do what we need and the codesize is only 576 Byte. I used a well know oversampling technique to get 12 BIT out of the ADC and calculate all corrections by fixed point arithmetic. Instead of calculating on a base by 10 I used base 2 instead as this will allow us to get the result by a simple shift operation. Once the code was working I could still see some jumps in the last digit caused by a ripple of arround 4 mVolt caused by the poor USB powersource of the Launchpad. So I have added also a low pass filter in Software to get rid of the remaining noise.
     
    The ADC result will be displayed @ the MSP430 USB Application COM Port. I have used the Soft. Uart code by NJC but slightly modified it to have a putChar function.
     
    To adjust your ADC and get the RawValues (AdcRawHigh, AdcRawLow) for the calculation of the constants use
    "return (AvgSum >> 8);" instead of the original return statement "return AdcVal;" and ignore the decimal point. In function "AdcValOut" use "while (m != 4)" to display all digits of the RawValues.
    So here we are, let me share this code snippet with you. Please try out the code and let me know your findings.
     
    Have fun,
     
    Bernd
    g2231AdcTestCode.c
  9. Like
    timotet reacted to xpg in MSP430g2231 two interrupts   
    Hi,
     
    The I/O port on the MSP430g2231 has only a single interrupt, meaning that you only can have one handler to deal with interrupts triggered by I/O pins. However, you can use the interrupt flag register, P1IFG, to determine which pin has triggered the interrupt. Note, also, that you have to reset the corresponding bit in P1IFG in your interrupt handler.
    A quick example:

    #pragma vector=PORT1_VECTOR __interrupt void port1_Interrupt (void) { if( P1IFG & BIT0 ) { // PIN 0 triggered the interrupt // Do stuff // Reset the interrupt flag P1IFG &= ~BIT0; } if (P1IFG & BIT5) { // PIN 5 triggered the interrupt // Do stuff // Reset the interrupt flag P1IFG &= ~BIT5; } }
     
    There are two time interrupts on the mgsp430g2231: TIMERA0 and TIMERA1. In compare mode TIMERA0 is triggered when CCR0 is reached, while TIMERA1 is triggered when CCR1 is reached, and TAR overflows. So, in a TIMERA1 interrupt handler you will have to check TAIV to see if the interrupt was triggered by CCR1 or TAR overflow.
     
    Cheers,
    Paul
  10. Like
    timotet got a reaction from RobG in Circuit Schematics   
    I just downloaded and am trying DesignSpark.
    so far its pretty cool too.
     
    http://www.designspark.com/
  11. Like
    timotet reacted to fj604 in Interfacing the Launchpad with MAX6957 SPI LED Driver   
    MAX6957 can be a useful tool: a LED driver + I/O expander, giving you 20 ports (PDIP) or 28 port (surface mount) selectable as:
    - constant current sink LED driver
    - input
    - input with pullup
    - output
     
    Here is a demo code for the Launchpad (MSP430G2231) using hardware SPI:
     

    /* * Interfacing MSP430G2231 to MAX6957 SPI LED driver and I/O expander Pins MSP430G2231 MAX6957 1 DVCC ----------- 28 V+ 3 P1.1 (CS) ----------- 27 CS 7 P1.5/SCLK ----------- 25 SCLK 8 P1.6/SDO ----------- 26 DIN 9 P1.7/SDI -/\/10K\/\- 4 DOUT 14 DVSS ----------- 2 GND ----------- GND 3 GND ----------- GND 1 ISET -/\/39K\/\- GND 12 P19 ----------- LED1 13 P20 ----------- LED2 14 P21 ----------- LED3 8 P15 ----/ ----- GND Upon startup, LED1-3 will light up for about 1.5 seconds, then LED2-3 will start glowing intermittently. While a button on P15 is pushed, LED1 will change brightness. */ #include #define PIN_CS BIT1 #define DELAY 40000 void spi_init(void) { P1DIR = PIN_CS; // Set CS to output P1OUT = PIN_CS; // CS to high USICTL0 = USIPE7 | USIPE6 | USIPE5 | USIMST | USIOE; // SDI enable, SDO enable, SCLK enable, Master mode, Data output enable, release USICTL1 = USICKPH | USIIE; // CKPH = 1, Interrupt Enable USICKCTL = USIDIV_7 | USISSEL_2 ; // Clock / 128, SMCLK; } void timer_init(void) { TACTL = TASSEL_2 | MC_0; // SMCLK, stop timer TACCTL0 = CCIE; // Enable timer compare interrupt } void sleep(unsigned int count) { TACCR0 = count; // Load top value in compare register TACTL |= TACLR | MC_1; // Clear counter, start timer in up mode _low_power_mode_0(); // Sleep in LPM0 until interrupt TACTL &= ~MC_1; // Stop timer } unsigned int cmd(unsigned char addr, unsigned char data) { P1OUT &= ~PIN_CS; // Take CS low USISRH = addr; // Load address to high byte USISRL = data; // Load data to low byte USICNT = USI16B | 16; // 16 bit transfer _low_power_mode_0(); // sleep in LPM0 until interrupt P1OUT |= PIN_CS; // Take CS high return USISR; } void sense(void) { static unsigned char g=0; cmd(0x2F | BIT7, 0); // Turn high bit on to read register 0x2F for port 15 if (!(cmd(0, 0) & BIT0)) // Send No-op command and check bit 0 = button pushed cmd(0x19, g++ << 4); // Increase brightness of LED on port 19 } void leds(unsigned char v) { cmd(0x1A, v | (0x0F-v) << 4); // control brightness of LEDs on ports 20-21 sense(); } void main(void) { signed char i=0; WDTCTL = WDTPW + WDTHOLD; // Disable WDT spi_init(); timer_init(); _enable_interrupts(); cmd(0x0C, 0x00); // set ports 16-19 to LED cmd(0x0D, 0x00); // set ports 20-23 to LED cmd(0x0B, 0xFF); // set ports 12-15 to GPIO Input with pullup cmd(0x33, 0x01); // Port 19 on cmd(0x34, 0x01); // Port 20 on cmd(0x35, 0x01); // Port 21 on cmd(0x07, 0x01); // Display test on _delay_cycles(1500000); // ~ 1.5s pause cmd(0x07, 0x00); // Display test off cmd(0x04, BIT0 | BIT6); // Individual segment current control, normal operation for (; { for (i=0; i<0x10; i++) { leds(i); sleep(DELAY); } for (i=0x0F; i>=0; i--) { leds(i); sleep(DELAY); } } } #pragma vector=USI_VECTOR __interrupt void usi_interrupt(void) { USICTL1 &= ~USIIFG; // Clear interrupt flag _low_power_mode_off_on_exit(); // Return from LPM } #pragma vector=TIMERA0_VECTOR __interrupt void timer_A_interrupt(void) { _low_power_mode_off_on_exit(); // Return from LPM }
     
    I figured that a 10K resistor is needed as without it MAX6957 would just stop - but I still cannot figure out why - any ideas?
     
    I also have the I2C version - MAX6956 - stay tuned
  12. Like
    timotet reacted to RobG in LaunchPad: Watchdog timer interrupts and TACTL   
    I am using WDT to generate the sound in one of my projects and there's no reason why it should not work.
     
    To make WDT work the way you want you need the following:
    //some global var to keep count
    unsigned int counter = 0;
     
    //enable WDT's interval mode
    WDTCTL = WDT_MDLY_0_064;
  13. Like
    timotet got a reaction from dannyboy in LaunchPad: Watchdog timer interrupts and TACTL   
    hey look at this viewtopic.php?f=10&t=509
     
    and to let you know you dont even need to use the watchdog for this.
     
    the delay is the problem
    use this delay instead :
     
    static void delay(int ms)// Delays by the specified Milliseconds
    {
    while (ms--)
    __delay_cycles(1000); //set to 1000 for 1 Mhz
    }
     
    and take out the watch dog interrupt call all together.
    and be sure to put this in
    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
     
    TACTL is for TIMER A and has nothing to do with the watchdog.
    page 410 of the msp430 users guide will explain the TACTL register and what it does
     
    good luck
  14. Like
    timotet reacted to bluehash in Playing music   
    There are optimization options in the Liker Options. Right click Prokect and select Build Properties.
     
    I'll try your program and see if I can reduce it is size. Also change
     
    eint() ---to---> _enable_interrupts()
    dint() ---to---> _disable_interrupts()
    nop() ---to---> __no_operation()
     
    Also change
    int notes[] = { } to
    const int notes[] = { }
     
    const makes the array read only which puts it into Flash and not RAM. That give more space for the stack.
     
    Modified file attached. Not Tested. Compiles and links fine.
    music.c
  15. Like
    timotet reacted to bluehash in Playing music   
    Sorry my mistake.
    This will not work.
     
    I totally forgot that the MSP430g2231 has 128bytes of RAM, which is 80h. No wonder it cannot allocate stack. Increasing the stack will not help.
     
    Do you have a chip with bigger memory.
     
    One thing you can do is remove any unused variables or optimize. If you dont know how to do that, I'll walk you through.
  16. Like
    timotet reacted to TopHatHacker in Nokia 3310 LCD and MSP430G2231   
    Hey, I just wanted to make a quick post about my new project, but I don't wana type it all out again so go check it out on my site Its just some example code of the Nokia3310 LCD running directly on the launchpad.
     
    http://tophathacker.com/


  17. Like
    timotet got a reaction from roger430 in Using 3 wires to control parallel LCD display   
    So Ive managed to get RobG's code to work on the Wintek 1 x 24 Character LCD Display Module that I got awhile ago from
    Electronic Goldmine for $1.99.
     
    Here's the link: http://www.goldmine-elec-products.com/p ... ber=G15318
     
    There are only 2 cons so far:
    1 It takes 5v to power the display.
    2 It takes 4 wires instead of 3. ( you have to toggle the reset pin on the display.)
     
    logic seems to work fine at the 3.6v the msp430 puts out.
     


     
    here's the code:

    /* hex instructions for display setup 0x1C == LCD power control PW 0x14 == Display on/off DO 0x28 == Display Control sets lines ect. DC 0x4F == Contrast Set CN 0xE0 == DDRAM address set DA */ #include "msp430g2452.h" #define sendData(data) send(data, 1) #define sendInstruction(data) send(data, 0) #define clearDisplay() sendInstruction(0x01); _delay_cycles(2000) #define DATAPIN BIT6 #define CLOCKPIN BIT5 #define ENABLEPIN BIT4 #define RESETPIN BIT7 void send(char data, char registerSelect); void sendDataArray(char data[], char length); //void resetPin(unsigned int bit); void initDisplay(void); char charIndex = 0; char bitCounter = 0; const char message1[8] = {0x34,0x33,0x6F,0x68,0x2E,0x63,0x6F,0x6D}; char message2[11] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xA4}; const char message3[16] = {0x34,0x2D,0x70,0x69,0x6E,0x20,0x73,0x65,0x72,0x69,0x61,0x6C,0x20,0x4C,0x43,0x44}; char message4[12] = {0x54,0x68,0x61,0x6E,0x6B,0x73,0x20,0xAE,0x6F,0x62,0x47,0x21}; void main(void) { WDTCTL = WDTPW + WDTHOLD; _delay_cycles(100000); P1DIR |= ENABLEPIN + CLOCKPIN + DATAPIN + RESETPIN; // sets ENABLEPIN,CLOCKPIN,DATAPIN and RESETPIN to outputs P1OUT &= ~(CLOCKPIN + DATAPIN + RESETPIN); // sets CLOCKPIN,RESETPIN and DATAPIN low P1OUT |= ENABLEPIN; // sets ENABLEPIN high initDisplay(); // initiate display while(1) { // send const message using sendDataArray clearDisplay(); sendDataArray((char *)message1, 8); _delay_cycles(3000000); // send message using sendDataArray clearDisplay(); sendDataArray(message2, 11); _delay_cycles(3000000); // send message one char at the time clearDisplay(); charIndex = 0; while(charIndex < 16) { sendData(message3[charIndex]); charIndex++; } _delay_cycles(3000000); // send message using sendDataArray clearDisplay(); sendDataArray(message4, 12); _delay_cycles(3000000); } } void sendDataArray(char data[], char length) { charIndex = 0; while(charIndex < length) { sendData(data[charIndex]); charIndex++; } } void send(char data, char registerSelect) { bitCounter = 0; while(bitCounter < 8) { (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); data <<= 1; P1OUT |= CLOCKPIN; P1OUT &= ~CLOCKPIN; bitCounter++; } registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); P1OUT &= ~ENABLEPIN; _delay_cycles(3000); P1OUT |= ENABLEPIN; _delay_cycles(10000); P1OUT &= ~ENABLEPIN; } void initDisplay(void) { P1OUT &= ~RESETPIN; // RESETPIN low _delay_cycles(10000); P1OUT |= RESETPIN; //RESETPIN high sendInstruction(0x1C); //PW sendInstruction(0x14); //DO 0x14 sendInstruction(0x28); //DC 0x28 sendInstruction(0x4F); //CN 0x4F sendInstruction(0xE0); //DA //sendInstruction(0x72); //SC //sendInstruction(0xC); //CR }
  18. Like
    timotet got a reaction from RobG in Using 3 wires to control parallel LCD display   
    So Ive managed to get RobG's code to work on the Wintek 1 x 24 Character LCD Display Module that I got awhile ago from
    Electronic Goldmine for $1.99.
     
    Here's the link: http://www.goldmine-elec-products.com/p ... ber=G15318
     
    There are only 2 cons so far:
    1 It takes 5v to power the display.
    2 It takes 4 wires instead of 3. ( you have to toggle the reset pin on the display.)
     
    logic seems to work fine at the 3.6v the msp430 puts out.
     


     
    here's the code:

    /* hex instructions for display setup 0x1C == LCD power control PW 0x14 == Display on/off DO 0x28 == Display Control sets lines ect. DC 0x4F == Contrast Set CN 0xE0 == DDRAM address set DA */ #include "msp430g2452.h" #define sendData(data) send(data, 1) #define sendInstruction(data) send(data, 0) #define clearDisplay() sendInstruction(0x01); _delay_cycles(2000) #define DATAPIN BIT6 #define CLOCKPIN BIT5 #define ENABLEPIN BIT4 #define RESETPIN BIT7 void send(char data, char registerSelect); void sendDataArray(char data[], char length); //void resetPin(unsigned int bit); void initDisplay(void); char charIndex = 0; char bitCounter = 0; const char message1[8] = {0x34,0x33,0x6F,0x68,0x2E,0x63,0x6F,0x6D}; char message2[11] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xA4}; const char message3[16] = {0x34,0x2D,0x70,0x69,0x6E,0x20,0x73,0x65,0x72,0x69,0x61,0x6C,0x20,0x4C,0x43,0x44}; char message4[12] = {0x54,0x68,0x61,0x6E,0x6B,0x73,0x20,0xAE,0x6F,0x62,0x47,0x21}; void main(void) { WDTCTL = WDTPW + WDTHOLD; _delay_cycles(100000); P1DIR |= ENABLEPIN + CLOCKPIN + DATAPIN + RESETPIN; // sets ENABLEPIN,CLOCKPIN,DATAPIN and RESETPIN to outputs P1OUT &= ~(CLOCKPIN + DATAPIN + RESETPIN); // sets CLOCKPIN,RESETPIN and DATAPIN low P1OUT |= ENABLEPIN; // sets ENABLEPIN high initDisplay(); // initiate display while(1) { // send const message using sendDataArray clearDisplay(); sendDataArray((char *)message1, 8); _delay_cycles(3000000); // send message using sendDataArray clearDisplay(); sendDataArray(message2, 11); _delay_cycles(3000000); // send message one char at the time clearDisplay(); charIndex = 0; while(charIndex < 16) { sendData(message3[charIndex]); charIndex++; } _delay_cycles(3000000); // send message using sendDataArray clearDisplay(); sendDataArray(message4, 12); _delay_cycles(3000000); } } void sendDataArray(char data[], char length) { charIndex = 0; while(charIndex < length) { sendData(data[charIndex]); charIndex++; } } void send(char data, char registerSelect) { bitCounter = 0; while(bitCounter < 8) { (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); data <<= 1; P1OUT |= CLOCKPIN; P1OUT &= ~CLOCKPIN; bitCounter++; } registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); P1OUT &= ~ENABLEPIN; _delay_cycles(3000); P1OUT |= ENABLEPIN; _delay_cycles(10000); P1OUT &= ~ENABLEPIN; } void initDisplay(void) { P1OUT &= ~RESETPIN; // RESETPIN low _delay_cycles(10000); P1OUT |= RESETPIN; //RESETPIN high sendInstruction(0x1C); //PW sendInstruction(0x14); //DO 0x14 sendInstruction(0x28); //DC 0x28 sendInstruction(0x4F); //CN 0x4F sendInstruction(0xE0); //DA //sendInstruction(0x72); //SC //sendInstruction(0xC); //CR }
  19. Like
    timotet reacted to Mac in Custom circuits on demand?   
    Generally speaking, yes, you're correct. Mind you, the built-in refresh rate on the HD44780 variations out there will probably be the limiting factor on how many frames-per-second you can get for animation effects. The refresh rate on some of the White-on-Blue HD44780 displays I use is so slow that I can't see the "rolling odometer" special effect on them until I slow down data transfer to some useless rate.
     
    I'm in the same boat and I've looked at various methods. Myke Predko's 2-pin shift register method is pretty neat and cheap. You could also use an inexpensive 74HC595 in a number of different configurations using 3 to 5 pins (see one example below). Once when challenged to design a 1-pin Serial LCD interface with a small footprint (in terms of board space), I found a way to feed the LCD (with its 6 inputs) with an 8 pin PIC (which has only 5 outputs).
     

     
    All in all, I think you're better off designing an LCD Backpack. We can get MSP430G2231's for the asking (samples) so it would be a pretty inexpensive interface with much more capability than the other "cheap" interface methods. And shouldn't we be able to implement a Serial, SPI, and/or I2C interface with the '2231? The hard part (for me) is coming up with the money to make professional PCB's.
     
    Some interesting project ideas guys. Keep 'em coming.
     
    Cheerful regards, Mike
     
     

     


  20. Like
    timotet reacted to zeke in Best information for those new to the MSP430?   
    If you are new to the MSP430 then you're probably drowning in information right now.

    It's true that there are a zillion configurations to make before the 430 will do what you want it do do.

    So I'm betting that you are asking yourself "Where do I start?"

    I humbly suggest the following TI application notes and books that will get you going in the right direction:

    1. slaa294: MSP430 Software Coding Techniques

    This application report covers software techniques and topics of interest to all MSP430
    programmers. The first part of the document discusses the MSP430 standard
    interrupt-based code flow model, recommended for the vast majority of applications.
    The next part discusses a handful of techniques that should be considered by any
    developer that sets out to develop an MSP430 application. Using these methods can
    greatly reduce debug time and/or provide additional robustness in the field. They
    include initialization procedures, validation of supply rails before performing
    voltage-sensitive operations, and use of special functions. Code examples are
    provided.

    2. : MSP430 32-kHz Crystal Oscillators

    Selection of the right crystal, correct load circuit, and proper board layout are important
    for a stable crystal oscillator. This application report summarizes crystal oscillator
    function and explains the parameters to select the correct crystal for MSP430
    ultralow-power operation. In addition, hints and examples for correct board layout are
    given. The document also contains detailed information on the possible oscillator tests
    to ensure stable oscillator operation in mass production.

    3. MSP430 Microcontroller Basics by John H. Davies

    The best thing I can say about this book at this time is that it describes well how to make use of the clocking system of the MSP430. This book should be in your personal library or at least on your wishlist.

    Once you digest the information above then you will be in good shape for success in working with the msp430.

    Have something to add?
    Then post up your valuable sources of knowledge.
  21. Like
    timotet got a reaction from GeekDoc in I am a Noob and I need help.   
    Don't give up! Everybody had to start somewhere.
    This forum is an awesome place to begin.
  22. Like
    timotet reacted to NatureTM in Flashing the missing DCO calibration constants   
    EDIT: Here's another really nice DCO calibration program. It's part of TinyOS-msp430. http://code.google.com/p/tinyos-msp430/ It's the file called calibrate-dco. As gordon, who discovered it said, "[it] appears to be a quite beefed-up DCO calibration app, with goodies on the side (taking silicon errata into account for various devices when calibrating)." It looks like it's built to be solid and reliable. I skimmed over the code and didn't see anything for calculating SegA checksum, but that usually isn't an issue for most non-critical applications.
     
    EDIT: maxpenna shared another version of the DCO calibration program. This is the one to use if you need a correct SegmentA checksum. It uses the C calibration function. You can get it here http://www.43oh.com/forum/download/file.php?id=292
     
    WARNING: Some of the programs in this thread will erase Segment A and only put back the DCO calibrations. They should not be used with chips that have an ADC12, as this process will destroy the ADC12 calibrations. Some of the programs do not calculate the Segment A checksum, so the integrity of Segment A cannot be verified during runtime after calibration. Still, I've been using it without any problems.
     
     
    There's been a bit of a discussion in another thread about an idea simpleavr had for adding the dco calibration constants to flash for the Value Line series. I've cobbled together some pieces of TI code and have it working. It seems to work great. Here's how I did it with CCS. I think the people on linux should be able to reproduce the result with a little adaptation.
     
    This requires the TI DCO library I modified in another thread and an external LF crystal like the one with Launchpad.
    http://naturetm.com/files/Launchpad%20setDCO%20lib.rar
     
    First, run this to calibrate the constants and write them to flash:
    EDIT: 43oh member zeke has made some changes to the code for finer tuning. Check page 2 for his code.

    //****************************************************************************** // MSP430F20xx Demo - DCO Calibration Constants Programmer // // NOTE: THIS CODE REPLACES THE TI FACTORY-PROGRAMMED DCO CALIBRATION // CONSTANTS LOCATED IN INFOA WITH NEW VALUES. USE ONLY IF THE ORIGINAL // CONSTANTS ACCIDENTALLY GOT CORRUPTED OR ERASED. // // Description: This code re-programs the F2xx DCO calibration constants. // A software FLL mechanism is used to set the DCO based on an external // 32kHz reference clock. After each calibration, the values from the // clock system are read out and stored in a temporary variable. The final // frequency the DCO is set to is 1MHz, and this frequency is also used // during Flash programming of the constants. The program end is indicated // by the blinking LED. // ACLK = LFXT1/8 = 32768/8, MCLK = SMCLK = target DCO // //* External watch crystal installed on XIN XOUT is required for ACLK *// // // MSP430F20xx // --------------- // /|\| XIN|- // | | | 32kHz // --|RST XOUT|- // | | // | P1.0|--> LED // | P1.4|--> SMLCK = target DCO // // A. Dannenberg // Texas Instruments Inc. // May 2007 // Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.42A //****************************************************************************** #include "msp430x20x1.h" #include "DCO_Library.h" unsigned char CAL_DATA[8]; // Temp. storage for constants volatile unsigned int i; int j; char *Flash_ptrA; // Segment A pointer void Set_DCO(unsigned int setting); void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT for (i = 0; i < 0xfffe; i++); // Delay for XTAL stabilization P1OUT = 0x01; // Red LED on P1SEL = 0x10; // P1.4 SMCLK output P1DIR = 0x51; // P1.0,4,6 output j = 0; // Reset pointer Set_DCO(TI_DCO_16MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(TI_DCO_12MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(TI_DCO_8MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(TI_DCO_1MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Flash_ptrA = (char *)0x10C0; // Point to beginning of seg A FCTL2 = FWKEY + FSSEL0 + FN1; // MCLK/3 for Flash Timing Generator FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY + LOCKA; // Clear LOCK & LOCKA bits *Flash_ptrA = 0x00; // Dummy write to erase Flash seg A FCTL1 = FWKEY + WRT; // Set WRT bit for write operation Flash_ptrA = (char *)0x10F8; // Point to beginning of cal consts for (j = 0; j < 8; j++) *Flash_ptrA++ = CAL_DATA[j]; // re-flash DCO calibration data FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCKA + LOCK; // Set LOCK & LOCKA bit P1OUT = 0; while (1) { P1OUT ^= BIT6; // Toggle green LED for (i = 0; i < 0x4000; i++); // SW Delay } } void Set_DCO(unsigned int setting){ volatile unsigned int I; // P1DIR |= BIT0; // P1.0 output BCSCTL1 &= ~XTS; // external source is LF; BCSCTL3 &= ~(LFXT1S0 + LFXT1S1); // watch crystal mode BCSCTL3 |= XCAP0 + XCAP1; // ~12.5 pf cap on the watch crystal as recommended for( I = 0; I < 0xFFFF; I++){} // delay for ACLK startup if(TI_SetDCO(setting) == TI_DCO_NO_ERROR) // if setting the clock was successful, P1OUT |= BIT0; // bring P1.0 high (Launchpad red LED) else while(1); // trap if setting the clock isn't successful }
     
    The green light should start blinking in a few seconds, indicating success. Now we need to modify some linker and header files so CCS knows about the new calibrations.
     
    I'm using the MSP430G2231, so I duplicated the file C:\Program Files (x86)\Texas Instruments\ccsv4\msp430\include\msp430g2231.cmd in that directory, and renamed the duplicate as msp430g2231_mod.cmd. Now I can edit it without affecting the original. Edit msp430g2231_mod.cmd and change the calibration section at the bottom to this:
     

    /************************************************************ * Calibration Data in Info Mem ************************************************************/ CALDCO_16MHZ = 0x10F8; CALBC1_16MHZ = 0x10F9; CALDCO_12MHZ = 0x10FA; CALBC1_12MHZ = 0x10FB; CALDCO_8MHZ = 0x10FC; CALBC1_8MHZ = 0x10FD; CALDCO_1MHZ = 0x10FE; CALBC1_1MHZ = 0x10FF;
     
    Now the linker knows we have calibration data in that section when we use the modified file.
     
    When we create a new project in CCS or modify an existing one, CCS will want to use the default linking file, and the default header. Here's an example about how to configure a project to use the new constants.
    First create a new project. Within the project, there should be a file called something like lnk_msp430g2231.cmd. The last line of that file should be something like -l msp430g2231.cmd. Open it, and change the last line to reflect the new linker file so it reads -l msp430g2231_mod.cmd.
    Next, add the appropriate header file to the project. Right-click the project folder in the left pane of CCS and click "Add files to project..." In this example, I'm using C:\Program Files (x86)\Texas Instruments\ccsv4\msp430\include\msp430g2231.h. Now we have a copy of the file in the project we can safely edit. Edit the file so the calibration section looks like this:

    /************************************************************ * Calibration Data in Info Mem ************************************************************/ #ifndef __DisableCalData SFR_8BIT(CALDCO_16MHZ); /* DCOCTL Calibration Data for 16MHz */ SFR_8BIT(CALBC1_16MHZ); /* BCSCTL1 Calibration Data for 16MHz */ SFR_8BIT(CALDCO_12MHZ); /* DCOCTL Calibration Data for 12MHz */ SFR_8BIT(CALBC1_12MHZ); /* BCSCTL1 Calibration Data for 12MHz */ SFR_8BIT(CALDCO_8MHZ); /* DCOCTL Calibration Data for 8MHz */ SFR_8BIT(CALBC1_8MHZ); /* BCSCTL1 Calibration Data for 8MHz */ SFR_8BIT(CALDCO_1MHZ); /* DCOCTL Calibration Data for 1MHz */ SFR_8BIT(CALBC1_1MHZ); /* BCSCTL1 Calibration Data for 1MHz */ #endif /* #ifndef __DisableCalData */
     
    Now you can begin using the new calibration data in your program. When you #include the msp430g2231.h file, put it in quotes instead of <> to ensure it's loading the modified header local to the project directory.
     
    I tested the constants with a cheap oscilloscope and they seemed correct. My scope doesn't have great accuracy at high frequencies so they might be a little off, but nothing I can detect. It works with my composite video prog, so that's a pretty good sign.
     
    EDIT: Oops! I had an incorrectly named file in these instructions. Corrected.
×
×
  • Create New...