
Технический проект
На данном этапе происходит описание и моделирование функций языка программирования, выбор организации проекта и принципов построения моделей и т.д.
Выполняются следующие работы:
составление и описание блоков на языке программирования;
определяются межблоковые связи;
описание констант и переменных;
отладка проекта (пошаговое тестирование основных блоков программы в процессе написания и исправление некорректной работы);
Далее подробно описаны все вышеперечисленные этапы [3].
4.1 Построение проекта
Осуществив, все выше изложенные этапы проектирования и проанализировав эскизный проект, мы переходим к следующей стадии проектирования – технический проект, а именно к описанию проекта для ввода в микроконтроллер PIC18F4520.
При описании моделей на языках программирования большое внимание следует уделять конструкциям языка [4]. Так нужно использовать конструкции, которые воспринимаются программой программирования микроконтроллера, а также оптимизировать конструкции для достижения наименьших аппаратных затрат. Данный процесс очень трудоемкий и требует совершенного знания языка и программы проводящей программирования микроконтроллера.
Рисунок 4.1 – Связи файлов в проекте
Описание интерфейса
Принципы построения модели включает методологию написания языкового кода. Спецификация составляется на всю программу, состоящую из основных блоков в соответствие со следующими этапами.
Необходимо выполнить анализ требуемых входных параметров и констант, а также определить их тип и начальные значения.
Начальные значения выбираются в соответствие с описанием устройства. Тип параметров – char целочисленный тип. При этом по умолчанию используется модификатор типа unsigned, который указывает, что переменная принимает неотрицательные значения. При этом самый левый бит области памяти, выделяемой для хранения значения, используется так же, как и все остальные биты области памяти - для представления значения [7].
Таблица 4.1 Описание интерфейса всей программы
Входы |
Начальные значения |
Тип |
Описание |
ptr_pos |
– |
unsigned char |
Переменная для указания строки из массива стандартных строк |
cmd_byte |
0x01 |
unsigned int |
Переменная для организации взаимодействия SSP и TC74 |
temperature |
– |
unsigned int |
Переменная для хранения значения текущей температуры |
seconds, minutes, hours |
– |
unsigned int |
Переменные для хранения значения текущего времени, соответственно секунд, минут и часов |
4.3 Основные конструкции и процедуры, используемые для написания программы
При разработке проекта необходимо подключить заголовочные файлы:
1. #include <p18f4520.h> – стандартный заголовочный файл с объявлением специальных регистров и битов микроконтроллера PIC18F4520;
2. #include <delay.h> – позволяет организовать задержки;
3. #include <stdlib.h> – позволяет использовать функции преобразующие целочисленные значения в символы, которые можно вывести на LCD;
4. p18lcd.asm – набор стандартных функций для работы с LCD.
Примеры наиболее значащих для проекта функций приведены в таблице 4.2.
Таблица 4.2 Описание основных функций программы.
-
Имя функции
Описание
main
Точка входа в программу
start
Вызывается первой, при входе в функцию main(). Выполняет настройку системы для дальнейшей работы. В частности, выполняет инициализацию экрана и интерфейса передачи данных
d_write
Производит автоматический вывод на экран содержимого глобальной переменной temp_wr
LCDInit
Выполняет настройку и разрешает доступ к LCD
LCDLine_1,
LCDLine_2
Выполняет переход виртуального курсора на первую (вторую) строку экрана
stan_char_1,
stan_char_2
Отображают на экране последовательность символов в зависимости от значения ptr_pos на соответственно 1ю и 2ю строках LCD
itoa
Преобразовывает целочисленные значения в символы, которые можно вывести на LCD
Разберем подробней наиболее важные функции.
void stan_char_1(void);
void stan_char_2(void);
start (). Функция выполняет настройку необходимых для нормальной работы устройства модулей микроконтроллера. К таковым можно отнести модуль LCD-экрана,MSSP,USART и CCP.
Функция LCDInit() описана в файле p18LCD.ASM.
void start (void)
{
LCDInit();
TXSTA=0b10100100; //initialize USART
SPBRG=25;
RCSTA=0b10010000;
TRISCbits.TRISC2=0; // initialize CCP
PR2=0x80;
CCPR1L=0x80;
CCP1CONbits.CCP1X=0;
CCP1CONbits.CCP1Y=0;
T2CON=0x05; //initialize timer2
TRISAbits.TRISA4=1; //knopki S1 I S2 aktivni
TRISBbits.TRISB0=1;
}
itoa(). Функция преобразует, полученную в качестве параметра переменную типа int в переменную типа *char и помещает её в массив char который обрабатывается в зависимости от входного значения int. Это стандартная функция, для обращения к ней подключаем библиотеку stdlib.h.
menu(). Функция организует в бесконечном цикле вывод на LCD меню, которое позволяет выбрать подпрограммы реализующие вольтметр, звуко-излучатель, термометр и часы.
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){};
……….
};}
voltmeter(). Функция реализует работу вольтметра измеряющего напряжение на контактах потенциометра. Задавая необходимые значения регистрам управления модуля USART, получает значения с выхода АЦП в цифровом представлении. Преобразует числовое значение температуры в строку выводим на LCD. Повторяется в цикле пока не нажата S3.
void voltmeter(void)
{
….
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];}
…..
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().Функция реализует работу звуко-излучателя с помощью модуля широтно-импульсной модуляции. Нажатие S2 приводит к увеличению длительности импульса, соответственно значение хранится в CCPR1L. Нажатие S3 приводит к увеличению периода возникновения импульсов, соответственно значение хранится в PR2. Повторяется в цикле пока одновременно не нажаты S2 и S3.
void buzzer(void)
{
….
PR2=0x80;
CCPR1L=0x80;
….
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];}
….
LCDLine_1();
for (i=0;i<ptr_count;i++)
{….
d_write();
} //for i
} //if n!=0
};//while
end: CCP1CON=0; //выключение}
temp(). Функция реализует работу термометра с помощью модуля SSP и термодатчика TC74. Сперва инициализируем MSSP после чего вносим последовательность изменений в управляющие регистры модуля SSP, ч то в свою очередь поток команд от MSSP к TC74 и обратно. В результате мы получаем текущее значение температуры, которое и выводим на LCD. Функция выполняется пока не нажата S3.
void temp (void)
{….
TRISCbits.TRISC3=1; //initialize MSSP module
TRISCbits.TRISC4=1;
SSPCON1=0b00101000;
SSPSTATbits.SMP=1;
SSPADD=0x05;
do {
get_temp: cmd_byte=0x01; //config register command byte
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++)
{…..
d_write();
} //for i
LCDLine_2();
ptr_pos=9;
stan_char_2();
}while(select==1);
}
clock(). Функция реализующая работу часов с помощью таймера TMR1. Инициализируем TMR1 в режим синхронизации с внешнем генератором тактового сигнала. После генерации периферийного прерывания инкрементируется численное значение секунд. После чего текущее время выводится на LCD. Из функции происходит вызов двух подфункций:
– clock_draw() – это функция, которая выводит на экран текущее значение времени;
– clock_set() – это функция, которая позволяет установить текущее время.
void clock (void)
{…
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);
}