CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Problem with 4X20 LCD display and dsPIC33EV256GM106
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

Problem with 4X20 LCD display and dsPIC33EV256GM106
PostPosted: Sat Dec 08, 2018 5:01 pm     Reply with quote

I seem to be having a very strange problem with FlexLCD4X20.c that was originally written by PCM-programmer I have used this driver file a million times before and it always works, never had an issue. Suddenly I incorporate this file with a new program using a dsPIC33EV256GM106 which is a new device for me that I need to use for SENT serial protocol.

It actually is the only PIC out there that has the hardware modules for this type of application. My LCD display is a 4X20 New Haven display that I have used many times before with this same 4X20 LCD driver, so I know it works at least with other PIC’s. The only modifications I have made to this FlexLCD4X20.c file is the remapping of the control and data pins to match my board, I have also not used the R/W signal and actually keep this pin low and have commented out of said file.

The behavior I am seeing on my display is that when I write to the first line (x=1, y=1) or lcd_gotoxy(1,1) everything is ok however any subsequent lines written to lines 2,3 and 4 do not show anything just blank? it only writes to line 1.

I have tested the display control lines and four bit data bus with a logic analyzer and everything appears to be OK, so obviously it is not an blatant issue on my hardware. So if I write the following:
lcd_gotoxy(1,1); printf(lcd_putc,"1,2,3"); I get exactly “1,2,3” on my first line of the display but any subsequent lines do not show up.

Now, if I change the R/W signal so it does both reads and writes a very interesting thing happens; the “1,2,3” on my first line begins to scroll to the right until it reaches the 20th character position, then it’s last character appears on the first position of line 3 and does the same scrolling on that line…….I am totally baffled by this???

Unfortunately the CCS debuggers that I have (ICD-U64 and ICD-U80) do not like to work on debug mode on this particular PIC, it continuously gets verification errors and crashes. I am trying to work with CCS on this issue. I have tried using MPLAB-X with ICD3 but doing debug while using the CCS compiler through MPLAB-X never works correctly. I am not sure if this is an issue with these PIC series as I have never seen this problem before.

I have written a very brief program just to drive the display and taken out anything else that could cause problems. My code is shown below, I have not included the FlexLCD4X20.c as that is kind of long. Any help or advice will be greatly appreciated.
Code:

******** test.h *********************
#include <33EV256GM106.h>
#FUSES ICSP1
//#device ICD=TRUE
//#FUSES DEBUG
#FUSES NODEBUG
#FUSES WDT_SW                      //NO Watch Dog Timer
//#FUSES XT
#FUSES NOBROWNOUT               //No brownout reset
#FUSES DMT_SW
/// tried various clock configurations but get the same results with display
#use delay(crystal= 8.00MHz, clock = 64000000,clock_out) //this is the required mode I will need
//#use delay(crystal= 8.00MHz,clock_out)
#define RED_LED_ON   output_low(PIN_A12)
#define RED_LED_OFF  output_high(PIN_A12)
#define GREEN_LED_ON  output_low(PIN_A11)
#define GREEN_LED_OFF output_high(PIN_A11)
#define PWR_ON   output_high(PIN_E13);  output_high(BKLIGHT)
#define PWR_OFF  output_low(PIN_E13)
******** test.h *********************

Code:

********* test.c **********************
#include <test.h>
#include <FlexLCD4X20.c>

void Init(void)
{
 set_tris_a(0X0303); //0b0000001100000011
 set_tris_b(0X7D8C); //0b
 set_tris_c(0X0000); // all outs
 set_tris_d(0X0000); // all outs
 set_tris_e(0X0000); // all outs
 set_tris_f(0X0001); // all outs except for F0
 set_tris_g(0X0000); // all outs
 RED_LED_OFF;
 GREEN_LED_OFF;
 PWR_ON; //latches the power ON
 output_low(PIN_B9); // this was done to set R/W on LCD to 0
 delay_ms(100);
 lcd_init();
}


void main()
{
     Init();
 
   RED_LED_ON;
   delay_ms(3000);
   RED_LED_OFF;
   
   GREEN_LED_ON;
   delay_ms(3000);
   GREEN_LED_OFF;
 
   while(TRUE)
{

lcd_putc("\f");
GREEN_LED_ON;  //RED_LED_ON;
delay_ms(500);
GREEN_LED_OFF;  //RED_LED_OFF;
lcd_gotoxy(1,1); 
delay_ms(5);
printf(lcd_putc,"1,2,3");
delay_ms(5);
lcd_gotoxy(1,2);
delay_ms(5);
printf(lcd_putc,"4,5,6");
delay_ms(5);
lcd_gotoxy(1,3);
delay_ms(5);
printf(lcd_putc,"7,8,9"); 
delay_ms(5);
lcd_gotoxy(1,4);
delay_ms(5);
printf(lcd_putc,"10,11,12,13");
delay_ms(2000);

      // restart_wdt();
     
   }

}

