Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Подключение HD44780 к МК по 3 проводной схеме.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
TamTam
Товарищи если кто делал поделитесь кодом на си, катострафически нехватает ног у мк.
Nanobyte
Ну так возьмите код на ASM и перепишите его на C. Ссылки были ранее. Да и написать самому, наверное, проще.
TamTam
Цитата(Nanobyte @ Jul 4 2006, 21:45) *
Ну так возьмите код на ASM и перепишите его на C. Ссылки были ранее. Да и написать самому, наверное, проще.


Дык вот сел, вооруживщись шитом на Дисплей, МК и асм для фуфлыжников, но чуствую я это будет пи....

Походу дела особо помогающей ссылкой будет эта любезно предоставленная rat.
Nanobyte
Может, все-таки Вам попробовать ASM ? Хороший повод его изучить. Если есть осциллограф, тогда вообще хорошо. Соберите нарисованную Вами схему, поправьте I/O, скормите код ассемблеру. (Самое главное, тестовое сообщение должно быть "HELLO WORLD" smile.gif )
P.S. Не так страшен ASM, как его малюют ... smile.gif
Nanobyte
Кстати, на нашем форуме эта тема уже обсуждалась:
http://electronix.ru/forum/index.php?showtopic=5493&st=0
Примеры на C.
TamTam
Разберающиеся в асм и си проверте плиз

Код
//                                C


#define LCDE     =  0;
#define LCDDATA  =  1;
#define LCDCLK   =  2;

void init_lcd_2wire();
void send_lcd_reg_2wire(unsigned char send_data);

void init_lcd_2wire()

{
PORTB.0 = 0;              
PORTB.1 = 0;
PORTB.2 = 0;
delay_ms(400);              // для правильного функционирования
delay_ms(15);
send_lcd_reg_2wire(0x30);   //
delay_ms(5);
send_lcd_reg_2wire(0x30);   //
delay_us(255);
send_lcd_reg_2wire(0x30);   //
delay_us(255);
send_lcd_reg_2wire(0x38);   // 8 проводной интерфейс, 2 строки, размер символа 5Х7.
delay_us(255);
send_lcd_reg_2wire(0x08);   // дисплей выкл, курсор выкл, мерцание выкл.                    
delay_us(255);
send_lcd_reg_2wire(0x01);   // очистка дисплея
delay_us(255);
send_lcd_reg_2wire(0x06);   // Increment cursor to the right when writing, don't shift screen
delay_us(255);
send_lcd_reg_2wire(0x0C);   // дисплей вкл, курсор выкл, мерцание выкл.                    
delay_us(255);
}

void send_lcd_reg_2wire(unsigned char send_data)
{
unsigned int i;

PORTB.1 = 0;
PORTB.2 = 0;
PORTB.0 = 1;              
for (i=0; i<8; i++)
   {
      if ((send_data & 0x08) != 0)
         PORTB.1 = 0;
      else
         PORTB.1 = 1;
      PORTB.2 = 1;
      PORTB.2 = 0;
      send_data = send_data << 1;
   }  
PORTB.1 = 0;  
PORTB.0 = 1;
PORTB.0 = 0;
}


Код
//                                     ASM


;**********************************************
;* Setup                                      *
;* Initialize the timer, LCD port and LCD     *
;**********************************************
Setup:              

;** Timer setup **
        ldi    AReg,TCK64
        sts    ClkDiv,AReg
        ldi    AReg,TSTOP    ;Timer 0 off (just in case)
        out    TCCR0,AReg    ;Stop timer
        ldi    AReg,0b00000010;Enable Timer 0 interrupt
        out    TIMSK,AReg
        sei                  ;enable interrupts

