(几乎)在闹钟中轻松应用AT90S2313或ATtiny2313,以将摩尔斯电码中的警报从“哔哔哔哔哔哔哔哔哔哔哔哔...”更改为“唤醒”。 该产品是根据要求设计的,并且每天都在使用
(见文末)
AVR Studio组装来源:morclk041204A
AVR STudio十六进制文件:morclk041204A.hex
总览
扬声器安装在顶部边缘,而AA电池座则粘在背面。 扁平带状电缆用于所有互连。
通过在钟体内安装一个小电路板,并将一些电线连接到时钟的电路板上,从而对廉价的闹钟进行了修改。 背面安装了第二个AA电池,该电压可将微控制器的电压提高到3伏。 当我思考最好的永久位置在哪里时,高阻抗扬声器被临时安装在顶部,就像许多决定由于临时解决而被推迟一样,它仍在等待最终处置。
电路图
该适配器是一个微控制器,具有晶体时钟,输入接口电路和扬声器的AC耦合,该扬声器由控制器的输出引脚直接驱动。 0.22 uf电容器是陶瓷单片电容器。
微控制器大部分时间处于休眠状态,仅消耗微安培,直到接收到中断。并唤醒,然后使用定时循环,在摩尔斯电码中为“唤醒”生成定时。中断会在针脚14和15上提供2 kHz方波,它们彼此异相180度(当一个针脚为高电平时,另一个针脚为低电平),这意味着扬声器看到了接近6伏的方波峰峰值(或3伏RMS,因为它是方波)。与扬声器串联的100 uf电容器可防止其汲取任何直流电。发送“唤醒”消息后,微控制器将返回睡眠状态。
芯片的内部弱上拉电阻将数字输入拉高,以最大程度地降低功耗。扬声器输出配置为输出(我希望这并不奇怪)。
时钟模块由单个1.5伏AA电池供电。为了将电压升至2.7V或更高以运行AT90S2313,我添加了第二个AA电池,该电池仅为AT90S2313供电。
警报信号取自从闹钟模块到时钟扬声器的电线之一。当信号摆动到地时,警报模块中的2N4401吸收足够的电流以将中断引脚拉低。 2N4401基极上的39k电阻将基极电流设置为(1.5V-0.7V)/ 39k = 20微安。接地时,引脚6上的弱上拉电流不足85微安,典型值为30微安,因此基本驱动器绰绰有余。请注意,该晶体管的主要功能是将警报模块的1.5 V峰峰值信号放大为一个从地摆动到微控制器的正电源的信号。 0.22 uf电容器会清除收集器上的信号,以使警报信号进入时收集器变为低电平,并在最后一次蜂鸣后保持低电平约2毫秒。
之所以使用晶体振荡器是因为我有很多AT90S2313,而它们没有内部振荡器。更好的选择将是像运行内部振荡器的ATtiny12一样。虽然可以做得更好,但只要修改固件以确保驱动扬声器的引脚14和15处于相同状态(高,低,作为输入),就可以省去100 uf电容器。没有发出声音或没有发出声音时,至少其中之一被配置为输入。
关于扬声器的注意事项:我使用了一个高阻抗传感器,该传感器是在一家过剩商店购买的。有人告诉我说它是压电的,似乎在欧姆表上测量的大于20兆欧。请小心使用具有足够高阻抗的压电换能器或其他类型的扬声器,以使使用6伏峰峰值信号驱动时流经它的电流不会超过40毫安。如果分流电容不大,则任何高于150 Ohms的直流电都可以满足此要求。
固件
上电复位后,固件会执行通常的内务处理-设置堆栈指针,初始化I / O端口以及设置计时器1,该计时器用于在发送代码时为扬声器产生声音,然后进入睡眠状态并等待闹钟中断。
- start:
- (HOUSEKEEPING CODE GOES HERE)
- sleep
- waithere:
- rjmp start
下面是中断服务程序,但有一些额外的注释。
- int0service: ;Alarm has gone off, so wake up
- ;The entire housekeeping routine is executed
- ;first to make sure everything is properly set up.
- clr temp
- out GIMSK,temp ;Interrupt are disabled.
- out MCUCR,temp
- clr flagreg ;Clear the firmware flag resister/
- ;TIMER 1 SETUP for proper tone pitch.
- ldi temp,$09 ;Set timer 1 to reset 0000 after compare match. Prescaler = 1X.
- out TCCR1B,temp
- ldi temp,intcounthigh ;Set compare register to establish interrupt frequency.
- out OCR1AH,temp
- ldi temp,intcountlow
- out OCR1AL,temp
- ldi temp,$40 ;Enable interrupt on compare match.
- out TIMSK,temp
- sbi PORTB,0
- cbi PORTB,1
- sei ;Enable interrupts so that the tone can be output when code is
- ;sent.
- ldi temp,20 ;Set a variable for 10 words per minute code speed.
- mov dotlength,temp
- rcall TypeMessage ;Send "WAKE UP" message in Morse Code
- rjmp start ;Go back to start (set up then sleep).
发送摩尔斯电码的部分在操作上相当原始,但是依靠巧妙的技巧在内存中格式化摩尔斯电码符号,并且比我自己想出的格式化方法干净得多。我在一个叫David Robinson的人的网页上找到了它,他在1997年2月发行的QST中的一篇文章中赞扬了N1KDO。在该格式中,每个字符都编码为一个字节,其中1代表dah,0代表dit。额外的1被写为一种“停止”位。字符移出,直到寄存器仅包含obooooooo1为止,此时,整个单词都移出了。例如,字母A编码为“ 0b00000110”
这是代码移出时移位寄存器的视图:
“ 0b00000110”发送任何内容之前
“ 0b00000011”发送同义字符并且该字节右移
“ 0b00000001”发送了一个dah,并且字节再次移位。 由于寄存器现在包含“ 0b00000001”,因此操作完成。
最困难的部分是将莫尔斯电码转换为二进制代码并输入。我感谢N1KDO的技术,并感谢David Robinson在其网页上介绍了该技术。
使用上述方法,例程将接受ASCII字符,查找摩尔斯电码字符的格式,然后在格式化的摩尔斯移出时调用点例程,破折号例程或退出。
发送要发送的ASCII字符串的例程直接取自Atmel应用说明AVR108:LPM指令的设置和使用。 可以在Atlems的网站http://www.atmel.com上找到它。 如果您只是在“ DOC1233.PDF”上进行Google搜索,则可以节省浏览Atmel网站的时间。
该例程如下:
- TypeMessage: ;Type greeting
- push ZL
- push ZH
- ldi ZH,high(2*Message) ;Load high part of byte address into ZH
- ldi ZL,low(2*Message) ;Load low part of byte address into ZL
- rcall sendromstring ;Send it
- pop ZH
- pop ZL
- ret
- Message:
- .db "WAKE UP "
- .db $0A,$0D
- .db $00,$00
例程sendromstring:实际上将字符发送出去,以更改为摩尔斯电码并发出提示音。空格被解释为一个字间周期。
施工
所有组件都安装在一小块预先打孔的电路板上,并且用一条带状电缆进行电气连接。
组件采用点对点布线,主要是通过将引线弯向其预定的连接点并进行焊接。放置这些组件是为了使我能够以最小的麻烦连接它们-这意味着尽可能少的绝缘跳线。
在带状电缆的应力点(如穿过闹钟盒中的孔的位置)和弯曲点处使用热缩管,并要格外小心,以防止弯曲的应力离开焊锡芯线的绞合线部分进入他们。
AVR Studio组装来源:morclk041204A
- ;Copy and paste into your assemble.
- ;Copyright 2004 Richard Cappels, projects@cappels.org
- ;Program Name: Send Morse
- ;Version morclk041204A Corrected reversed code for the letter "D".
- ;Mores code message for alarm clock
- ;Pin 20 + 5V.
- ;Pin 15 High Z speaker return. Anti-phase of signal on pin 14
- ;Pin 14 High Z speaker output. Tone with message.
- ;Pin 13 Normally high, goes low during message.
- ;Pin 12 Normally low, goes high during message.
- ;Pin 10 Ground.
- ;Pin 6 - Message starts on negative edge on this pin.
- ;Pins 4 and 5 - crystal oscialltor per datasheet.
- ;Pin 1 may be grounded to terminate message.
- ;Key subroutines:
- ; dottime - set of delay loops to set basic dot time. Interacts with interupt routine.
- ;The dot time is set by adjusting the value loaded into temp at the start of the routine.
- ;Loading 100 into temp gives 1 wpm. Loading 1 into temp gives 100 wmp. Loadign 20 gets 5 wpm.
- ;sendromstring -send a string from Flash ROM. See TypeGreeting for example of use.
- ;sendSerialMorse - sends ASCII Data via serial port and as Morse Code.
- ; ldi temp,'A'
- ; rcall sendSerialMorse
- ;sendnumberMorseASCII -Sends binary nummber in temp as a 3 digit number via serial port and as Morse Code.
- ; ldi temp,123 ;Send the nummber, 123
- ; rcall sendnumberMorseASCII
- ;interword - Delays one inter-word delay period
- ; rcall interword
- .include "2313def.inc" ;Include file in same directory as project.
- ;03e7
- ;Interrupt timer parameters
- .equ intcountlow =$E7 ;Low byte of number of clocks between interrupts.
- .equ intcounthigh =$03 ;High byte of number of clocks between interrupts.
- ;UART baud rate calculation
- .equ clock = 4000000 ;clock frequency
- .equ baudrate = 9600 ;choose a baudrate
- .equ baudconstant = (clock/(16*baudrate))-1
- .def delaycount = r2 ;Counter for delay generation
- .def dotlength = r3 ;Number of 1/100 seconds for dot time.
- .def temp = r16 ;General purpose scratch register.
- .def temp2 = r17 ;General purpose scratch register.
- .def h = r22 ;Binary to decimal conversion.
- .def t = r23 ;Binary to decmial conversion.
- .def u = r24 ;Binary to decimal conversion.
- .def flagreg = r25 ;Flags.
- ;definiton of flagreg bit assignments
- ;0 Status of code out bit last sent (memory used to toggle)
- ;1 True enables toggling of code output
- ;2
- ;3
- ;4
- ;5
- ;6
- ;7
- .equ codeport = PORTB
- .equ codeout = DDRB
- .equ codebit = 2
- .equ pulsebit = 3
- ;definition of I/O
- ;B0 + comparitor input (Reserved)
- ;B1 - comparitor input (Reserved)
- ;B2 Tone (code) output
- ;B3 Anti-phase of signal on B2.
- ;B4 (not assigned - configure as INPUT with weak pullup)
- ;B5 (not assigned - configure as INPUT with weak pullup)
- ;B6 (not assigned - configure as INPUT with weak pullup)
- ;B7 (not assigned - configure as INPUT with weak pullup)
- ;D0 Reserved FOR UART RECEIVE
- ;D1 Reserved FOR UART TRANSMIT -input has weak pullup.
- ;D2 (not assigned - configure as INPUT with weak pullup)
- ;D3 (not assigned - configure as INPUT with weak pullup)
- ;D4 (not assigned - configure as INPUT with weak pullup)
- ;D5 (not assigned - configure as INPUT with weak pullup)
- ;D6 (not assigned - configure as INPUT with weak pullup)
- ;D7 (not assigned - configure as INPUT with weak pullup)
- .cseg
- .ORG $0000 ;Initializaton code
- rjmp start
- .ORG $0001
- rjmp int0service
- .ORG $0004
- rjmp timerservice ;Timer/counter compare interrupt handler
- start:
- ldi r16,RAMEND ;Initialize Stack Pointer.
- out spl,r16
- ;Set PORTD.
- ldi temp,0b00000000
- out DDRD,temp
- ldi temp,0b10111111
- out PORTD,temp
- ;Set PORTB.
- ldi temp,0b00001111
- out DDRB,temp
- ldi temp,0b11110010
- out PORTB,temp
- ldi temp,$40
- out GIMSK,temp
- sei
- ldi temp,$38
- out MCUCR,temp
- sleep
- waithere:
- rjmp start ;Added so it would repeat if interrupt repeated.
- int0service: ;Alarm has gone off, so wake up
- clr temp
- out GIMSK,temp
- out MCUCR,temp
- clr flagreg ;Clear flagreg (flag register).
- ;TIMER 1 SETUP.
- ldi temp,$09 ;Set timer 1 to reset 0000 after compare match. Prescaler = 1X.
- out TCCR1B,temp
- ldi temp,intcounthigh ;Set compare register to establish interrupt frequency.
- out OCR1AH,temp
- ldi temp,intcountlow
- out OCR1AL,temp
- ldi temp,$40 ;Enable interrupt on compare match.
- out TIMSK,temp
- sbi PORTB,0
- cbi PORTB,1
- sei ;Enable interrupts.
- ldi temp,20 ;Set for 10 words per minute
- mov dotlength,temp
- rcall TypeMessage ;Send message three times
- rjmp start ;added so it would repeat message each time interrupted.
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rcall TypeMessage ;Send message three times
- rjmp start ;Go back to sleep
- TypeMessage: ;Type greeting
- push ZL
- push ZH
- ldi ZH,high(2*Message) ;Load high part of byte address into ZH
- ldi ZL,low(2*Message) ;Load low part of byte address into ZL
- rcall sendromstring ;Send it
- pop ZH
- pop ZL
- ret
- Message:
- .db "WAKE UP " "
- .db $0A,$0D
- .db $00,$00
- sendromstring: ;call with location of string in Z.
- push ZL ;Save Z on stack.
- push ZH
- srs1:
- lpm ;Load byte from program memory into r0.
- tst r0 ;Check if we've reached the end of the message.
- breq finishsendstering;If so, return.
- mov temp,r0
- rcall sendSerialMorse ;Send via serial link and as Morse Code.
- adiw ZL,1 ;Increment Z registers
- rjmp srs1
- finishsendstering:
- pop ZH ;Pop Z from stack.
- pop ZL
- rcall interword
- ret
- sendcodedcode: ;Send Coded Morse Code
- ;Shift out morse code from coded character.
- ;Enter with code for character in temp.
- ;Description of data format from David Robinson's web page:
- ;"At this point I was reminded of the N1KDO NHRC-2 repeater controller published
- ;in February 97 QST that had Morse ID. Investigation of the assembler listing (1)
- ;revealed a simple conversion scheme, where all morse characters are encoded in a
- ;single Byte, bitwise, LSB to MSB.; ì0î = dit, ì1î = dah. The Byte is shifted out
- ;to the right, until only a ì1î remains. As an example 3 is encoded as binary 00111000,
- ;which translates to 38 in hexadecimal. "
- morecode:
- cpi temp,0b00000001
- breq codedcodesent
- clc
- ror temp
- brcs senddash ;Send a dash if lsb was a one
- rcall dot ;Send a dot if lsb was not a one
- rjmp morecode
- senddash:
- rcall dash
- rjmp morecode
- codedcodesent: ;Finished sending the coded code.
- ret
- SendMorseAscii: ;Look up coded Morse code and send, followed by rcall to interchar.
- ;Enter with ASCII character in temp. Upper-case, don't process
- ;control characters.
- push ZL
- push ZH
- cpi temp,$20 ;If space character, do interword delay.
- brne SMA1
- rcall interword
- rjmp lookupdone
- SMA1:
- cpi temp,$5B
- brmi upperacse
- andi temp,$5F ;Make upper-case
- upperacse:
- cpi temp,$2A
- brmi lookupdone
- ;Set up pointer into codechart.
- ldi ZH,high(2*codechart) ;Load high part of byte address into ZH.
- ldi ZL,low(2*codechart) ;Load low part of byte address into ZL.
- subi temp,$2A ;Removed offset from ASCII value in temp.
- add ZL,temp ;Add the value to the index.
- clr temp
- adc ZH,temp
- lpm ;Fetch the value from the table.
- mov temp,r0
- rcall sendcodedcode ;Send as Morse Code
- rcall interchar ;Dealy one interchar time
- lookupdone:
- pop ZH
- pop ZL
- ret ;Return
- dot: ;Send dot, wait one dot time.
- sbr flagreg,0b00000010 ;Set flag to send tone.
- rcall dottime
- cbr flagreg,0b00000010 ;Clear flag to send tone.
- rcall dottime
- ret
- dash: ;Send dash, wait one dot time.
- sbr flagreg,0b00000010 ;Set flag to send tone.
- rcall dottime
- rcall dottime
- rcall dottime
- cbr flagreg,0b00000010 ;Clear flag to send tone.
- rcall dottime
- ret
- interchar: ;Wait interchear period with output off -3 dot times
- rcall dottime
- rcall dottime
- rcall dottime
- ret
- interword: ;Wait interword period with output off-6 dot times
- rcall dottime
- rcall dottime
- rcall dottime
- rcall dottime
- rcall dottime
- rcall dottime
- rcall dottime
- ret
- dottime: ;Delay one dot time.
- ;reload values for 100 wmp with 4 MHz Crystal:
- ;temp = 1
- ;temp2 = 20
- ;dealycount = 0 (cleared)
- ;With these interrupt reload values:
- ;.equ intcountlow =$E7
- ;.equ intcounthigh =$03
- ;Using dotlength = 20 (decmimal), dot time is 83.37 milliseconds.
- ;Using dotlength = 200 (decimal), dot time is 833.64 milliseconds
- push temp
- push temp2
- mov temp,dotlength ;<= vary this from 1 to 100 to get 100 to 1 wpm. 20 = 5 wpm; 100 = 1
- moretime3:
- clr delaycount
- moretime2:
- ldi temp2,20
- moretime1:
- dec temp2
- brne moretime1
- dec delaycount
- brne moretime2
- dec temp
- brne moretime3
- pop temp2
- pop temp
- ret
- ;go back
- sendSerialMorse: ;Send ASCII Character via serial port and via Morse Code.
- ;Enter with char in temp.
- push temp
- pop temp
- rcall SendMorseAscii
- ret
- codechart: ;Coded Morse Code look up table. Use ASCII value -$30, so zero = 0, "A" = $11, etc.
- ;Note: Some ASCII characters are silent, and are coded as 0b00000001
- ;Also note: BT (pause) is coded for ASCII "<" and SK (end of contanct) is coded for ASCII "*",
- ;and End of Message is coded for ASCII "+".
- ; * (SK) + (End of Message)
- .db 0b01101000, 0b00101010
- ; ,(comma) - . /
- .db 0b01110011,0b1011110,0b01111010,0b00101001
- ; 0 1 2 3
- .db 0b00111111,0b00111110,0b00111100,0b00111000
- ; 4 5 6 7
- .db 0b00110000,0b00100000,0b00100001,0b00100011
- ; 8 9 : ;
- .db 0b00100111,0b00101111,0b01000111,0b01010101
- ; < (BT) = > ?
- .db 0b000110001,0b00000001,0b00000001,0b01001100
- ; @ A B C
- .db 0b00000001,0b00000110,0b00010001,0b00010101
- ; D E F G
- .db 0b00001001,0b00000010,0b00010100,0b00001011
- ; H I J K
- .db 0b00010000,0b00000100,0b00011110,0b00001101
- ; L M N 0
- .db 0b00010010,0b00000111,0b00000101,0b00001111
- ; P Q R S
- .db 0b00010110,0b00011011,0b00001010,0b0001000
- ; T U V W
- .db 0b00000011,0b00001100,0b00011000,0b00001110
- ; X Y Z [
- .db 0b00011001,0b00011101,0b00010011,0b00000001
- timerservice: ;Service Timer 1
- push temp
- in temp,sreg
- push temp
- sbrs flagreg,1
- rjmp notoggle
- ;Toggle tone output
- sbi codeout,codebit ;Enable code output pin.
- mov temp,flagreg ;Toggle it, using flagreg 0 as memory of last one.
- andi temp,0b00000001
- inc temp
- andi temp,0b00000001
- brne codehigh
- cbi codeport,codebit
- sbi codeport,pulsebit
- andi flagreg,0b11111110
- rjmp toggledone
- codehigh:
- sbi codeport,codebit
- cbi codeport,pulsebit
- ori flagreg,0b00000001
- toggledone:
- pop temp
- out sreg,temp
- pop temp
- reti ;Return from interrupt.
- notoggle: ;Don't toggle port, but delay to equalize interrupt time toggling and not toggling.
- cbi codeout,codebit ;Disable code out pin.
- nop
- nop
- nop
- nop
- nop
- nop
- rjmp toggledone
- .exit
- Liability Disclaimer and intellectual property notice
- (Summary: No warranties, use these pages at your own risk. You may use the information provided here for personal and educational purposes but you may not republish or use this information for any commercial purpose without explicit permission.) I neither express nor imply any warranty for the quality, fitness for any particular purpose or use,or freedom from patents or other restrictions on the rights of use of any software, firmware, hardware, design, service,information, or advice provided, mentioned,or made reference to in these pages. By utilizing or relying on software, firmware, hardware, design, service,information, or advice provided, mentioned, or made reference to in these pages, the user takes responsibility to assume all risk and associated with said activity and hold Richard Cappels harmless in the event of any loss or expense associated with said activity. The contents of this web site, unless otherwise noted, is copyrighted by Richard Cappels. Use of information presented on this site for personal, nonprofit educational and noncommercial use is encouraged, but unless explicitly stated with respect to particular material, the material itself may not be republished or used directly for commercial purposes. For the purposes of this notice, copying binary data resulting from program files, including assembly source code and object (hex) files into semiconductor memories for personal, nonprofit educational or other noncommercial use is not considered republishing. Entities desiring to use any material published in this pages for commercial purposes should contact the respective copyright holder(s).
- :020000020000FC
- :0400000004C014C064
- :10000800B8C00FED0DBF00E001BB0FEB02BB0FE066
- :1000180007BB02EF08BB00E40BBF789408E305BFF9
- :100028008895EFCF00270BBF05BF992709E00EBDC4
- :1000380003E00BBD07EE0ABD00E409BFC09AC198F2
- :10004800789404E1302E15D0DCCF13D012D011D023
- :1000580010D00FD00ED00DD00CD00BD00AD009D0B4
- :1000680008D007D006D005D004D003D002D001D0E4
- :10007800C8CFEF93FF93F0E0EAE809D0FF91EF9142
- :10008800089557414B45205550200A0D0000EF9325
- :10009800FF93C895002021F0002D4ED03196F9CF5E
- :1000A800FF91EF9133D00895013039F08894079586
- :1000B80010F01CD0F9CF1FD0F7CF0895EF93FF931E
- :1000C800003211F423D00FC00B350AF00F750A3235
- :1000D80052F0F1E0E8E40A52E00F0027F01FC8955B
- :1000E800002DE2DF0FD0FF91EF910895926016D0B6
- :1000F8009D7F14D00895926011D010D00FD09D7FAD
- :100108000DD008950BD00AD009D0089507D006D095
- :1001180005D004D003D002D001D008950F931F93C7
- :10012800032D222414E11A95F1F72A94D9F70A9598
- :10013800C1F71F910F9108950F930F91BFDF089595
- :10014800682A735E7A293F3E3C3830202123272FC6
- :1001580047553101014C010611150902140B100411
- :100168001E0D1207050F161B0A08030C180E191D81
- :1001780013010F930FB70F9391FF11C0BA9A092F6C
- :1001880001700395017021F4C298C39A9E7F03C041
- :10019800C29AC39891600F910FBF0F911895BA98A2
- :0E01A800000000000000000000000000F4CF86
- :00000001FF