attiny2313. LCD Ekran Özel Karakter Oluşturma Sorunu

Başlatan volkanunal, 04 Eylül 2015, 00:33:29

volkanunal

Merhabalar  16x2 ekran da özel karakterler yaratmak istiyorum.Daha önce arduino kullanırken yapmıştım.Ancak atmel studio kullanırken , tuhaf bir şeylerle karşılaştım.Şöyle ki , kütüphaneyi kendime göre düzenledim , yazı vs normal olarak yazdırabiliyorum. Font ayarını kütüphaneden kontrol ettim ,5x7 dot matrix  ayarında init edilmiş.Örneği oluşturmak istediğim şekil



Ekranda çıkan




uint8_t  customChar[8] = {
	0b00100,
	0b00100,
	0b00100,
	0b00100,
	0b00100,
	0b00100,
	0b00100,
	0b11111
};

Bastığım kod:
for(int i=0; i<8; i++)
	{
		
		lcd_putc(customChar[i]);
	}


Primum nil nocere

mehmet

Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr

volkanunal

#2
a

mesaj birleştirme:: 04 Eylül 2015, 12:46:40

Aynı sorun devam etmekte.Kullandığım kod.

#include <avr/io.h>
#include <util/delay.h>

// LCD interface (should agree with the diagram above)
#define lcd_D7_port     PORTB                 // lcd D7 connection
#define lcd_D7_bit      3
#define lcd_D7_ddr      DDRB
#define lcd_D7_pin      PINB                    // busy flag

#define lcd_D6_port     PORTB	                // lcd D6 connection
#define lcd_D6_bit      2
#define lcd_D6_ddr      DDRB

#define lcd_D5_port     PORTB                  // lcd D5 connection
#define lcd_D5_bit      1
#define lcd_D5_ddr      DDRB		

#define lcd_D4_port     PORTB                  // lcd D4 connection
#define lcd_D4_bit      0
#define lcd_D4_ddr      DDRB

#define lcd_D3_port     PORTD                   // lcd D3 connection
#define lcd_D3_bit      0
#define lcd_D3_ddr      DDRD

#define lcd_D2_port     PORTD                   // lcd D2 connection
#define lcd_D2_bit      2
#define lcd_D2_ddr      DDRD

#define lcd_D1_port     PORTD                   // lcd D1 connection
#define lcd_D1_bit      4
#define lcd_D1_ddr      DDRD

#define lcd_D0_port     PORTD                   // lcd D0 connection
#define lcd_D0_bit      5
#define lcd_D0_ddr      DDRD

#define lcd_E_port      PORTB                   // lcd Enable pin
#define lcd_E_bit      4
#define lcd_E_ddr       DDRB

#define lcd_RS_port     PORTD                  // lcd Register Select pin
#define lcd_RS_bit      3
#define lcd_RS_ddr      DDRD

#define lcd_RW_port     PORTD                // lcd Read/Write pin
#define lcd_RW_bit		6
#define lcd_RW_ddr      DDRD

// LCD module information
#define lcd_LineOne     0x00                    // start of line 1
#define lcd_LineTwo     0x40                    // start of line 2
//#define   lcd_LineThree   0x14                  // start of line 3 (20x4)
//#define   lcd_lineFour    0x54                  // start of line 4 (20x4)
//#define   lcd_LineThree   0x10                  // start of line 3 (16x4)
//#define   lcd_lineFour    0x50                  // start of line 4 (16x4)

// LCD instructions
#define lcd_Clear           0b00000001          // replace all characters with ASCII 'space'
#define lcd_Home            0b00000010          // return cursor to first position on first line
#define lcd_EntryMode       0b00000110          // shift cursor from left to right on read/write
#define lcd_DisplayOff      0b00001000          // turn display off
#define lcd_DisplayOn       0b00001100          // display on, cursor off, don't blink character
#define lcd_FunctionReset   0b00110000          // reset the LCD
#define lcd_FunctionSet8bit 0b00111000          // 8-bit data, 2-line display, 5 x 7 font
#define lcd_SetCursor       0b10000000          // set cursor position

