Например TDA7294

Форум РадиоКот • Просмотр темы - Работа с ЖКИ на контроллере HD44780 и его аналогах
Форум РадиоКот
Здесь можно немножко помяукать :)

Текущее время: Пн июл 28, 2025 04:09:42

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 2431 ]     ... , , , 97, , , ...  
Автор Сообщение
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Ср авг 05, 2015 20:13:05 
Друг Кота
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1859
Зарегистрирован: Чт сен 12, 2013 00:54:12
Сообщений: 4119
Откуда: ЗаМКАДье. Там, где ЦУП
Рейтинг сообщения: 0
Медали: 5
Получил миской по аватаре (5)
amd9800 писал(а):
Это аналоговая клавиатура....

При отпускании B3, при оцифровке, вы фактически даёте команду 74HC595 на загрузку данных в выходной регистр.
Вы уверены что это правильно?
----
P.S.
На мой взгляд, работа схемы на грани фола.
Я бы не экономил выводы контроллера (если нужно сделать надёжное изделие).


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Ср авг 05, 2015 20:23:48 
Опытный кот

Карма: -3
Рейтинг сообщений: 13
Зарегистрирован: Вс июн 02, 2013 12:23:03
Сообщений: 822
Рейтинг сообщения: 0
Albert_V писал(а):
При отпускании B3, при оцифровке, вы фактически даёте команду 74HC595 на загрузку данных в выходной регистр.
Вы уверены что это правильно?

Делал испытания и все прекрасно.
Дело в том что в момент оцифровки запрещена передача данных в регистры.
Поэтому данные на выводы не будут меняться.
Мы можем хоть 100 раз дергать этой ногой а данные так и останутся.
Вот если я бы передавал данные в момент оцифровки это было бы ужасно.

Ниже библиотека работы с Шиной передачи данных для этих экранов
экраны могут быть 2х типов
1-LCD(HD44780) - управляется одним регистром 595
2-LED (7 семисегментник до 4digit) - управляется двумя регистрами 595
Спойлер
Код:
/* ************************************************************************** */
/*   Для работы укажите подключеные дисплеи обязательно минимум 1 дисплей     */
/*   в скобках вы определяете номер регистра который соотвествует дисплею,    */
/*   запятыми выделяются дисплеи, порядок это будет порядковый номер дисплея  */
/*              П Р И М Е Р                                                   */ 
/*   Обьявление 1 дисплея LCD и 3-х LED                                       */
/*   #define SPI_LCD  {0}                                                     */
/*   #define SPI_LED  {1,3,5}                                                 */

/*   определение функциональных ножек МК                                      */
/*   просто укажите букву порта как в примере                                 */
/*   #define SPI_PORT_SIMBOL B                                                */

/*   также укажите номер пина                                                 */
/*   #define SS_PIN 2                                                         */

/*   Если порт пина отличается просто укажите букву порта пина                */
/*   #define SS_PORT_SIMBOL B                                                 */


/*  ************************************************************************* */
/*    Надо определить рабочие дисплеи указав его регистр работы от 0          */
/*    #define SPI_LCD  {0}                                                    */
/*    #define SPI_LED  {1,3,5}                                                */
/*  ************************************************************************* */

#include <MY\adc.h>
/* ************************************************************************** */
//******              макрос  для  работы  с  портами                   *******/
/* ************************************************************************** */
#ifndef CONCAT
#define CONCAT(x,y)         x ## y
#define DDR(x)            CONCAT(DDR,x)
#define PORT(x)            CONCAT(PORT,x)
#define PIN(x)            CONCAT(PIN,x)
#endif


/* ************************************************************************** */
/*********           Если хедер обьявлен в другом файле               *********/ 
/*********       следующие определения будут игнорированы             *********/
/* ************************************************************************** */
#ifndef _BUS_SPI_INCLUDED
#define _BUS_SPI_INCLUDED

/* ************************************************************************** */
/*      Configure Harware SPI - if you connect dispay to phisical SPI         */
/* ************************************************************************** */
/* ************************************************************************** */
/*********           Если вы не определили порты и пины               *********/ 
/*********       тогда будут сделаны определения по дефольту          *********/
/* ************************************************************************** */
#ifndef SPI_PORT_SIMBOL
#define SPI_PORT_SIMBOL          B
#endif

#define SPI_PORT                 PORT(SPI_PORT_SIMBOL)
#define SPI_DDR                  DDR(SPI_PORT_SIMBOL)
#define SPI_RPIN                 PIN(SPI_PORT_SIMBOL)

/* ************************************************************************** */
/*********   Расположение пинов SPI зависит от МК                     *********/ 
/* ************************************************************************** */
#define SPI_MOSI_PIN             3
#define SPI_SCK_PIN              5


//Если порт пина SS не определен пользователем тогда берется порт SPI
#ifndef SPI_SS_PORT_SIMBOL
#define SPI_SS_PORT                  SPI_PORT
#define SPI_SS_DDR                   SPI_DDR
#define SPI_SS_RPIN                  SPI_RPIN
#else //Если определен пользователем тогда назначаем все связи к определеному порту
#define SPI_SS_PORT                  PORT(SPI_SS_PORT_SIMBOL)
#define SPI_SS_DDR                   DDR(SPI_SS_PORT_SIMBOL)
#define SPI_SS_RPIN                  PIN(SPI_SS_PORT_SIMBOL)
#endif

