Устройство для чтения кода морзе на основе микропроцессора PIC16F84

4429
0
28 апреля 2009
Итак, вы решили заняться любительской радиосвязью или у вас уже есть лицензия, но как и многие начинающие чувствуете, что вам чего-то не хватает,… у вас ещё нет того опыта, которым обладают бывалые радиооператоры.
К тому же, как прочим новичкам, вам никак не удаётся освоить код. Для многих людей сложность заключается в неестественной временной природе процесса: вы записываете последний символ, при этом прослушиваете и декодируете уже следующий!

А если вы допустили ошибку, то весь процесс рушится в тот самый момент, когда ваш ум пытается провести «работу над ошибками», пытаясь заполнить пробелы, что ведёт к тому, что вы пропускаете ещё несколько символов.

Из этой дилеммы есть выход, однако вам потребуется устройство, которое бы копировало и отображало код параллельно с вами. Именно эти функции выполняет устройство, описанное в данной статье.

Декодер работает на скорости от примерно 6 слов в минуту до более чем 36 слов в минуту. Алгоритм адаптации быстро отвечает на изменения скорости кода, поэтому вы можете копировать обе части двусторонней связи, даже если стороны передают на различной скорости.

Аппаратная часть

Принципиальная схема декодера показана на рисунках 1а и 1b. Устройство состоит из четырёх основных частей, питание которых осуществляется посредством набора из четырёх (4) элементов питания типа «АА». Первая часть, входной каскад, состоит из электретного микрофона и транзисторного усилителя с общим эмиттером. Этот функциональный блок обеспечивает беспроводное соединение с вашим радиоприёмным устройством или звуковым генератором для тренировки операторов. Резистор 15 кОм, подающий смещение на электрет, может быть заменён резистором с другим номиналом, в зависимости от характеристик используемого вами электрета. Помимо усиления сигнала, транзисторный усилитель также функционирует в качестве полосового фильтра первого порядка. Границы его полосы определяются ёмкостью разделительных конденсаторов и конденсаторов обратной связи между базой Q1 и выводами коллектора.

mrscode1_show.gif

Рисунок 1 a

mrscode2_show.gif

Рисунок 1 b
 

Второй функциональный блок — узкополосный детектор звука на основе системы фазовой автоподстройки частоты (PLL), состоящий из перестраиваемого детектора звука NE567 PLL. Здесь не применяется никаких радикальных решений: схема взята непосредственно из документации производителя, причём для предотвращения помех применяется гистерезис, главная цель которого — устранение дребезга декодированного сигнала. Узкополосная система распознавания этого блока позволяет с лёгкостью отличить один сигнал от другого, даже если сила копируемого вами сигнала значительно слабее, чем помехи с соседних каналов, если между их частотами есть разница в 100 Гц или около того. На выходе детектора имеем шаблон, образованный последовательностью нулей и единиц, и точно копирующий последовательность точек и чёрточек принятого сигнала. Выход детектора соединяется со входом микроконтроллера PIC16F84 и светодиодом, используемым в качестве вспомогательного средства для настройки приёмника. Мы ещё вернёмся к этому моменту.

Третий функциональный блок — собственно микроконтроллер PIC16F84. Его функция заключается в измерении длительности строки, входящей с декодера звука, и переводе шаблонов в точки кода, чёрточки кода, межбуквенные и междусловные пробелы. Блок микропроцессора также осуществляет устранение дребезжания входного сигнала, в том случае если этот этап был пропущен на входном каскаде.

Кроме того, микроконтроллер выполняет задачи по настройке скорости приёма кода, что осуществляется посредством вычисления средних значений различных компонентов сигнала в реальном времени. Средние значения по символам затем используются для вычисления пороговых уровней времени, необходимого для корректной интерпретации символов. По мере получения символов, как только собирается слово из кода Морзе, происходит сверка/конвертация в эквивалентный символ кода ASCII. Микроконтроллер также обеспечивает синхронную со входом работу светодиода. Хотя изначально эта функция использовалась как средство наладки, она также может служить вспомогательным средством для настройки, а также проверкой того, получает ли микропроцессор сигнал, посылаемый входным каскадом. И, наконец, микропроцессор служит средством связи с жидкокристаллическим дисплеем, посылая на него символы кода ASCII и проводя мониторинг состояния дисплея.