// Program ID

char karakter0[8] = { 0x04, 0x0E, 0x15, 0x04, 0x04, 0x04, 0x04, 0x00 };

// Function Prototypes
void lcd_write_8(uint8_t);
void lcd_write_instruction_8f(uint8_t);
void lcd_write_character_8f(uint8_t);
void lcd_write_string_8f(uint8_t *);
void lcd_init_8f(void);
void lcd_check_BF_8(void);
uint8_t i;

/******************************* Main Program Code *************************/
int main(void)
{
// configure the microprocessor pins for the data lines
    lcd_D7_ddr |= (1<<lcd_D7_bit);                  // 8 data lines - output
    lcd_D6_ddr |= (1<<lcd_D6_bit);
    lcd_D5_ddr |= (1<<lcd_D5_bit);
    lcd_D4_ddr |= (1<<lcd_D4_bit);
    lcd_D3_ddr |= (1<<lcd_D3_bit);
    lcd_D2_ddr |= (1<<lcd_D2_bit);
    lcd_D1_ddr |= (1<<lcd_D1_bit);
    lcd_D0_ddr |= (1<<lcd_D0_bit);

// configure the microprocessor pins for the control lines
    lcd_E_ddr |= (1<<lcd_E_bit);                    // E line - output
    lcd_RS_ddr |= (1<<lcd_RS_bit);                  // RS line - output
    lcd_RW_ddr |= (1<<lcd_RW_bit);                  // RW line - output 

// initialize the LCD controller as determined by the defines (LCD instructions)
    lcd_init_8f();                                  // initialize the LCD display for an 8-bit interface

 lcd_write_instruction_8f(lcd_SetCursor | lcd_LineTwo);

for(i=0; i<=8; i++) {
    lcd_write_character_8f(karakter0[i]);
}
// set cursor to start of second line
  //  lcd_check_BF_8();                               // make sure LCD controller is ready
  //  lcd_write_instruction_8f(lcd_SetCursor | lcd_LineTwo);

// display the second line of information
   // lcd_write_string_8f(program_version);

// endless loop
    while(1);
    return 0;
}
/******************************* End of Main Program Code ******************/

/*============================== 8-bit LCD Functions ======================*/
/*
  Name:     lcd_init_8f
  Purpose:  initialize the LCD module for a 8-bit data interface
  Entry:    equates (LCD instructions) set up for the desired operation
  Exit:     no parameters
  Notes:    uses the busy flag instead of time delays when possible
*/
void lcd_init_8f(void)
{
// Power-up delay
    _delay_ms(100);                                 // initial 40 mSec delay

// Reset the LCD controller
    lcd_write_instruction_8f(lcd_FunctionReset);    // first part of reset sequence
    _delay_ms(10);                                  // 4.1 mS delay (min)

    lcd_write_instruction_8f(lcd_FunctionReset);    // second part of reset sequence
    _delay_us(200);                                 // 100uS delay (min)

    lcd_write_instruction_8f(lcd_FunctionReset);    // third part of reset sequence
    _delay_us(200);                                 // this delay is omitted in the data sheet

// Function Set instruction
    lcd_write_instruction_8f(lcd_FunctionSet8bit);  // set mode, lines, and font
// --> from this point on the busy flag is available <--       

// The next three instructions are specified in the data sheet as part of the initialization routine, 
//  so it is a good idea (but probably not necessary) to do them just as specified and then redo them 
//  later if the application requires a different configuration.

// Display On/Off Control instruction
    lcd_check_BF_8();                               // make sure LCD controller is ready
    lcd_write_instruction_8f(lcd_DisplayOff);       // turn display OFF

// Clear Display instruction
    lcd_check_BF_8();                               // make sure LCD controller is ready
    lcd_write_instruction_8f(lcd_Clear);            // clear display RAM

// ; Entry Mode Set instruction
    lcd_check_BF_8();                               // make sure LCD controller is ready
    lcd_write_instruction_8f(lcd_EntryMode);        // set desired shift characteristics

// This is the end of the LCD controller initialization as specified in the data sheet, but the display
//  has been left in the OFF condition.  This is a good time to turn the display back ON.

// Display On/Off Control instruction
    lcd_check_BF_8();                               // make sure LCD controller is ready
    lcd_write_instruction_8f(lcd_DisplayOn);        // turn the display ON
}

