PIC мк. Эксперимент №6. Подключение LCD дисплея.

Задача: Управление графическим дисплеем

Исходный материал: PIC16f628a, LCD 2×16, breadboard

Схема подключения дисплея (кварц не подключен, но предполагается, что он есть):

Следующий шаг – написание функций управления дисплеем. Я просто взял файлы из директории samples папки компилятора и переделал под себя.

Файл lcd.c


/*
 *    LCD interface example
 *    Uses routines from delay.c
 *    This code will interface to a standard LCD controller
 *    like the Hitachi HD44780. It uses it in 4 bit mode, with
 *    the hardware connected as follows (the standard 14 pin
 *    LCD connector is used):
 *
 *    PORTD bits 0-3 are connected to the LCD data bits 4-7 (high nibble)
 *    PORTA bit 3 is connected to the LCD RS input (register select)
 *    PORTA bit 1 is connected to the LCD EN bit (enable)
 *
 *    To use these routines, set up the port I/O (TRISA, TRISD) then
 *    call lcd_init(), then other routines as required.
 *
 */

#ifndef _XTAL_FREQ
 // Unless specified elsewhere, 4MHz system frequency is assumed
 #define _XTAL_FREQ 4000000
#endif

#include    <htc.h>
#include    "lcd.h"</htc.h>

#define    LCD_RS RA1
#define    LCD_RW RA2
#define LCD_EN RA3

#define LCD_DATA    PORTB

#define    LCD_STROBE()    ((LCD_EN = 1),(LCD_EN=0))

/* write a byte to the LCD in 4 bit mode */

void
lcd_write(unsigned char c)
{
 __delay_us(40);
 LCD_DATA = ( ( c >> 4 ) & 0x0F );
 LCD_STROBE();
 LCD_DATA = ( c & 0x0F );
 LCD_STROBE();
}

/*
 *     Clear and home the LCD
 */

void
lcd_clear(void)
{
 LCD_RS = 0;
 lcd_write(0x1);
 __delay_ms(2);
}

/* write a string of chars to the LCD */

void
lcd_puts(const char * s)
{
 LCD_RS = 1;    // write characters
 while(*s)
 lcd_write(*s++);
}

/* write one character to the LCD */

void
lcd_putch(char c)
{
 LCD_RS = 1;    // write characters
 lcd_write( c );
}

/*
 * Go to the specified position
 */

void
lcd_goto(unsigned char pos)
{
 LCD_RS = 0;
 lcd_write(0x80+pos);
}

/* initialise the LCD - put into 4 bit mode */
void
lcd_init()
{
 char init_value;

 CMCON  = 0x07;    // Disable analog pins on PORTA

 init_value = 0x3;
 TRISA=0;
 TRISB=0;
 LCD_RS = 0;
 LCD_EN = 0;
 LCD_RW = 0;

 __delay_ms(15);    // wait 15mSec after power applied,
 LCD_DATA     = init_value;
 LCD_STROBE();
 __delay_ms(5);
 LCD_STROBE();
 __delay_us(200);
 LCD_STROBE();
 __delay_us(200);
 LCD_DATA = 2;    // Four bit mode
 LCD_STROBE();

 lcd_write(0x28); // Set interface length
 lcd_write(0xF); // Display On, Cursor On, Cursor Blink
 lcd_clear();    // Clear screen
 lcd_write(0x6); // Set entry Mode
}

и файл lcd.h


/*
 *    LCD interface header file
 *    See lcd.c for more info
 */

/* write a byte to the LCD in 4 bit mode */

extern void lcd_write(unsigned char);

/* Clear and home the LCD */

extern void lcd_clear(void);

/* write a string of characters to the LCD */

extern void lcd_puts(const char * s);

/* Go to the specified position */

extern void lcd_goto(unsigned char pos);

/* intialize the LCD - call before anything else */

extern void lcd_init(void);

extern void lcd_putch(char);

/*    Set the cursor position */

