Рабочий проект
Рабочий проект включает в себя программирование устройства и физическое тестирование.
Реализация и программирование
Разработка программного кода, его компиляция и процесс отладки проекта был выполнен в программном продукте компании Microchip, MPLAB IDE. Эта среда разработки предоставляет единую среду для разработки кода, отладки и прошивки для всех типов микроконтроллеров фирмы Microchip. Она позволяет использовать в одном проекте как код, написанный на языке низко уровня (ассемблер), так и код, написанный на языке высокого уровня (С). Это позволяет разработчику добиться желаемого соотношения между скорость работы программы и легкость ее разработки [9,12].
При запуске Mplab появиться 2 внутренних окна: Untitled Workspace и Output. В окне Workspace отображаются все файлы, прикрепленные в проект. А в окне Output выводится вся выходная информация Mplab: ошибки, результаты компиляции, результаты программирования микроконтроллера, результаты поиска в проекте и т.п. Для удобства, располагаем их в таком виде:
Рисунок 5.1 – Интерфейс главного окна среды Mplab
Для создания проекта воспользуемся мастером Project > Project Wizard. Переходим по кнопке «Далее». Появляется окно, в котором мы выбираем из выпадающего списка нужный нам микроконтроллер, в нашем случае: PIC18F4520. Снова нажимаем кнопку «Далее». Следующим, появится окно, в котором мы выбираем язык программирования, на котором будем писать программу к нашему микроконтроллеру. Окно выглядит следующим образом:
Рисунок 5.2 – Интерфейс окна помощника создания проекта.
В поле «Active Toolsuite» выбирается язык программирования, на рисунке выбран язык си для микроконтроллеров PIC – Microchip C18 Toolsuit. В поле «Toolsuite Contents» показаны исполняемые модули, которые принимают участие в компиляции программы с выбранного языка. В поле «Location» указывается полный путь к выделенному исполняемому модулю. Если путь будет неверен (перед исполняемым модулем будет стоять крестик), то его нужно прописать вручную, с использованием кнопки «Browse».
Обычно, для ассемблера микроконтроллеров серии PIC18, это путь: С:\Program Files\Microchip\MPASM Suite\. Для сборщика проекта: C:\mcc18\bin\mplink.exe, для подключения библиотек: C:\mcc18\bin\mplib.exe. Так как для создания проекта выбран язык СИ, то используем, специальный компилятор MCC18, который устанавливается отдельно от среды: C:\mcc18\bin\mcc18.exe. После того, как все исполняемые модули задействованы, нажимаем кнопку «Далее».
Мы перейдем на окно, где задается имя проекта и путь к нему. Вводим любое имя (нельзя использовать русские буквы) и выбираем путь к этому проекту.
В итоге, появится окно, в котором Wizard выдаст конечную информацию о настройках и параметрах создаваемого проекта: тип микроконтроллера; путь, по которому будет лежать проект и основной язык компилятора, на котором будет писаться программа в этом проекте. Нажимаем кнопку «Готово». В окне Workspace стал отображаться наш проект (появилось дерево файлов проекта). Если у Вас пропало окно Output, то его нужно включить через пункт меню: View > Output. А в папке появились файлы проекта *.mcw и *.mcp. Для создания файла с кодом программы запускаем пункт меню: File > New (Ctrl+N). У нас появится новое окно в проекте – MPLAB IDE Editor.
Теперь сохраняем полученный файл. Переходим по пункту меню: File > Save. Появляется стандартное окно сохранения файла. Выбираем папку, пишем имя и расширение. Теперь, добавляем созданный файл в проект. Для этого, в окне проекта Workspace (теперь это окно будет называться *.mcw), находим в дереве файлов папку Source Files (файлы с исходной программой). Кликаем правой кнопкой мыши на этой папке и выбираем пункт Add Files… .Появится окно, в котором мы выбираем нашу папку и наш файл. Выбираем этот файл и нажимаем кнопку «Открыть». Мы увидим, что наш файл появился в дереве файлов проекта. Теперь сохраняем проект.
Компилируем полученную программу [12]. Переходим на пункт меню Project > Build All(Ctrl+F10). Что проект скомпилировался без ошибок, говорит окно Output. В нем будет вот такая запись: BUILD SUCCEEDED. И в нашей папке появится загрузочный файл *.hex, который зашивается в микроконтроллер программатором. Если в процессе компиляции возникли ошибки, то в этом окне они все отобразятся. И будет вот такая запись: BUILD FAILED. Двойной клик мышкой на записи об ошибке в окне Output, автоматически указывает на строку в программе, где находится данная ошибка. После того как код был успешно скомпилирован, необходимо выполнить прошивку устройства. Для этого необходимо выбрать тип программатора. Мы использовали программатор Microchip MPLAB ICD 2.
Рисунок 5.3 – Дебаггер MPLAB-ICD2 и демо-плата PICDEM 2 Plus
Для этого, чтобы указать этот тип программатора необходимо выбрать пункт меню Programmer -> Select Programmer -> MPLAB ICD 2. После это в окне программы MPLAB ICD 2 будет отображен ход подключения программатора. Если программатор подключен к компьютеру (для коммуникации используется интерфейс USB), включено питание на плате и выбраны правильные настройки, то появиться сообщение об успешном подключении программатора.
После этого станут активными кнопки управления программатором (Запрограммировать устройство, Проверить состояние устройства и другие). Теперь необходимо нажать кнопку «Запрограммировать устройство». Если код не содержит ошибок, то появиться сообщение об успешной прошивке устройства. Нажав кнопку «Снять со сброса», мы начинаем непосредственное выполнение программы на реальном устройстве.
Физическое тестирование
После выполнения всех вышеописанных действий, необходимо проверить соответствие полученного результата поставленной задаче[1,2].
В первую очередь проверим работоспособность алгоритмы работы с АЦП и LCD дисплеем. На экране периодически отображаются данные, считанные с АЦП:
Рисунок 5.4 – Результаты работы устройства
Полученные данные соответствует поставленной задаче, периодически отображать результаты измерений напряжения на контактах потенциометра.
Для проверки работоспособности вольтметра проведем эксперимент: сравним его показатели с другим устройством, предназначенным для измерения напряжения. Тест показал соответствие напряжения, показанной тестером и данными с АЦП микроконтроллера. Также проверим работоспособность АЦП и потенциометра изменив положение потенциометра, последствия наших действий сразу отображаются на LCD. Граничные значения от 0В до 5В.
Для проверки звуко-излучателя достаточно запустить его из меню, сразу излучается звук. Если нажимать кнопки управления то звук меняет тональность. Аппарат работает адекватно т.к. в момент когда длительность импульсов становится равной или больше длительности задержки между импульсами звук исчезает.
Для проверки работоспособности термометра проведем два эксперимента: сравним его показатели с другим устройством, предназначенным для измерения температуры, и изменим температуру окружающей среды. Первый тест показал соответствие температуры, показанной ртутным термометром и датчиками микроконтроллера. После этого было произведено термическое воздействие (нагревание) на датчик. Через небольшой промежуток времени показатели этого датчика возросли, а после прекращения воздействий вернулись на прежние показатели, что подтверждает работоспособность термодатчика.
Для проверки работоспособности часов необходимо оставить их включёнными на довольно длительный период, после чего сравнить результаты обычных часов и часов реализованных на PICDEM 2. Проведённый эксперимент показал что за 10 часов часы сбились на 1 секунду. Что есть приемлемым результатом.
ВЫВОДЫ
В результате выполнения комплексного курсового проекта был описан процесс создания и программно реализованы устройства измерения напряжения, температуры, генерирования звуков и реализация часов на микроконтроллере PIC.
Полученные результаты показывают, что программа работоспособна и готова к использованию на микроконтроллере PIC18F4520.
Также к недостатком устройства можно отнести то, что само устройство работает при наличии постоянного питания. Это значительно ограничивает область применения усройства.
Данный курсовой проект можно разрабатывать дальше, реализовав передачу информации в компьютер по последовательному интерфейсу RS-232. При этом необходимо будет использовать дополнительное программное обеспечение и это значительно усложнит весь проект.
ПЕРЕЧЕНЬ ССЫЛОК
1. Методические указания к лабораторным работам по курсу “Микроконтроллеры во встроенных системах управления для студентов всех специальностей / Составители Аврунин О.Г., Крук О.Я., Семенец В.В. – ХНУРЭ, 2005. – 105 с.
2. В. А. Гулиус, В. Г. Лобода, В. П. Степанов, В. Ю. Цуканов. “Средства автоматизированного проектирования специализированных микропроцессорных устройств”: Учебное пособие – Харьков: ХНУРЭ, 2001. – 228 с.
3. Белова Н. В., Коряк С. Ф., Лобода В. Г.. “Основы построения ориентированных ЭВМ и систем”. Под общ. ред. В. Г. Лободы. – Харьков: ООО «Компания СМИТ», 2007. – 148 с.
4. Проектирование встроенных устройств на микропроцессорах: Учеб. пособие /В. Г. Лобода, В. В. Логвин, В. Б. Таранов. – К.: УМК ВО, 1988. – 128 с.
5. Методические указания к комплексному курсовому проекту / Составители: В.Г. Лобода, А.С. Шкиль, Л.К. Штец.- Харков, ХНУРЭ,2001. – 8с.
6. Документация на демонстрационную плату PICDEM 2 Plus Users Guide 51275c.pdf
7. Руководство пользователя MPASM & MPLINK 33014g
8. MPASM Quick Reference Guide 30400f
9. Руководство пользователя MPASM
10. Документация на семейство микроконтроллеров PIC18FXX2 manual
11. Руководство пользователя PICDEM 2 Plus Demonstration Board
12. Руководство пользователя MPLAB C18
13. Библиотеки MPLAB C18
ПРИЛОЖЕНИЕ А. Программа реализации устройств
p18main.c
#include <p18f4520.h>
#include <delays.h>
#include <stdlib.h>
#pragma config OSC = HS //oscillator
#pragma config FCMEN = OFF //Fail Safe Clock Monitor
#pragma config IESO = OFF //Internal External Osc. Switch Over
#pragma config PWRT = ON //Power Up Timer
#pragma config BOREN = OFF //Brown Out Reset
#pragma config WDT = OFF //Watchdog Postscaler
#pragma config MCLRE = ON //Vhod sbrosa mikrokontrollera
#pragma config PBADEN = OFF //Port B A/D digital on Reset
#pragma config LVP = OFF /Lov Voltage ICSP
#pragma config XINST = OFF //xinst
#define scroll_dir TRISAbits.TRISA4
#define scroll PORTAbits.RA4
#define select_dir TRISBbits.TRISB0
#define select PORTBbits.RB0
extern near void LCDInit(void);
extern unsigned temp_wr;
extern near void d_write(void);
extern near void i_write(void);
extern near void LCDLine_1(void);
extern near void LCDLine_2(void);
extern unsigned char WREG;
unsigned char ptr_pos;
unsigned char ptr_count;
unsigned char cmd_byte;
unsigned char temperature;
unsigned char seconds ;
unsigned char minutes ;
unsigned char hours ;
int temph;
char tempv_char[3],temph_char[16]={"0.00V RB0=Exit "},
tempb_char[16]={"Prd.=128 DC=128 "},tempt_char[16]={"Temp= C "},
tempc_char[16]={" 00:00:00 "};
char zero[1]={"0"};
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
rom const char stan_table[15][16]={
" Voltmeter ", //;0
" Buzzer ", //;1
" Temperature ", //;2
" Clock ", //;3
"RA4=Next RB0=Now", //;4
" Dimasya ", //;5
" tut koviryal ", //;6
"RA4=Set RB0=Menu", //;7
"RBO=Prd+ RA4=DC+", //;8
" RB0 = Exit ", //;9
" Volts = ", //;10
"Prd.=128 DC=128 ",//;11
"Minutes RB0=++",//12
"Hours RB0=++",//13
"again? RB0=Exit"};//14
//functions define
void ssprw (void);
void start (void);
void main (void);
void menu(void);
void voltmeter(void);
void buzzer(void);
void temp(void);
void clock(void);
void clock_set(void);
void clock_draw(void);
void stan_char_1(void);
void stan_char_2(void);
//functions work
void ssprw (void)
{
do {
_asm movlw 0x00 _endasm
WREG=WREG&&SSPCON2;
_asm sublw 0x00 _endasm
} while (STATUSbits.Z==0);
while (SSPSTATbits.R_W==1) {};
}
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
void start (void)
{
LCDInit();
TXSTA=0b10100100; //initialize USART
SPBRG=25;
RCSTA=0b10010000;
TRISCbits.TRISC2=0; //CCP
PR2=0x80;
CCPR1L=0x80;
CCP1CONbits.CCP1X=0;
CCP1CONbits.CCP1Y=0;
T2CON=0x05;
TRISAbits.TRISA4=1;
TRISBbits.TRISB0=1;
}
void main(void)
{
temp_wr=0;
ptr_count=16;
start();
menu();
}
void menu(void)
{
ptr_count=16;
ptr_pos=5;
stan_char_1();
ptr_pos=6;
stan_char_2();
Delay10KTCYx(900);
while (scroll==0){};
while (select==0){};
//------------------ VOLT MEASUREMENT ----------------------------
while(1){
ptr_pos=0;
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
stan_char_1();
ptr_pos=4;
stan_char_2();
while (scroll==1) {if (select==0) {voltmeter();break;}} ;
while (select==0){};while (scroll==0){};
//------------------ BUZZER --------------------------------------
while (select==0){};
ptr_pos=1;
stan_char_1();
ptr_pos=4;
stan_char_2();
while (scroll==1) {if (select==0) {buzzer();break;} } ;
while (select==0){};while (scroll==0){};
//----------------- TEMPERATURE MEASUREMENT ----------------------
while (select==0){};
ptr_pos=2;
stan_char_1();
ptr_pos=4;
stan_char_2();
while (scroll==1) {if (select==0) {temp();break;} };
while (select==0){};while (scroll==0){};
//------------------ CLOCK TIME ----------------------------------
while (select==0){};
ptr_pos=3;
stan_char_1();
ptr_pos=4;
stan_char_2();
while (scroll==1) {if (select==0) {clock();break;}};
while (select==0){};while (scroll==0){};
};
}
//************* STANDARD USER CODE **********************************
//------------- Voltmeter--------------------------------------------
void voltmeter(void)
{
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
int i;
char temp_char;
while(select==0){};
ADCON0bits.ADON=1;
ADCON1=0b00001110;
ADCON2=0x01;
ptr_pos=10;
stan_char_1();
do{
ADCON0bits.GO=1;
while (ADCON0bits.GO==0){};
temph=ADRESH;
temph*=2;
itoa(temph,tempv_char);
if (temph<10) {temph_char[0]=zero[0];temph_char[2]=zero[0];temph_char[3]=tempv_char[0];}
else if (temph<100) {temph_char[0]=zero[0];temph_char[2]=tempv_char[0];temph_char[3]=tempv_char[1];} //10<=x<100
else {temph_char[0]=tempv_char[0];temph_char[2]=tempv_char[1];temph_char[3]=tempv_char[2];} //10<=x<100
LCDLine_2();
for (i=0;i<ptr_count;i++)
{
temp_char=temph_char[i];
temp_wr=temp_char;
d_write();
} //for i
}while(select==1);
}
//--------------------- BUZZER --------------------------------------
void buzzer(void)
{
char temp_char;
int n,i;
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
while(select==0){};
PR2=0x80;
CCPR1L=0x80;
LCDLine_1();
ptr_pos=11;
stan_char_1();
LCDLine_2();
ptr_pos=8;
stan_char_2();
CCP1CON=0x0f;
while(1){
n=0;
if (select==0)
{
PR2+=1;
n=5;
temph=PR2;
if (scroll==0)
goto end;
} //if select
if (scroll==0)
{//inc dc
CCPR1L+=1;
temph=CCPR1L;
n=12;
if (select==0)
goto end;
}
if (n!=0) {
itoa(temph,tempv_char);
if (temph<10) {tempb_char[n]=zero[0];tempb_char[n+1]=zero[0];tempb_char[n+2]=tempv_char[0];}
else if (temph<100) {tempb_char[n]=zero[0];tempb_char[n+1]=tempv_char[0];tempb_char[n+2]=tempv_char[1];} //10<=x<100
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
else {tempb_char[n]=tempv_char[0];tempb_char[n+1]=tempv_char[1];tempb_char[n+2]=tempv_char[2];} //10<=x<100
LCDLine_1();
for (i=0;i<ptr_count;i++)
{
temp_char=tempb_char[i];
temp_wr=temp_char;
d_write();
} //for i
} //if n!=0
};//while
end: CCP1CON=0;
}
//---------------------- Temperature --------------------------------
void temp (void)
{
char tempw,temp_char;
int i;
while (select==0){};
TRISCbits.TRISC3=1; //initialize MSSP module
TRISCbits.TRISC4=1;
SSPCON1=0b00101000;
SSPSTATbits.SMP=1;
SSPADD=0x05;
PIR1bits.TMR1IF=0; //load Timer1 for 2 sec overflow
TMR1H=0;
TMR1L=0;
do {
//GET_TEMP
get_temp: cmd_byte=0x01; //config register command byte
//TEMP_NOW
temp_now: SSPSTATbits.CKE=1; //SMBUS spec for TC74
SSPCON2bits.SEN=1; //write to TC74
while (SSPCON2bits.SEN==1){};
SSPBUF=0b10011010; //send TC74 ADDRESS (write)
ssprw();
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
while (SSPCON2bits.ACKSTAT==1) {}; //ack?
WREG=cmd_byte;
SSPBUF=WREG; //send COMMAND byte (config)
ssprw();
while (SSPCON2bits.ACKSTAT==1) {}; //ack?
SSPCON2bits.RSEN=1; //send repeated start
while (SSPCON2bits.RSEN==1) {};
SSPBUF=0b10011011; //send TC74 ADDRESS (read)
ssprw(); //module idle?
while (SSPCON2bits.ACKSTAT==1) {}; //ack?
SSPCON2bits.RCEN=1; //enable receive mode
while (SSPCON2bits.RCEN==1) {};
WREG=SSPBUF; //retrieve config reg or temp reg
SSPCON2bits.ACKDT=1; //send NOT-ACK
SSPCON2bits.ACKEN=1;
while (SSPCON2bits.ACKEN==1){};
SSPCON2bits.PEN=1; //stop
while(SSPCON2bits.PEN==1){};
tempw=WREG;
if (cmd_byte==1) { //config command OR temp command
WREG=tempw;
_asm
andlw 0x40 //is temp ready ??
sublw 0x40
_endasm
if (STATUSbits.Z==0) {goto get_temp;}
cmd_byte=0x00;
goto temp_now;
}
temperature=tempw;
itoa(temperature,tempv_char);
tempt_char[6]=tempv_char[0]; tempt_char[7]=tempv_char[1];
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
LCDLine_1();
for (i=0;i<ptr_count;i++)
{
temp_char=tempt_char[i];
temp_wr=temp_char;
d_write();
} //for i
LCDLine_2();
ptr_pos=9;
stan_char_2();
}while(select==1);
}
//----------------- CLOCK ------------------------------------------
void clock (void)
{
char temp_char;
int i,n;
while (select==0){};
T1CON=0x0F;
seconds=0;minutes=0;hours=0;
do {
PIR1bits.TMR1IF=0;
TMR1H=0x68;
TMR1L=0x00;
seconds++;
if (seconds-60==0) {
minutes++;
seconds=0;
}
if (minutes-60==0){
hours++;
minutes=0;
}
if (hours-13==0){
hours=0;
}
if (scroll==0) clock_set();
clock_draw();
LCDLine_2();
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
ptr_pos=7;
stan_char_2();
while (PIR1bits.TMR1IF==0){if (scroll==0) clock_set();};
} while (select==1);
}
void clock_set(void)
{
while (scroll==0){};
while (select==1) {
while (scroll==1) {
clock_draw();
LCDLine_2();
ptr_pos=12;
stan_char_2();
if (select==0) {minutes++;}
if (minutes-60==0){
hours++;
minutes=0;
} //if
if (hours-13==0){hours=0;}
} //while
while (scroll==0){};
while (scroll==1) {
clock_draw();
LCDLine_2();
ptr_pos=13;
stan_char_2();
if (select==0) {hours++;}
if (hours-13==0){hours=0;}
}
while (scroll==0){};
while (scroll==1) {
clock_draw();
LCDLine_2();
ptr_pos=14;
stan_char_2();
if (select==0)
{goto clock_set_end;}
}
ПРИЛОЖЕНИЕ А. Программа реализации устройств (продолжение)
}
clock_set_end: while (select==0){};
}
void clock_draw(void)
{
char temp_char;
int i,n;
temph=seconds;
n=10;
itoa(temph,tempv_char);
if (temph<10) {tempc_char[n]=zero[0]; tempc_char[n+1]=tempv_char[0];}
else {tempc_char[n]=tempv_char[0]; tempc_char[n+1]=tempv_char[1];}
temph=minutes;
n=7;
itoa(temph,tempv_char);
if (temph<10) {tempc_char[n]=zero[0]; tempc_char[n+1]=tempv_char[0];}
else {tempc_char[n]=tempv_char[0]; tempc_char[n+1]=tempv_char[1];}
temph=hours;
n=4;
itoa(temph,tempv_char);
if (temph<10) {tempc_char[n]=zero[0]; tempc_char[n+1]=tempv_char[0];}
else {tempc_char[n]=tempv_char[0]; tempc_char[n+1]=tempv_char[1];}
LCDLine_1();
for (i=0;i<ptr_count;i++)
{
temp_char=tempc_char[i];
temp_wr=temp_char;
d_write();
} //for i
}
void stan_char_1(void)
{
int i;
char temp_char;
ПРИЛОЖЕНИЕ А. Программа реализации устройств (окончание)
LCDLine_1();
for (i=0;i<ptr_count;i++)
{
temp_char=stan_table[ptr_pos][i];
temp_wr=temp_char;
d_write();
}
}
void stan_char_2(void)
{
int i;
char temp_char;
LCDLine_2();
for (i=0;i<ptr_count;i++)
{
temp_char=stan_table[ptr_pos][i];
temp_wr=temp_char;
d_write();
}
}
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций
p18lcd.asm
********************************************************************
;* Microchip Technology Inc. 2002 *
;* Revised on 5/6/03 - Removed Linker file declaration *
;* Assembler version: 2.0000 *
;* Filename: *
;* p18lcd.asm *
;********************************************************************
list p=18f442
#include p18f442.inc
#define LCD_D4 PORTD, 0; LCD data bits
#define LCD_D5 PORTD, 1
#define LCD_D6 PORTD, 2
#define LCD_D7 PORTD, 3
#define LCD_D4_DIR TRISD, 0 ; LCD data bits
#define LCD_D5_DIR TRISD, 1
#define LCD_D6_DIR TRISD, 2
#define LCD_D7_DIR TRISD, 3
#define LCD_E PORTA, 1; LCD E clock
#define LCD_RW PORTA, 2; LCD read/write line
#define LCD_RS PORTA, 3; LCD register select line
#define LCD_E_DIR TRISA, 1
#define LCD_RW_DIR TRISA, 2
#define LCD_RS_DIR TRISA, 3
#define LCD_INS 0
#define LCD_DATA 1
D_LCD_DATA UDATA
COUNTER res 1
delay res 1
temp_wr res 1
temp_rd res 1
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
GLOBAL temp_wr
PROG1 CODE
LCDLine_1
movlw 0x80
movwf temp_wr
rcall i_write
return
GLOBAL LCDLine_1
LCDLine_2
movlw 0xC0
movwf temp_wr
rcall i_write
return
GLOBAL LCDLine_2
;write data
d_write;
movff temp_wr,TXREG;
btfss TXSTA,TRMT;
goto $-2
rcall LCDBusy
bsf STATUS, C
rcall LCDWrite
return
GLOBAL d_write;
write instruction
i_write
rcall LCDBusy
bcf STATUS, C
rcall LCDWrite
return
GLOBAL i_write
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
rlcd macro MYREGISTER
IF MYREGISTER == 1
bsf STATUS, C
rcall LCDRead
ELSE
bcf STATUS, C
rcall LCDRead
ENDIF
endm
LCDInit
clrf PORTA
bcf LCD_E_DIR;configure control lines
bcf LCD_RW_DIR
bcf LCD_RS_DIR
movlw b'00001110'
movwf ADCON1
movlw 0xff; Wait ~15ms @ 20 MHz
movwf COUNTER
lil1
movlw 0xFF
movwf delay
rcall DelayXCycles
decfsz COUNTER,F
bra lil1
movlw b'00110000'; #1 Send control sequence
movwf temp_wr
bcf STATUS,C
rcall LCDWriteNibble
movlw 0xff; Wait ~4ms @ 20 MHz
movwf COUNTER
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
lil2
movlw 0xFF
movwf delay
rcall DelayXCycles
decfsz COUNTER,F
bra lil2
movlw b'00110000'; #2 Send control sequence
movwf temp_wr
bcf STATUS,C
rcall LCDWriteNibble
movlw 0xFF; Wait ~100us @ 20 MHz
movwf delay
rcall DelayXCycles
movlw b'0011000'; #3 Send control sequence
movwf temp_wr
bcf STATUS,C
rcall LCDWriteNibble
;test delay
movlw 0xFF; Wait ~100us @ 20 MHz
movwf delay
rcall DelayXCycles
movlw b'00100000'; #4 set 4-bit
movwf temp_wr
bcf STATUS,C
rcall LCDWriteNibble
rcall LCDBusy; Busy?
movlw b'00101000'; #5 Function set
movwf temp_wr
rcall i_write
movlw b'00001101'; #6 Display = ON
movwf temp_wr
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
rcall i_write
movlw b'00000001'; #7 Display Clear
movwf temp_wr
rcall i_write
movlw b'00000110'; #8 Entry Mode
movwf temp_wr
rcall i_write
movlw b'10000000'; DDRAM addresss 0000
movwf temp_wr
rcall i_write;
movlw b'00000010';
return home;
movwf temp_wr;
call i_write
return
GLOBAL LCDInit;
_ ______________________________;
RS _>--<______________________________;
_____;
RW \_____________________________;
__________________;
E ____________/ \___;
_____________ ______;
DB _____________>--------------<______;
LCDWriteNibble
btfss STATUS, C; Set the register select
bcf LCD_RS
btfsc STATUS, C
bsf LCD_RS
bcf LCD_RW; Set write mode
bcf LCD_D4_DIR; Set data bits to outputs
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
bcf LCD_D5_DIR
bcf LCD_D6_DIR
bcf LCD_D7_DIR
NOP; Small delay
NOP
bsf LCD_E; Setup to clock data
btfss temp_wr, 7; Set high nibble
bcf LCD_D7
btfsc temp_wr, 7
bsf LCD_D7
btfss temp_wr, 6
bcf LCD_D6
btfsc temp_wr, 6
bsf LCD_D6
btfss temp_wr, 5
bcf LCD_D5
btfsc temp_wr, 5
bsf LCD_D5
btfss temp_wr, 4
bcf LCD_D4
btfsc temp_wr, 4
bsf LCD_D4
NOP
NOP
bcf LCD_E; Send the data
return
LCDWrite;
rcall LCDBusy
rcall LCDWriteNibble
swapf temp_wr,F
rcall LCDWriteNibble
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
swapf temp_wr,F
return
GLOBAL LCDWrite;
_____ _____________________________________________________;
RS _____>--<_________________________________________________;
____________________________________________________;
RW _________/;
____________________ ____________________;
E ____________/ \____/ \__;
_________________ __________ ___;
DB _________________>--------------<__________>--------------<___;
LCDRead
bsf LCD_D4_DIR; Set data bits to inputs
bsf LCD_D5_DIR
bsf LCD_D6_DIR
bsf LCD_D7_DIR
btfss STATUS, C; Set the register select
bcf LCD_RS
btfsc STATUS, C
bsf LCD_RS
bsf LCD_RW; Read = 1
NOP
NOP
bsf LCD_E; Setup to clock data
NOP
NOP
NOP
NOP
btfss LCD_D7 ; Get high nibble
bcf temp_rd, 7
btfsc LCD_D7
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (продолжение)
bsf temp_rd, 7
btfss LCD_D6
bcf temp_rd, 6
btfsc LCD_D6
bsf temp_rd, 6
btfss LCD_D5
bcf temp_rd, 5
btfsc LCD_D5
bsf temp_rd, 5
btfss LCD_D4
bcf temp_rd, 4
btfsc LCD_D4
bsf temp_rd, 4
bcf LCD_E; Finished reading the data
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
bsf LCD_E; Setup to clock data
NOP
NOP
btfss LCD_D7; Get low nibble
bcf temp_rd, 3
btfsc LCD_D7
bsf temp_rd, 3
btfss LCD_D6
bcf temp_rd, 2
ПРИЛОЖЕНИЕ В. Подключаемый файл с описанием функций (окончание)
btfsc LCD_D6
bsf temp_rd, 2
btfss LCD_D5
bcf temp_rd, 1
btfsc LCD_D5
bsf temp_rd, 1
btfss LCD_D4
bcf temp_rd, 0
btfsc LCD_D4
bsf temp_rd, 0
bcf LCD_E; Finished reading the data
FinRd
return
LCDBusy;
Check BF
rlcd LCD_INS
btfsc temp_rd, 7
bra LCDBusy
return
GLOBAL LCDBusy
DelayXCycles
decfsz delay,F
bra DelayXCycles
return
END