19 Ekim 2021, 11:31:58

Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H


XC8 HD44780

Başlatan a.zorba, 06 Temmuz 2012, 12:16:35

a.zorba

acemi C ci için  .  mplabx  xc8 derleyici ile yapılmış  18f2550  uyumlu tercihen  OpenXLCD  ile yapılmış karekter ve rakam göstermeyi içeren örnek bir program paylaşabilirimisiniz.
İçinizdeki düşmanlık yakıp yıkmayı hoşgörüyorsa yerine koyacağınız sistemin özgürlük olacağını mı düşünüyorsunuz?

Tagli

Daha önceden C18 ile biraz uğraşarak çalıştırdığım Microchip XLCD kütüphanesini geçenlerde baya bir boğuşmama rağmen nedense XC8'de çalıştıramadım. Sonunda pes edip kendi kütüphanemi yazdım. Şimdilik sadece 4 bit modunu destekliyor ve tanımlı portun büyük nibble'ı için test ettim. Küçük nibble için de kod var ama onu denemedim. Eminim pek çok eksiği vardır, işime yarayan özelliklerini çalıştıracak kadar uğraştım sadece.

lcd.h
#ifndef LCD_H
#define LCD_H

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include "globals.h"  ****** BU KISMI ÇIKARMAN GEREKECEK, ASAGIDA ACIKLADIM

#define LCD_DELAY 5

#define ON 1
#define OFF 0

//Control Pins
#define LCD_RS LATCbits.LATC0
#define LCD_RW LATCbits.LATC1
#define LCD_E LATCbits.LATC2

//Data Port
#define UPPER //Lower nibble support is NOT tested!
#define INTERNAL_WAIT //Wait for BF included in functions.
#define LCD_LAT LATD
#define LCD_PORT PORTD
#define LCD_TRIS TRISD

//LCD Shift Commands for lcdCommand()
#define CURSOR_LEFT B'00010000'
#define CURSOR_RIGHT B'00010100'
#define SCREEN_LEFT B'00011000'
#define SCREEN_RIGHT B'00011100'

//Function Prototypes
void lcdInit();
void lcdPutChar(char c);
char lcdBusy(void);
void lcdPutStr(char *str);
void lcdSetAddr(char addr);
void lcdCommand(char cmd);
void lcdDisplay(char onOff);
void lcdCursor(char onOff);
void lcdBlink(char onOff);
void lcdNewChar(char pos, const char *ptr);

//LCD Macros
#define lcdClear() lcdCommand(0x01)
#define lcdHome() lcdCommand(0x02)

#endif


lcd.c
#include "lcd.h"

//Local Function Prototypes
void clockE(void);
void write(char c);
char read(void);

//Local variables
char displayMode;


void lcdInit(){
	
displayMode 0x08;

#ifdef UPPER
	
LCD_LAT &= 0x0F;
	
LCD_TRIS &= 0x0F;
#else
	
LCD_LAT &= 0xF0;
	
LCD_TRIS &= 0xF0;
#endif
	
LCD_E 0;
	
LCD_RS 0;
	
LCD_RW 0;

	
//----Software Reset Sequence----
	
delayMS(30); // > 15 ms
#ifdef UPPER
	
LCD_LAT &= 0x0F;
	
LCD_LAT |= 0b00110000//LCD_PORT = 0b00110000
#else
	
LCD_LAT &= 0xF0;
	
LCD_LAT |= 0b00000011;
#endif
	
clockE();
	
delayMS(10); // > 4.1 ms
	
clockE();
	
delayMS(1); // > 100 us
	
clockE();

#ifdef UPPER
	
LCD_LAT &= 0x0F;
	
LCD_LAT |= 0b00100000//LCD_LAT = 0b00100000
#else
	
LCD_LAT &= 0xF0;
	
LCD_LAT |= 0b00000010;
#endif
	
clockE();

	
lcdCommand(0b00101000);
	
lcdCommand(0b00001000); //Shutdown everything
	
lcdCommand(0b00000001); //Clear Display
	
lcdCommand(0b00001100); //Display On
}

//Common write routine
void write(char c){
	
LCD_RW 0;
	
char low 0high 0;
	
char temp 0;

	
low 0x0F;
	
high = (0xF0) >> 4;
#ifdef UPPER
	
LCD_TRIS &= 0x0F;
	
LCD_LAT &= 0x0F;
#else
	
LCD_TRIS &= 0xF0;
	
LCD_LAT &= 0xF0;
#endif

	
//Sending high nibble
#ifdef UPPER
	
temp = (high << 4) & 0xF0;
#else
	
temp high 0x0F;
#endif
	
LCD_LAT |= temp;
	
clockE();

	
//Sending low nibble
#ifdef UPPER
	
LCD_LAT &= 0x0F;
	
temp = (low << 4) & 0xF0;
#else
	
LCD_LAT &= 0xF0;
	
temp low 0x0F;
#endif
	
LCD_LAT |= temp;
	
clockE();

#ifdef UPPER
	
LCD_LAT &= 0x0F;
#else
	
LCD_LAT &= 0xF0;
#endif
}

