Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Драйвери за матрични дисплеи
http://mcu-bg.com/mcu_site/viewtopic.php?f=22&t=6401
Страница 1 от 2

Автор:  michev [ Сря Дек 24, 2008 12:04 am ]
Заглавие:  Драйвери за матрични дисплеи

Здравейте.
От няколко дни безуспешно се мъча да покарам въпросния дисплей. Изпровах повечето известни библиотеки, но резултатите бяха трагични - или не изписва текста който е въведен, или излизат странни символи.
В карйна сметка реших да разбера как се командва дисплея...Написах малка програмка за тестване, чиито код е базиран на обяснения събирани през интернет. Проблема е че отново някъде нещо пропускам или греша.
Моля тези от вас, които са успели да използват ЛЦД дисплей 2х16 базиран на HD44780 да споделят своя опит.
ето и въпросната тестова програма
Код:
#define F_CPU   8000000
#include <avr/io.h>
#include <util/delay.h>

#define RS_PIN   5
#define E_PIN   4

#define RS_LOW   PORTC |= _BV(RS_PIN)
#define RS_HI   PORTC &= ~_BV(RS_PIN)

#define E_LOW   PORTC |= _BV(E_PIN)
#define E_HI   PORTC &= ~_BV(E_PIN)

void lcd_low(unsigned char data);
void lcd_hi(unsigned char data);
void lcd_pulse_e();
void lcd_cmd(unsigned char cmd);
void lcd_char(unsigned char data);
void lcd_string(unsigned char *data);

void lcd_hi(unsigned char data) {
  PORTC = (PORTC & 0xf0) |((data & 0xf0) >> 4);
}

void lcd_low(unsigned char data) {
  PORTC = (PORTC & 0xf0) | (data&0x0F);
}

void lcd_init() {
  DDRC = 0b00111111;
  _delay_ms(300);
 
  RS_LOW;
  lcd_hi(0x20);
  lcd_pulse_e();
  _delay_ms(100);

  lcd_cmd(0x28);

  _delay_us(110);
  lcd_cmd(0x0f);

  _delay_us(110);
  lcd_cmd(0x01);

  _delay_us(110);
  lcd_cmd(0x06);

    _delay_us(110);
  lcd_cmd(0x80);
  lcd_char('A');
}

void lcd_string(unsigned char *data) {
  while (*data != 0) {
    lcd_char(*data);
    data++;
  }
}

void lcd_char(unsigned char data) {
  RS_HI;
  lcd_hi(data);
  lcd_pulse_e();
  _delay_us(100);
  lcd_low(data);
  lcd_pulse_e();
}

void lcd_cmd(unsigned char cmd) {
  RS_LOW;
  lcd_hi(cmd);
  lcd_pulse_e();
  _delay_us(100);
  lcd_low(cmd);
  lcd_pulse_e();
}

void lcd_pulse_e() {
  E_HI;
  _delay_us(100);
  E_LOW;
}


int main() {
  lcd_init();
  lcd_string("tova e test\0");
  return 0;
}



Ето и схемата на свързване
Код:
Дисплей                    МЦУ
                                 PORT C
д5                              0
д6                              1
д7                              2
д8                              3
RS                              5
Е                                4

Благодаря за отделеното внимание![/code]

Автор:  michev [ Чет Дек 25, 2008 12:49 am ]
Заглавие: 

Проблема е решен!
Поствам отново тестова програма за тези от вас, които имат проблем с подкарването на LCD 16х2 (Ampire AC-162B).
(Незнайно защо, упорито отказват да работят библиотеките които намерих в нет-а...включително и вградената библиотека на БАСКОМ)

Код:
#define F_CPU   8000000
#include <avr/io.h>
#include <util/delay.h>

#define RS_PIN   5
#define E_PIN   4

#define RS_HI   PORTC |= _BV(RS_PIN)
#define RS_LOW   PORTC &= ~_BV(RS_PIN)

#define E_HI   PORTC |= _BV(E_PIN)
#define E_LOW   PORTC &= ~_BV(E_PIN)

void lcd_low(unsigned char data);
void lcd_hi(unsigned char data);
void lcd_pulse_e();
void lcd_cmd(unsigned char cmd);
void lcd_char(unsigned char data);
void lcd_string(char *data);


void lcd_xy(unsigned char x, unsigned char y) {
if (y <= 1) {
    lcd_cmd(0x80 + x);
} else {
    lcd_cmd(0xC0 +  x);
}
}
void lcd_hi(unsigned char data) {
  PORTC = (PORTC & 0xf0) |((data >>4) & 0x0f);
}

