介绍:
这个制作有点逗。
有趣之一它是使用一台坏仪表的米字管来作显示;
有趣之二是计时的频率用交流的60Hz(国内是50Hz);
有趣之三是用Basic语言编写的。(终于见识到开发AVR的第三种语言了)。
源代码如下:
- ' Andy Maxwell
- ' A 12-hour clock driven by 60hz from the wall.
- ' 13 Feb 2002
- ' Going to drive some numitron tubes in a scale head
- ' I found at a a government surplus place.
- ' Made for Royal Hutchinson because it's so perfect for his office
- ' BASCOM-AVR basic source for the Atmel 90AT2313 microcontroller
- ' Also, there is a 7404 inverter with a diode to clean up
- ' the 60hz from a 9v AC input.
- ' the 9vAC is from an old TRS-80 powersupply I opened up,
- ' took out the 1/2-wave rectifier and capacitor, left the fuse in,
- ' and closed back up.
- ' The input for the 7404 is taken from before the rectifier/7805
- ' powersupply, with a signal diode pointing back towards the powersupply
- ' and connected to an input.
- Dim Clock_t As Integer ' count ticks for a hole second
- Dim Clock_s As Byte ' seconds
- Dim Clock_m As Byte ' Minutes
- Dim Clock_h As Byte ' hours
- ' A flag to alert when a new second has passed
- Dim Clock_newsec As Bit
- ' This cycles at 120Hz (set on each transition from high to low)
- Dim Clock_ticker As Bit
- ' last level of the 60Hz input, used to determine when it changes
- Dim Lastlevel As Bit
- ' clear the clock.
- Clock_h = 0
- Clock_m = 0
- Clock_s = 0
- Clock_t = 0
- ' this is a temp variable
- ' that will hold the hour in either 12 or 24-hour format
- ' used by the display
- Dim Temp_h As Byte
- ' variables for the display routine
- Dim Tempstr As String * 4
- Dim Y As Byte
- Dim Z As Byte
- Dim Tempbyte As Byte
- ' This one holds which digit is being shown right now
- Dim Digit As Byte
- ' what goes out to the Numitron tubes
- Dim Fourdigitdisplay As String * 4
- ' Okay, set all of port B (pins 12 - 19) to high
- Ddrb = &B11111111
- ' ------
- ' Here's stuff to set the clock with
- '
- ' Minutes
- ' set the pin to be an input
- Reset Ddrd.4
- ' If you set a pin to be an input and set the output to be 1
- ' it turns on the internal pullup
- Set Portd.4
- ' Hours
- ' set the pin to be an input
- Reset Ddrd.5
- ' internal pullup
- Set Portd.5
- ' diagnostic output
- ' no longer used
- ' Set Ddrd.3
- ' Reset Portd.3
- ' Military time switch
- ' set the pin to be an input
- Reset Ddrd.2
- ' If you set a pin to be an input and set the output to be 1
- ' it turns on the internal pullup
- Set Portd.2
- ' --- 60Hz square wave (cleaned up by the 7404)
- ' set this guy to be an input,
- Reset Ddrd.6
- ' no pullup resistor
- Reset Portd.6
- Reset Lastlevel
- ' *** Main Program Loop
- Do
- ' See if the 60Hz input is different from the last time
- ' we came through
- If Lastlevel <> Pind.6 Then
- ' We have a state change in the AC
- ' Set the ticker so the clock subroutine can do it's gig
- ' and toggle Lastlevel so we can notice it next time
- Toggle Lastlevel
- Set Clock_ticker
- 'Toggle Portd.3 ' Diagnostic 60hz output
- End If
- ' Go check to see if it's a new second, and update all the
- ' clock_? variables.
- Gosub Check_clock
- ' This is the hour value. Fine if we're in 24-hour military mode
- Temp_h = Clock_h
- If Pind.2 = 0 Then
- ' we are in 12-hour mode
- ' figure out what the 12-hour equivelent is
- Temp_h = Clock_h
- If Temp_h > 12 Then
- Temp_h = Temp_h - 12
- End If
- ' there ain't no zero hour in normal 12-hour clocks
- ' I didn't realize this until I started building
- ' a Nixie clock and Michele pointed it out.
- If Temp_h = 0 Then
- Temp_h = 12
- End If
- End If
- ' format the display. pad with zeros,
- ' and concatenate the hours and minutes
- Fourdigitdisplay = Format(str(temp_h) , "00") + Format(str(clock_m) , "00")
- '' ************ Start OF DISPLAY CODE
- ' each pass through the main do loop, show a different digit
- Incr Digit
- ' wrap around if it's 4.
- If Digit = 4 Then : Digit = 0 : End If
- ' add 1 to the digit count 'cause MID is 1 based
- Y = Digit + 1
- ' and get the digit that we want
- Tempstr = Mid(fourdigitdisplay , Y , 1)
- ' Okay, this is confusing, so pay attention.
- ' The low nibble (4-bits) of portb is connected to the 7448
- ' 7-segment display driver on the old display subboard
- ' Send it Binary Coded Decimal (BCD) and it lights up the right
- ' segments on all the lit tubes. That's the val(tempstr) you see.
- '
- ' The high nibble of portb is connected to the switching
- ' transistors that power the individual digits.
- ' So, we want to power-up digit 1, and send BCD for digit 1
- ' To get just one line high, I raise 2 to the Digit power
- ' and get 1, 2, 4, or 8 (check it out in binary)
- ' then I multiply it by 16 to shift it up to the high nibble.
- '
- ' Then, I add the BCD value of the digit to set the low nibble
- '
- ' Trust me, it works.
- Tempbyte = 2 ^ Digit ' and light up the one line for the common cathode
- Tempbyte = Tempbyte * 16 ' move it up to the high nibble
- Tempbyte = Tempbyte + Val(tempstr) ' add low byte number..
- ' and send it to portb (pins 12-19)
- Portb = Tempbyte
- '' ************ END OF DISPLAY CODE
- ' this is left over from the serial testing
- 'Print Clock_h ; ":" ; Clock_m ; ":" ; Clock_s ; ":"
- ' **** CLOCK SETTING ***
- ' Now, this is the clock setting routine
- If Clock_newsec = 1 Then
- ' we've got ourselves a new second!
- ' clear the flag.
- Reset Clock_newsec
- ' see if they've pressed the Minute set button
- If Pind.4 = 0 Then
- ' if so, increment the minute counter
- Incr Clock_m
- ' reset the seconds
- Clock_s = 0
- ' if we're over 60 minutes, set it back to zero
- If Clock_m = 60 Then Clock_m = 0
- End If
- 'ditto for the hours button
- If Pind.5 = 0 Then
- Incr Clock_h
- Clock_s = 0
- If Clock_h = 24 Then Clock_h = 0
- End If
- End If ' clock_newsec = 1
- Loop ' go back to the loop
- '---------------------------------------
- Check_clock:
- '---------------------------------------
- 'output: Clock_t,h,m,s
- If Clock_ticker = 0 Then
- ' we haven't seen a change in the 60Hz line
- Return
- End If
- ' If we're here, we have seen a change in the 60hz line
- ' either up or down
- ' reset the flag so we'll notice it next time
- Reset Clock_ticker
- ' and increment the sub counter
- Incr Clock_t
- ' this is 120Hz because it's counting -transitions-.
- ' the up and the down of the 60hz wave each count as one
- If Clock_t = 120 Then
- ' Woo! It's been a full second!
- Clock_t = 0
- ' this is the flag for the time setting routine
- Set Clock_newsec
- ' Now, increment each unit counter by one and see if we've overflowed
- ' TICK
- Incr Clock_s
- ' Did we overflow the seconds?
- If Clock_s = 60 Then
- ' reset the seconds to zero
- Clock_s = 0
- ' and bump up the minutes counter
- Incr Clock_m
- ' and so forth...
- If Clock_m = 60 Then
- Clock_m = 0
- Incr Clock_h
- If Clock_h = 24 Then
- Clock_h = 0
- ' here are all the end ifs from the incrementers
- End If
- End If
- End If
- End If
- ' and return to the main loop
- Return
- ' **** END OF PROGRAM