/*...........................................................................
  Name:     lcd_write_string_8f
; Purpose:  display a string of characters on the LCD
  Entry:    (theString) is the string to be displayed
  Exit:     no parameters
  Notes:    uses the busy flag instead of time delays 
*/
void lcd_write_string_8f(uint8_t theString[])
{
    volatile int i = 0;                             // character counter*/
    while (theString[i] != 0)
    {
        lcd_check_BF_8();                           // make sure LCD controller is ready    
        lcd_write_character_8f(theString[i]);
        i++;
    }
}

/*...........................................................................
  Name:     lcd_write_character_8f
  Purpose:  send a byte of information to the LCD data register
  Entry:    (theData) is the information to be sent to the data register
  Exit:     no parameters
  Notes:    configures RW (busy flag is implemented)
*/
void lcd_write_character_8f(uint8_t theData)
{
    lcd_RW_port &= ~(1<<lcd_RW_bit);                // write to LCD module (RW low)
    lcd_RS_port |= (1<<lcd_RS_bit);                 // select the Data Register (RS high)
    lcd_E_port &= ~(1<<lcd_E_bit);                  // make sure E is initially low
    lcd_write_8(theData);                           // write the data
}

/*...........................................................................
  Name:     lcd_write_instruction_8f
  Purpose:  send a byte of information to the LCD instruction register
  Entry:    (theInstruction) is the information to be sent to the instruction register
  Exit:     no parameters
  Notes:    configures RW (busy flag is implemented)
*/
void lcd_write_instruction_8f(uint8_t theInstruction)
{
    lcd_RW_port &= ~(1<<lcd_RW_bit);                // write to LCD module (RW low)
    lcd_RS_port &= ~(1<<lcd_RS_bit);                // select the Instruction Register (RS low)
    lcd_E_port &= ~(1<<lcd_E_bit);                  // make sure E is initially low
    lcd_write_8(theInstruction);                    // write the instruction
}


/*...........................................................................
  Name:     lcd_write_8
  Purpose:  send a byte of information to the LCD module
  Entry:    (theByte) is the information to be sent to the desired LCD register
            RS is configured for the desired LCD register
            E is low
            RW is low
  Exit:     no parameters
  Notes:    use either time delays or the busy flag
*/
void lcd_write_8(uint8_t theByte)
{
    lcd_D7_port &= ~(1<<lcd_D7_bit);                        // assume that data is '0'
    if (theByte & 1<<7) lcd_D7_port |= (1<<lcd_D7_bit);     // make data = '1' if necessary 

    lcd_D6_port &= ~(1<<lcd_D6_bit);                        // repeat for each data bit
    if (theByte & 1<<6) lcd_D6_port |= (1<<lcd_D6_bit);

    lcd_D5_port &= ~(1<<lcd_D5_bit);
    if (theByte & 1<<5) lcd_D5_port |= (1<<lcd_D5_bit);

    lcd_D4_port &= ~(1<<lcd_D4_bit);
    if (theByte & 1<<4) lcd_D4_port |= (1<<lcd_D4_bit);

    lcd_D3_port &= ~(1<<lcd_D3_bit);
    if (theByte & 1<<3) lcd_D3_port |= (1<<lcd_D3_bit);

    lcd_D2_port &= ~(1<<lcd_D2_bit);
    if (theByte & 1<<2) lcd_D2_port |= (1<<lcd_D2_bit);

    lcd_D1_port &= ~(1<<lcd_D1_bit);
    if (theByte & 1<<1) lcd_D1_port |= (1<<lcd_D1_bit);

    lcd_D0_port &= ~(1<<lcd_D0_bit);
    if (theByte & 1<<0) lcd_D0_port |= (1<<lcd_D0_bit);

// write the data
                                                    // 'Address set-up time' (40 nS)
    lcd_E_port |= (1<<lcd_E_bit);                   // Enable pin high
    _delay_us(1);                                   // implement 'Data set-up time' (80 nS) and 'Enable pulse width' (230 nS)
    lcd_E_port &= ~(1<<lcd_E_bit);                  // Enable pin low
    _delay_us(1);                                   // implement 'Data hold time' (10 nS) and 'Enable cycle time' (500 nS)
}

