4-bit LCD s PICF877A HITEC MPLAB a PICKIT3

Dobrý den, mám problém ohledně kódu. Když nahraju tento program, tak kurzor začne blikat na 3. políčku na první lajně a nic jineého se nezobrazí. Mám to jako projekt do školy a piny do lcd už jsou dány. že RC0 je RS, RC1 je RW a RC2 je E. A databity jsou RC4-RC7. Porad´te prosím.

/*

  • This code will interface to a standard LCD controller
  • like the Hitachi HD44780. It uses it in 4 bit mode, with
  • the hardware connected as follows (the standard 14 pin
  • LCD connector is used):
  • PORTD bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
  • PORTC bit 0 is connected to the LCD RS input (register select)
  • PORTC bit 2 is connected to the LCD EN bit (enable)
  • PORTC bit 1 is connected to the LCD RW bit (read or write)
    • To use these routines, set up the port I / O (TRISE, TRISD) then
  • call Init_lcd (), then other routines as required.

*/
#include <pic.h>
#include <htc.h>
#include <stdio.h>
#define _XTAL_FREQ 20000000
#define EN_TRIG ((LCD_EN = 1),(LCD_EN = 0));

static bit LCD_RS @ ((unsigned)&PORTC8+0); // Register select
static bit LCD_EN @ ((unsigned)&PORTC
8+2); // Enable
static bit LCD_RW @ ((unsigned)&PORTC*8+1); // R/W

//Functions

void DelayMs (int x);
void DelayUs (int x);
void Init_lcd (void);
void Write_com_lcd (unsigned char c);
void Write_char_lcd (unsigned char c);
void Write_string_lcd (const char * s);
void Clear_lcd (void);
void Goto_lcd (unsigned char pos);

void main ()
{
ADCON1 = 0x0e; // Set PORTA as digital port
TRISC=0;
Init_lcd(); // LCD Initialization
Clear_lcd(); // Reset LCD and move to start position
Write_string_lcd(“Micro”);
while(1);
}

/---------------------------------------------/
void Init_lcd (void)
{
LCD_RW = 0; // write to LCD
LCD_RS = 0; // write control bytes
DelayMs(150); // power on delay
PORTD = 0x3; // attention!
EN_TRIG;
DelayMs(5);
EN_TRIG;
DelayUs(100);
EN_TRIG;
DelayMs(5);
PORTD = 0x2; // set 4 bit mode
EN_TRIG;
DelayUs(40);
Write_com_lcd(0x28); // 4 bit mode, 1/16 duty, 5x8 font
Write_com_lcd(0x08); // display off
Write_com_lcd(0x0F); // display on, blink curson on
Write_com_lcd(0x06); // entry mode

}

void DelayMs(int x)

{
int y=(x*1000)/15;
while(–y != 0)
continue;
}

void DelayUs(int x)

{
int y = x/15;
while(–y != 0)
continue;

}

void Write_com_lcd(unsigned char c)// send command to lcd

{
LCD_RW = 0;
LCD_RS = 0; // write the command
PORTC = (PORTC & 0xF0) | (c >> 4);
EN_TRIG;
PORTC = (PORTC & 0xF0) | (c & 0x0F);
EN_TRIG;
DelayUs(40);
}

void Write_char_lcd(unsigned char c)

{
LCD_RW = 0;
LCD_RS = 1; // write characters
PORTC = (PORTC & 0xF0) | (c >> 4);
EN_TRIG;
PORTC = (PORTC & 0xF0) | (c & 0x0F);
EN_TRIG;
DelayUs(40);
}

void Write_string_lcd(const char * s)

{
LCD_RS = 1; // write characters
while(*s)
Write_char_lcd(*s++);
}

void Clear_lcd(void)

{
LCD_RS = 0;
Write_com_lcd(0x1);
DelayMs(2);
}

void Goto_lcd(unsigned char pos)
{
LCD_RS = 0;
Write_com_lcd(0x80+pos);
}

:arrow_right: administrator: přesunuto z "Elektronika s mikrokontroléry, procesory"

Začal bych tím, jak to máš celé zapojené. V popisu uvádíš, že na PC4…PC7 jsou připojeny databity LCD, ale ve funkci Init_lcd je použit příkaz PORTD = 0x03. Změň to na PORTC = 0x30; //(0b00110000) a ještě změň PORTD = 0x02 na PORTC = 0x20; //(0b00100000).

Další problém je v příkazu PORTC = (PORTC & 0xF0) | (c >> 4);
a PORTC = (PORTC & 0xF0) | (c & 0x0F);

toto by mělo být PORTC = (c & 0xF0);
a PORTC = ((c & 0x0F) <<4);

Ještě bych upravil EN_TRIG, při fcpu = 20MHz/4 = 5MHz => Tcy = 0,2us
Délka pulzu EN by měla být cca 1us, takže bych to upravil na

void EN_TRIG(void)
{
LCD_EN = 1;
__delay_us(10);
LCD_EN = 0;
__delay_us(10);
}
Ve funkci to pak použiješ jako příkaz EN_TRIG();

Ty jo supr :wink:, tak fce goto už umí skákat přesně na políčka, fce clear taky podle mě funguje, ale ještě to nic nenapíše, jakmile napíšu třeba Write_string_lcd(“a”); tak blikající kurzor zmizí a nic se neobjeví :-/

Zkus tuhle úpravu:

void Write_char_lcd(unsigned char c)
{
LCD_RW = 0;
LCD_RS = 1; // write characters
PORTC = (c & 0xF0);
EN_TRIG();
LCD_RS = 1; // write characters
PORTC = ((c & 0x0F)<<4);
EN_TRIG();
}

void Write_string_lcd(const char *s)
{
unsigned char x = 0;
while(s[x]!=0)
{
__delay_us(100);
Write_char_lcd(s[x]);
x++;
}
}

Nic se nezměnilo. Zase to zmizí a nic se nestane, prostě jen zmizí kurzor a nic, čístý displej.

Ve funkci void Write_char_lcd(unsigned char c) nejdřív pomocí příkazu LCD_RS = 1; nastavíš bit RC0 na jedničku, ale příkazem PORTC = (c & 0xF0); bity 0-3 nastavíš na nulu. Když pak kmitneš pinem LCD_EN (RC2) jsou ostatní řídící piny VŽDY na nule…

Místo PORTC = (c & 0xF0);

musíš napsat :

PORTC = (PORTC & 0x0F) | (c & 0xF0);

Stejně tak místo PORTC = ((c & 0x0F)<<4);

musíš napsat :

PORTC = (PORTC & 0x0F) | ((c & 0x0F)<<4);

Případně by mělo stačit prohodit pořadí příkazů
PORTC= ???;
a
LCD_RS=1;

Díky moc všem za odpovědi. Spojil jsem je dohromady a funguje to :wink:. Kdyžtak kdybyste chtěli tak sem můžu dát hotový kód kdyby někdo chtěl díky moc ještě jednou :wink:

Akurat nechapem preco pouzivas svoje funkcie void DelayMs (int x);

ked prekladac ma vlastne __delay_us(100);