void lcd_low(unsigned char data) {
  PORTC = (PORTC & 0xf0) | (data&0x0F);
}

void lcd_init() {

  DDRC = 0xff;
  PORTC = 0x00;
  _delay_ms(200);
 

  lcd_cmd(0x00);
  _delay_ms(15);

  lcd_cmd(0x20);
  lcd_pulse_e();
  _delay_ms(5);


  _delay_ms(5);


  lcd_cmd(0x28);
  lcd_pulse_e();
  _delay_ms(5);


  lcd_cmd(0x06);
  lcd_pulse_e();
  _delay_us(100);


  lcd_cmd(0x0f);
  lcd_pulse_e();
  _delay_us(100);

  lcd_cmd(0x01);
  lcd_pulse_e();
  _delay_us(100);

}

void lcd_string(char *data) {
  while (*data != 0) {
    lcd_char(*data);
    data++;
  }
}

void lcd_char(unsigned char data) {
  _delay_us(100);
  RS_HI;
  _delay_us(100);
  lcd_hi(data);
  lcd_pulse_e();
  _delay_us(1000);
  lcd_low(data);
  lcd_pulse_e();
}

void lcd_cmd(unsigned char cmd) {
  RS_LOW;
  lcd_hi(cmd);
  lcd_pulse_e();
  _delay_us(100);
  lcd_low(cmd);
  lcd_pulse_e();
  _delay_us(100);
}

void lcd_pulse_e() {
  E_HI;
  _delay_us(1000);
  E_LOW;
}


int main() {
  lcd_init();
  lcd_string("tova e test\0");
  lcd_xy(0,2);
  lcd_string("vtori red!\0");
  _delay_ms(3000);
  lcd_xy(0,0);
  lcd_string("Otnovo na red 1\0");
  return 0;
}



Весели празници!

Автор:  bobyk [ Чет Дек 25, 2008 3:09 pm ]
Заглавие: 

Радвам се че си успял да си решиш проблема САМ, много хора прекалено много разчитат на чужда помощ. Между другото не знам да ли си търсил из форума подобни проблени са били обсъждани и най че сто причината да не тръгват тези дисплеи е недостатъчни закъснения или контраста на дисплея.

Автор:  Реконструктор [ Съб Дек 27, 2008 12:17 am ]
Заглавие: 

Аз използвам прикачения драйвер. Много е добър, поддържа всичко и се конфигурира 100%. При мен (mega16 и 20х4 дисплей) тръгна от първия път (софтуерно). :)

Прикачени файлове:
lcd.zip [7.72 KiB]
460 пъти

Автор:  michev [ Съб Дек 27, 2008 1:49 pm ]
Заглавие: 

Този драйвер беше един от първите които тествах.. Дисплея не "запали" с него. (дори и времезадръжките увеличавах, но нямаше ефект)
Имам чувството, че дисплеите на Ampire са нещо малко по странни.
Имам направен проект с 128х64 дисплей отново на същата фирма, който отново тръгна с голяяям зор.

Автор:  vgeorgiev [ Сря Юли 03, 2013 11:30 am ]
Заглавие:  Re: C, atmega8 и hd44780 LCD проблемче

Здравейте,

Използвам LCD библиотеката на колегата Michev. Всичко за сега работи както трябва.
Добавих възможност, за зареждане на потребителси дефинирани знаци.
Зареждам 8 знака. Първите 3 не се показват коректно.
Предположих, че проблема може да е в това, че пазя данните в програмната памет. Прочетох данните. Изглеждат ОК.

Играх си с таймингите, но няма ефект. Предостатъчно са удължени.
Едва ли проблема е от тайминг, защото всички останали символи се печатат правилно и няма черги по екрана.

Намерих заобиколен начин да си реша проблема. Зареждам два пъти и всичко се оправя, но ми се иска да знам причината за проблема и да я оправя.

Прилагам кода и снимка на грешните знаци.
Изображение

Прикачени файлове:
lcd.h [1.63 KiB]
495 пъти
lcd.c [3.12 KiB]
486 пъти

Автор:  Реконструктор [ Пет Юли 05, 2013 4:24 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Позволих си да преместя и прекръстя темата. :) Мисля, че ще бъде полезно на мнозина.

