|
|
View previous topic :: View next topic |
Author |
Message |
ratgod
Joined: 27 Jan 2006 Posts: 69 Location: Manchester, England
|
LCD on Port A problem |
Posted: Mon Oct 27, 2008 11:14 pm |
|
|
I have a Hitachi type LCD I am trying to get to work on port A of a PIC18F4520. I have no problem with any other port, but nothing appears on the screen when using port A. I know the screen works and I have also had identical trouble while simulating it in ISIS.
I am using a 20x4 LCD which I got the code of this forum somewhere and have had great success with.
my pin configuration is listed in the code below, the RW pin is taken to 0v, which is a normal configuration I use the LCDs in.
I have all the analogues turned off but still no avail.
anyone have any ideas?
lcd driver code (this is known to work):
Code: |
////////////////////////////////////////////////////////////////////////////
//// LCD_4b.C ////
//// Driver for common 4x20 LCD modules ////
//// ////
//// lcd_init() Must be called before any other function. ////
//// ////
//// lcd_putc(c) Will display c on the next position of the LCD. ////
//// The following have special meaning: ////
//// \f Clear display ////
//// \n Go to start of second line ////
//// \b Move back one position ////
//// ////
//// lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1) ////
//// ////
//// lcd_getc(x,y) Returns character at position x,y on LCD ////
//// ////
////////////////////////////////////////////////////////////////////////////
// lcd4.c
// 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)
//#define LCD_CGRAM_ADDR 0x40 // Set the CGRAM address
//#define LCD_DDRAM_ADDR 0x80 // Set the DDRAM address
#define LCD_CGRAM_ADDR 0x40 // Set the CGRAM address
#define LCD_DDRAM_ADDR 0x80 // Set the DDRAM address
int8 lcd_line;
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
};
//-------------------------------------
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);
}
//-----------------------------------
// 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
int8 lcd_read_nibble(void)
{
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
int8 lcd_read_byte(void)
{
int8 low;
int8 high;
output_high(LCD_RW);
delay_cycles(1);
high = lcd_read_nibble();
low = lcd_read_nibble();
return( (high<<4) | low);
}
#endif
//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, 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);
delay_cycles(1);
#ifdef USE_RW_PIN
output_low(LCD_RW);
delay_cycles(1);
#endif
output_low(LCD_E);
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
//----------------------------
void lcd_init(void)
{
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(int8 x, int8 y)
{
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;
}
if (lcd_line>4)
{
lcd_line=1;
}
}
//------------------------------
#ifdef USE_RW_PIN
char lcd_getc(int8 x, 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
|
And the basic parts of my main code:
Code: |
#include <18F4520.h>
#device adc=8
#FUSES NOWDT, WDT128, HS, NOPROTECT, BROWNOUT, BORV20, PUT, NOCPD, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, IESO, FCMEN, NOPBADEN, NOWRTC, NOWRTB, NOEBTR, NOEBTRB, NOCPB, LPT1OSC, MCLR, NOXINST
#use delay(clock=20000000,RESTART_WDT)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,restart_wdt,errors)
#USE FAST_IO(A)
#define LCD_RS PIN_A0
#define LCD_E PIN_A1
#define LCD_DB4 PIN_A2
#define LCD_DB5 PIN_A3
#define LCD_DB6 PIN_A4
#define LCD_DB7 PIN_A5
#include "drivers\lcd_20x4.c" // LCD driver
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
lcd_init();
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
printf(lcd_putc,"\fThis is a test\n");
printf(lcd_putc,"This is a test\n");
printf("\fThis is a test\n");
while(true)
{
process_tasks();
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 27, 2008 11:30 pm |
|
|
The Flex drivers don't work with Fast i/o enabled. It says that in the
instructions in the Code Library. You need to delete that line.
Thinking about it some more, since you're not using the R/W pin
all pins are write-only. You could use fast i/o mode in that case
but you need to set the TRIS on pins A0-A5 to be all outputs.
You could try it by adding this line to main(). Put it after all the
Wizard code:
Quote: | enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL); |
You don't have an #int_rda interrupt service routine. If you receive
a character, the PIC will jump to address 0x0008, except there will
be nothing there and your program will crash. Delete those lines. |
|
|
ratgod
Joined: 27 Jan 2006 Posts: 69 Location: Manchester, England
|
|
Posted: Tue Oct 28, 2008 7:25 am |
|
|
unfortunately it didn't do anything extra.
But a work colleague suggested putting pull up resistors and it worked a treat.
the INT_RDA is already in my code, I just removed it for the posting.
many thanks for your suggestions |
|
|
|
|
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
|