P!-Ro 4 Posted April 11, 2011 Share Posted April 11, 2011 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. bluehash 1 Quote Link to post Share on other sites
bluehash 1,581 Posted April 11, 2011 Share Posted April 11, 2011 I see a Propeller! Thanks for sharing. If you have any of the Lcds for sale, put up a thread in the Buy/sell forum. You may have better luck selling them there. Do you play TF2? Quote Link to post Share on other sites
P!-Ro 4 Posted April 11, 2011 Author Share Posted April 11, 2011 No I don't play TF2, I had to Google it I will probably post some info in the for sale forum with a link to this thread. I've been feeling particularly broke lately (woes of being a high school student) so I suppose "better luck" could make the difference in making "better projects" (shows you where all my money has been going...) As for the Parallax Propeller, that would be my favorite heavy-duty microcontroller. The MSP340 is now my favorite light duty microcontroller, or at least it is a lot easier to use than the Pickit1 which I just have lying around. Quote Link to post Share on other sites
bluehash 1,581 Posted April 11, 2011 Share Posted April 11, 2011 TF2, because your username is Pi-ro or pyro and there is a class named after it. I just noticed it was an exclamation and not an i. Anyways, if you are in need of something(sensors and stuff), place a "want to buy" thread in the buy/sell. If a member has no use or has one in a parts bin, they may give it away. Quote Link to post Share on other sites
P!-Ro 4 Posted April 11, 2011 Author Share Posted April 11, 2011 That's interesting. It is technically Pi-Ro, with the ! meant to act as an i. Quote Link to post Share on other sites
P!-Ro 4 Posted April 11, 2011 Author Share Posted April 11, 2011 Also, I just wanted to post a link to a thread that I found helpful: viewtopic.php?f=9&t=540#p3717 It requires another IC to work, but may be quite nice for some applications. I would buy a couple of the chips to try it out, but I'm broke, so I'm going to go ahead and see if I can learn off of his code to help me improve mine for a direct connection to the LCD. Quote Link to post Share on other sites
cde 334 Posted April 11, 2011 Share Posted April 11, 2011 Nice work. These character lcds are just everywhere, and there are so many different implementations of them that it makes it easy to find a way of making them work to one's own taste But I do find it annoying that some if not all 16x1s are setup as 8x2s in series. Makes no logical sense. Silly manufactures. I do want to ask though, how did you end up with a few hundred of them? Quote Link to post Share on other sites
P!-Ro 4 Posted April 11, 2011 Author Share Posted April 11, 2011 Hey cde, as I was trying to write this code I was looking at yours for help. I couldn't figure out how you used the i2c to program the lcd, but I did get the idea to put the clock into low power mode at the end from your code. I attempted to use functions in the same way that you did as well, but it gave me errors. As for how I got the LCD's, Craigslist. I don't normally check for things there, but you sometimes just have to thank god for luck! The person I bought them off of had them because he worked for an electronics company and when they had surplus of something after a run they would let their employees buy the surplus for cheap. It still cost a bit much for me, so I borrowed off of a friendly guy I've worked for off and on and soon payed him back with the profits. In fact, if I were to sell any here I would probably ask his wife to help me figure out how to use my paypal to sell them, but before I was 18 she was kind enough to let me use hers since she controls the sales for TechZone. Quote Link to post Share on other sites
P!-Ro 4 Posted April 11, 2011 Author Share Posted April 11, 2011 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. GeekDoc 1 Quote Link to post Share on other sites
GeekDoc 226 Posted April 12, 2011 Share Posted April 12, 2011 Hey P!-Ro, VERY nice job for a first post! I wish I'd learned this stuff when I was in high school. :? Like bulehash wrote, if you are in need of certain chips, put a post in the buy/sell forum. I've sent a couple parts here and there to those in need. I sometimes buy in bulk from eBay (takes a while, but cheap ), so I end up with leftovers; sometimes more than I need. Quote Link to post Share on other sites
P!-Ro 4 Posted April 12, 2011 Author Share Posted April 12, 2011 That's funny GeekDoc, I wish I learned this stuff before I was almost out As for searching for chips, I'll probably post a small list soon enough. I'm more focused on making my code easy-to-use and functional right now. Not only will I need it for what I plan to submit into this Month's contest, but I'm also hoping it will help anyone else hoping to use an MSP with a parallel LCD. I'm planning to make a version after this set to work well with the 16x2 lcd's as well (I don't have one, but I may be able to find one) and I would also like to look into making a routine that uses a bit register to save on I/O. Maybe then I'll call it good enough It's good to learn to do things right, especially if I get a career in electronics. And I feel like I've accomplished something which isn't too bad either. Quote Link to post Share on other sites
P!-Ro 4 Posted April 12, 2011 Author Share Posted April 12, 2011 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); } bluehash 1 Quote Link to post Share on other sites
P!-Ro 4 Posted April 16, 2011 Author Share Posted April 16, 2011 Well, I found my self stuck the past couple days. I added functionality for displaying decimal numbers, and, just like the previous code, I set it up so the decimal numbers could jump past it's 8x2 segment gap. However, while debugging it, any time the code functioned to display numbers I noticed that the global variable for telling me character position and when to jump to address 40 would remain at 1 even when told to increment. After deleting another variable today as I tried to convert the code to number showing only I found that everything suddenly worked, which means I had too much ram being used up so it was delving into that global variable I needed. Who knew? Quote Link to post Share on other sites
zeke 693 Posted April 16, 2011 Share Posted April 16, 2011 Sounds like your chainsaw needs some guards bolted onto it. RobG 1 Quote Link to post Share on other sites
P!-Ro 4 Posted April 16, 2011 Author Share Posted April 16, 2011 Perhaps... Guess I better get used to making more efficient code :? Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.