/*...........................................................................
  Name:     lcd_check_BF_8
  Purpose:  check busy flag, wait until LCD is ready
  Entry:    no parameters
  Exit:     no parameters
  Notes:    main program will hang if LCD module is defective or missing
            data is read while 'E' is high
*/
void lcd_check_BF_8(void)
{
    uint8_t busy_flag_copy;                         // busy flag 'mirror'

    lcd_D7_ddr &= ~(1<<lcd_D7_bit);                 // set D7 data direction to input
    lcd_RS_port &= ~(1<<lcd_RS_bit);                // select the Instruction Register (RS low)
    lcd_RW_port |= (1<<lcd_RW_bit);                 // read from LCD module (RW high)

    do
    {
        busy_flag_copy = 0;                         // initialize busy flag 'mirror'
        lcd_E_port |= (1<<lcd_E_bit);               // Enable pin high
        _delay_us(1);                               // implement 'Delay data time' (160 nS) and 'Enable pulse width' (230 nS)

        busy_flag_copy |= (lcd_D7_pin & (1<<lcd_D7_bit));  // get actual busy flag status

        lcd_E_port &= ~(1<<lcd_E_bit);              // Enable pin low
        _delay_us(1);                               // implement 'Address hold time' (10 nS), 'Data hold time' (10 nS), and 'Enable cycle time' (500 nS )
        
    } while (busy_flag_copy);                       // check again if busy flag was high

// arrive here if busy flag is clear -  clean up and return 
    lcd_RW_port &= ~(1<<lcd_RW_bit);                // write to LCD module (RW low)       <-- (not really necessary)
    lcd_D7_ddr |= (1<<lcd_D7_bit);                  // reset D7 data direction to output
}
Primum nil nocere

RaMu

lcd_putc( 0b00100 );
yazsan da "ekranda çıkan" dediğin 7 karakterden 1 tane yazılır, gibi görünüyor.

LCD de özel karakter yazdırmadım hiç ama
cgram vs. birşeyler vardı yanlış hatırlamıyorsam.

Ekrana özel karakter yazma işi sadece lcd_putc ile olmaz sanırım.

Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

volkanunal

Daha önce forumda açılan bir konuda bir arkadaş pic ile char göndermeli fonksiyon ile yaptığını gördüm.Arduino da kullanılan fonk arkasına baktım , yine bu temelinde bu olan fonksiyonu kullanmış hocam.
Primum nil nocere

Erhan YILMAZ

Burada MSP430 modüllerini hazırlarken bahsettiğin konuya değinmiştim. Farklı denetleyici ama fikir verir.

https://320volt.com/msp430-denetleyiciler-ile-karakter-lcd-kullanimi

Kabil ATICI

Ekrana doğrudan karakter yazıdırır gibi değilde, CGRAM bölümüne yazıyor ve karakterinizi oradan karakter adresler gibi çağırıyorsunuz.
CGRAM bölümüne yazmak için RAM adresini komut  (0x40   CGRAM başlangıç adresi) ile tanımlıyor ve data olarak karakterinizi oluşturan veriyi yüklüyorsunuz.
Karakter olarak çağırırken, 0x00....0x07 aralığında karakterinize dek düşen adresden çağırıyorsunuz.
ambar7

volkanunal

Teşekkürler herkese , kullandığım kütüphanede sizlerin dediğini bir cgram yeri varmış farkedememiştim. hallettim :)
Primum nil nocere