//Если пин SS не определен пользователем тогда берется 2 ножка
#ifndef SPI_SS_PIN
#define SPI_SS_PIN              2
#endif

#define SPI_SS_PIN_UP                SPI_SS_PORT |=(1<<SPI_SS_PIN)
#define SPI_SS_PIN_DN                SPI_SS_PORT &=(~(1<<SPI_SS_PIN))

/* ************************************************************************** */
/*********             Изминение направления пина SS                  *********/ 
/* ************************************************************************** */
#define SPI_SS_PIN_IN                 SPI_SS_DDR&=(~(1<<SPI_SS_PIN))
#define SPI_SS_PIN_OUT                SPI_SS_DDR|=(1<<SPI_SS_PIN)
#define IS_SPI_SS_PINOUT              ((SPI_SS_DDR)&(1<<SPI_SS_PIN))
#define SPI_SS_GET                    ((SPI_SS_PORT)&(1<<SPI_SS_PIN))

#define SPI_REG_BUF_SEND_IF_PINOUT    if(IS_SPI_SS_PINOUT){spi_reg_buf_send;}

#pragma used+
/* ************************************************************************** */
/*****   создание переменных хранящих расположение регистров дисплея      *****/
/* ************************************************************************** */
#ifdef SPI_LCD
flash char spi_lcd[]=SPI_LCD;
#endif

#ifdef SPI_LED
flash char spi_led[]=SPI_LED;
#define SPI_LED_LENTGH (sizeof(spi_led))
#endif

/* ************************************************************************* */
//определение длины буфера для передачи в регистры 1регистр = 1байт буфера
//Длина определяется автоматически если выбран один LCD и один LED или больше
/* ************************************************************************* */
#ifndef SPI_LCD
#define SPI_REG_BUF_LENGTH      (sizeof(spi_led)*2)
#else
  #ifndef SPI_LED
  #define SPI_REG_BUF_LENGTH    (sizeof(spi_lcd))
  #else
    #define SPI_REG_BUF_LENGTH  (sizeof(spi_lcd)+sizeof(spi_led)*2)
  #endif
#endif


/* ************************************************************************* */
/* специальные макросы которые определят дисплей с какой шиной будут работать*/
/* ************************************************************************* */

#ifndef LCD_POS
#define LCD_POS                       spi_lcd
#endif

#ifndef LED_POS
#define LED_POS                       spi_led
#endif


#ifndef REG_BUF_SEND
#define REG_BUF_SEND                  spi_reg_buf_send()
#endif

#ifndef REG_BUF
#define REG_BUF                       spi_reg_buf
#endif

#ifndef BUS_INI
#define BUS_INI                       spi_ini()
#endif

#ifndef IS_SS_PINOUT                 
#define SS_PIN_IN                     SPI_SS_PIN_IN                     
#define SS_PIN_OUT                    SPI_SS_PIN_OUT
#define IS_SS_PINOUT                  IS_SPI_SS_PINOUT
#define REG_BUF_SEND_IF_PINOUT        SPI_REG_BUF_SEND_IF_PINOUT             
#endif

/* ************************************************************************* */
/* ************       К О Н Е Ц    О П Р Е Д Е Л Е Н И Й          ********** */
/* ************************************************************************* */


/* ************************************************************************* */
/* ********    Буфер хранящий информацию помещаемую в регистры 595    ****** */
/* ************************************************************************* */
char spi_reg_buf[SPI_REG_BUF_LENGTH];