Code:

********* test.c **********************


// This is my setup on setup on the FlexLCD4X20.c
 #define LCD_DB4   PIN_C7
 #define LCD_DB5   PIN_C8
 #define LCD_DB6   PIN_D5
 #define LCD_DB7   PIN_D6
 #define LCD_E     PIN_C6
 #define LCD_RS    PIN_C9
 #define LCD_RW    PIN_B9


// These are the line addresses for most 4x20 LCDs. (always worked on this display)
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54
temtronic



Joined: 01 Jul 2010
Posts: 9222
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Dec 08, 2018 6:17 pm     Reply with quote

Sigh, well I feel your pain..
don't use 33 series PICs but, general comments...

1) Is the power supply good, stable and 'over rated' ?

2) Any special power requirements for this PIC, like 'extra' caps or PCB layout ?

3) any chance there's an internal peripheral still 'attached' to the LCD I/O pins ?

4) If you have LCD on one port (say all PortB) does it work or fail ?

5) can I assume you've tried another LCD module, one you know works 100% ?

I know most of this is obvious but..it's a new PIC to you, hopefully you'll have some good luck soon !

Jay
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Sat Dec 08, 2018 7:21 pm     Reply with quote

Thank you temtronic,
Yes the power supply is very stable (currently using a bench lab supply).
Supposedly no different than other pics and I verified every voltage level agains the data sheet.
No, no other peripherals are mapped or conflicting with the I/O, I have also tested all the I/O and it appears to be working normally.
For your #4 question I cannot do that as the board is already etched and designed, but if I recall the 4X20 Flex display driver can use different I/O bits from multiple ports, they do not have to be contiguous to any port.
I have actually tried this same module using the same identical driver on another PIC and it works flawlessly.

I have strong suspicions and I hope I am wrong that there is something to do with the CCS compiler as I keep having a lot of issues with their programmers / debuggers. This thing is going to make my head explode.
temtronic



Joined: 01 Jul 2010
Posts: 9222
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Dec 08, 2018 9:54 pm     Reply with quote

OK, been thinking again...
maybe cut same code for another PIC that you know works. Just the bare minimum 'Hello World' program.compile both and test, then printout the listings for both. They should be very, very similar..the LCD drive has to be the same.

I've used the flex420 driver for years as well and never had a problem, though I use the 'write only' version.

As I type this I wonder about if the driver is accessing the port latch register instead of the output one (or whatever it's called....it's late, long day, need zzzzzs !) it's gotta be some silly 'quirk' though...
when you solve it, tomorrow, after your 4th cup of joe, post what it was....
good luck !
Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19500

View user's profile Send private message

PostPosted: Sun Dec 09, 2018 2:01 am     Reply with quote

Have you checked the B9 signal is being generated?. This is one of the op-
amp input pins, and this has priority over normal I/O.
Try adding a comparator disable to the code to ensure this is off:

setup_comparator(5, NC_NC);

I'd suggest the most likely issue is timing. Though the flexLCD code has been
tested with most chips, a DSPIC at 64MHz, will be performing I/O faster than
any PIC12/16/18 can manage. The first thing I'd do is lengthen the boot up
delay slightly. The original Hitachi LCD controller, specified that it took 90mSec
from power applied to the chip being able to receive data. Many of the 'clone'
chips take longer, and I notice you have not got any power on delay in the
fuses, so the PIC will be starting very quickly. Add PLLWAIT, which will delay
boot until the PLL is synchronised, and increase the delay to perhaps 200mSec.
It's possible that the issue is that the chip is not being initialised quite right.
The ST066U used by most of the Newhaven displays, does not give a figure
for the boot time from power on.


Other thing is it may be a timing issue between the nibbles.
If you look at the code, it drops the E bit, and then exits. When sending a
byte, the next write then follows immediately, outputting 4 bits, and then
pulsing the E bit again. Issue is that on a chip as fast as this, outputting
these four bits may not take the required time between two successive
enables. So try:
Code:

//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));   
 output_bit(LCD_DB7, !!(nibble & 8));   

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
 delay_us(1); //add this delay
}

This controller requires a minimum of 1200nSec between successive cycles.
On any slower PIC, the output instructions provide this. It may be that on
the DsPIC this is not quite being met....

The address values look right. The 20x4 display, is actually controlled as a 40x2 display,
with the third 'display' line, being the second half of the first 'controller' line.
This is why the 'scroll' behaviour is what you are seeing. As a character moves out the
right end of line1, it should appear at the start of line 3.