Автор:  tgi [ Пет Юли 05, 2013 11:20 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Ами преди година и нещо и аз слагах някакъв такъв май дисплей, 4 реда.
Не помня да имаше някакво чудене, трябва да е станало за малко над колкото
ми е било нужно да напиша текста. Ама ето го, на асемблер за coldfire,
може и да е полезно някому (и се чете по-лесно от C код дори от C писачи :D ):

http://tgi-sci.com/misc/lcd4r.sa

То не е дълго всъщност, ей го и изцъркано тука:

Код:
*
*
* display on - turn display power on, initialize it etc.
*
dispon:
         push      d1,a0               save regs
         bsr.w     dion      turn display power on
* wait for >15 mS
        move.l     #30000,d0 30mS time
         scall     xtwt$     make sure to wait that long
         moveq     #$30,d1   wakeup command
         bsr.w     dispcmd   issue display command
         bcs       retdpon   if error
         move.l    #$200000,d1 to wait 160 mS or so
         scall     xtwt$     wait
         moveq     #$38,d1   8 bit mode, 2 lines
         bsr.w     dispcmd   issue command to display
         bcs       retdpon   if error
         moveq     #$c,d1    display on, cursor on (to test)
         bsr.w     dispcmd
         bcs       retdpon   if error
         moveq     #$6,d1    to set increment mode
         bsr.w     dispcmd   do so
         bcs       retdpon   if error
         moveq     #1,d1     clearhome
         bsr.w     dispcmd   
*
retdpon
         pull      d1,a0     restore regs
         rts                 *return*
*
* output a message formatted as:
* X coord byte, y coord byte, length, text
* a0 -> message beg. (the x coord length)
*
pmsg0
         push      d1-d3,a0  save regs
         clr.l     d1
         clr.l     d2
         clr.l     d3        zero extend all
         move.b    (a0)+,d1  x coord                                                               
         move.b    (a0)+,d2  y coord
         move.b    (a0)+,d3  length
         bsr       pmsg123   do display the message
         pull      d1-d3,a0  restore regs
         rts       *return*
*
*
* output a message starting at d1,d2 coords.
* a0 -> message; length is in d3
*
pmsg123:
         push      d1-d3,a0
         and.l     #$1f,d1   make sure to have just a X coord (actually 24 is the max.)
         and.l     #$3,d2    and an Y one
         move.l    d3,d0     length extra copy
         cmp.l     #linelen,d1         within line?
         bcc       retpmg3   branch not, nothing to be shown
         add.l     d1,d0     x coord past string end
         sub.l     #linelen,d0  negative no. of characters going past line end
         bls       llnok1    if non, length is OK
         sub.l     d0,d3     show only those showable
llnok1
         clr.l     d0        zero extend
         move.b    ((lbegtb).b,pc,d2),d0   take line beg. address
         add.l     d0,d1     beg. address to write to
         bset      #7,d1     to issue as "set address" command
         bsr       dispcmd   do so
         bcs       retpmg3   if error
* output the data now
         set       loop,*
         move.b    (a0)+,d0  a character
         bsr       putdd0    output it
         bcs       retpmg3   if error
         subq.l    #1,d3     count down
         bgt       loop      if more
retpmg3
         pull      d1-d3,a0
         rts       *return*
*
lbegtb   dc.b      0,$40,$14,$54
*
putddp
         set       loop,*
         clr.l     d0
         move.b    (a0)+,d0  pickup a data byte
         cmp.l     #eot,d0   CR (end of string)?
         beq       endpudd   branch yes
         bsr       putdd0    send to display
         bra       loop
endpudd
         rts       *return*
*
* output d0 to current dsiplay address
* putdd0
*
putdd0
         push      d0-d2     save regs
         lea       (gp_beg+ipsbarv).l,a3         point to gpio port
         move.l    #200000,d2          200 mS timeout
         bsr       wairdy              wait for ready
         bcs       retpudd             if error
         moveq     #$f4,d2             
         move.b    d2,(gp_cltc,a3)     E, a0, R/W all 0
         moveq     #$8,d2            to set a0 high
         move.b    d2,(gp_sptc,a3)
         moveq     #$ff,d2   all ones to write
         move.b    d2,(gp_dddd,a3)     data bits are outputs now
         move.l    (a7),d0   recall data
         move.b    d0,(gp_podd,a3)     do output the data
         moveq     #$2,d2              to set E high
         move.b    d2,(gp_sptc,a3)     do so
         tst.b     (gp_spdd,a3)       just some time holding E high
         tst.b     (gp_spdd,a3)       some more (missed characters)
         tst.b     (gp_spdd,a3)       and some more (missed characters)
         not.l     d2                  to clear now
         move.b    d2,(gp_cltc,a3)     then set E back low
retpudd
         pull      d0-d2        restore regs
         rts       *return*
*
* write byte in d1 as a command to the display
*
dispcmd
         move.l    d2,-(a7)  save regs
         lea       (gp_beg+ipsbarv).l,a3         point to gpio port
         move.l    #200000,d2          200 mS timeout
         bsr       wairdy              wait for ready
         bcs       retdicd             if error
         moveq     #$f4,d2             
         move.b    d2,(gp_cltc,a3)     E, a0, R/W all 0
         moveq     #$ff,d2   all ones to write
         move.b    d2,(gp_dddd,a3)     data bits are outputs now
         move.b    d1,(gp_podd,a3)     do output the data
         moveq     #1!<1,d2            to set E high
         move.b    d2,(gp_sptc,a3)     do so
         tst.b     (gp_spdd,a3)        just some time holding E high
         not.l     d2                  to clear now
         move.b    d2,(gp_cltc,a3)     then set E back low
retdicd
         pull      d2        restore regs
         rts       *return*
*
* wait for display to get ready; timeout in d2
* (in microseconds). If no error (no timeout), returns in d0
* the last data read together with the flag (address counter)
*
wairdy
* check for ready
         push      d1-d2               save regs
         move.l    (sy$slic).w,d1     
         divu.l    d1,d2               no. of slices to wait
         add.l     (sy$time).w,d2      timeout moment
*
         clr.b     (gp_dddd,a3)        all inputs
         moveq     #$f4,d1             
         move.b    d1,(gp_cltc,a3)     E, a0, R/W all 0
         moveq     #1!<0,d1  to set R/W high
         move.b    d1,(gp_sptc,a3)  set R/W high
         set       loop,*
         moveq     #1!<1,d1            to set E high
         move.b    d1,(gp_sptc,a3)     do so
         tst.b     (gp_spdd,a3)        just some delay
         tst.b     (gp_spdd,a3)        some more delay
         move.b    (gp_spdd,a3),d0     read data
         not.l     d1        to clear it now
         move.b    d1,(gp_cltc,a3)     then set E back low
         btst      #7,d0               ready?
         beq       isrdy               branch yes, just return
         scall     xtask$    exit task
         cmp.l     (sy$time).w,d2      timeout?
         bcc       loop      if no timeout, wait here
         moveq     #e$tout,d2          else indicate timeout
         moveq     #1,d1     to set carry
         move.w    d1,ccr    do so
isrdy
         pull      d1-d2     restore regs
         rts                 *return*

Автор:  Реконструктор [ Съб Юли 06, 2013 10:13 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Колеги, тука се получи едно механично нестиковане. :) Има ли начин картинката да се обърне на 180 градуса?

Автор:  michev [ Нед Юли 07, 2013 12:56 am ]
Заглавие:  Re: Драйвери за матрични дисплеи

В документите не се поменава да има такава възможност.
Веднъж от недоглеждане се получи като при теб и от тогава - дисплей задължително с кабел към платката.

Автор:  Ки4о [ Нед Юли 07, 2013 6:56 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Рек, ако контролера е на Hitachi:
Цитат:
The HD44780U character generator ROM can generate 208 5х8 dot character patterns and
32 5х10 dot character patterns for a total of 240 different character patterns

това е от 15 страница от описанието на HD44780U. Така че със собствени символи може да спасиш
положението ама ще е гърч докато ги направиш.

Прикачени файлове:
HD44780.pdf [322.07 KiB]
392 пъти

Автор:  tgi [ Нед Юли 07, 2013 7:00 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Рек, ако решиш да се гърчиш да правиш знаков генератор и не намериш редактор
мога да ти пусна онлайн една емулация на прастара машина, за която имам (правен
преди 25+ години). Мъка ще е пак разбира се, то и кодът е един от най-нечистите
дето съм писал някога, ама работи някак, виждат се знаците и могат да се редактират.

Автор:  Cekins [ Нед Юли 07, 2013 7:27 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Ки4о, аз що си мисля че има място само за 8 user символа (CGRAM). Другото е ром и незнам как мое се ръчка в него след като веднъж е бил записан.

Автор:  Ки4о [ Нед Юли 07, 2013 7:53 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Cekins, прав си, но какво ти пречи на ход да сменяш съдържанието на CG RAM-а и да пишеш каквото си искаш ?
Изисква ресурс и си е гърч,но не е невъзможно :)

http://www.circuitvalley.com/2012/02/lc ... -16x2.html
http://deanandara.com/robots/ApuLcd.html

Автор:  ike [ Нед Юли 07, 2013 8:08 pm ]
Заглавие:  Re: Драйвери за матрични дисплеи

Ки4о написа:
Cekins, прав си, но какво ти пречи на ход да сменяш съдържанието на CG RAM-а и да пишеш каквото си искаш ?

Не по-дълго от 8 символа.

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/