;** LCD port setup and HD44780 LCD setup **
        sbi    DDRB,LCDE     ;DDRB bit 5 = 1 = output
        sbi    DDRB,LCDDat;DDRB bit 6 = 1 = output
        sbi    DDRB,LCDClk;DDRB bit 7 = 1 = output
        cbi    PORTB,LCDE    ;set E low
        cbi    PORTB,LCDDat  ;set Data bit low
        cbi    PORTB,LCDClk  ;set Clk low
        
        ldi    BReg,TCK1024  ;switch to a 1024 clock divisor
        sts    ClkDiv,BReg
        ldi    DelayVal,d15ms;15ms delay
        rcall  Delay

        ldi    AReg,$30
        rcall  LCDCmd

        ldi    DelayVal,d4x1ms;4.1ms countdown
        rcall  Delay

        ldi    AReg,$30
        rcall  LCDCmd

        ldi    BReg,TCK64    ;switch to a 64 clock divisor
        sts    ClkDiv,BReg

        ldi    DelayVal,d100us
        rcall  Delay

        ldi    AReg,$30
        rcall  LCDCmd


        ldi    BReg,TCK1024  ;switch to a 1024 clock divisor
        sts    ClkDiv,BReg

        ldi    DelayVal,d4x1ms
        rcall  Delay

        ldi    AReg,$38      ;RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
        rcall  LCDCmd        ;0   0   0   1   1   1   0   x   x
                             ;8-bit operation, 1/16 duty cycle
                             ;5x8 dot matrix

        ldi    BReg,TCK64    ;switch to a 64 clock divisor
        sts    ClkDiv,BReg
        ldi    DelayVal,d40us
        rcall  Delay

        ldi    AReg,$08      ;RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
        rcall  LCDCmd        ;0   0   0   0   0   1   0   0   0
                             ;Display off, cursor off, blink off
        ldi    DelayVal,d40us
        rcall  Delay

        ldi    AReg,$01      ;RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
        rcall  LCDcmd        ;0   0   0   0   0   0   0   0   1
                             ;Clear screen, cursor home
        ldi    DelayVal,d1ms
        rcall  Delay
        rcall  Delay

        ldi    AReg,$06      ;RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
        rcall  LCDCmd        ;0   0   0   0   0   0   1   1   0
                             ;Increment cursor to the right when writing, don't shift screen
        ldi    DelayVal,d40us
        rcall  Delay

        ldi    AReg,$0c      ;RS DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
        rcall  LCDCmd        ;0   0   0   0   0   0   1   1   0
                             ;Display on, cursor off, blink off
        ldi    DelayVal,d40us
        rcall  Delay

        ret
            
;**********************************************
;* Write byte to LCD bus                      *
;**********************************************

;**********************************************
;* PutByte clock byte into 74hc164.           *
;* Data is in AReg                            *
;* BReg is used as acounter                   *
;**********************************************
PutByte:
        ldi    BReg,8        ;bit counter
ShiftB:
        cbi    PORTB,LCDDat  ;set LCD Data bit to 0
        lsl    AReg          ;shift bits in AReg into carry
        brcc   CLKBit        ;if zero, clock it out
        sbi    PORTB,LCDDat  ;if 1, set LCD Data bit to 1
CLKBit:
        sbi    PORTB,LCDClk  ;bit clocks on rising edge
        cbi    PORTB,LCDClk  ;bring clock back to 0
NextB:
        dec    BReg          ;shift out 8 bits
        brne   ShiftB
        ret

;**********************************************
;* LCDCmd - Send a command to the LCD         *
;* data in AReg                               *
;**********************************************
LCDCmd:
        rcall  PutByte
        cbi    PORTB,LCDDat  ;set RS low
        sbi    PORTB,LCDE    ;set E High
        cbi    PORTB,LCDE    ;set E low
        ret

;**********************************************
;* LCDChr - Display a character on the LCD    *
;* data in AReg                               *
;**********************************************
LCDChr:
        rcall  PutByte
        sbi    PORTB,LCDDat  ;set RS High
        sbi    PORTB,LCDE    ;set E High
        cbi    PORTB,LCDE    ;set E low
        ret
TamTam
Только сейчас я начал понемать, когда посмотрел на код, мало того что я закосячил с загрузкой в сдвиговый регистр, так и оказывается , завершения для команд и данных разные.

Подскажите как правильно грузить данные в регистр сдвига
ILYCHOFF
Мне кажется что сделать можно легко на 74HC595. Вот здесь это обсуждалось только здесь не про HD44780 но идея такая же

http://electronix.ru/forum/index.php?showtopic=13235

Поищите на форуме драйвер для LCD перепешите в нем функцию посылки байта на LCD c учетом регистра сдвига. Там ничего сложного нет.
otrog
Цитата(TamTam @ Jul 5 2006, 06:16) *
Только сейчас я начал понемать, когда посмотрел на код, мало того что я закосячил с загрузкой в сдвиговый регистр, так и оказывается , завершения для команд и данных разные.