#define    lcd_cursor(x)    lcd_write(((x)&0x7F)|0x80)

Ну и, наконец, тестовая программа


#include <htc.h>
#include "lcd.h"
#define _XTAL_FREQ 4000000</htc.h>

__CONFIG(WDTDIS & UNPROTECT & MCLREN & LVPDIS & HS);

void main() {
lcd_init();
 lcd_goto(0);    // select first line
 lcd_puts("PIC manual");
 lcd_goto(0x40);    // Select second line
 lcd_puts("SARGE.PP.UA");

 for(;;);

}

Результат:

Исходники здесь

UPD: Новую версию кода, адаптированную под любой пин порта можно посмотреть здесь.

PIC мк. Эксперимент №6. Подключение LCD дисплея.: 94 комментария

  1. Уважаемый sarge
    Материалы Ваших статей использую для освоения C, многое уже проянилось, за что Вам большое спасибо! В целом разобрался с работой LCD-панели – в Proteus и на макетке все работает! Но появились вопросы.
    1. Помогите разобраться с работой функции lcd_puts(const char * s), она у Вас выводит в LCD строку прямо из PIC. И действительно выводит! А по описанию дисплея (использую MT-16S2R), как я понял, можно отправлять лишь адреса символов по внутренней кодовой таблице. Написал код на ASM-е – все работает, но это же неудобно. А тут сразу выводится строка. Пожалуйста, поясните как понимать выражение с параметрами функции, в частности, фрагмент “*s” (т.е. как это все работает)? В т.ч. и цикл while(*s), ведь в скобках д.б. условие?
    2. Большую помощь в понимании процессов оказывает режим пошаговой отладки. Но вот с чем я никак не могу справиться. Содержимое регистров PIC прекрасно отображается в окне Watch. А вот значения глобальных и локальных переменных посмотреть никак не удается. В окне Watch они не отображаются (и не должны). Есть окно Locals (полагаю, как раз для этих целей), но оно пустое. И добавить в него информацию никак не получается. В контекстном меню окна почти все опции “серые”, кроме Properties. Все листинги брал с Вашего сайта “Эксперимент №6”, но и в других проектах все аналогично. Подумал, у меня MPLAB “кривая” (v8.85.00), но и в Proteus окно PIC CPU Variables также пустое и ничего в него не вводится.
    Прошу извинить, если вопросы “детские”, но я полный новичок в C, пока в стадии обучения.

    • 1. Для отправки символа используется функция lcd_write(c), которая как раз таки также расположена внутри lcd_puts(), отправляющей всю строку.
      *s – читайте про работу с указателями в C, while(*s) пока не закончится вся строка, выдираем по одному символу.

      2. Показывайте пример конкретный, кидайте архив на мыло мне (sargein@gmail.com) и попробуем разобраться. Но предупреждаю, мплаба у меня сейчас даже нету, поэтому под протеус давайте все.

      • Большое спасибо за ответ. Указатели… Читал про это, но на практике не признал. Звезду пытался интерпретировать, как умножение. Теперь идея начинает проясняться в деталях, но надо еще поработать.
        К вопросу 2 – Проект отправил Вам на почту, там все вместе: и Proteus, и MPLAB. Собственно, это код из текущего Эксперимента, немного измененный под PIC16F873A. Зачем такой большой PIC? Во-первых, я уже убедился: на шину данных нужно вешать порт целиком. Иначе можно долго ошибки выкорчевывать. А к порту B планировал на перспективу подключить кнопки для переключения режимов. Так вот, в файле lcd.c собраны функции проекта. К примеру, я хочу наблюдать значение параметра “с” в теле функции lcd_write, либо текущее значение указателя “*s” в lcd_puts, либо значение переменной “init_value” в lcd_init(). Судя по документации, окно PIC CPU Variables как раз для этого и должно служить. Но не получается.

  2. Уведомление: Pic Lab, PIC16, Experiment #6, LCD display | diymicro.org

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.