/* ************************************************************************* */
/* ********       Функция синхронизации буфера с регистрами 595       ****** */
/* ************************************************************************* */
void spi_reg_buf_send()
{
char i=SPI_REG_BUF_LENGTH;
unsigned char reg, temp, pin_was_out, ss_pin_pos=SPI_SS_GET;
reg=SREG;
#asm("cli")
/* ************************************************************************* */
/* ********      мы должны синхронизировать полностью буфера          ****** */
/* ********      со всеми регистрами 595, до нового прерывания        ****** */
/* ************************************************************************* */

pin_was_out=IS_SPI_SS_PINOUT; //сохраняем направление пина SS для будущего востановления
/* ************************************************************************* */
/* ******   Если пиг SS в положение IN, ждем окончания АЦП            ****** */
/* ******   преобразования и включаем пиноут                          ****** */
/* ************************************************************************* */
if (!pin_was_out) {WAIT_ADC_CONVERSION;SPI_SS_PIN_OUT;}
/* ************************************************************************* */
/* ******          ставим на землю пин SS                             ****** */
/* ************************************************************************* */
SPI_SS_PIN_DN;

//SPDR=0;while(!(SPSR & (1<<SPIF)));//без этой команды не работает правильно
 while(i>0)
      {
      i--;
      SPDR=spi_reg_buf[i];
      while(!(SPSR & (1<<SPIF)));//Wait to write data to SPI
      }
 SPI_SS_PIN_UP;
 #asm("nop");
 if (!ss_pin_pos) {SPI_SS_PIN_DN;}
 if (reg&(1<<SREG_I)) {#asm("sei")}
}

/* ************************************************************************* */
/* ********         Функция  инициализации  интерфейса  S P I         ****** */
/* ************************************************************************* */

void spi_ini()
{
SPCR=0b01010000;
SPSR=0x00;
SPI_DDR|=((1<<SPI_MOSI_PIN)|(1<<SPI_SCK_PIN)|(1<<2));
SPI_SS_DDR|=(1<<SPI_SS_PIN);
}
#pragma used-

#endif //#ifndef _MY_BUS_INCLUDED
/* ************************************************************************* */
/* ************                 К   О   Н   Е   Ц                 ********** */
/* ************************************************************************* */


библиотека LCD дисплея
Спойлер
Код:
#ifndef _BUS_LCD_DISPLAY_INCLUDED
#define _BUS_LCD_DISPLAY_INCLUDED
/***** LCD дисплей, в отличие от LED будет работать на первой оперделенной шине  *****/

/***** Определение функциональных пинов дисплея                                  *****/
#define E_PIN      1
#define RS_PIN     0

//new universal
/***** Макросы по управлению пинами дисплея - Light имеет 4 поз от 0-3          *****/
#define LCD_BUF(A)                 REG_BUF[LCD_POS[A]]
#define LCD_E_ENABLE(LCD_NR)       ((LCD_BUF(LCD_NR))|=(1<<E_PIN))
#define LCD_E_DISABLE(LCD_NR)      ((LCD_BUF(LCD_NR))&=(~(1<<E_PIN)))
#define LCD_RS_ENABLE(LCD_NR)      ((LCD_BUF(LCD_NR))|=(1<<RS_PIN))
#define LCD_RS_DISABLE(LCD_NR)     ((LCD_BUF(LCD_NR))&=(~(1<<RS_PIN)))
#define LCD_LightSET(LCD_NR,L)     (LCD_BUF(LCD_NR))=((LCD_BUF(LCD_NR))&0b00111111)|(L<<6)
#define LCD_LightON(A)             LCD_LightSET(A,3)
#define LCD_LightOFF(A )           LCD_LightSET(A,0)

#define CV_NR(NR)                  (NR+48)

#pragma used+

#define REG_BUF_write_nibble(data, REG_B) (REG_B)&=0b11000011;\
                                          (REG_B)|=((data>>2)|(1<<E_PIN)) //запись данных в буффере

void lcd_write_nibble(unsigned char data, unsigned char lcd_nr) {
   //REG_BUF_write_nibble((data), REG_BUF);
   (LCD_BUF(lcd_nr))&=0b11000011;
   (LCD_BUF(lcd_nr))|=((data>>2)|(1<<E_PIN));//запись данных в буффере
   REG_BUF_SEND;
   LCD_E_DISABLE(lcd_nr);
   REG_BUF_SEND;
}
void lcd_write_data(unsigned char data, unsigned char lcd_nr) {
    lcd_write_nibble(data & 0b11110000, lcd_nr);    // старшый полубайт
    lcd_write_nibble(data << 4,         lcd_nr);    //младший полубайт
}
/* константы дисплея */
#define ON                                 1
#define OFF                                0

#define C_LCD_CLEAN                        0b00000001

#define C_LCD_CURS_RIGHT                   0b00000110
#define C_LCD_CURS_LEFT                    0b00000100
#define C_LCD_RIGHT                        0b00000111
#define C_LCD_LEFT                         0b00000101

#define C_LCD                              3
#define C_LCD_ON                           2
#define C_LCD_CURS_ON                      1
#define C_LCD_BLINK_ON                     0
#define C_LCD_SET(ON_OFF,CURSOR,BLINK)     (1<<C_LCD)|(ON_OFF<<C_LCD_ON)|(CURSOR<<C_LCD_CURS_ON)|(BLINK<<C_LCD_BLINK_ON)

/* FUNCTION_SET - выбор режима работы дисплея */
#define C_FS                               5
#define C_DL_8b4b                          4
  #define BIT_8                            1
  #define BIT_4                            0
#define C_LINE                             3
  #define LINE_2                           1
  #define LINE_1                           0
#define C_FONT_11_8                        2
  #define FONT_11                          1
  #define FONT_8                           0
#define C_FUNCTION_SET(DL,LINE,FONT)      (1<<C_FS)|(DL<<C_DL_8b4b)|(LINE<<C_LINE)|(FONT<<C_FONT_11_8)

/* операции с дисплеем */
#define SPI_WRITE_DATA(data, lcd_nr)       spi_write_nibble(data & 0b11110000, lcd_nr);spi_write_nibble(data << 4, lcd_nr)
#define LCD_SET_LINE0(lcd_nr)              lcd_write_cmd(0b10000000, lcd_nr)
#define LCD_SET_LINE1(lcd_nr)              lcd_write_cmd(0b10000000+0x40, lcd_nr)
#define LCD_SET_LINE0_Y(Y,lcd_nr)          lcd_write_cmd((0b10000000+Y), lcd_nr)
#define LCD_SET_LINE1_Y(Y,lcd_nr)          lcd_write_cmd((0b10000000+0x40+Y), lcd_nr)

#define LCD_FAST_CLEAR(lcd_nr)             lcd_write_cmd(0x01, lcd_nr)
#define LCD_CLEAR(lcd_nr)                  lcd_write_cmd(0x01, lcd_nr);delay_ms(3)
#define LCD_OFF(lcd_nr)                    lcd_write_cmd(C_LCD_SET(OFF,0,0),lcd_nr);delay_us(50)
#define LCD_ON(lcd_nr, CURSOR, BLINK)      lcd_write_cmd(C_LCD_SET(ON,CURSOR,BLINK),lcd_nr);delay_us(50)
#define LCD_CURS_DIRECTION_SET(D)          lcd_write_cmd(D,lcd_nr);delay_us(50)
#define LCD_DIRECTION_SET(D)               lcd_write_cmd(D,lcd_nr);delay_us(50)



void lcd_init(unsigned char lcd_nr) {
    LCD_RS_DISABLE(lcd_nr);
    //REG_BUF_SEND;
   
    /* FUNCTION_SET - выбираем режим работы дисплея - выбираем в начале 4бит */
    lcd_write_nibble(C_FUNCTION_SET(BIT_4,0,0), lcd_nr);            delay_us(50);
   
    /* теперь выбираем все функции режима работы дисплея - 4бит +  */   
    lcd_write_data(C_FUNCTION_SET(BIT_4, LINE_2, FONT_8), lcd_nr);  delay_us(50);
   
    /* *** полное выключение дисплея *** */
    lcd_write_data(C_LCD_SET(OFF,OFF,OFF), lcd_nr);                 delay_us(50);
     
    /* ***  очистка дисплея - надо ждать долго после команды = 3мс *** */
    lcd_write_data(C_LCD_CLEAN, lcd_nr);
    delay_ms(3);
   
    /* ***  направление курсора или экрана - выбираем сдвиг курсора вправо *** */
    lcd_write_data(C_LCD_CURS_RIGHT, lcd_nr);                       delay_us(50);
   
    /* ***  включение дисплея и настройка курсора *** */
    /* ***  C_LCD_SET(ON_OFF,CURSOR,BLINK) *** */
    lcd_write_data(C_LCD_SET(ON,OFF,OFF), lcd_nr);                  delay_us(50);
    LCD_RS_ENABLE(lcd_nr);  //rs = 1

    REG_BUF_SEND;
}

void lcd_write_str(unsigned char*str, unsigned char lcd_nr) {
    do {lcd_write_data(*str, lcd_nr);}while(*++str);
}
void lcd_write_str_delay(unsigned char*str, unsigned int delay, unsigned char lcd_nr) {
    do {
        lcd_write_data(*str, lcd_nr);
        delay_ms(delay);
       }while(*++str);
}
void lcd_write_str_delay_plus(unsigned char*str, unsigned int delay, signed char plus, unsigned char lcd_nr) {
    do {
        lcd_write_data(*str, lcd_nr);
        delay_ms(delay);
        delay=delay+plus;
       }while(*++str);
}

void lcd_write_str_accel(unsigned char*str, unsigned int delay, unsigned char accel, unsigned char lcd_nr) {

    do {
        lcd_write_data(*str, lcd_nr);
        delay_ms(delay);
        delay=(unsigned int)((delay*20)/accel);       
       }while(*++str);
}

/* ***  Функция отправки команды: *** */

void lcd_write_cmd(unsigned char cmd, unsigned char lcd_nr) {
    LCD_RS_DISABLE(lcd_nr);
    //REG_BUF_SEND;   //posibil nu e necesar regim de testare
    lcd_write_data(cmd, lcd_nr);
    LCD_RS_ENABLE(lcd_nr);
    REG_BUF_SEND;
}

/* ***  Функция перемещения курсора: *** */
void lcd_set_cursor(unsigned char line, unsigned char pos, unsigned char lcd_nr) {
    pos |= 0b10000000;
    if (line == 1) {
        pos += 0x40;
       
    }
    lcd_write_cmd(pos, lcd_nr);
}

/* 1 tick = 0.1ms */
void lcd_delay(char ticks) {

}

/* ***  Функция быстрой очистки дисплея *** */   
void lcd_sf_clear(char lcd_nr) {
    unsigned char i,y=0;
    while (1){
      if (y!=1) {LCD_SET_LINE0(lcd_nr);if (y>1){return;}} else {LCD_SET_LINE1(lcd_nr);}
      i=0;
      while (i<17){
      i++;
      lcd_write_data(32, lcd_nr);
      }
      y++;
     }
}

  void lcd_put_num3d(char lcd_nr, unsigned char Num){
 unsigned char Temp;
 unsigned char Rest;
 Temp=100;
  do
  {
  Rest=Num/Temp;
  lcd_write_data(CV_NR(Rest),lcd_nr);
  Num=Num-(Rest*Temp);
  Temp=Temp/10;
  }while(Temp>0);
 }


#pragma used-

#endif  //_BUS_LCD_DISPLAY_INCLUDED


Библиотека LED дисплея
Спойлер
Код:
#ifndef _BUS_LED_DISPLAY_INCLUDED
#define _BUS_LED_DISPLAY_INCLUDED

/* ************************************************************************** */
//******         Расположение сегментов в 16bit регистре                *******/
/* ************************************************************************** */
#define S_A      10
#define S_B      15
#define S_C      1
#define S_D      6
#define S_E      0
#define S_F      9
#define S_G      2
#define S_H      5
#define POS_LED1 11
#define POS_LED2 13
#define POS_LED3 14
#define POS_LED4 3
#define INI_DISP (1<<POS_LED1)|(1<<POS_LED2)|(1<<POS_LED3)|(1<<POS_LED4)
#define POS_1    (~(1<<POS_LED1))    //selected position is 0 another bits 1
#define POS_2    (~(1<<POS_LED2))
#define POS_3    (~(1<<POS_LED3))
#define POS_4    (~(1<<POS_LED4))


#pragma used+
/* ************************************************************************** */
//******      хранит отрисовку символов на 7-ми сегментном дисплее       *******/
/* ************************************************************************** */

flash unsigned int nr16[16] = {
INI_DISP|(0<<S_G)|(1<<S_F)|(1<<S_E)|(1<<S_D)|(1<<S_C)|(1<<S_B)|(1<<S_A),//0
INI_DISP|(0<<S_G)|(0<<S_F)|(0<<S_E)|(0<<S_D)|(1<<S_C)|(1<<S_B)|(0<<S_A),//1
INI_DISP|(1<<S_G)|(0<<S_F)|(1<<S_E)|(1<<S_D)|(0<<S_C)|(1<<S_B)|(1<<S_A),//2
INI_DISP|(1<<S_G)|(0<<S_F)|(0<<S_E)|(1<<S_D)|(1<<S_C)|(1<<S_B)|(1<<S_A),//3
INI_DISP|(1<<S_G)|(1<<S_F)|(0<<S_E)|(0<<S_D)|(1<<S_C)|(1<<S_B)|(0<<S_A),//4
INI_DISP|(1<<S_G)|(1<<S_F)|(0<<S_E)|(1<<S_D)|(1<<S_C)|(0<<S_B)|(1<<S_A),//5
INI_DISP|(1<<S_G)|(1<<S_F)|(1<<S_E)|(1<<S_D)|(1<<S_C)|(0<<S_B)|(1<<S_A),//6
INI_DISP|(0<<S_G)|(0<<S_F)|(0<<S_E)|(0<<S_D)|(1<<S_C)|(1<<S_B)|(1<<S_A),//7
INI_DISP|(1<<S_G)|(1<<S_F)|(1<<S_E)|(1<<S_D)|(1<<S_C)|(1<<S_B)|(1<<S_A),//8
INI_DISP|(1<<S_G)|(1<<S_F)|(0<<S_E)|(1<<S_D)|(1<<S_C)|(1<<S_B)|(1<<S_A), //9
INI_DISP|(1<<S_G)|(1<<S_F)|(1<<S_E)|(0<<S_D)|(1<<S_C)|(1<<S_B)|(1<<S_A), //A
INI_DISP|(0<<S_G)|(1<<S_F)|(1<<S_E)|(1<<S_D)|(1<<S_C)|(1<<S_B)|(0<<S_A), //V
INI_DISP|(0<<S_G)|(0<<S_F)|(1<<S_E)|(1<<S_D)|(1<<S_C)|(0<<S_B)|(0<<S_A), //v
INI_DISP|(0<<S_G)|(0<<S_F)|(1<<S_E)|(1<<S_D)|(1<<S_C)|(0<<S_B)|(1<<S_A), //v med
INI_DISP|(1<<S_G)|(1<<S_F)|(1<<S_E)|(0<<S_D)|(1<<S_C)|(1<<S_B)|(0<<S_A), //H
INI_DISP|(0<<S_G)|(0<<S_F)|(0<<S_E)|(0<<S_D)|(0<<S_C)|(0<<S_B)|(0<<S_A) //NULL
};

flash unsigned char SEG_POS[8] = {
S_A,//A
S_B,//B
S_C,//C
S_D,//D
S_E,//E
S_F,//F
S_G,//G
S_H//H
};
flash int seg_led_pos[4] = {
POS_1,
POS_2,
POS_3,
POS_4
};

#ifdef SPI_LED_LENTGH
unsigned char        spi_led_buf[SPI_LED_LENTGH][4][2];
#define SPI_LED_ADR(NR)      ((unsigned int *)&(spi_led_buf[NR][0][0]))
#define SPI_LED_BUF(NR,POS)  ((unsigned int *)(spi_led_buf[NR][POS][0]))
#define LED_BUF(NR,POS)      ((unsigned int *)(sw_led_buf[NR][POS][0]))
#endif

#ifdef SW_LED_LENTGH
unsigned char       sw_led_buf[SW_LED_LENTGH][4][2];
#define SW_LED_ADR(NR)      ((unsigned int *)&(sw_led_buf[NR][0][0]))
#define SW_LED_BUF(NR,POS)  ((unsigned int *)(sw_led_buf[NR][POS][0]))
 #ifndef LED_BUF
 #define LED_BUF(NR,POS)    ((unsigned int *)(sw_led_buf[NR][POS][0]))
 #endif
#endif


//Universal functions
 //Round function
 unsigned int round(unsigned int Number){
 unsigned int Num;
 Num=Number/10;
 if ((Number%10)>4) {Num++;}
 return Num; 
 }


void led7_cleanscr(unsigned int *led_buffer) {
   //led_buffer это ссылка на участок 2 байт памяти которые пренадлежат конкретному LED дисплею
 //итого мы запишем 4 разряда по 2 байта = 8 байт
  char i=0;
  while(i<4){
  (*led_buffer)=0;
  i++;
  }
}
void led7_cleandigit(unsigned int *led_buffer, unsigned char pos) {
  (*(led_buffer+pos))=0;
}

void led7_setpoint(unsigned int *led_buffer, unsigned char pos) {
  //pos&=0b00000011;  //защита от переполнения позиции макс=3
  (*(led_buffer+pos))|=(1<<S_H);
}
#define SPI_LED7_SETPOINT(led_nr,pos) (led7_setpoint(SPI_LED_ADR(led_nr),pos))

void led7_setdigit_nr(unsigned int *led_buffer, unsigned char data, unsigned char pos) {
  (*led_buffer)=seg_led_pos[pos]&nr16[data];
}


  void led_put_num4d(unsigned int *led_buffer, unsigned int Number){
 //led_buffer это ссылка на участок 2 байт памяти которые пренадлежат конкретному LED дисплею
 //итого мы запишем 4 разряда по 2 байта = 8 байт
 unsigned int Num,Temp;
 unsigned char Rest,i=4;
 Num=Number;
 Temp=Num;
   
  while(i>0)
  {
  i--;
  Num=Temp;
  Temp=Num/10;
  Rest=Num-(Temp*10);
  led7_setdigit_nr(led_buffer, Rest, i);
  led_buffer++; //переход к следующему разряду +2байта
  };
 }
 
 
   void led_put_num(unsigned int *led_buffer, unsigned int Number, unsigned char startpos){
 //led_buffer это ссылка на участок 2 байт памяти которые пренадлежат конкретному LED дисплею
 //итого мы запишем 4 разряда по 2 байта = 8 байт
 unsigned int Num,Temp;
 unsigned char Rest,i=4;
 Num=Number;
 Temp=Num;
 startpos++;   
  while(i>0)
  {
  i--;
   if (i<startpos)
   {
   Num=Temp;
   Temp=Num/10;
   Rest=Num-(Temp*10);
   led7_setdigit_nr(led_buffer, Rest, i);
   }
   else
   {
   led7_setdigit_nr(led_buffer, 15, i);
   }
   led_buffer++; //переход к следующему разряду +2байта
  };
 }
 

   void led_put_bin(unsigned int *led_buffer, unsigned char Number){
 unsigned int Num;
 unsigned char i=4;
 Num=Number;
  while(i>0)
  {
  i--;
  //led7_setdigit_nr(led_buffer, (Num&1), i);
  (*led_buffer)=seg_led_pos[i]&nr16[Num&1];
  Num=Num>>1;
  led_buffer++; //переход к следующему разряду +2байта
  };
 } 
 
//only SPI functions
#ifdef SPI_LED_LENTGH
/* void spi_led_buffer_show(unsigned char led_nr,unsigned char pos){
 spi_reg_buf[spi_led[led_nr]]  =spi_led_buf[led_nr][pos][0];
 spi_reg_buf[spi_led[led_nr]+1]=spi_led_buf[led_nr][pos][1];
} */
 void spi_led_buffer_show(unsigned char led_nr,unsigned char pos){
 char *aaa, *bbb;
 aaa=&spi_reg_buf[spi_led[led_nr]];
 bbb=&spi_led_buf[led_nr][pos][0];
 *aaa=*bbb;
 *(aaa+1)=*(bbb+1);
}
//#define SPI_LED_BUFFER_SHOW(led_nr,pos)   spi_reg_buf[spi_led[led_nr]]=spi_led_buf[led_nr][pos][0];spi_reg_buf[spi_led[led_nr]+1]=spi_led_buf[led_nr][pos][1]   
#define SPI_LED_BUFFER_SHOW(led_nr,pos)   *((int *)&spi_reg_buf[spi_led[led_nr]])=(*((int *)&spi_led_buf[led_nr][pos][0]));
#endif


//only SW functions
#ifdef SW_LED_LENTGH
 void sw_led_buffer_show(unsigned char led_nr,unsigned char pos){
 sw_reg_buf[sw_led[led_nr]]  =sw_led_buf[led_nr][pos][0];
 sw_reg_buf[sw_led[led_nr]+1]=sw_led_buf[led_nr][pos][1];

}
#endif

/* ************************************************************************** */
//******         Макросы для записи данных в LED SPI или SW             *******/
/* ************************************************************************** */
#define LEDSW_BIN_PUT(LedNR, A)            led_put_bin(SW_LED_ADR(LedNR), A)
#define LEDSPI_BIN_PUT(LedNR, A)           led_put_bin(SPI_LED_ADR(LedNR), A)

#pragma used-

#endif //#ifndef  _BUS_LED_DISPLAY_INCLUDED


Последний раз редактировалось amd9800 Ср авг 05, 2015 20:30:57, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Ср авг 05, 2015 20:27:26 
Друг Кота
Аватар пользователя

Карма: 90
Рейтинг сообщений: 1859
Зарегистрирован: Чт сен 12, 2013 00:54:12
Сообщений: 4119
Откуда: ЗаМКАДье. Там, где ЦУП
Рейтинг сообщения: 0
Медали: 5
Получил миской по аватаре (5)
Это ваше устройство. Смотрите сами....
Я бы такое в серию не пустил /но это моё личное мнение/.
Удачи.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Ср авг 05, 2015 20:31:54 
Опытный кот

Карма: -3
Рейтинг сообщений: 13
Зарегистрирован: Вс июн 02, 2013 12:23:03
Сообщений: 822
Рейтинг сообщения: 0
Я вас прекрасно понимаю. Ну для клавы всегда можно будет выделить один провод.
Это для случаев когда устройство находится где то на расстояние 2-4 метра, а экран (экраны) + клавиатура в удобном месте.

Либо ситуация хочу собрать простое устройство которая собирает данные. у устройства выход на данную шину.
И периодически могу подключатся к устройству и на экран смотреть информацию.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Чт авг 06, 2015 02:25:36 
Держит паяльник хвостом

Карма: 10
Рейтинг сообщений: 161
Зарегистрирован: Чт апр 03, 2014 23:16:55
Сообщений: 963
Откуда: Россия
Рейтинг сообщения: 0
amd9800 писал(а):
...{CLOCK=250kHz}...
Вот это значение пробуйте изменить и тестируйте, может помочь.
Мне иногда приходилось ставить 300-350 кГц для симуляции.
По поводу библиотеки LCD, почему не хотите сделать "универсально", т.е. не только писать в дисплей, но и читать дисплей?
Тогда и глюков меньше будет.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 10:38:30 
Опытный кот

Карма: -3
Рейтинг сообщений: 13
Зарегистрирован: Вс июн 02, 2013 12:23:03
Сообщений: 822
Рейтинг сообщения: 0
Rtmip писал(а):
но и читать дисплей? Тогда и глюков меньше будет.

Потому что через регистры 595 могу только передавать информацию.
И как же мне в данном случае читать дисплей ума не приложу.

Но я готов обсудить любые изменения - предлагайте...


Последний раз редактировалось amd9800 Пт авг 07, 2015 10:43:23, всего редактировалось 2 раз(а).

Вернуться наверх
 
Распродажа паяльного оборудования ATTEN!
Паяльные станции, паяльники и аксессуары по самой выгодной цене.

По промокоду radiokot скидка 10%
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 10:41:55 
Друг Кота
Аватар пользователя

Карма: 67
Рейтинг сообщений: 1060
Зарегистрирован: Чт сен 18, 2008 12:27:21
Сообщений: 19733
Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
amd9800 писал(а):
И как же мне в данном случае читать дисплей
Зачем вам его читать?

_________________
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Измерить нннада?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 10:44:46 
Опытный кот

Карма: -3
Рейтинг сообщений: 13
Зарегистрирован: Вс июн 02, 2013 12:23:03
Сообщений: 822
Рейтинг сообщения: 0
Как зачем? Вот выше колега предложил

Rtmip писал(а):
По поводу библиотеки LCD, почему не хотите сделать "универсально", т.е. не только писать в дисплей, но и читать дисплей?
Тогда и глюков меньше будет.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 10:49:43 
Друг Кота
Аватар пользователя

Карма: 67
Рейтинг сообщений: 1060
Зарегистрирован: Чт сен 18, 2008 12:27:21
Сообщений: 19733
Откуда: Столица Мира Санкт-Петербург
Рейтинг сообщения: 0
Медали: 1
Получил миской по аватаре (1)
Если все тайминги выдержать, то и читать ничего не надо...
... если, конечно, не используется какой-то хитрый алгоритм отображения.

_________________
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Измерить нннада?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 12:44:25 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1035
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4884
Откуда: Минск
Рейтинг сообщения: 0
Таковым хитрым алгоритмом может быть, например, использование буфера. Например, для дисплея 2x16 заводим массив buf[2][16]. А потом код вроде этого:
Код:
void any_timer_interrupt() {
  static uint8_t col = 0;
  static uint8_t row = 0;
  if (col >= 16) {
    col = 0;
    if (++row >= 2)
      row = 0;
    ks0066SetCommand(установка на начало строки row); // RS = 0
  } else {
    ks0066SetData(buf[row][col]); // RS = 1;
    col++;
  }
}

И это прерывание вызывать по таймеру, например, один раз в 100мкс. Этого времени вполне достаточно для отработки дисплея. Весь экран будет обновляться за 34 команд (32 данных + 2 смены строки), то есть, частота обновления картинки при периоде 100мкс будет около 300Гц.

В основном коде любая функция вывода на экран сведётся всего лишь к записи данных в нужные ячейки буфера buf, при этом никаких задержек не нужно вообще - о выводе изменившегося буфера на экран позаботится данное прерывание.

Естественно, инициализировать дисплей нужно как обычно, и только после инициализации запускать этот таймер.


Последний раз редактировалось WiseLord Пт авг 07, 2015 13:15:42, всего редактировалось 1 раз.

Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 12:54:59 
Друг Кота

Карма: 28
Рейтинг сообщений: 568
Зарегистрирован: Чт май 05, 2011 21:26:34
Сообщений: 4550
Откуда: Украина, Славутич
Рейтинг сообщения: 0
На задержках такое не взлетит... на один символ минимум по 16мкс... да не успеет просто отработать до следующего прерывания.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 13:13:07 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1035
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4884
Откуда: Минск
Рейтинг сообщения: 0
Вот именно что взлетит, и никаких задержек не понадобится вообще. Команды (данные) в дисплей за счёт таймера будут посылаться не чаще 50мкс (либо как настроишь таймер - если дисплей позволяет, можно и чаще).

P.S. Вот за часа полтора даже простейшую библиотеку на этом принципе набросал (всё равно самому скоро понадобится) + демо-проект для Proteus.

Частота обновления экрана 115 Гц (с лихвой достаточно), интервал между командами дисплею 256 мкс (аналогично - с лихвой достаточно). Никаких задержек на работу с дисплеем не требуется (кроме необходимых по даташиту при инициализации дисплея).


Вложения:
ks0066buf.7z [14.06 KiB]
Скачиваний: 160
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 15:21:01 
Опытный кот

Карма: -3
Рейтинг сообщений: 13
Зарегистрирован: Вс июн 02, 2013 12:23:03
Сообщений: 822
Рейтинг сообщения: 0
WiseLord писал(а):
Таковым хитрым алгоритмом может быть, например, использование буфера. Например, для дисплея 2x16 заводим массив buf[2][16].

Правильно говорите
Я как раз тоже об этом думал. Но вот после этого у меня появилось куча вопросов как сделать библиотеку достаточно универсальной. Ведь есть куча нюансов.
Дисплеи могут быть 1, 2 и 4х строчные.
Также строка может иметь 16 и 20 символов длины.
А также минус этого метода то что буферы всех дисплеев будут сильно забивать RAM, а ее очень мало на МК.

Давайте тогда обсуждать алгоритм работы библиотеки с буфером.

Также у меня был вариант создания кольцевого буфера в котором будут помещаться команды.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 16:11:18 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1035
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4884
Откуда: Минск
Рейтинг сообщения: 0
Совершенно не проблема.

Код, приведённый выше, работает для дисплеев размера 16x2. Для любого другого дисплея будет лишь самую малость отличаться инициализация и команда позиционирования. Это всё легко разрулить через те же макросы KS0066_HEIGHT и KS0066_WIDTH, в зависимости от совокупности значений которых и реализовывать эти отличия. Размер массива buf[KS0066_WIDTH][KS0066_HEIGHT] будет выбираться автоматически.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 19:18:08 
Опытный кот

Карма: -3
Рейтинг сообщений: 13
Зарегистрирован: Вс июн 02, 2013 12:23:03
Сообщений: 822
Рейтинг сообщения: 0
По какому методу лучше синхронизировать буфер с дисплеем?
вот один пример.
Например настраиваем таймер и запускаем прерывание каждые 100us.
Один символ из буфера дисплея помещается в буфер регистра.
Если дисплеев несколько тогда со всех дисплеев по одной букве(или ниблу) перемещается в регистр.
Потом данные из буфера регистра отправляются в сами регистры.
Но вот когда нужно посылать команды на дисплее как поступать?
Например инициализация или очистка дисплея.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 19:39:27 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1035
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4884
Откуда: Минск
Рейтинг сообщения: 0
Если ба Вы глянули код, то таких вопросов бы не задавали. Там всё понятно.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 21:27:05 
Друг Кота

Карма: 28
Рейтинг сообщений: 568
Зарегистрирован: Чт май 05, 2011 21:26:34
Сообщений: 4550
Откуда: Украина, Славутич
Рейтинг сообщения: 0
Добавить еще одну очередь команд, приоритетную. или ячейку, в которую помещаете команду и ставите флажок исполнения - как только она исполнится, в прерывании флажок должен будет снят и можно слать следующую. А в прерывании делать проверку на этот флажок - если он поднят, исполнить команду занесённую в ячейку и снять флажок.

Можно конечно более грубо - запретить прерывания, отправить команду, сбросить таймер и разрешить прерывания.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 21:38:31 
Друг Кота
Аватар пользователя

Карма: 86
Рейтинг сообщений: 1035
Зарегистрирован: Чт апр 11, 2013 11:19:59
Сообщений: 4884
Откуда: Минск
Рейтинг сообщения: 0
Не понимаю, зачем такие сложности. Нет никакой причины посылать в дисплей какие-либо команды. Просто пишем в буфер даные - это покрывает все необходимые нужды.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Пт авг 07, 2015 21:58:50 
Друг Кота

Карма: 28
Рейтинг сообщений: 568
Зарегистрирован: Чт май 05, 2011 21:26:34
Сообщений: 4550
Откуда: Украина, Славутич
Рейтинг сообщения: 0
Есть очень часто необходимость например включить курсор. аппаратно. Или его тоже эмулировать через буффер?


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Работа с ЖКИ на контроллере HD44780 и его аналогах
СообщениеДобавлено: Сб авг 08, 2015 01:15:48 
Держит паяльник хвостом

Карма: 10
Рейтинг сообщений: 161
Зарегистрирован: Чт апр 03, 2014 23:16:55
Сообщений: 963
Откуда: Россия
Рейтинг сообщения: 0
amd9800 писал(а):
Потому что через регистры 595 могу только передавать информацию.
И как же мне в данном случае читать дисплей ума не приложу.
Но я готов обсудить любые изменения - предлагайте...
Это понятно :)
Но если вы прислушаетесь к Albert_V и не будете так уж сильно экономить на выводах МК, то могу предложить
такие варианты:
Спойлер1 - тут надо позаботиться о том, чтобы при чтении флага занятости на выходе 595-го были единицы.
Изображение
2 - "правильный" вариант, еще один вывод МК задействован, но зато в соответствии с ДШ на дисплей
линии данных переводятся в третье состояние и нет проблемы считывать данные из дисплея.
Изображение

Далее создаете еще одну функцию, например:
Код:
SPI_READ_DATA(data, lcd_nr)
в которой надо будет управлять регистром 74НС595 и давать команду чтения.
При этом проверяете выбранный пин МК на 0 или 1, это и будет флаг BF.
Может быть можно использовать тот пин МК, что управляет ST_CP?
Это просто идея, интересно, что скажут профи? :roll:


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 2431 ]     ... , , , 97, , , ...  

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y