Последний блок — это жидкокристаллический дисплей. В этом варианте схемы был использован резервный дисплей, в котором используется контроллер Hitachi HD44780.

В прототипном варианте сборки микропроцессора, рисунок 1а, для создания модуля тактового сигнала был использован кварцевый генератор, однако можно использовать и конфигурацию ёмкостно-резистивного генератора, поскольку большую часть времени PIC16F84 простаивает, и он вполне может работать на частоте 1 МГц.

Сборка

Есть несколько причин, по которым декодер необходимо собирать в виде двух отдельных блоков:

1) возможность поместить микроконтроллер и дисплей на некотором расстоянии от вашего приёмника, что позволит минимизировать создаваемый им цифровой шум;

2) таким образом тактовые сигналы ЦП и дисплея будут удалены от чувствительного входного каскада электретного усилителя и PLL.

Входной каскад собирается посредством последовательного монтажа от точки к точке на макетной плате размером 5,0?6,5 см. Края можно обернуть медной полосой покрытой клеем, для того чтобы обеспечить достаточное пространство для размещения элементов заземления. Переменное сопротивление 10 кОм с вывода 5 NE567 обеспечивает возможность регулировки частоты, так что появляется возможность настройки частоты звукового генератора для тренировки, или же на нужную высоту для принятия радиоканалов. Входной каскад соединяется с блоком ЦП/дисплей посредством трёхпроводного интерфейса, по которому передаются сигнал, питание и земля.

Все компоненты конструкции доступны в свободной продаже от многих поставщиков.

PIC16F84 ассемблер/машинный код

Встроенное ПО описываемого устройства представлено в листинге 1. Данный код был написан на языке ассемблера Mirochip, и содержит всего 365 команд. Для лучшего понимания хода выполнения программы, прочитайте псевдокод, находящийся в окончании листинга. Здесь также содержатся другие важные детали.

Центральная часть кода — два скользящих средних буфера, сохраняющих метки длины четырёх предыдущих образцов интервалов точек и чёрточек. Эти короткие буферы позволяют сделать практически мгновенной коррекцию скорости. Конечно можно «складывать» средние точки и чёрточки в один и тот же буфер, поскольку со временем накопится примерно равное количество точек и чёрточек, и среднее значение, следовательно, будет находиться где–то посередине, а значит будет и прекрасным дискриминатором символов. Однако всё–таки нередки ситуации, когда происходит искажение данных буфера, если только у него не значительная глубина. Однако больший размер буфера ведёт к снижению адаптации к скорости, поэтому вариант двойного буфера выглядит более предпочтительным.

Три подпрограммы в заключительной части кода работают с интерфейсом жидкокристаллического дисплея. Возможно вы сможете использовать их в других проектах на PIC–контроллерах.
 

Листинг 1



;******************************************************************

****
; Filename: picmrsrc.asm
; Date: Wednesday, December 30, 1998 10:28
; File Version:
; Author: Lawrence Foltzer
; Size: 365 bytes
;******************************************************************

****
 list p=16F84; list directive to define processor
 #include; processor specific variable definitions

 __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC
; timing based on 1.12MHz RC oscillator configuration using 5.1Kohm

+ 100pf

; __CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC
; timing based on 1.12MHz RC oscillator configuration using 5.1Kohm

+ 100pf
;******************************************************************

****
;***** application specific equates
E equ .4
R_W equ .5
RS equ .6
code_in equ .7; PORTB,7 (also ICSPDATA and tone LED)
busy equ .3
BusyChk equ B'00100000'
FuncSet41 equ 0?22; get its attention
FuncSet42 equ 0?20; get it in right mode
DisplayOn equ 0?0c
EntryMode equ 0?06
InitDdRam equ 0?27
Ddra4Input equ B'00001111'
led equ .4; RA4 runs LED
Ddrb4Input equ B'10001111'
Ddrb4Output equ B'10000000'
ReadCntrl equ B'10100000'
pad1 equ 0?68; = 104
noise equ 0?02; 16 milliseconds or less is noise
Ithres equ 0?80
tabsize equ .4
; optest equ .16