Your behaviour when R/W is used, is 'interesting'. Thinking about it, I wonder if you are the first person to use the 20x4 driver on a DsPIC, with a
recent compiler?.
Try changing all references in the driver that are to 'int8', to 'unsigned int8'.
On the DsPIC, the default integer is signed.
Now this shouldn't normally matter with the things that the driver does, but
a couple of compiler versions ago, CCS changed the default behaviour on
rotation to be arithmetic, rather than logical. So rotation of a signed value
now behaves differently. This could affect the behaviour when two nibbles
are combined/separated in the driver.
Ttelmah



Joined: 11 Mar 2010
Posts: 19500

View user's profile Send private message

PostPosted: Sun Dec 09, 2018 12:20 pm     Reply with quote

Can confirm, you need to change all the int8 references to unsigned int8.

The chip is sign extending on the or instruction to generate the goto. Doesn't
do this on a compiler a few versions old, but is doing it on the current compiler.
Also does it when dealing with the busy bit, when you enabled R/W.
Ttelmah



Joined: 11 Mar 2010
Posts: 19500

View user's profile Send private message

PostPosted: Mon Dec 10, 2018 1:58 am     Reply with quote

OK. I've played with flex_lcd, and rewritten the timings to be confident of
working at faster clock rates. A couple of macros now calculate the minimum
number of delay cycles needed for some parts of the code.

Code:

// Flex_LCD420.c
//PCM_Programmer's flex_lcd driver for 4x20
//Modified for the chip being used in this thread, and PIC24/30

// This is my setup on setup on the FlexLCD4X20.c
 #define LCD_DB4   PIN_C7
 #define LCD_DB5   PIN_C8
 #define LCD_DB6   PIN_D5
 #define LCD_DB7   PIN_D6
 #define LCD_E     PIN_C6
 #define LCD_RS    PIN_C9
 #define LCD_RW    PIN_B9

// If you want only a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.  Doing so will save one PIC
// pin, but at the cost of losing the ability to read from
// the LCD.  It also makes the write time a little longer
// because a static delay must be used, instead of polling
// the LCD's busy bit.  Normally a 6-pin interface is only
// used if you are running out of PIC pins, and you need
// to use as few as possible for the LCD.
//#define USE_RW_PIN   1     
// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

//#define USE_LCD_RW   1     

// These are the line addresses for most 4x20 LCDs.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x40
#define LCD_LINE_3_ADDRESS 0x14
#define LCD_LINE_4_ADDRESS 0x54

// These are the line addresses for LCD's which use
// the Hitachi HD66712U controller chip.
/*
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x20
#define LCD_LINE_3_ADDRESS 0x40
#define LCD_LINE_4_ADDRESS 0x60
*/


//========================================

#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more)

unsigned int8 lcd_line;

unsigned int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2),  // Set mode: 4-bit, 2+ lines, 5x8 dots
 0xc,                     // Display on
 1,                       // Clear display
 6                        // Increment cursor
 };
                             
#define INS_TIME 1000000000LL/(getenv("INSTRUCTION_CLOCK"))
//Gives time for one instruction in nSec
#define NS80 ((80/(INS_TIME))+1)
//gives instruction count for 80nSec (remember though integer so
//rounds down). Hence +1 instruction.
#define NS320 ((320/(INS_TIME))+1)
//gives instruction count for 320nSec.

//-------------------------------------
void lcd_send_nibble(unsigned int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2));
 output_bit(LCD_DB6, !!(nibble & 4));   
 output_bit(LCD_DB7, !!(nibble & 8));   

 //delay_cycles(1); //Issue here not enough delay at fast CPU speeds
 delay_cycles(NS80); //min 80nSec
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.     

