MAERKEK
Moderator
Microchip PİC18F45K50 İ2C Kullanım Sorunu
Arkadaşlar merhaba ,
Uzun zamandır yapamadığım bir olayı sizlere sormak istedim. Belki bir bilen eden aramızda vardır .
Microchip firmasının pic18f45k50 mikro kontrolcüsüyle 16x2 ebatında lcd ekran çalıştırmak istiyorum . Bunu yaparken araya pcf8574 i2c haberleşme modülü kullanacağım. MPLAB İDE 6.15 sürümünü kullanıyorum .
Projemde yer alan header dosyalarından ilki
LCD_i2c_h
#ifndef LCD_I2C_H
#define LCD_I2C_H
#include <stdint.h>
// LCD I2C adresi burada tanımlanır (örnek: 0x27 ya da 0x3F)
#define LCD_ADDRESS 0x26
void LCD_Init(void);
void LCD_SendCommand(uint8_t cmd);
void LCD_SendData(uint8_t data);
void LCD_SetCursor(uint8_t row, uint8_t col);
void LCD_Clear(void);
void LCD_Print(const char* str);
#endif
lcd_i2c_pcf8574.h
#ifndef LCD_I2C_PCF8574_H
#define LCD_I2C_PCF8574_H
#include <stdint.h>
#include <xc.h>
// LCD komut sabitleri
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_FUNCTIONSET 0x20
#define LCD_SETDDRAMADDR 0x80
// LCD mod ayarlar?
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTDECREMENT 0x00
#define LCD_DISPLAYON 0x04
#define LCD_CURSOROFF 0x00
#define LCD_BLINKOFF 0x00
#define LCD_2LINE 0x08
#define LCD_5x8DOTS 0x00
#define LCD_4BITMODE 0x00
// Pin tan?mlar?
#define En 0x04 // Enable bit
#define Rw 0x02 // Read/Write bit
#define Rs 0x01 // Register select bit
// Arka ???k
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
// Fonksiyon prototipleri
void LCD_Init(uint8_t addr, uint8_t cols, uint8_t rows);
void LCD_Command(uint8_t cmd);
void LCD_WriteChar(char data);
void LCD_WriteString(const char* str);
void LCD_Home(void);
void LCD_Backlight(void);
void LCD_NoBacklight(void);
#endif
lcd_i2c_pcf8574.c
#include "lcd_i2c_pcf8574.h"
#include "mcc_generated_files/i2c1_master.h"
#include <xc.h>
#define _XTAL_FREQ 8000000 // F_CPU 8MHz
static uint8_t lcd_addr;
static uint8_t lcd_cols;
static uint8_t lcd_rows;
static uint8_t backlight_val = LCD_BACKLIGHT;
static void LCD_Write4Bits(uint8_t data);
static void LCD_ExpanderWrite(uint8_t data);
static void LCD_PulseEnable(uint8_t data);
static void LCD_Send(uint8_t data, uint8_t mode);
void LCD_Init(uint8_t addr, uint8_t cols, uint8_t rows) {
lcd_addr = addr;
lcd_cols = cols;
lcd_rows = rows;
__delay_ms(50); // LCD baÅlatma süresi
LCD_ExpanderWrite(backlight_val);
__delay_ms(1000);
LCD_Write4Bits(0x03 << 4);
__delay_ms(5);
LCD_Write4Bits(0x03 << 4);
__delay_us(150);
LCD_Write4Bits(0x03 << 4);
LCD_Write4Bits(0x02 << 4); // 4-bit mod
LCD_Command(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE);
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
LCD_Command(LCD_CLEARDISPLAY);
__delay_ms(2);
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
LCD_Home();
}
void LCD_Clear() {
}
void LCD_Home() {
LCD_Command(LCD_RETURNHOME);
__delay_ms(2);
}
void LCD_SetCursor(uint8_t col, uint8_t row) {
const uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54};
if (row >= lcd_rows) row = lcd_rows - 1;
LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
void LCD_WriteChar(char data) {
LCD_Send(data, Rs);
}
void LCD_WriteString(const char *str) {
while (*str) {
LCD_WriteChar(*str++);
}
}
void LCD_Command(uint8_t cmd) {
LCD_Send(cmd, 0);
}
void LCD_Backlight() {
backlight_val = LCD_BACKLIGHT;
LCD_ExpanderWrite(0);
}
void LCD_NoBacklight() {
backlight_val = LCD_NOBACKLIGHT;
LCD_ExpanderWrite(0);
}
static void LCD_Send(uint8_t value, uint8_t mode) {
uint8_t high_nibble = value & 0xF0;
uint8_t low_nibble = (value << 4) & 0xF0;
LCD_Write4Bits(high_nibble | mode);
LCD_Write4Bits(low_nibble | mode);
}
static void LCD_Write4Bits(uint8_t data) {
LCD_ExpanderWrite(data);
LCD_PulseEnable(data);
}
static void LCD_ExpanderWrite(uint8_t data) {
}
static void LCD_PulseEnable(uint8_t data) {
LCD_ExpanderWrite(data | En);
__delay_us(1);
LCD_ExpanderWrite(data & ~En);
__delay_us(50);
}
void I2C1_Write1ByteRegister(uint8_t address, uint8_t reg, uint8_t data)
{
uint8_t buffer[2];
buffer[0] = reg; // PCF8574 için genelde 0
buffer[1] = data; // gönderilecek veri
if (I2C1_Open(address) == I2C1_NOERR)
{
I2C1_SetBuffer(buffer, 2);
I2C1_MasterWrite(); // Yazma i?lemini ba?lat
while (I2C1_MasterOperation(false) != I2C1_NOERR); // false: write mode
I2C1_Close(); // ??lem tamam, kapat
}
}
main.c
#include "mcc_generated_files/mcc.h"
#include "lcd_i2c_pcf8574.h"
void main(void) {
SYSTEM_Initialize();
__delay_ms(1000); // LCD ba?lang?ç için bekle
LCD_Init(0x26, 16, 2); // LCD adres, kolon, sat?r
LCD_WriteString("Merhaba!");
while (1) {
// Ana döngü
}
}
Ekranı bir türlü çalıştıramadım . Aurdino ile basit şekilde çalışıyor .
Uzun zamandır yapamadığım bir olayı sizlere sormak istedim. Belki bir bilen eden aramızda vardır .
Microchip firmasının pic18f45k50 mikro kontrolcüsüyle 16x2 ebatında lcd ekran çalıştırmak istiyorum . Bunu yaparken araya pcf8574 i2c haberleşme modülü kullanacağım. MPLAB İDE 6.15 sürümünü kullanıyorum .
Projemde yer alan header dosyalarından ilki
LCD_i2c_h
#ifndef LCD_I2C_H
#define LCD_I2C_H
#include <stdint.h>
// LCD I2C adresi burada tanımlanır (örnek: 0x27 ya da 0x3F)
#define LCD_ADDRESS 0x26
void LCD_Init(void);
void LCD_SendCommand(uint8_t cmd);
void LCD_SendData(uint8_t data);
void LCD_SetCursor(uint8_t row, uint8_t col);
void LCD_Clear(void);
void LCD_Print(const char* str);
#endif
lcd_i2c_pcf8574.h
#ifndef LCD_I2C_PCF8574_H
#define LCD_I2C_PCF8574_H
#include <stdint.h>
#include <xc.h>
// LCD komut sabitleri
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_FUNCTIONSET 0x20
#define LCD_SETDDRAMADDR 0x80
// LCD mod ayarlar?
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTDECREMENT 0x00
#define LCD_DISPLAYON 0x04
#define LCD_CURSOROFF 0x00
#define LCD_BLINKOFF 0x00
#define LCD_2LINE 0x08
#define LCD_5x8DOTS 0x00
#define LCD_4BITMODE 0x00
// Pin tan?mlar?
#define En 0x04 // Enable bit
#define Rw 0x02 // Read/Write bit
#define Rs 0x01 // Register select bit
// Arka ???k
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00
// Fonksiyon prototipleri
void LCD_Init(uint8_t addr, uint8_t cols, uint8_t rows);
void LCD_Command(uint8_t cmd);
void LCD_WriteChar(char data);
void LCD_WriteString(const char* str);
void LCD_Home(void);
void LCD_Backlight(void);
void LCD_NoBacklight(void);
#endif
lcd_i2c_pcf8574.c
#include "lcd_i2c_pcf8574.h"
#include "mcc_generated_files/i2c1_master.h"
#include <xc.h>
#define _XTAL_FREQ 8000000 // F_CPU 8MHz
static uint8_t lcd_addr;
static uint8_t lcd_cols;
static uint8_t lcd_rows;
static uint8_t backlight_val = LCD_BACKLIGHT;
static void LCD_Write4Bits(uint8_t data);
static void LCD_ExpanderWrite(uint8_t data);
static void LCD_PulseEnable(uint8_t data);
static void LCD_Send(uint8_t data, uint8_t mode);
void LCD_Init(uint8_t addr, uint8_t cols, uint8_t rows) {
lcd_addr = addr;
lcd_cols = cols;
lcd_rows = rows;
__delay_ms(50); // LCD baÅlatma süresi
LCD_ExpanderWrite(backlight_val);
__delay_ms(1000);
LCD_Write4Bits(0x03 << 4);
__delay_ms(5);
LCD_Write4Bits(0x03 << 4);
__delay_us(150);
LCD_Write4Bits(0x03 << 4);
LCD_Write4Bits(0x02 << 4); // 4-bit mod
LCD_Command(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE);
LCD_Command(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF);
LCD_Command(LCD_CLEARDISPLAY);
__delay_ms(2);
LCD_Command(LCD_ENTRYMODESET | LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT);
LCD_Home();
}
void LCD_Clear() {
}
void LCD_Home() {
LCD_Command(LCD_RETURNHOME);
__delay_ms(2);
}
void LCD_SetCursor(uint8_t col, uint8_t row) {
const uint8_t row_offsets[] = {0x00, 0x40, 0x14, 0x54};
if (row >= lcd_rows) row = lcd_rows - 1;
LCD_Command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}
void LCD_WriteChar(char data) {
LCD_Send(data, Rs);
}
void LCD_WriteString(const char *str) {
while (*str) {
LCD_WriteChar(*str++);
}
}
void LCD_Command(uint8_t cmd) {
LCD_Send(cmd, 0);
}
void LCD_Backlight() {
backlight_val = LCD_BACKLIGHT;
LCD_ExpanderWrite(0);
}
void LCD_NoBacklight() {
backlight_val = LCD_NOBACKLIGHT;
LCD_ExpanderWrite(0);
}
static void LCD_Send(uint8_t value, uint8_t mode) {
uint8_t high_nibble = value & 0xF0;
uint8_t low_nibble = (value << 4) & 0xF0;
LCD_Write4Bits(high_nibble | mode);
LCD_Write4Bits(low_nibble | mode);
}
static void LCD_Write4Bits(uint8_t data) {
LCD_ExpanderWrite(data);
LCD_PulseEnable(data);
}
static void LCD_ExpanderWrite(uint8_t data) {
}
static void LCD_PulseEnable(uint8_t data) {
LCD_ExpanderWrite(data | En);
__delay_us(1);
LCD_ExpanderWrite(data & ~En);
__delay_us(50);
}
void I2C1_Write1ByteRegister(uint8_t address, uint8_t reg, uint8_t data)
{
uint8_t buffer[2];
buffer[0] = reg; // PCF8574 için genelde 0
buffer[1] = data; // gönderilecek veri
if (I2C1_Open(address) == I2C1_NOERR)
{
I2C1_SetBuffer(buffer, 2);
I2C1_MasterWrite(); // Yazma i?lemini ba?lat
while (I2C1_MasterOperation(false) != I2C1_NOERR); // false: write mode
I2C1_Close(); // ??lem tamam, kapat
}
}
main.c
#include "mcc_generated_files/mcc.h"
#include "lcd_i2c_pcf8574.h"
void main(void) {
SYSTEM_Initialize();
__delay_ms(1000); // LCD ba?lang?ç için bekle
LCD_Init(0x26, 16, 2); // LCD adres, kolon, sat?r
LCD_WriteString("Merhaba!");
while (1) {
// Ana döngü
}
}
Ekranı bir türlü çalıştıramadım . Aurdino ile basit şekilde çalışıyor .