;******************************************************************

****
;***** ram allocation
 ORG 0?0c

temp_w res 1
temp_status res 1

flags res 1
; «flags» bit assignment follows
DitDah equ 7; set (1) for DIT, clear (0) for DAH
overflow equ 6; slow code can cause counter overflow

PortaImage res 1
PortbImage res 1

timecnt res 1; this is increment in the ISR
period res 1; and transferred here on edge detection
thres res 1; computed symbol type decision threshold

codeword res 1; 1/0 representation of mickey morse

ditptr res 1; pointer to ditvals buffer
ditsum res 1
ditave res 1
ditvals res tabsize

dahptr res 1; pointer th dahvals buffer
dahsum res 1
dahave res 1
dahvals res tabsize

stack res 1; available RAM
;******************************************************************

****
 org 0?000
boot goto init
;

*******************************************************************

*************
; this IRQ is entered every 4 milliseconds
 org 0?004
ISR movwf temp_w
 movf STATUS, W
 movwf temp_status
 incf timecnt,1
 btfss STATUS, Z
 goto isrjmp
 bsf flags, overflow
 decf timecnt,1
isrjmp movlw 0?74; 116
 movwf TMR0
 bcf INTCON, T0IF
exit1 movf temp_status, W
 movwf STATUS
 swapf temp_w,1
 swapf temp_w, W
 retfie
;

*******************************************************************

*************
; morse tables follow ISR to keep them in 1st page, hopefully.
ditab clrf PCLATH
 movf codeword, W
 andlw B'00111111'
 addwf PCL,1
 retlw " «
 retlw «e»
 retlw «a»
 retlw «i»
 retlw «w»
 retlw «r»
 retlw «u»
 retlw «s»
 retlw «j»
 retlw «p»
 retlw 0?5f
 retlw «l»
 retlw 0?5f
 retlw «f»
 retlw «v»
 retlw «h»
 retlw "1«
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?7c; is "|" rather than «\» end of message
 retlw 0?5f
 retlw 0?5f; _ = wait
 retlw "2«
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw "3«
 retlw «! » ; acknowledge
 retlw "4«
 retlw "5«
 retlw 0?5f
 retlw «'»
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw «.»
 retlw 0?5f
 retlw 0?5f
 retlw 0?22; quotation mark
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw «_»
 retlw «? »
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw «<" ; end of work
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f

dahtab clrf PCLATH
 movf codeword, W
 andlw B'00111111'
 addwf PCL,1
 retlw " «
 retlw «t»
 retlw «n»
 retlw «m»
 retlw «d»
 retlw «k»
 retlw «g»
 retlw «o»
 retlw «b»
 retlw «x»
 retlw «c»
 retlw «y»
 retlw «z»
 retlw «q»
 retlw 0?5f
 retlw 0?5f
 retlw "6«
 retlw "=" ; double dash
 retlw «/» ; fraction bar
 retlw 0?5f
 retlw 0?5f
 retlw ">» ; starting signal
 retlw «(»
 retlw 0?5f
 retlw "7«
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw "8«
 retlw 0?5f
 retlw "9«
 retlw "0«
 retlw 0?5f
 retlw «-»
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw «; »
 retlw 0?5f
 retlw 0?5f
 retlw «)»
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw «, »
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw «: »
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f
 retlw 0?5f

;

*******************************************************************

*************
; next is for xtal clock
init movlw 0?04; divide XTAL OSC by 4 and then 32 for 4ms ticks
 option; later, load TMR0 with 256–140 and let overflow
; next is for rc clock
; init movlw 0?02; divide RC OSC by 4 and then 8 for ~4ms ticks
; option; later, load TMR0 with 256–140 and let overflow

 movlw Ddra4Input
 tris PORTA
 bcf PORTA, led; on initially
 movlw Ddrb4Input
 tris PORTB

 clrf PortbImage
 clrf PortaImage