#ifdef USE_RW_PIN
unsigned int8 lcd_read_nibble(void)
{
unsigned int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;
   
output_high(LCD_E);
delay_us(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
 
output_low(LCD_E);
delay_us(1);
   
return(retval);   
}   
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_RW_PIN
unsigned int8 lcd_read_byte(void)
{
unsigned int8 low;
unsigned int8 high;

output_high(LCD_RW);
//same delay issue here
delay_cycles(NS320); //320nSec minimum required

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(unsigned int8 address, unsigned int8 n)
{
output_low(LCD_RS);

#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60);
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);
     
#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif
delay_cycles(NS320);

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------

void lcd_init(void)
{
unsigned int8 i;

lcd_line = 1;

output_low(LCD_RS);

#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif

output_low(LCD_E);

// Some LCDs require 15 ms minimum delay after
// power-up.  Others require 30 ms.  I'm going
// to set it to 35 ms, so it should work with
// all of them.
delay_ms(35);         

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);
   
    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 50 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_RW_PIN
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(unsigned int8 x, unsigned int8 y)
{
unsigned int8 address;


switch(y)
  {
   case 1:
     address = LCD_LINE_1_ADDRESS;
     break;

   case 2:
     address = LCD_LINE_2_ADDRESS;
     break;

   case 3:
     address = LCD_LINE_3_ADDRESS;
     break;

   case 4:
     address = LCD_LINE_4_ADDRESS;
     break;

   default:
     address = LCD_LINE_1_ADDRESS;
     break;
     
  }

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      lcd_line = 1;
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1, ++lcd_line);
       break;
   
    case '\b':
       lcd_send_byte(0,0x10);
       break;
   
    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_RW_PIN
char lcd_getc(unsigned int8 x, unsigned int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7));

output_high(LCD_RS);
value = lcd_read_byte();
output_low(LCD_RS);

return(value);
}
#endif


I've tested this in MPLAB, and all the bit timings look right, and correct
values are being sent throughout.

See if this fixes the display issue.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 10, 2018 7:47 am     Reply with quote

Ttelmah, I don't know how to thank you enough. Originally I had suspected that perhaps the execution time for this device with a 64MHz clock might be a problem, however if you note on my posted test code that at one point I had tried using the internal oscillator running at 7.37MHz which is close to the 8MHz that I normally used on other PIC's and never had a problem in the past. When I tried the slower oscillator, I still had the same problem with the display so at this point I was not sure to what the real problem was. Your comment on the unsigned int8 on the compiler was another thing that I had not yet tried. If I recall the CCS compiler by default always uses the unsigned version unless specified and I have not had any issues with the last few code releases regarding your observation. I just want to let you know that when I used your modified file the LCD display now works normally as it should. I guess I don't really understand why it would not work with the slower 7.37MHz clock and yet it is now working with the high speed clock using the cycle delays that you have added. So I guess there is a lot of things that I don't know, but I certainly have to figure this one out.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 10, 2018 7:49 am     Reply with quote

Thank you all for your suggestion and kind help, as usual this forum has always been a life saver over the years.
Ttelmah



Joined: 11 Mar 2010
Posts: 19500

View user's profile Send private message

PostPosted: Mon Dec 10, 2018 7:55 am     Reply with quote

Good. Smile

Glad it worked.
I'll have a word with PCM_programmer, and see if he would like to update
the posted drivers to ensure they will work with PCD.

Best Wishes
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 10, 2018 8:02 am     Reply with quote

Ttelmah FYI, for curiosity sake I changed all the unsigned int8 back to int8 on the 4X20 display driver and found no difference it appears to work just fine so your fix of adding the proper wait times was the real solution. So why would it not work with a 7.37MHz clock???? (NO PLL when I tried that) I will need to get back to basics and try to understand this one.
Ttelmah



Joined: 11 Mar 2010
Posts: 19500

View user's profile Send private message

PostPosted: Mon Dec 10, 2018 8:06 am     Reply with quote

I'd suggest the speed was not changing as you thought...

What compiler version are you on?.
Have you tested using the RW line?.

It was the code for the later that potentially has an issue with signed.

In fact the unsigned code, is slightly smaller, so it's better to use this
anyway!.....
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 10, 2018 8:13 am     Reply with quote

I have to say that when I went down to 7.37MHz I did not verify such on a scope or the like, should have written a routine to toggled a bit using delay_cycle(1) and verified the timing on a scope. I am using the latest version of PCD (V5.081) and I still cannot get either CCS debugger to work with this particular family of dsPIC and I know it is a CCS issue. I will try to contact the later to day on that.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 10, 2018 8:14 am     Reply with quote

YES, I have tested it using the R/W line and it works fine!
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Mon Dec 10, 2018 8:17 am     Reply with quote

cbarberis wrote:
...If I recall the CCS compiler by default always uses the unsigned version unless specified...


The 8 bit versions of the compiler (PCB, PCM and PCH) which target any of the PIC10, PIC12, PIC16, and PIC18 devices are all unsigned by default. The 16 bit version (PCD) which targets the PIC24, PIC30, dsPIC-whatever, etc. is signed by default.

Ordinarily, this is not a problem if your project will never be migrated to a different platform (PIC18 -> dsPIC or PIC24 -> PIC16 for example). However, if you do try to migrate from one to another, pretty much guaranteed you're going to have problems. I learned the hard way when I migrated a proof-of-concept project developed for a PIC18 to a dsPIC. Ever since, all code I generate and all code my employees generate is always explicit in all variable declarations (signed or unsigned).
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group