Микроконтроллер должен осуществлять такие действия:
1) начальную настройку своих узлов и периферийных устройств;
2) прием параметров измерения фазы от компьютера;
3) измерение частоты сигнала;
4) выбор режима измерения фазы;
5) выдача информации о частоте и фазе компьютеру.
Соответственно этому МК будет работать по алгоритму указанному на рис.5.
Рис.5. Блок-схема алгоритма программы для МК
Программа для МК
BSEG
ORG 0h
Cell_Tr: DBIT 1
DSEG
ORG 30h
Fr_low: DS 1
Fr_high: DS 1
Fase_low: DS 1
Fase_high: DS 1
Contr_sum: DS 1
CSEG
ORG 0h
Jmp On_Reset:
ORG 3h
Jmp Freq
ORG 0Bh
Reti
ORG 13h
Jmp Fase
ORG 1Bh
Reti
ORG 23h
Reti
ORG 40h
On_Reset:
Mov IE, #0; запрет всех прерываний
Mov Sp, #40h; установка вершины стека
Mov IP, #0; все приоритеты прерываний одинаковы
Mov TCON,#0; внешние прерывания вызываются по низкому уровню
; на входах INT0,INT1
Mov TMOD,#00100000B; таймер/счетчик Т1 работает в режиме 8-битного с
; таймера c автоперезагрузкой
Mov SCON,#11001100B; 8-битовый приемопередатчик + бит паритета
Mov PCON,#10000000B; удвоенная скорость передачи данных (SMOD=1)
Mov A, #243; настройка скорости последовательного интерфейса
Mov TH1, A; 4800 бод/с
Setb TR1; запуск таймера T1
Mov DPTR, #0;
Mov IE, #10000001B; разрешение прерываний от INT0 измерение частоты
Mov R0, #100; проверка правильности работы фазометра
Next_wait:; при разрешенном прерывании
Acall Del_10; каждые 10 мс проверяется содержимое DPL
Mov A, R0;
Mov R1, A;
Fr_beat:
NOP
Djnz R1, Fr_beat; этот участок кода нужен для обнаружения частот
Mov A, DPL; с периодом кратным 10 мс
Jnz Work; если в DPL не ноль то фазометр работает нормально
Djnz R0, Next_wait; иначе снова проверять
Clr EA; запрет прерываний
Clr Cell_tr; сбросить флаг работоспособности
Rjmp Send_error
Work:
Setb Cell_tr; установить флаг работоспособности
Send_error:
Acall Get_COM; ждать сообщения от ПК
Mov Acc.0, Cell_tr
Acall Transmit_COM; послать сообщение ПК о работоспособности
Jb Cell_tr, To_do; если фазометр работает, то продолжать работу
Ret; иначе конец программы
To_do:
Acall Get_COM; получить количество измерений
Mov R1, A
Acall Get_COM; получить период измерений
Mov R5, A
Clr A
Mov Contr_sum, A; обнуляем контрольную сумму
Next_measure:
Mov DPTR, #0; померять частоту
Mov IE, #10000001B; разрешение прерываний от INT0 измерение частоты
Jnb IE0, $
Jb IE0, $
Clr EA
Mov A, DPH
Acall Transmit_COM; передача ПК
Mov Fr_high, A; сохранить старший байт
Mov A, DPL
Acall Transmit_COM; передача ПК
Mov Fr_low, A; сохранить младший байт
Mov A, Fr_high
Subb A, #36h
Jnc Meas_MK; если DPH > 36h, то фазу меряет MK
Mov A, Fr_high
Subb A, #1Bh; если DPH > 1Bh, то фазу меряет таймер с
Jnc Meas_T4; предделением частоты на 4
Mov A, Fr_high
Subb A, #0Dh; если DPH > Dh, то фазу меряет таймер с предделением
Jnc Meas_T2; частоты на 2
Mov A, Fr_low
Subb A, #06h; если DPL > 6, то фазу меряет таймер без предделения
Jnc Meas_T; частоты, иначе таймер работает на
; максимальной частоте 60 МГц
Acall First_reset; начальный сброс генератора
Mov A, #1; код команды записи в регистр DIV
Acall Write_Byte; запись в генератор
Mov A, #00110010В; загрузка 8 бит константы для задания частоты
; генератора
Acall Write_Byte; запись в генератор
Acall Write_0; 9-ый бит
Ajmp Meas_G
Meas_T:
Mov R2, Fr_low; вычисление
Mov R3, Fr_high
Mov R1, #4
Acall Dividing
Mov A, R2
Mov B, #75
MUL AB
Mov R2, A
Mov A, B
Mov R3, A
Mov R1, #5
Acall Dividing
Dec R2
Mov A, R3
Jnc Meas_G
Dec A
Mov R3, A
Acall First_reset; начальный сброс
Mov A, #1; код команды записи в регистр DIV
Acall Write_Byte; запись в генератор
Mov A, #00110100В; загрузка 8 бит константы для задания частоты
; генератора
Acall Write_Byte; запись в генератор
Acall Write_0; 9-ый бит
Ljmp Meas_G
Meas_T2:
Mov R2, Fr_low; вычисление
Mov R3, Fr_high
Mov R1, #5
Acall Dividing
Mov A, R2
Mov B, #75
MUL AB
Mov R2, A
Mov A, B
Mov R3, A
Mov R1, #5
Acall Dividing
Acall First_reset; начальный сброс
Mov A, #1; код команды записи в регистр DIV
Acall Write_Byte; запись в генератор
Mov A, #00111000В; загрузка 8 бит константы для задания частоты
; генератора
Acall Write_Byte; запись в генератор
Acall Write_0; 9-ый бит
Ljmp Meas_G
Meas_T4:
Mov R2, Fr_low; вычисление
Mov R3, Fr_high
Mov R1, #6
Acall Dividing
Mov A, R2
Mov B, #75
MUL AB
Mov R2, A
Mov A, B
Mov R3, A
Mov R1, #5
Acall Dividing
Acall First_reset; начальный сброс
Mov A, #1; код команды записи в регистр DIV
Acall Write_Byte; запись в генератор
Mov A, #00110000В; загрузка 8 бит константы для задания частоты
; генератора
Acall Write_Byte; запись в генератор
Acall Write_0; 9-ый бит
Meas_G:
Mov A, #2; код команды записи в программный делитель
Acall Write_Byte; запись в генератор
Mov A, R2; младшие 8 бит предделителя
Acall Write_Byte; запись в генератор
Mov A, R3; старший бит
Jb Acc.0, Wr1
Acall Write_0; запись в генератор 0
Ljmp St_m
Wr_1:
Acall Write_1; запись в генератор 1
St_m:
Acall First_reset; начало работы генератора после программирования
Clr P0.1; сброс счетчиков
Jnb IE1, $; ждем пока не возникнет прерывания от изм. фазы
Setb P0.1; разрешение счета счетчиков
Jb IE1, $; ждем пока не завершиться прерывания от изм. фазы
Mov A, P1; считываем младший байт результата
Mov Fase_low, A
Mov A, P0; считываем старший байт результата
Anl A, #1111B; обнуляем незначащие биты
Mov Fase_high, A
Ljmp Transm_fase
Meas_MK:
Mov DPTR, #0; обнуление счетчика
Mov IE, #10000100B; пуск измерения фазы на частоте меньшей 28.6 Гц
Jnb IE1, $; с помощью аппаратных возможностей МК
Jb IE1, $
Clr EA
Mov A, DPН; считывания старшего байта фазы
Mov Fase_high, A; сохранение
Mov A, DPL; считывания младшего байта фазы
Mov Fase_low, A; сохранение
Transm_fase:
Mov A, Fase_high
Acall Transmit_COM; передача ПК
Mov A, Fase_low
Acall Transmit_COM; передача ПК
Acall Del_c; задаем период измерения
Djnz R1, Next_measure; следующее измерение
Mov A, Contr_sum; передача контрольной суммы
Acall Transmit_COM
Ljmp To_do
ret
; подпрограмма начального сброса генератора
First_reset:
Clr I/O
Mov R0, #139
Acall Del_any
Setb I/O
Mov R0, #12
Acall Del_any
Jnb I/O, Rst3
Mov A, #1
Ret
Rst3:
Mov R0, #99
Acall Del_any
Jb I/O, Rst5
Mov A, #2
Ret
Rst5:
Mov A, #0
Ret
; подпрограмма записи бита #0 по однопроводному интерфейсу
Write_0:
Clr I/O
Mov R0, #15
Acall Del_any
Setb I/O
Ret
; подпрограмма записи бита #1 по однопроводному интерфейсу
Write_1:
Clr I/O
Mov R0, #1
Acall Del_any
Setb I/O
Mov R0, #14
Acall Del_any
Ret
; подпрограмма записи байта по однопроводному интерфейсу
Write_Byte:
Clr I/O; запрет прерывания
Mov R1, #8; 8 бит
Wb1:
Rrc A; А0→С
Jc Wb2;
Acall Write_0;
Jmp Wb3
Wb2:
Acall Write_1;
Djnz R1, Wb1;
Setb EA;
Ret
; прием байта по COM-порту в аккумулятор
Get_COM:
Jnb RI, Get_COM
Mov A, SBUF
Clr RI
Ret
; передача байта по COM-порту через аккумулятор
Transmit_COM:
Mov SBUF, A
SEND:
Jnb TI, SEND
Clr TI
Push A; контроль правильности передачи данных
Mov A, Contr_sum; поблочным суммированием
Pop R4
Add A, R4
Mov Contr_sum, A
Ret
; задержка 5мкс
Del_5:
NOP
Ret
; подпрограмма задержки, параметр R0, задержка=5*R0 мкс
Del_Any:
Next_del:
Acall Del_5
Djnz R0, Next_del
Ret
; подпрограмма задержки на 10 мс
Del_10:
Push R1
Push R0
Mov R1, #10
To_next:
Mov R0, #199
Acall Del_any
Djnz R1, To_next
Pop R0
Pop R1
Ret
; подпрограмма задержки на R5 с
Del_c:
Mov A, R5
Mov R7, A
Del_sec:
Clr C
Mov R6, #100
Next_1c:
Acall Del_10
Dec R6
Jnc Next_1c
Mov R1, #10
Dec R7
Jnc Del_sec
Ret
; подпрограмма деления на 2n двухбайтового числа R3:R2 сдвигом n=R1
Dividing:
Clr C
Mov A, R3
Rrc A
Mov R3, A
Mov A, R2
Rr A
Mov R2, A
Djnz R0, Dividing
ret
; подпрограммы обработки прерываний
Freq:
Inc DPTR
reti
Fase:
Inc DPTR
NOP
NOP
NOP
NOP
NOP
reti