Вот пример, который работает с как угодно разбросанными по любым портам линиями LCD:
Код: Выделить всё
//----------------------------------------------------------------------------
//модуль поддержки LCD 2x16
//----------------------------------------------------------------------------
#include <Main.h>
#include <Lcd.h>
//----------------- Используемые модулем аппаратные ресурсы: -----------------
//Модуль LCD используется в 4-битном режиме.
//Чтение данных из модля не используется, сигнал W заземлен.
//Управляющие сигналы: LCD_E, LCD_RS, LCD_D4, LCD_D5, LCD_D6, LCD_D7.
//Для включения подсветки используется порт BKL, активный уровень - высокий.
//Используется функция Delay_ms и макрос Delay_us.
//---------------- Таблица пользовательских символов LCD: --------------------
__flash char UsrChr[]= { 0x0C,0x12,0x12,0x0C,0x00,0x00,0x00,0x00, //° (0x00)
0x04,0x04,0x1F,0x04,0x04,0x00,0x1F,0x00, //± (0x01)
0x10,0x10,0x10,0x1E,0x11,0x11,0x1E,0x00, //Ь (0x02)
0x15,0x11,0x13,0x15,0x19,0x11,0x11,0x00, //Й (0x03)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // (0x04)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // (0x05)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // (0x06)
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; // (0x07)
//----------------- Таблица перекодировки русских букв: ----------------------
__flash char CharsR[]= { 0x41,0xA0,0x42,0xA1,0xE0,0x45,0xA3,0xA4,
0xA5,0x03,0x4B,0xA7,0x4D,0x48,0x4F,0xA8,
0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB,
0xAC,0xE2,0xAD,0xAE,0x02,0xAF,0xB0,0xB1,
0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7,
0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,0xBE,
0x70,0x63,0xBF,0x79,0xE4,0x78,0xE5,0xC0,
0xC1,0xE6,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7 };
//----------------------------------------------------------------------------
void LCD_Wr(char d); //запись байта в LCD
void LCD_Wr4(char d); //запись ниббла в LCD
void LCD_WrCmd(char d); //запись команды в LCD
void LCD_WrData(char d); //запись данных LCD
void LCD_UsrChr(void); //загрузка символов пользователя
//-------------------------- Инициализация LCD: ------------------------------
void LCD_Init(void)
{
Delay_ms(15);
LCD_WrCmd(0x30);
Delay_ms(5); //delay >4.1 mS
LCD_WrCmd(0x30);
Delay_us(100); //delay >100 uS
LCD_WrCmd(0x30);
Delay_ms(5); //delay >4.1 mS
LCD_WrCmd(0x20); //FUNCTION SET (8 bit)
Delay_ms(15);
LCD_WrCmd(0x28); //FUNCTION SET (4 bit)
Delay_ms(15);
LCD_WrCmd(0x0C); //DISPLAY ON
Delay_ms(15);
LCD_WrCmd(0x06); //ENTRY MODE SET
Delay_ms(15);
LCD_Clear(); //CLEAR
Delay_ms(15);
LCD_UsrChr(); //загрузка символов пользователя
}
//------------------------- Загрузка LCD CGRAM: ------------------------------
//UsrChr - таблица символов: 8 байт на символ x 8 символов
//Матрица точек 5x8: BYTE1 D4 D3 D2 D1 D0
// BYTE2 D4 D3 D2 D1 D0
// ...
// BYTE8 D4 D3 D2 D1 D0
void LCD_UsrChr(void)
{
LCD_WrCmd(0x40); //установка нулевого адреса CGRAM
for(char i = 0; i < 64; i++)
LCD_WrData(UsrChr[i]); //загрузка CGRAM
}
//----------------------------- Очистка LCD: ---------------------------------
void LCD_Clear(void)
{
LCD_WrCmd(0x01); //DISPLAY CLEAR
Delay_ms(5); //delay >1.64mS
}
//------------------- Включение/выключение подсветки LCD: --------------------
void LCD_Backlight(bool on)
{
if(on) Port_BKL_1;
else Port_BKL_0;
}
//------------------------- Запись команды в LCD: ----------------------------
void LCD_WrCmd(char d)
{
Port_LCD_RS_0; //RS <- 0
LCD_Wr(d); //write byte to LCD
}
//------------------------- Запись данных в LCD: -----------------------------
void LCD_WrData(char d)
{
Port_LCD_RS_1; //RS <- 1
LCD_Wr(d); //write byte to LCD
}
//------------------------- Запись байта в LCD: ------------------------------
void LCD_Wr(char d)
{
LCD_Wr4(d);
Delay_us(10);
LCD_Wr4(__swap_nibbles(d));
Delay_us(50);
}
//------------------------ Запись ниббла в LCD: ------------------------------
void LCD_Wr4(char d)
{
(d & 0x10)? Port_LCD_D4_1 : Port_LCD_D4_0;
(d & 0x20)? Port_LCD_D5_1 : Port_LCD_D5_0;
(d & 0x40)? Port_LCD_D6_1 : Port_LCD_D6_0;
(d & 0x80)? Port_LCD_D7_1 : Port_LCD_D7_0;
Port_LCD_E_1; //E <- 1
Delay_us(2); //delay 2 uS
Port_LCD_E_0; //E <- 0
}
//------------------------ Установка позиции на LCD: -------------------------
//line = 1..2
//pos = 1..16
void LCD_Pos(char line, char pos)
{
pos = pos - 1;
pos = pos | 0x80;
if(line > 1)
pos = pos | 0x40;
LCD_WrCmd(pos);
}
//----------------------------------------------------------------------------
void LCD_CurOff(void)
{
LCD_WrCmd(0x0C);
}
//----------------------------------------------------------------------------
void LCD_CurOn(void)
{
LCD_WrCmd(0x0E); //0x01 - мигание знакоместа, 0x02 - курсор on
}
//------------------------- Cдвиг курсора влево: -----------------------------
void LCD_CurLeft(void)
{
LCD_WrCmd(0x10);
}
//------------------------- Вывод символа на LCD: ----------------------------
void LCD_Char(char ch)
{
if(ch == 0x10) { LCD_Clear(); return; } //ch = 0x10 - LCD clear
if(ch == 0x0D) { LCD_Pos(2, 1); return; } //ch = 0x0D - перевод строки
if(ch == '°') {LCD_WrData(0x00); return; } //ch = '°'
else if(ch < 0xC0) LCD_WrData(ch); //ch < 0xC0 - english
else { ch -= 0xC0; LCD_WrData(CharsR[ch]); } //ch >= 0xC0 - russian
}
//------------------ Вывод null-terminated string на LCD: --------------------
void LCD_Str(char __flash *s)
{
char __flash *i;
for(i = s; *i; i++)
LCD_Char(*i);
}
//---------------------- Вывод текста меню на LCD: -------------------------
void LCD_Menu(char __flash *s)
{
char __flash *i;
LCD_Clear(); //очистка дисплея
LCD_Pos(1, 1); //установка позиции
for(i = s; *i; i++)
{
if(i == s + 16)
LCD_Pos(2, 1);
LCD_Char(*i); //вывод 16-ти символов
}
}
//---------------- Вывод беззнакового числа 0..9999 на LCD: ------------------
void LCD_UInt9999(int n)
{
char d, ch = ' ';
d = n / 1000;
if(d)
ch = d + 0x30;
LCD_Char(ch);
n = n % 1000;
d = n / 100;
if(ch != ' ' || d)
ch = d + 0x30;
LCD_Char(ch);
n = n % 100;
d = n / 10;
if(ch != ' ' || d)
ch = d + 0x30;
LCD_Char(ch);
n = n % 10;
LCD_Char(n + 0x30);
}
//----------------------------------------------------------------------------
main.h:
#define LCD_D5 (1 << PC2) //OX - линия данных LCD D5
#define LCD_D4 (1 << PC3) //OX - линия данных LCD D4
#define LCD_D7 (1 << PC4) //OX - линия данных LCD D7
#define LCD_D6 (1 << PC5) //OX - линия данных LCD D6
#define Port_LCD_D7_0 (PORTC &= ~LCD_D7)
#define Port_LCD_D7_1 (PORTC |= LCD_D7)
#define Port_LCD_D6_0 (PORTC &= ~LCD_D6)
#define Port_LCD_D6_1 (PORTC |= LCD_D6)
#define Port_LCD_D5_0 (PORTC &= ~LCD_D5)
#define Port_LCD_D5_1 (PORTC |= LCD_D5)
#define Port_LCD_D4_0 (PORTC &= ~LCD_D4)
#define Port_LCD_D4_1 (PORTC |= LCD_D4)
#define LCD_E (1 << PD0) //OL - линия E LCD
#define LCD_RS (1 << PD1) //OL - линия RS LCD
#define Port_LCD_E_0 (PORTD &= ~LCD_E)
#define Port_LCD_E_1 (PORTD |= LCD_E)
#define Port_LCD_RS_0 (PORTD &= ~LCD_RS)
#define Port_LCD_RS_1 (PORTD |= LCD_RS)