Подскажите как правильно грузить данные в регистр сдвига

Помоему так:
Код
/////////////////////
#define reg_clk PORTB.2
#define reg_dat PORTB.1

void send_lcd_reg_2wire(unsigned char send_data)
{
  unsigned int i;

  for (i=0; i<8; i++) // цикл на 8 итераций
  {
    if ((send_data & 0x80) == 0x80) // если 7-й бит == 1 (т.е. грузим сначала старший бит)
      reg_dat = 1; // запись 1 в линию данных
    else // иначе
      reg_dat = 0; // запись 0 в линию данных
    
    #asm("nop"); // задержка для установления уровня
    reg_clk = 1; // передний фронт CLK
    #asm("nop"); // выдержка времени CLK
    reg_clk = 0; // задний фронт CLK

    send_data = send_data << 1; // сдвиг данных на 1 бит влево
  }  

/* это я не понял зачем......
  PORTB.0 = 1;
  #asm("nop"); // задержка для установления уровня
  PORTB.0 = 0;
*/  
}
////////////////////

А вообще посмотрите как сделан SPI. Принцип такой же.
vet
да, с Two-Wire (I2C) эта схема ничего общего не имеет.
otrog
но ведь 2wire(Two-Wire) это не обязательно I2C.
TamTam
Блин ну помогите плиз, почемуто не работает, вроде все по доке,

Код
/*****************************************************
This program was produced by the
CodeWizardAVR V1.24.8b Professional
Automatic Program Generator
© Copyright 1998-2006 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 04.07.2006
Author  : F4CG                            
Company : F4CG                            
Comments:


Chip type           : AT90S2313
Clock frequency     : 11,059200 MHz
Memory model        : Tiny
External SRAM size  : 0
Data Stack size     : 32
*****************************************************/

#include <90s2313.h>

#include <delay.h>

//  Добамим именованный тип данных
#define BOOL    unsigned char            // тип
#define false    0                        // Значения типа
#define true    1                        // Значения типа

// Линии управления LCD
#define LCD_E     PORTB.0    // сигнал разрешения чтения/записи;
#define LCD_DATA  PORTB.1    // сигнал данных + RS - переключение типа данные/инструкции, ( 0 - данные, 1 - инстр );
#define LCD_CLK   PORTB.2    // Сигнал сдвига
#define LCD_BCL   (1 << PD7) // подсветка

// Параметры ЖКИ
#define LCD_ROW_SIZE    20    // длина строки дисплея в символах
#define LCD_ROW_NUM        4      // количество строк в дисплее






void init_lcd_2wire();
void send_lcd_reg_2wire(unsigned char send_data, BOOL RS);
void lcd_putchar(unsigned char data);
void lcd_gotoxy(unsigned char x, unsigned char y);
void lcd_clear(void);







void init_lcd_2wire()

{
LCD_E    = 0;              
LCD_DATA = 0;
LCD_CLK  = 0;
delay_ms(400);              // для правильного функционирования
delay_ms(15);
send_lcd_reg_2wire(0x30,0);   //
delay_ms(5);
send_lcd_reg_2wire(0x30,0);   //
delay_us(255);
send_lcd_reg_2wire(0x30,0);   //
delay_us(255);
send_lcd_reg_2wire(0x38,0);   // 8 проводной интерфейс, 2 строки, размер символа 5Х7.
delay_us(255);
send_lcd_reg_2wire(0x08,0);   // дисплей выкл, курсор выкл, мерцание выкл.                    
delay_us(255);
send_lcd_reg_2wire(0x01,0);   // очистка дисплея
delay_us(255);
send_lcd_reg_2wire(0x06,0);   // Increment cursor to the right when writing, don't shift screen
delay_us(255);
send_lcd_reg_2wire(0x0C,0);   // дисплей вкл, курсор выкл, мерцание выкл.                    
delay_us(255);

send_lcd_reg_2wire(0x0,0);    
delay_us(255);
send_lcd_reg_2wire(0x1,0);
delay_us(255);
send_lcd_reg_2wire(0x0,0);    
delay_us(255);
send_lcd_reg_2wire(0x6,0);
delay_us(255);

}


void lcd_gotoxy(unsigned char x, unsigned char y)
{
//_lcd_ready(); // RS=0
//_lcd_write_data(_base_y[y]+x);
//_lcd_x=x;
//_lcd_y=y;
}

