View previous topic :: View next topic |
Author |
Message |
dale.grand
Joined: 26 Aug 2011 Posts: 7
|
String Manipulation |
Posted: Fri Aug 26, 2011 8:01 pm |
|
|
I am using a PIC16F887 with a New Haven Display LCD (16x2) and I had troubles using LCD.C...could only get 8 characters dimly and then the PIC would freeze up. I can display perfectly using the long drawn out program of displaying one digit/character at a time via regular programming i/o functions, but I'd like to simplify that. I am new to C and only do this in my spare time as a hobby. I can get the results I want if i attempt one character at a time. However, is there a way to load a string to memory/variable and then extract one character at a time from that location/variable? I'm generally not one to ask for help...I usually figure things out on my own so they stick better, but this one is really causing me some trouble. Any help is much appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 26, 2011 8:58 pm |
|
|
Quote: | then the PIC would freeze up
|
Use the Flex lcd driver:
http://www.ccsinfo.com/forum/viewtopic.php?t=24661
Quote: | could only get 8 characters dimly |
Make sure you have a contrast circuit connected to the contrast pin on the LCD.
This thread has a schematic of two resistors connected as a voltage
divider to get the contrast voltage:
http://www.ccsinfo.com/forum/viewtopic.php?t=33292&start=11
Or you can use a 10K trimpot. Connect the two ends to +5v and ground,
and connect the wiper pin to the LCD's contrast pin. Set it for about
0.5v to start. Then when something is displayed, fine tune it for best
contrast.
Quote: |
Is there a way to load a string to memory/variable and then extract one
character at a time from that location/variable?
|
Use printf as shown near the beginning of the thread in the link below.
See how it's used to display a string from an array on the lcd:
http://www.ccsinfo.com/forum/viewtopic.php?t=45935
A string is an contiguous group of ASCII characters with a 0x00 byte at
the end of the group. The array must be at least be large enough to hold
all the characters and the string terminator byte of 0x00. |
|
|
dale.grand
Joined: 26 Aug 2011 Posts: 7
|
|
Posted: Sat Aug 27, 2011 11:44 pm |
|
|
I have used both the LCD.C and the Flex with similar results from both. I am also trying to stick with passing bytes instead of nibbles and it seems like both default to nibbles...still only 8 characters and my status LEDs stop and so does the LCD.
Contrast is poor when using the inits from both the LCD.c and Flex, but if I initialize it with general I/O commands per the LCD data sheet...very crisp once on I adjusted my pot that I have connected to the contrast pin...not really sure why the inits from LCD and Flex would cause that.
I have tried the printf(lcd_putc...) and it works great up to eight characters...I even tested sending like 2 characters with one line of code and then another 8 or more from another line of code...but still after 8 characters...everything stops...no more status/debug LEDs changing, nor do I get any progress on my LCD. However, if I use general I/O lines of code I can write perfectly to the whole display and without any contrast problems...hence my desire to abandon both the LCD and Flex files and go about it a different way if that is at all possible. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Aug 28, 2011 5:19 am |
|
|
Sorry to hear about the problem! I've used the flexLCD driver for years without problems. Can you supply the LCD model# to link to it's datasheet? Could be a silly 'timing'or setup problem. What pins are you using for the driver as well. Also be sure to have a good ground (though if it works in 8 bit mode...sigh) |
|
|
dale.grand
Joined: 26 Aug 2011 Posts: 7
|
|
Posted: Sun Aug 28, 2011 5:36 pm |
|
|
I am using a Newhaven Display NHD-C0216AZ-FSW-GBW which has a built in Novatek driver (NT7605). I have the data pins 0-7 wired to port b 0-7. I have RS connected to C0, RW to C1, and Enable on C3...C2 is used to drive a transitor connected to the backlight. Oh and the contrast pin is connected to a resistor and a pot that I have adjusted for best visual results...and my ground is good clear on back to the incoming supply from my Microchip PICKit2.
If you can let me know where I went wrong, or make any suggestions on how I might get the FlexLCD to work...that would be sooo awesome! I'm not really one for reinventing the wheel and I'd really like to get past this speed bump and on to other projects. Also, if you can let me know what LCDs you have found to work well with PICs and C that would also be very helpful...I'd much rather buy LCDs that are known to work well instead of be someones fieldtester.
Thanks in advance for yout time and effort temtronic. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sun Aug 28, 2011 6:20 pm |
|
|
I've looked at the datasheet and it seems like a 'generic' LCD.
If you open up the flex_lcd driver at the top you have to change the #defines to whatever pins you've wired up the LCD to PIC pins. I do NOT use the R/W pin (my LCDs are used as Write Only). There's a line near there to uncomment to change that use I believe.
It's best to open up the driver, save AS 'myLCDdriver.c' and make the appropriate changes there NOT the original.
I've used 3 or 4 different LCDs and never had a problem..hopefully you'll get it going soon ! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Aug 29, 2011 2:12 am |
|
|
It is also perhaps worth understanding 'why' nibble mode is the commonest format.
Transferring the data using this, with even a reasonably slow PIC, only takes a couple of uSec. The fastest LCD commands take 40uSec to complete, so the time penalty from nibble mode is negligible. However four pins is a big saving. The controllers also wake up in nibble mode.
Now, there is nothing normally in the LCD driver, that can affect contrast, _except_ setting the unit up for the wrong number of lines/columns. My guess is that perhaps in trying to change the driver to use byte mode, these values have got set wrongly.
Realistically, much simpler, to just use nibble mode, and the driver 'as is', just with the bit definitions changed to match your board, and I suspect you will find everything then works.
Best Wishes |
|
|
dale.grand
Joined: 26 Aug 2011 Posts: 7
|
|
Posted: Mon Sep 05, 2011 10:23 pm |
|
|
Alright, I have been trying all of your suggestion with no improvements on my situation. I have tried several times and even restarted from scratch again...only to arrive at the same aggrivating destination...the PIC freezes up. I used the " printf(lcd_putc,"\fCurrent Temp 75deg")", but all I get is a very crisp and clear "Current " with a blinking cursor afer the space at the end and then my status LEDs no longer change state. I can only get 8 characters to display using the fancy LCD.c and similar results when I have tried the FlexLCD.c on my 16 character 2 line LCD. I'd like to be able to use the quick drivers like everybody else. I'm certain I keep making the same novice error...maybe someone can look over this code and give me some pointers please?
Code: |
#include <16F887.h> // header file for the PIC16F887
// includes built-in functions and constants
// for arguments/returns.
//RS = Pin_C0
//RW = Pin_C1
//Back Light = Pin_C2
//Enable = Pin_C3
//Data 0-7 = Port B Pin 0-7
// FUSES sets the PIC16F887 Configuration Words. See top of the header file
// 16F887.h for fuse option constants.
#FUSES INTRC,NOWDT,NOPUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOIESO,NOFCMEN,NOLVP
#use fast_io(B)
#use delay(clock=4000000)
#include "My_LCD.c"
void main(void)
{
int16 shift = 100; //delay between letters
int Disp1 = 0x0f; //used to store characters from LcD
int8 Disp2 = 0xf0; //used to store characters from LcD
int16 time = 1000; //delay variable
output_d(Disp1); //status LEDs
output_high(pin_c2);
delay_ms(time);
output_d(Disp2); //status LEDs
delay_ms(time);
lcd_init();
output_d(0xaa);
delay_ms(time);
lcd_putc("\f");
output_d(0x55);
delay_ms(time);
printf(lcd_putc,"\fCurrent Temp 75deg");
delay_ms(time);
top:
output_d(Disp1);
delay_ms(time);
output_d(Disp2);
delay_ms(time);
goto top;
}
|
Last edited by dale.grand on Tue Sep 06, 2011 7:32 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Tue Sep 06, 2011 2:23 am |
|
|
Remove the LCD.c, from the post. Read it's header, and understand that you are in breach of copyright....
Just post your changes.
One thing leaps out though. LCD.c _requires_ the pin order to be enable, rs, RW, working up from the bottom of the port. To change this, you need to modify LCD_PIN_MAP.
Flex_lcd does not have this limitation and should work with just:
Code: |
#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7
#define LCD_E PIN_C3
#define LCD_RS PIN_C0
#define LCD_RW PIN_C1
#define USE_LCD_RW 1
|
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Sep 06, 2011 5:22 am |
|
|
Couple of quick comments...
re...
#use fast_io(B)
I'd get rid of the use fast_io(..) line because if you don't configure the TRIS registers correctly it'll come back to bite you ! Let the compiler handle it automatically (one of the joys of the CCS C compiler!!).99.9999999% of the programs presented on this forum do NOT need the minor speed increase that set_tris(...) gives but ALL can be 'sunk' by incorrect coding.Yes, I was one of them, once).
Also, I'm using the flex_lcd.c driver, NO problems, easy to setup, understand,modify. I use 4 or 5 different PICs and have NEVER had any LCD issues (timing or bad data). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Sep 06, 2011 12:53 pm |
|
|
Quote: |
New Haven Display LCD (16x2)
|
1. Post the full part number of your LCD.
2. Post a list of the physical connections to your LCD. Look at the LCD
on the board, and post the connections that you have to each pin.
Don't post a list of #defines. Look at the actual, real, wire connections
to the LCD and post what you see. |
|
|
dale.grand
Joined: 26 Aug 2011 Posts: 7
|
|
Posted: Tue Sep 06, 2011 10:50 pm |
|
|
Ok, I just tried the flex_lcd driver with only making/confirming that the pin map mods as suggested...I remembered right away why I abandoned this one. I just got a blank screen...not even a cursor. Do I need to modify the LCD_Init string too?
@PCM Programmer:
I am using a Newhaven Display NHD-C0216AZ-FSW-GBW which has a built in Novatek driver (NT7605). I have pins connected as follows:
LCD Pin 1(GND)...GND
LCD Pin 2(Contrast V+)...Pot Pin 2
LCD Pin 3(V+)...VDD
LCD Pin 4(RS)...PIN_C0
LCD Pin 5(RW)...PIN_C1
LCD Pin 6(Enable)...PIN_C3
LCD Pin 7(DB0)...PIN_B0
LCD Pin 8(DB1)...PIN_B1
LCD Pin 9(DB2)...PIN_B2
LCD Pin 10(DB3)...PIN_B3
LCD Pin 11(DB4)...PIN_B4
LCD Pin 12(DB5)...PIN_B5
LCD Pin 13(DB6)...PIN_B6
LCD Pin 14(DB7)...PIN_B7
I have used long code as below to send and read characters across the entire display to test all of my connections and LCD functionality so I am certain of my pin out and connections. Only trouble that I have encountered is reading some certain characters gives different characters, but I'm assuming that has something to do with signed and unsigned characters...
Some of the code in my long hand test program
Code: |
//set to 8-bit operation and select 2-line display and character font
output_low(pin_c0);
output_low(pin_c1);
Output_b(0x38);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0x0f); //status LEDs
delay_ms(1000);
//Display on and cursor on and blinking (0e=no blinking and 0f=blinking)
output_low(pin_c0);
output_low(pin_c1);
Output_b(0x0f);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0xf0); //status LEDs
delay_ms(1000);
//increase address by one...shift the cursor to the right when writing to the DDRAM/CGRAM...
//now the display has no shift.
output_low(pin_c0);
output_low(pin_c1);
Output_b(0x06);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0x0f); //status LEDs
delay_ms(1000);
//clear display
output_low(pin_c0);
output_low(pin_c1);
Output_b(0x01);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0x0f); //status LEDs
delay_ms(3000);
//write "W" and increment the cursor to the right one space.
output_high(pin_c0);
output_low(pin_c1);
Output_b(temp);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(temp); //status LEDs
delay_ms(3000);
//write "e"...
output_high(pin_c0);
output_low(pin_c1);
Output_b(0x65);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0xf0); //status LEDs
delay_ms(shift);
.
.
.
//the cursor is moved to the beginning of the second line
output_low(pin_c0);
output_low(pin_c1);
Output_b(0xc0);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0x0f); //status LEDs
delay_ms(shift);
//write "Y"...
output_high(pin_c0);
output_low(pin_c1);
Output_b(0x59);
delay_cycles(1);
output_high(pin_c3);
delay_cycles(1);
output_low(pin_c3);
output_d(0xf0); //status LEDs
delay_ms(shift);
.
.
.
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Sep 07, 2011 8:14 am |
|
|
The one line this does not test, is the LCD R/W line, with you simply delaying, rather than reading data back from the LCD.
So try the flex driver with:
Code: |
#define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7
#define LCD_E PIN_C3
#define LCD_RS PIN_C0
#define LCD_RW PIN_C1
#define USE_LCD_RW 0
|
and add "output_low(PIN_C1);" before calling the driver.
Sequence needed is:
Code: |
#include <16F887.h> // header file for the PIC16F887
#FUSES INTRC,NOWDT,NOPUT,NOMCLR,NOPROTECT,NOCPD,NOBROWNOUT,NOIESO,NOFCMEN,NOLVP
#use delay(clock=4000000)
#include flex_lcd.h //With the pin section changed as above
void main(void) {
int8 ctr=0;
output_low(PIN_C1); //Turn off reading from LCD
output_high(PIN_C2); Turn on your backlight
delay_ms(100); //Some LCD's are slow to wake up
lcd_init();
printf(lcd_putc,"\fLCD Live");
do {
lcd_gotoxy(1,2);
printf(lcd_putc,"Count %d ",ctr++);
delay_ms(1000);
} while(TRUE);
}
|
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 07, 2011 1:23 pm |
|
|
Quote: | #define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5
#define LCD_DB6 PIN_B6
#define LCD_DB7 PIN_B7
#define LCD_E PIN_C3
#define LCD_RS PIN_C0
#define LCD_RW PIN_C1
// #define USE_LCD_RW 1
and add "output_low(PIN_C1);" before calling the driver.
|
To disable use of the R/W pin by the flex driver, you need to comment
out the line in bold. But as Ttlemah says, if you have the lcd's R/W line
connected to your PIC, then you will need to set that PIC pin to a low-
level with a line of code.
And get rid of all the #use fast_io() statements. The flex driver doesn't
use fast i/o. |
|
|
dale.grand
Joined: 26 Aug 2011 Posts: 7
|
|
Posted: Wed Sep 07, 2011 11:25 pm |
|
|
Ok, I tried your suggestions with the flex_lcd driver, but I still came up with a blank display. I even tried pasting your code with the "LCD Live" and Counter...after adding the "//" before the second "Turn" and compiled it...still no display. I even adjusted my potentiometer for the contrast up and down 5 complete turns. Something just isn't jiving. My next move is to create and debug some 4-bit operation long hand code...considering all the drivers seem to resort to that operation anyway. Then once I work through that and learn a few lessons along the way, I will have a better understanding what I need the drivers to do...or what I need to do to better use the drivers. Thanks for your help and I will post any updates. |
|
|
|