dlp1 decfsz PortaImage,1
 goto dlp1
 decfsz PortbImage,1
 goto dlp1

 call ChkBusy

 movlw FuncSet41
 movwf PORTB
 call SendCmmd

 movlw FuncSet42
 movwf PORTB
 call SendCmmd
 movlw DisplayOn
 call SendCmmd
 movlw EntryMode
 call SendCmmd
 movlw InitDdRam
 call SendCmmd

 movlw .13
 movwf ditptr
 movlw ditptr
 movwf FSR
ilp1 incf FSR,1
 clrf INDF
 decfsz ditptr,1
 goto ilp1

 movlw 0?18
 movwf thres

 clrf TMR0
 clrf flags
 clrf INTCON
 bsf INTCON, T0IE
 bsf INTCON, GIE
;

*******************************************************************

*************

 clrf PortbImage
 clrf PortaImage
dlp1 decfsz PortaImage,1
 goto dlp1
 decfsz PortbImage,1
 goto dlp1

 call ChkBusy

 movlw FuncSet41
 movwf PORTB
 call SendCmmd

 movlw FuncSet42
 movwf PORTB
 call SendCmmd
 movlw DisplayOn
 call SendCmmd
 movlw EntryMode
 call SendCmmd




start btfss PORTB, code_in
 goto start; receiving a tone, exit on a space
 bsf PORTA, led
; we are now receiving a space
start2 btfsc PORTB, code_in
 goto start2; now we wait for a tone to time
; detected the start of a dit or dah
 bcf PORTA, led; light LED
 clrf timecnt; reset timer count
db1 movlw noise; debounce (db) tone edge
 subwf timecnt, W; timecnt — noise
 btfss STATUS, C
 goto db1
w84spc1 btfss PORTB, code_in
 goto w84spc1; tone still present
; tone stopped, but this is first so we don’t know what it is. we

assume it is a dah!
 movf timecnt, W
 movwf period
 clrf timecnt
 bsf PORTA, led
 movlw 0?01
 movwf codeword; prep for 1st symbol
 movf thres, W
 subwf period, W; period — thres
 btfsc STATUS, C
 goto isadah
isadit bsf flags, DitDah
 call avedit
 goto mainlp
isadah bcf flags, DitDah
 call avedah
; now we wait for a tone to start so we can see what kind of space

just passed
mainlp btfsc PORTB, code_in
 goto mainlp; space while set
 movf timecnt, W
 movwf period
 clrf timecnt
; we are timing the current tone period now. so light the LED.
 bcf PORTA, led; let there be light
;

*******************************************************************

*************
; so how long was the space? symbol or char
 movf thres, W
 subwf period, W; period — thres
 btfss STATUS, C
 goto symbolspc
 goto longspc
longspc rlf thres, W
 subwf period, W; period — thres
 btfss STATUS, C
 goto charspc
 goto wordspc
;

*******************************************************************

*************
symbolspc movlw noise
db3 subwf timecnt, W; timecnt — noise
 btfss STATUS, C
 goto db3
db4 btfss PORTB, code_in
 goto db4; wait for the tone to end
 movf timecnt, W
 movwf period
 clrf timecnt
 bsf PORTA, led
 movf thres, W
 subwf period, W; period — thres
 btfsc STATUS, C
 goto itsadah
 goto itsadit
;

*******************************************************************

*************
itsadit call avedit
 btfsc flags, DitDah
 bsf STATUS, C
 btfss flags, DitDah
 bcf STATUS, C
 rlf codeword,1
 goto mainlp
;

*******************************************************************

*************
itsadah call avedah
 btfss flags, DitDah
 bsf STATUS, C
 btfsc flags, DitDah
 bcf STATUS, C
 rlf codeword,1
 goto mainlp
;

*******************************************************************

*************
charspc btfsc flags, DitDah
 goto ditstart1
; goto dahstart1
;

*******************************************************************

*************
dahstart1 call dahtab
 goto printit
;

*******************************************************************

*************
ditstart1 call ditab
printit call SendText; printit, send to LCD
 goto db1
;

*******************************************************************

*************
wordspc btfsc flags, DitDah
 goto ditstart2
