[pic16f88] Этап 9. Подключение ЖКИ через сдвиговый регистр

Основные приёмы работы с ЖКИ WH1602A-YGH-CTK были рассмотрены на четвёртом этапе. Теперь просто заменим МК на pic16f88.

Информация
Процесс компиляции такой же, как на 8 этапе. Даташит на дисплей можно найти в описании 4 этапа.

Радиокомпоненты и приборы
- микроконтроллер pic16f88
- регистр сдвига 74HC595
- символьный жидкокристаллический индикатор Winstar WH1602A-YGH-CTK (1602H REV.0)
- источник стабилизированного питания напряжением +5 В

Электрическая принципиальная схема
Исходный код прошивки на языке C
Файл pic.c, компилятор SDCC

#include <pic16f88.h>

__code char __at _CONFIG1 conf1 = _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO;
__code char __at _CONFIG2 conf2 = _IESO_OFF & _FCMEN_OFF;

#define RS_SHCP RA1 //Сдвоенные сигналы: тактовый и тип данных
#define DS RA6
#define E_STCP RA0 //Сдвоенные сигналы: стробирующий и защёлка

void __delay_us(unsigned char t){
while(t--){
__asm
NOP
NOP
NOP
NOP
NOP
__endasm;
}
}

void __delay_ms(unsigned char m){
while(m--){
__delay_us(1000);
}
}

void lcd_write(unsigned char c, unsigned char sig_rs){
int i;
E_STCP = 0; //Здесь Е нас не интересует, может быть любым
for(i=7;i>=0;i--){
DS = (c >> i) & 1;
RS_SHCP = 0; //Здесь важна SHCP, RS может быть любым
RS_SHCP = 1; //-//-
}
E_STCP = 1; //Защёлкнули данные и выставили высокий уровень стробирующего сигнала. Интересуют оба.
RS_SHCP = sig_rs; //Теперь можем пренебрегать SH. Выставили нужный уровень сигнала RS
__delay_us(200); //Теперь имеем сигналы DS (DB7-DB0), для создания которых отработали SH и ST, и сигнал RS
E_STCP = 0; //Начинаем выполнять операцию записи в ЖКИ, STCP не интересует
/*
До тех пор, пока мы снова не защёлкнем данные, на выходах регистра байт не изменится.
Мы можем делать всё, что угодно, но на ножках будет стабильный сигнал.
Операция записи в ЖКИ начинается только при спадающем фронте, поэтому с Е тоже можем
делать всё, что угодно, пока она не была переведена в единицу и затем в ноль.
Все сигналы надо успеть установить до Е = 0, но SH мы можем играться только после
защёлкивания данных. Поэтому в функции представлен единственно верный порядок операций
*/
}

void print_str(unsigned char *c){
unsigned char k;
while (k=*c++) {
lcd_write(k, 1);
}
}

void lcd_init(){
__delay_ms(15);

lcd_write(0b00111100, 0); //Шина 8 бит, 2 строки, 5х8 точек - Function Set
__delay_ms(40);

lcd_write(0b00000001, 0); //Очистка экрана - Clear Display
__delay_ms(2);

lcd_write(0b00000110, 0); //Инкремент - Entry Mode Set
__delay_ms(40);

lcd_write(0b00001100, 0); //Включили дисплей и курсор, мигание курсора отключили - Display ON/OFF Control
__delay_ms(40);

lcd_write(0b10000000, 0); //Очистили дисплей - Set DDRAM Address
__delay_ms(2);
}

main(){
OSCTUNE = 0b00000000; // Калиброванная частота
OSCCON = 0b01100100; // 4MHz
CCP1CON = 0b00000000; // Отключить модуль CCP
ANSEL = 0b00000000; // AN6:AN0 работают как цифровые I/O
ADCON1 = 0b00000000; // Отключить АЦП
CMCON = 0b00000111; // Отключить компаратор
TRISA = 0b00000000; // PORTA все как output
PORTA = 0b00000000; // Очистка PORTA (RA5:RA0)

lcd_init();

lcd_write(0b01000011, 1); //С
lcd_write(0b01100001, 1); //а
lcd_write(0b10111001, 1); //й
lcd_write(0b10111111, 1); //т
lcd_write(0b00111010, 1); //:
lcd_write(0b00100000, 1); //
print_str("RxLab.Org");
lcd_write(0b11000000, 0); //Перевести каретку на вторую строку (на первую: 0b10000000)
lcd_write('0', 1); //0
lcd_write('1', 1); //1
lcd_write('2', 1); //2
lcd_write('3', 1); //3
lcd_write('4', 1); //4
lcd_write('5', 1); //5
lcd_write('6', 1); //6
lcd_write('7', 1); //7
lcd_write('8', 1); //8
lcd_write('9', 1); //9
lcd_write('A', 1); //A
lcd_write('B', 1); //B
lcd_write('C', 1); //C
lcd_write('D', 1); //D
lcd_write('E', 1); //E
lcd_write('F', 1); //F

while(1){
__asm
NOP
__endasm;
}
}

Примечания
В примере исходного кода прошивки продемонстрированы все рассмотренные ранее способы отправки символов на дисплей, а также показана команда перевода каретки на другую строку.
2013-12-05