// clear the LCD
void lcd_clear(void)
{
//_lcd_ready();         // RS=0
//_lcd_write_data(2);   // cursor home
//_lcd_ready();
//_lcd_write_data(0xc); // cursor off
//_lcd_ready();
//_lcd_write_data(1);   // clear
//_lcd_x=_lcd_y=0;
}


void lcd_putchar(unsigned char data)
{
send_lcd_reg_2wire(0x00, false);
send_lcd_reg_2wire(data, true);
}




void send_lcd_reg_2wire(unsigned char send_data, BOOL RS)
{
unsigned int i;

if (RS!=0)                                                    // переключение типа данные/инструкции
   LCD_DATA = RS;                                              // Данные
else                                                          // иначе
   LCD_DATA = RS;                                              // команда
LCD_E = 1;                                                    // Начать прием
for (i=0; i<8; i++)                                           // цикл на 8 итераций
  {
    if ((send_data & 0x80) == 0x80)                           // если 7-й бит == 1 (т.е. грузим сначала старший бит)
      LCD_DATA = 1;                                           // запись 1 в линию данных
    else                                                      // иначе
      LCD_DATA = 0;                                           // запись 0 в линию данных  
    #asm("nop");                                              // задержка для установления уровня
    LCD_CLK = 1;                                              // передний фронт CLK
    #asm("nop");                                              // выдержка времени CLK
    LCD_CLK = 0;                                              // задний фронт CLK
    send_data = send_data << 1;                               // сдвиг данных на 1 бит влево
  }
delay_us(255) ;
LCD_E = 0;  // завершить прием
}



void main(void)
{
// Declare your local variables here
PORTB=0x00;
DDRB=0xFF;

init_lcd_2wire();

//     send_lcd_reg_2wire(0x4c,false);

lcd_putchar('b');

while (1)
     {
     // Place your code here


     };
}
TamTam
И может это все былобы не так сложно еслибы не было так легко.

Засада крылась в отсутствие предпоследней строки а именно LCD_DATA = RS;

привожу рабочую процедуру.

Код
void send_lcd_reg_2wire(unsigned char send_data, BOOL RS)
{
unsigned int i;

//if (RS!=0)                                                    // переключение типа данные/инструкции
//   LCD_DATA = 1;                                             // Данные
//else                                                          // иначе
   LCD_DATA = 0;                                             // команда
LCD_E = 1;                                                    // Начать прием
//PORTB.3 = RS;
for (i=0; i<8; i++)                                           // цикл на 8 итераций
  {
    if ((send_data & 0x80) == 0x80)                           // если 7-й бит == 1 (т.е. грузим сначала старший бит)
      LCD_DATA = 1;                                           // запись 1 в линию данных
    else                                                      // иначе
      LCD_DATA = 0;                                           // запись 0 в линию данных  
    #asm("nop");                                              // задержка для установления уровня
    LCD_CLK = 1;                                              // передний фронт CLK
    #asm("nop");                                              // выдержка времени CLK
    LCD_CLK = 0;                                              // задний фронт CLK
    send_data = send_data << 1;                               // сдвиг данных на 1 бит влево
  }
delay_us(255) ;
LCD_DATA = RS;                                            
LCD_E = 0;  // завершить прием

}
TamTam
Как вывести строку

пробовал так

Код
void lcd_puts(char *str)
{
char k;
while (k=*str++) lcd_putchar(k);
}


компилятор пишет что так нельзя
otrog
Я вывожу так:
Код
void OutStrRam(unsigned char *Str,unsigned char Position) // печать строки из ОЗУ
{
  lcd_write((Position|0x80), 0); // установка видео-адреса
  while((*Str)!=0) lcd_write(*(Str++), 1); // передача символа
}

Строка должна заканчиваться нулем(число).
Сделайте по аналогии.

Если надо печатать строку из флеш, то так:
Код
void OutStrFlash(unsigned char flash *Str,unsigned char Position) // печать строки из Flash
{
  lcd_write(Position|0x80, 0); // установка видео-адреса
  while((*Str)!=0) lcd_write(*(Str++), 1); // передача символа
}
TamTam
Тема закрыта. Проэкт с исходниками и моделью в Proteuse 6.9. sp4 кинул в "Исходники программ и библиотек, у вас есть чем поделиться?"
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.