; goto dahstart2
dahstart2 call dahtab
doit call SendText
 movlw 0?20; space
 call SendText
 goto db1
ditstart2 call ditab
 goto doit
;

*******************************************************************

*************
avedit movf ditptr, W
 addlw ditvals
 movwf FSR
 movf INDF, W
 subwf ditsum,1
 movf period, W
 movwf INDF
 addwf ditsum,1
 rrf ditsum, W
 movwf ditave
 rrf ditave,1
 movlw 0?3f
 andwf ditave,1
 incf ditptr,1
 movlw 0?03
 andwf ditptr,1
 goto makethres
;

*******************************************************************

*************
avedah movf dahptr, W
 addlw dahvals
 movwf FSR
 movf INDF, W
 subwf dahsum,1
 movf period, W
 movwf INDF
 addwf dahsum,1
 rrf dahsum, w
 movwf dahave
 rrf dahave,1
 movlw 0?3f
 andwf dahave,1
 incf dahptr,1
 movlw 0?03
 andwf dahptr,1
makethres movf ditave, W
 subwf dahave, W
 movwf thres
 bcf STATUS, C
 rrf thres,1
 movf ditave, W
 addwf thres,1
 return
;

*******************************************************************

*************
SendText clrf PORTB
 bsf PORTB, RS
 goto Send1
SendCmmd clrf PORTB
Send1 movwf PortbImage
 swapf PortbImage, w
 andlw 0?0f
 iorwf PORTB,1
 bsf PORTB, E
 bcf PORTB, E
 movlw 0xf0
 andwf PORTB,1
 movf PortbImage, w
 andlw 0?0f
 iorwf PORTB,1
 bsf PORTB, E
 bcf PORTB, E
;

*******************************************************************

*************
ChkBusy movlw Ddrb4Input
 tris PORTB
SampleAgain movlw ReadCntrl
 movwf PORTB
 bsf PORTB, E
 movf PORTB, w
 movwf PortbImage
 bcf PORTB, E
 bsf PORTB, E
 bcf PORTB, E
 btfsc PortbImage, busy
 goto SampleAgain
 movlw Ddrb4Output
 tris PORTB
 return
;******************************************************************

****
; this version is based on use of an NE567 tone decoder
; as input filter. decoder output is low when a tone is detected.
; advantages: immunity to adjacent channel signal, and amplitude

variation.

; timing considerations, how long is a symbol?
; the reference symbol duration is the DIT!.
; a DAH symbol is 3 DITs long.
; the space between a pair of symbols is 1 DIT long.
; characters are groups of symbols and the spaces between them.
; the space between characters is 3 DITs long.
; the space between words is 5 DITs long.
; there are 50 symbol periods in the reference string: PARIS
; «. _ _ . . _ . _ . . . . . . «
; so at 12 WPM, we have 600 symbols in 60 seconds, ===> 0.1 sec /

symbol
; @ 36 WPM, the shortest (DIT) symbol period is 33ms long.
;

*******************************************************************

*************
;

*******************************************************************

*************
; *****************************************


 end.inc>


Тактические и профессиональные фонари. В первую очередь, это светотехнические средства, пригодные для применения в экстремальных и сложных условиях, а так же техника, оптимизированная для узкого спектра задач, например подствольные фонари или фонари для дайвинга.
12879 0
Активная распределенная антенная система представляет собой двунаправленный репитер, который усиливает и дублирует выходной сотовый сигнал внутри одного помещения. Усиленный сигнал дублируется с помощью внутренней антенны. Подобным образом дублируется сотовый сигнал и за пределами здания.
5696 0
Для схемы данного интегратора подойдёт практически любая модель операционного усилителя, но в списке необходимых компонентов указана модель 1458, так как входные токи смещения этого ОУ гораздо выше. Как правило, высокий входной ток смещения считается плохой стороной того или иного операционного усилителя, если он используется в схеме усилителя постоянного тока (и особенно в схеме интегратора!).
7010 0

    Вы должны авторизоваться, чтобы оставлять комментарии.

    При использовании материалов данного сайта прямая и явная ссылка на сайт radiomaster.ru обязательна. 0.2516 s