;-----------------------------------------------------------------------;
; MORSENBR.ASM Send numbers 0-9 in morse code to speaker and LEDs ;
;-----------------------------------------------------------------------;
LIST P=16F84 ; tells which processor is used
INCLUDE "p16f84.inc" ; defines various registers etc. Look it over.
ERRORLEVEL -224 ; supress annoying message because of tris
__CONFIG _PWRTE_ON & _LP_OSC & _WDT_OFF ; configuration switches
CBLOCK H'C'
temp ; a temporary variable
bitcount ; counter for bits
nbr ; holds current number to send
ENDC
ORG 0 ; start at location 0
goto main ; jump over to main routine
;-----------------------------------------------------------------------;
; Use W to convert number in W to pattern needed to send # ;
;-----------------------------------------------------------------------;
pattern:
addwf PCL, f ; PCL points to the first entry in the table
dt H'1F',H'0F',H'07',H'03',H'01',H'00',H'10',H'18',H'1C',H'1E'
; 0 1 2 3 4 5 6 7 8 9
;-----------------------------------------------------------------------;
; Delay routine ;
;-----------------------------------------------------------------------;
nmsec: ; delay for # msec in W on entry
nop ; each nop is 0.122 milliseconds
nop
nop ; each total loop is 8 X 0.122 = 0.976 msec
nop
addlw H'FF' ; same as subtracting 1 from W
btfss STATUS, Z ; skip if result is zero
goto nmsec ; this is 2 X 0.122 msec
return ; back to calling point
;-----------------------------------------------------------------------;
; Sound routine lasting about 100 milliseconds ;
;-----------------------------------------------------------------------;
snd1:
movlw D'153' ; 103 additional would mean roll-over
sndloop:
bsf PORTA,3 ; RA3 high
nop
nop
bcf PORTA,3 ; RA3 low
addlw 1 ; bump W and check for roll-over to 0
btfss STATUS, Z ; 8 instructions in loop
goto sndloop ; 0.122 msec/instruction
return ; 103 loops
;-----------------------------------------------------------------------;
; Output number in W to LEDs on Port B and to spkr on RA3 ;
;-----------------------------------------------------------------------;
sendnbr:
movwf PORTB ; display number on LEDs
call pattern ; get pattern of dits and dahs
movwf temp ; save it
movlw 5 ; total of 5 dits or dahs ...
movwf bitcount ; into a counter
bitloop: btfss temp, 4 ; check 5th bit, if it is 1, send dah
call dit ; else it is 0, send dit
btfsc temp, 4 ; and skip next instruction
call dah ; get here only if bit 5 is 1
rlf temp, f ; rotate left once giving new bit 5
decfsz bitcount, f ; are we finished?
goto bitloop ; no, send new bit 5
clrf PORTB ; yes, turn display off
return
;-----------------------------------------------------------------------;
; Dit routine ;
;-----------------------------------------------------------------------;
dit
call snd1 ; 100 msec of tone
movlw D'100' ; followed by 100 msec of silence
call nmsec
return
;-----------------------------------------------------------------------;
; Dah routine ;
;-----------------------------------------------------------------------;
dah:
call snd1 ; 100 msec of tone
call snd1 ; stretch it to 300 msec
call snd1
movlw D'100' ; and 100 msec of silence
call nmsec
return
;-----------------------------------------------------------------------;
; Wait until button on RB4 is released ;
;-----------------------------------------------------------------------;
waitup:
btfss PORTB, 4 ; test RB4
goto $ -1 ; ck again if pressed
movlw D'10'
call nmsec ; wait 10 msec for debounce
btfss PORTB, 4 ; check again, still up?
goto waitup ; no start over
return ; yes, finished
;-----------------------------------------------------------------------;
; Initialization Subroutine ;
;-----------------------------------------------------------------------;
init:
movlw 0 ; RA0 - RA4 outputs
tris PORTA
movlw H'10' ; all outputs except RB4
tris PORTB ; on port B
movlw H'0' ; all outputs low (off)
movwf PORTB
movwf PORTA
movlw 0 ; pull-ups enabled
option
return
;-----------------------------------------------------------------------;
; Main routine, sends a new number each time button pressed ;
;-----------------------------------------------------------------------;
main:
call init ; set up ports etc
start: clrf nbr ; start with nbr = 0
mainloop: call waitup
btfsc PORTB, 4 ; wait on button press
goto $ -1
movf nbr, W ; get number into W
call sendnbr ; and output it
incf nbr, f ; set up for next number
movlw H'0A' ; reached 10?
subwf nbr, W
btfss STATUS, Z ; yes start again at 0
goto mainloop ; no, wait for next button press
goto start
end
A major addition in this program is using a table to get patterns describing the dits and dahs to be sent. It appears right at the first of the assembly listing. The register PCL represents the low 8 bits of the program counter, ( tells where the next instruction comes from ). When a call to pattern is made the instruction 'addwf PCL, f' is executed. Just before the instruction is executed, PCL points at the instruction. After the instruction is executed PCL would normally point to the next memory location, but the instruction itself modifies PCL. If W = 0, then indeed no modification is made and the first entry in the data table, (dt), is taken as the next instruction. If W = 1, it is the 2nd entry in the table and so on.
The data table assembles as a bunch of 'retlw' instructions which in words says: ' return from the subroutine but first put this literal, (number), in W'. That is, in this case; retlw H'1F', retlw H'0F', retlw H'07' etc. So you see that the result of calling 'pattern' is to place a number in W given by the table value specified by W on entry. You of course have to stay within the table. If W is too large on entry you will overun the table.
The routine 'snd1' is like a delay routine with toggling of pin RA3 built in. The loops are 1 msec long and flipping is about half way through, meaning a almost square wave of frequency 1 kHz. The speaker is a piezoelectric speaker which is looks like a capacitor as a load. The 100 ohm resistor prevents a large inrush current. If you have a voice coil speaker you might also try it with a 100 resistor. Unless it is fairly high impedance, you may not get a very loud sound. Piezo speakers with a paper cone attached seem to give louder sound. I have what I think is a Radio Shack 40-1383 which works well.
This instructions rotates the bits of register f left through carry. Each bit 0 - 6 moves one bit position higher and the carry bit of STATUS moves into bit 0. Bit 7 is pushed into the carry bit of STATUS. There is also and instruction 'rrf', ( roll right through carry ), which moves the bits the other way. If you are concerned about the bits coming in from carry you should set, ( bsf STATUS, C), or clear, ( bcf STATUS, C ), carry before you do the shift. In this program we are only interested in getting the original bits 4-0 into the bit 4 position in order.
The program is supposed to be used to learn morse code numbers but it's too easy if you know what the next number is to be. How about changing it so you get a random number between 0 and 9. Where can we get a random number? How about TMR0? It is continually running and the press of the button should be fairly random. Can you write the code? Hint: how about adding a random number 0-2 to a random number 0-8 and not allowing 10?
How about sending the value of an external BCD switch out the speaker whenever a button is pressed? The switch could be hooked to RB4-RB7, with the pushbutton moved to RA0. Remember that Port A has no internal pull-up resistors, you will need to supply and external one.
The output from the Counter in program #2 could also be output to the speaker with the routines contained here. What happens when you get to double digits though, (10-15)? One way to handle this is to have a units and a tens register as in program #3. What if another button press comes in while the current number is being output on the speaker? Perhaps the counting can be done using an interrupt routine.
The code for this program was simplified considerably because it sends only numbers. Morse digits are all 5 dot-dash combinations long. Not so with other Morse characters. Can you think of a scheme to handle various length combinations?
One way to do this is to make all higher order bits not used zeros and then use a one to signify that all lower bits make up the valid pattern. Could you write the code to decode such a pattern?
Comments:
See:
| file: /Techref/piclist/cheapic/morsenbr.htm, 11KB, , updated: 2007/4/20 20:09, local time: 2025/10/24 12:17,
216.73.216.20,10-1-5-169:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://ecomorder.com/Techref/piclist/cheapic/morsenbr.htm"> Morse Code Number Program </A> |
| Did you find what you needed? |
Welcome to ecomorder.com! |
Welcome to ecomorder.com! |
.