//Common read routine
char read(void){
	
char temp 0;
	
LCD_RW 1;
#ifdef UPPER
	
LCD_LAT &= 0x0F;
	
LCD_TRIS |= 0xF0;
#else
	
LCD_LAT &= 0xF0;
	
LCD_TRIS |= 0x0F;
#endif
	
__delay_us(LCD_DELAY);

	
LCD_E 1;
	
__delay_us(LCD_DELAY);
#ifdef UPPER
	
temp |= LCD_PORT 0xF0;
#else
	
temp |= (LCD_PORT 0x0F) << 4;
#endif
	
LCD_E 0;
	
__delay_us(LCD_DELAY);

	
LCD_E 1;
	
__delay_us(LCD_DELAY);
#ifdef UPPER
	
temp |= (LCD_PORT 0xF0) >> 4;
#else
	
temp |= LCD_PORT 0x0F;
#endif
	
LCD_E 0;
	
__delay_us(LCD_DELAY);

	
return 
temp;
}

void lcdCommand(char cmd){
#ifdef INTERNAL_WAIT
	
while(
lcdBusy() == 1);
#endif

	
//Checking for display option change
	
if ((
cmd 0b11111000) == 0b00001000){
	
	
displayMode cmd;
	
}

	
LCD_RS 0;
	
write(cmd);
}

void lcdPutChar(char c){
#ifdef INTERNAL_WAIT
	
while(
lcdBusy() == 1);
#endif
	
LCD_RS 1;
	
write(c);
}

char lcdBusy(){
	
LCD_RS 0;

	
if ((
read() & 0b10000000) == 0b10000000)
	
	
return 
1//LCD is busy
	
else
	
	
return 
0//LCD is free
}

void lcdPutStr(char *str){
	
while (*
str != '\0'){
	
	
lcdPutChar(*str);
	
	
++
str;
	
}
}

void lcdSetAddr(char addr){
	
addr |= 0x80;
	
lcdCommand(addr);
}

void lcdNewChar(char pos, const char *ptr){
	
char i;
	
char addr = (pos << 3);
	
lcdCommand(addr 0b01000000);
	
for (
08; ++i){
	
	
lcdPutChar(*ptr++);
	
}
}

void lcdDisplay(char onOff){
	
if (
onOff == OFF)
	
displayMode &= 0b11111011;
	
else 
displayMode |= 0b00000100;
	
lcdCommand(displayMode);
}

void lcdCursor(char onOff){
	
if (
onOff == OFFdisplayMode &= 0b11111101;
	
else 
displayMode |= 0b00000010;
	
lcdCommand(displayMode);
}

void lcdBlink(char onOff){
	
if (
onOff == OFFdisplayMode &= 0b11111110;
	
else 
displayMode |= 0b00000001;
	
lcdCommand(displayMode);
}

void clockE(void){
	
__delay_us(LCD_DELAY);
	
LCD_E 1;
	
__delay_us(LCD_DELAY);
	
LCD_E 0;
	
__delay_us(LCD_DELAY);
}


lcd.h içinde include edilen globals.h dosyası benim projeye özgü genel değişken ve fonksiyonları sakladığım bir header dosyası. Dosyanın içinde alakasız şeyler de olduğu için paylaşmıyorum ama yanlış hatırlamıyorsam içinden aldığım iki şey var:
#define _XTAL_FREQ  40000000ULL
void delayMS(unsigned int ms);

Bunlardan delayMS() fonksiyonunu kendim yazdım, zaten çok basit birşey. Programın ana .c dosyasında tanımlamıştım:
void delayMS(unsigned int ms){
	
while (
ms 0){
	
	
__delay_ms(1);
	
	
ms--;
	
}
}

__delay_ms() zaten kendi kütüphane fonksiyonu ama giriş değeri bir değerden büyük olamıyor (20 miydi neydi...) o sebeple kendi fonksiyonum ile bunu kullandım. Bekleme süresi çok hassas değil tabi ama benim için çok hassas olması da gerekmiyor zaten.

Ana programda da bu şekilde kullandım:
#include "lcd.h"
lcdInit();
lcdClear();
lcdPutStr("Satir 1");
lcdSetAddr(0x40);
lcdPutStr("Satir 2");

Portlarla ilgili yön tanımlamalarını (TRIS) senin ana programda yapman gerekiyor yanlış hatırlamıyorsam (programı yazalı biraz oldu). Data hatlarını kendisi hallediyor ama kontrol hatlarının yönlerini belirtmen lazım ana programda. Ayrıca, lcd.h içinde değiştirmen gereken tanımlamalar var.
Gökçe Tağlıoğlu

Yasal Uyarı: Picproje.org sitemizde 5651 sayılı kanunun 8. maddesine ve T.C.Knın 125. maddesine göre tüm üyelerimiz yaptıkları paylaşımlardan kendileri sorumludur. Picproje.org hakkında yapılacak tüm hukuksal şikayetleri İletişim sayfamızdan bize bildirdikten en geç 3 (üç) iş günü içerisinde ilgili kanunlar ve yönetmelikler çerçevesinde tarafımızca incelenerek gereken işlemler yapılacak ve site yöneticilerimiz tarafından bilgi verilecektir.