Jump to content
43oh

P!-Ro

Members
  • Content Count

    21
  • Joined

  • Last visited

  • Days Won

    1

Reputation Activity

  1. Like
    P!-Ro reacted to zeke in Flashing the missing DCO calibration constants   
    Hi Guys,
     
    I wanted to tack on my calibration code that I successfully used to calibrate my G2231 device.
     
    It's almost exactly like naturetm's code. The only difference is the setDCO() function has a little more fine tuning in it.
     
    Take a look and notice that the setDCO() function is slightly different. I stole the idea from a post aBUGSworstnightmare made on the ti.com website. Here's the link.
     

    //****************************************************************************** // 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" // do not forget to change this according to the device you're using #include #define DELTA_1MHZ 244 // 244 x 4096Hz = 999.4Hz #define DELTA_8MHZ 1953 // 1953 x 4096Hz = 7.99MHz #define DELTA_12MHZ 2930 // 2930 x 4096Hz = 12.00MHz #define DELTA_16MHZ 3906 // 3906 x 4096Hz = 15.99MHz 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 Delta); void main(void) { WDTCTL = WDTPW + WDTHOLD; // Stop WDT BCSCTL3 |= XCAP_3; // Launchpad watch crystals need ~12.5 pF for (i = 0; i < 0xfffe; i++); // Delay for XTAL stabilization P1OUT = 0x00; // Clear P1 output latches P1SEL = 0x10; // P1.4 SMCLK output P1DIR = 0x11; // P1.0,4 output j = 0; // Reset pointer Set_DCO(DELTA_16MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_12MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_8MHZ); // Set DCO and obtain constants CAL_DATA[j++] = DCOCTL; CAL_DATA[j++] = BCSCTL1; Set_DCO(DELTA_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 while (1) { P1OUT ^= 0x01; // Toggle LED for (i = 0; i < 0x4000; i++); // SW Delay } } void Set_DCO(unsigned int Delta) // Set DCO to selected frequency { unsigned int Compare, Oldcapture = 0; BCSCTL1 |= DIVA_3; // ACLK = LFXT1CLK/8 TACCTL0 = CM_1 + CCIS_1 + CAP; // CAP, ACLK TACTL = TASSEL_2 + MC_2 + TACLR; // SMCLK, cont-mode, clear while (1) { while (!(CCIFG & TACCTL0)); // Wait until capture occured TACCTL0 &= ~CCIFG; // Capture occured, clear flag Compare = TACCR0; // Get current captured SMCLK Compare = Compare - Oldcapture; // SMCLK difference Oldcapture = TACCR0; // Save current captured SMCLK if (Delta == Compare) break; // If equal, leave "while(1)" else if (Delta < Compare) { DCOCTL--; // DCO is too fast, slow it down if (DCOCTL == 0xFF) // Did DCO roll under? if (BCSCTL1 & 0x0f) BCSCTL1--; // Select lower RSEL } else { DCOCTL++; // DCO is too slow, speed it up if (DCOCTL == 0x00) // Did DCO roll over? if ((BCSCTL1 & 0x0f) != 0x0f) BCSCTL1++; // Sel higher RSEL } } TACCTL0 = 0; // Stop TACCR0 TACTL = 0; // Stop Timer_A BCSCTL1 &= ~DIVA_3; // ACLK = LFXT1CLK }
     
    Concerning the mods that were made to the cmd file, I just threw them into the default files because I know that I'm going to forget to made the project edits that are suggested in the first post above.
     
    Just calibrate the g2231 first then use the code after.
  2. Like
    P!-Ro 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.
  3. Like
    P!-Ro got a reaction from bluehash in 4-bit LCD Code for 16x1 LCD (have the LCD's for sale too)   
    Code update:
     
    Why not have a scrolling text demo?
     

    /*Scrolling Demo for 16x1 LCD written by Derrick Huestis (P!-Ro) v1.4 * * This code will drive a 16x1 * lcd with memory set up in two * 8 caracter blocks. * * It is my first C program, so * let me know if it has problems! * * pinout: * lcdpin1----ground LCD Ground * lcdpin2----5v Supply Voltage * lcdpin3----ground Contrast Adjustment * lcdpin4----P1.7 Data/Instruction select * lcdpin5----ground Read/Write * lcdpin6----P1.6 Enable * lcdpin7----ground Unused pins for 8 bit mode * lcdpin8----ground * lcdpin9----ground * lcdpin10---ground * lcdpin11---P1.0 Data pins * lcdpin12---P1.3 * lcdpin13---P1.4 * lcdpin14---P1.5 */ #include //change this if you are using a different chip void init(); void byteout(int a,int b, int mode); void pinshift(int out,int mode); void display(char lcd[48],int position); int main() { // message for the lcd char text[48] = " Hello There! "; //note: the extra spaces allows it to scroll int shift; //this variable allows the text to scroll WDTCTL = WDTPW + WDTHOLD; /* Stop watchdog timer */ init(); //initialize lcd display while(1) { for(shift=28;shift>0;shift--) { //loop dragging text to the right _delay_cycles(250000); pinshift(2,0); //return to home position display(text, shift); //send text } for(shift=0;shift<28;shift++) { //drag text to the left _delay_cycles(250000); pinshift(2,0); //return to home display(text, shift); //send text } } //and repeat! } void display(char lcd[48],int position) { int e; //declare variables needed to run the lcd e = 0; while(e<16) { //this will loop 16 times for 16 characters if(e==8) { pinshift(168,0); //change to new line after 8 characters } pinshift(lcd[position],1); //send data to setup pinouts, then send to lcd e++; //get ready to send next character position++; } } void pinshift(int out,int mode) { int i,d,d2; d = 0; i = out; //first 4 pinouts i >>= 4; //this uses bitwise to skip over P1.1 and P1.2 used for serial communication i &= 1; //it breaks the character into the first 4 bits d |= i; i = out; i >>= 5; i &= 7; i <<= 3; d |= i; d2 = 0; i = out; //last 4 pinouts i &= 1; //same as above, but it breaks the pinouts into the last 4 bits d2 |= i; i = out; i >>= 1; i &= 7; i <<= 3; d2 |= i; byteout(d,d2,mode); } void init() { P1DIR = BIT0 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // output lcd pins P1DIR = BIT0 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // output lcd pins P1OUT = 0; _delay_cycles(1000000); //pause to ensure the lcd is on P1OUT |= BIT3 + BIT6; // Function set routine _delay_cycles(1000); P1OUT &= ~BIT3 + BIT6; _delay_cycles(1000); pinshift(40,0); //set to 2 line mode pinshift(12,0); //display on } void byteout(int a,int b,int mode) { P1OUT = a; //send first 4 bits to lcd P1OUT |= BIT6; if(mode) { P1OUT |= BIT7; } _delay_cycles(400); P1OUT &= 0x80; _delay_cycles(400); P1OUT |= b; //send last 4 bits to lcd P1OUT |= BIT6; _delay_cycles(400); P1OUT = 0; _delay_cycles(400); }
  4. Like
    P!-Ro got a reaction from GeekDoc in 4-bit LCD Code for 16x1 LCD (have the LCD's for sale too)   
    Since I couldn't help myself I decided to stay up late improving the code (yeah, I know, it's a school night...)
    I figured out how to use the functions, I think I was just trying to declare them in the wrong spot.
     
    Here is the much-improved and less space-consuming code:

    /*LCD Demo written by Derrick Huestis (P!-Ro) v1.2 * * This code will drive a 16x1 * lcd with memory set up in two * 8 caracter blocks. * * It is my first C program, so * let me know if it has problems! * * pinout: * lcdpin1----ground LCD Ground * lcdpin2----5v Supply Voltage * lcdpin3----ground Contrast Adjustment * lcdpin4----P1.7 Data/Instruction select * lcdpin5----ground Read/Write * lcdpin6----P1.6 Enable * lcdpin7----ground Unused pins for 8 bit mode * lcdpin8----ground * lcdpin9----ground * lcdpin10---ground * lcdpin11---P1.0 Data pins * lcdpin12---P1.3 * lcdpin13---P1.4 * lcdpin14---P1.5 */ #include //change this if you are using a different chip void init(); void byteout(int a,int b, int mode); int main() { // message for the lcd char lcd[16] = "Hello There! "; //note: this message will end with black squares // if it doesn't have spaces for the last 4 characters WDTCTL = WDTPW + WDTHOLD; /* Stop watchdog timer */ init(); int i,d,d2,e,p,q; //declare variables needed to run the lcd d = 0; //must be set to 0 before using bitwise, it will be the output for the pins e = 0; //this variable incruments to display different characters of the message for(p=0;p<2;p++) { //the code loops twice with a command after 8 characters to change memory address for(q=0;q<8;q++) { //this will loop 16 times for 16 characters d = 0; i = lcd[e]; //first 4 pinouts i >>= 4; //this uses bitwise to skip over P1.1 and P1.2 used for serial communication i &= 1; //it breaks the character into the first 4 bits d |= i; i = lcd[e]; i >>= 5; i &= 7; i <<= 3; d |= i; d2 = 0; i = lcd[e]; //last 4 pinouts i &= 1; //same as above, but it breaks the pinouts into the last 4 bits d2 |= i; i = lcd[e]; i >>= 1; i &= 7; i <<= 3; d2 |= i; byteout(d,d2,1); e++; //get ready to send next character } if(p<1) { byteout(40,32,0); //this will change the address of the lcd so additional text will flow across lcd } //instead of acting like an 8x2 lcd } _BIS_SR(LPM4_bits); //program complete, enter low power mode } void init() { P1DIR = BIT0 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // output lcd pins // _delay_cycles(1000000); //pause to ensure the lcd is on P1DIR = BIT0 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // output lcd pins P1OUT = 0; _delay_cycles(1000000); //pause to ensure the lcd is on P1OUT |= BIT3 + BIT6; // Function set routine _delay_cycles(1000); P1OUT &= ~BIT3 + BIT6; _delay_cycles(1000); byteout(8,32,0); //set to 2 line mode byteout(0,57,0); //display on, cursor on, cursor blink on } void byteout(int a,int b,int mode) { P1OUT = a; //send first 4 bits to lcd P1OUT |= BIT6; if(mode) { P1OUT |= BIT7; } _delay_cycles(500); P1OUT &= 0x80; _delay_cycles(500); P1OUT |= b; //send last 4 bits to lcd P1OUT |= BIT6; _delay_cycles(500); P1OUT = 0; _delay_cycles(500); }
    Hopefully tomorrow I will be able to get it running some of the capabilities I stated in my first post.
  5. Like
    P!-Ro got a reaction from bluehash in 4-bit LCD Code for 16x1 LCD (have the LCD's for sale too)   
    I just got my MSP430 last week so I thought I'd give it a try and make some code to interface it to an LCD. The LCD's I have are all 16x1 parallel LCD's, about a hundred in all that I haven't sold yet. Since they are so cheap (I sell them for $3 each) it makes no sense for me to buy a parallel to serial adapter for them.
     
    In my searches for code I ran across this forum, but unfortunately the code I found required an extra IC to interface to the LCD. Since I didn't want this, I decided to have a go at making the code myself.
     
    I am new to programming C, just as I am new to the MSP430, so I am sure there are a lot of things that can be improved in the code if any of you experts out there want to help me out. This is a list of current abilities and the abilities I hope for the code to later have:
     
    Current ability:
    runs in 4 bit mode, uses pins 1.0, 1.3-1.7 (avoiding the pins for USB communication)
    Display 16 characters continuous, moving around the flaw of the memory being set up as 8x2
    Additional commands besides those preset requires you to manually set the pin outputs
    scrolling is possible, requires the loop to be modified somewhat
     
    Future desired ability:
    Pins can be decided at beginning of code, using the bitshift routine only if you want to avoid the rx/tx pins
    characters can be shifted left or right with command for easy scrolling
    commands can be sent easily to a function (I had trouble using functions, if anyone wants to show me how that would be great)
    set it up routine to show text less than 16 characters by reading the variable length (not sure how to do this yet)
    easy to display variables (such as from sensors) along with text --the above method may work for this
     
    There is I lot I want the code to do still, but not too bad I suppose considering I got this far while learning C at the same time
     
    The code is attached below for any one who wants to look at it. I would have made it an attachment but the forum software doesn't allow it. I have also included a picture of the MSP430 running the LCD below, as well as an image of the LCD's for anyone interested in buying some.

    /*LCD Demo written by Derrick Huestis (Pi-Ro) * * This code will drive a 16x1 * lcd with memory set up in two * 8 caracter blocks. * * It is my first C program, so * let me know if it has problems! * * pinout: * lcdpin1----ground LCD Ground * lcdpin2----5v Supply Voltage * lcdpin3----ground Contrast Adjustment * lcdpin4----P1.7 Data/Instruction select (please use a resistor, 1k is fine) * lcdpin5----ground Read/Write * lcdpin6----P1.6 Enable (use a resistor) * lcdpin7----ground Unused pins for 8 bit mode * lcdpin8----ground * lcdpin9----ground * lcdpin10---ground * lcdpin11---P1.0 Data pins (use resistors) * lcdpin12---P1.3 * lcdpin13---P1.4 * lcdpin14---P1.5 #include //change this if you are using a different chip int main() { // message for the lcd char lcd[16] = "Hello There! "; //note: this message will end with black squares // if it doesn't have spaces for the last 4 characters WDTCTL = WDTPW + WDTHOLD; /* Stop watchdog timer */ P1DIR = BIT0 + BIT3 + BIT4 + BIT5 + BIT6 + BIT7; // output lcd pins P1OUT = 0; _delay_cycles(1000000); //pause to ensure the lcd is on // ----- initialize lcd ---- // This section would look a lot better if I could figure out how to use function // routines, but I just had errors when I tried so I will clean it up // when I learn how to do it properly //------------------------- P1OUT |= BIT3 + BIT6; // Function set routine _delay_cycles(1000); P1OUT &= ~BIT3 + BIT6; _delay_cycles(1500); P1OUT |= BIT3 + BIT6; // and repeat in 4-bit mode to declare 2 line mode _delay_cycles(500); P1OUT &= ~BIT3 + BIT6; _delay_cycles(500); P1OUT |= BIT5 +BIT6; // finish last 4 bits of function routine _delay_cycles(500); P1OUT = 0; _delay_cycles(350000); // delay for the lcd to start up P1OUT |= BIT6; // Display on, turn on cursor and blink _delay_cycles(500); //first 4 bits P1OUT = 0; _delay_cycles(500); P1OUT |= BIT5 + BIT3 + BIT4 + BIT0 + BIT6; // last 4 bits of display on routine _delay_cycles(500); P1OUT = 0; _delay_cycles(500); int i,d,e,p,q; //declare variables needed to run the lcd d = 0; //must be set to 0 before using bitwise, it will be the output for the pins e = 0; //this variable incruments to display different characters of the message for(p=0;p<2;p++) { //the code loops twice with a command after 8 characters to change memory address for(q=0;q<8;q++) { //this will loop 16 times for 16 characters d = 0; i = lcd[e]; //first 4 pinouts i >>= 4; //this uses bitwise to skip over P1.1 and P1.2 used for serial communication i &= 1; //it breaks the character into the first 4 bits d |= i; i = lcd[e]; i >>= 5; i &= 7; i <<= 3; d |= i; P1OUT = d; //send first 4 bits to lcd P1OUT |= BIT6 + BIT7; _delay_cycles(500); P1OUT = 0x80; _delay_cycles(500); d = 0; i = lcd[e]; //last 4 pinouts i &= 1; //same as above, but it breaks the pinouts into the last 4 bits d |= i; i = lcd[e]; i >>= 1; i &= 7; i <<= 3; d |= i; P1OUT = d; //send last 4 bits to lcd P1OUT |= BIT6 + BIT7; _delay_cycles(500); P1OUT = 0; _delay_cycles(500); e++; //get ready to send next character } if(p<1) { P1OUT |= BIT5 + BIT3 + BIT6; //this will change the address of the lcd _delay_cycles(500); //so additional text will flow across lcd P1OUT = 0; //instead of acting like an 8x2 lcd _delay_cycles(500); P1OUT |= BIT5 + BIT6; //last 4 bits _delay_cycles(500); P1OUT = 0; _delay_cycles(500); } } _BIS_SR(LPM4_bits); //program complete, enter low power mode }
     
    Note to those who want to buy LCD's: they don't have a backlight, I glued 2 blue led's on to the one in the picture below. If you want one then just send me a PM. $3 each for under 10, $2.50 for 10+, 50 cents off of each display goes to charity.



×
×
  • Create New...