![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
smee
Joined: 16 Jan 2014 Posts: 24
|
2 x 16 Fordata lcd display at 80 Mc/s [Solved] |
Posted: Sun Jun 02, 2019 5:38 am |
|
|
Could someone help me with this?
I have a dspic33fj128gp802 connected to a Fordata 3v lcd.
Farnell part number 2674133, it uses the splc780d chip.
I have been using Ttelmah's speeded up driver for the lcd.
But i cannot for the life of me, get the thing to function properly.
It misses characters.
The example '/fTest of print' will display
' Ts f rnt' for example.
I am using ICD3 with mplab 8.92 and compiler version 4.120.
Code: |
// test of display.
#include "33FJ128GP802.h" // include the processor header file
#ifdef __DEBUG
#device icd=true
#endif
#FUSES NOWDT
#FUSES FRC_PLL
//#FUSES PUT128
#FUSES ICSP1
#FUSES NOJTAG
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOIESO // NO INTERNAL/EXTERNAL SWITCHOVER
#build (stack=4096)
#OCS 80 Mhz
// LCD connections
#define LCD_DB4 PIN_B10
#define LCD_DB5 PIN_B9
#define LCD_DB6 PIN_B8
#define LCD_DB7 PIN_B6
#define LCD_RS PIN_A2
#define LCD_RW PIN_A3
#define LCD_E PIN_A4
#ifndef __DEBUG
#define BLight PIN_B1
#endif
//-----------------------------------
// LCD Display
unsigned int8 Lcd_address;
#include "LCD216/Flex_new.c" // include the lcd driver
//-----------------------------------
#zero_ram
void main()
{
delay_ms(500);
lcd_init(); // initialise the lcd display
printf(lcd_putc,"\fTest of print");
do { } while (1==1);
}
|
and the flex_new file is
Code: |
// Flex_LCD420.c
//PCM_Programmer's flex_lcd driver for 4x20
//Modified for the chip being used in this thread, and PIC24/30
// 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 the fordata 2 x 16 lcd.
#define LCD_LINE_1_ADDRESS 0x00
#define LCD_LINE_2_ADDRESS 0x28
// Screen is 16 characters wide.
#define LCD_WIDTH 0x10
// 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 INS_TIME 50
//#define INS_TIME 10 // have doubled the actual
// 50 nano seconds instruction time
#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.
#use standard_io(a)
#use standard_io(b)
//-------------------------------------
void lcd_send_nibble(unsigned int8 nibble)
{
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(1);
output_low(LCD_E);
// delay_us(1);
}
//-----------------------------------
// 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=0;
high = lcd_read_nibble();
high=high<<4;
low=0;
low = lcd_read_nibble();
low=high | low;
return(low);
}
#endif
//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(unsigned int8 address, unsigned int8 n)
{
unsigned int8 x,z;
output_low(LCD_RS);
#ifdef USE_RW_PIN
while(bit_test(lcd_read_byte(),7)) ;
Lcd_Address=x;
#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)
{// initialise the lcd ready for use.
unsigned int8 i;
output_low(LCD_E);
lcd_line = 1;
output_low(LCD_RS);
#ifdef USE_RW_PIN
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(45); // Greater than 40ms after vdd =2.7v
lcd_send_nibble(0x03);
delay_ms(5);
lcd_send_nibble(0x03);
delay_us(100);
lcd_send_nibble(0x03);
while(bit_test(lcd_read_byte(),7)) ;
lcd_send_nibble(0x02);
while(bit_test(lcd_read_byte(),7)) ;
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
#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 36:
// lcd_send_byte(1,1); // translates to correct currency.
// break;
case '\f':
lcd_send_byte(0,1); // 0x01=clear the display
lcd_line = 1;
delay_ms(2);
break;
case '\n':
lcd_gotoxy(1, ++lcd_line);
lcd_send_byte(1,' ');
break;
case '\b':
lcd_send_byte(0,0x10);
break;
case '\r':
lcd_gotoxy(1, lcd_line);
lcd_send_byte(1,' ');
break;
default:
lcd_send_byte(1,c);
break;
}
if (lcd_line>2)
{
lcd_line=1;
}
if (lcd_line==1)
if (Lcd_Address>16)
{
lcd_gotoxy(1, lcd_line);
lcd_send_byte(1,' ');
}
if (lcd_line==2)
if (Lcd_Address>(0x28+16))
{
lcd_gotoxy(1, lcd_line);
lcd_send_byte(1,' ');
}
}
//------------------------------
#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 have altered some bits of this from Ttelmah's original, but only in desperation.
I don't know what to do next.
Last edited by smee on Tue Jun 04, 2019 8:35 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Sun Jun 02, 2019 6:40 am |
|
|
I downloaded the spec sheet from Farnell for the LCD module. TR, TF ( rise time, fall time) is specified at typical 150 milliseconds. While there is no minimum listed, well, there has to be ! There isn't a 'device access speed' listed.
I suspect you're accessing it way too fast. I haven't time to look at the revised driver but generally speaking LCD modules are SLOW. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 02, 2019 9:04 am |
|
|
List the connections between the PIC and the lcd. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19382
|
|
Posted: Sun Jun 02, 2019 9:46 am |
|
|
In the posted code, there is no #use delay statement.
delays won't give the times they should without this. Result the code
won't work.
#OCZ, does not do the clock configuration that #USE DELAY does. Use
#USE DELAY, otherwise PLL setups etc., will not always be done correctly. |
|
![](templates/subSilver/images/spacer.gif) |
smee
Joined: 16 Jan 2014 Posts: 24
|
|
Posted: Tue Jun 04, 2019 6:59 am |
|
|
I have made the following alterations to the code.
main.c
Code: |
// test of display.
#include "33FJ128GP802.h" // include the processor header file
#ifdef __DEBUG
#device icd=true
#endif
#FUSES NOWDT
#FUSES FRC_PLL
//#FUSES PUT128
#FUSES ICSP1
#FUSES NOJTAG
#FUSES OSCIO //OSC2 is general purpose output
#FUSES NOIESO // NO INTERNAL/EXTERNAL SWITCHOVER
#build (stack=2048)
//#OCS 80 Mhz
#use delay(internal=80mhz)
// LCD connections
#define LCD_DB4 PIN_B10
#define LCD_DB5 PIN_B9
#define LCD_DB6 PIN_B8
#define LCD_DB7 PIN_B6
#define LCD_RS PIN_A2
#define LCD_RW PIN_A3
#define LCD_E PIN_A4
#ifndef __DEBUG
#define BLight PIN_B1
#endif
//-----------------------------------
// LCD Display
unsigned int8 Lcd_address;
//#include "LCD216/Flex_new.c" // include the lcd driver
#include "LCD216/Flex_orig.c"
//-----------------------------------
#zero_ram
void main()
{
output_low(LCD_E);
output_low(LCD_RW);
output_low(LCD_RS);
output_low(LCD_DB4);
output_low(LCD_DB5);
output_low(LCD_DB6);
output_low(LCD_DB7);
delay_ms(500);
lcd_init(); // initialise the lcd display
printf(lcd_putc,"\fTest of screen");
do {
output_toggle(PIN_B7);
delay_ms(1);
} while (1==1);
}
|
The file flex_orig.c is that posted from
http://www.ccsinfo.com/forum/viewtopic.php?t=57617
The posting is by Ttelmah.
It still malfunctions.
I can fix it by putting a delay_ms(1) at the start of lcd_putc.
But i can not understand why it won't function correctly without it.
I now have the output_toggle at the end to prove that the timings are correct, which they are. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19382
|
|
Posted: Tue Jun 04, 2019 7:32 am |
|
|
I'd suspect the issue is your splc780d chip timings.
The calculations I did were to just ensure the 80nSec and 320nSec timings
needed by the standard Hitachi controller. You'd need to go through the
data sheet for this chip and see where it differs. You'll probably find the
actual data cycle time requires just a little more delay than is being given. |
|
![](templates/subSilver/images/spacer.gif) |
smee
Joined: 16 Jan 2014 Posts: 24
|
|
Posted: Tue Jun 04, 2019 8:33 am |
|
|
The splc780d has a faster response than those used, so it should of have worked out of the box.
I have been looking at the data sheets.
My current fix, is to test for the busy flag to be clear at the end of the lcd_send_byte function.
Exiting only once the busy flag is clear, seems to fix it.
Entry to exit of the lcd_send_byte function is averaging about 25us.
Thank you to everyone for the help. ![Very Happy](images/smiles/icon_biggrin.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19382
|
|
Posted: Tue Jun 04, 2019 10:36 am |
|
|
It doesn't have faster timings. Slightly slower, but not enough to matter.
It has faster on the first, but slower on the second. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|