Ds1307 Bascom Programmer
The timekeeping will be done by a DS1307 IC. This is a handy little IC, because it not only keeps track of time but also of the date and the day of the week. For this little project we'll only use it to keep track of the time. Therefore it needs a 32.768kHz quartz crystal connected between pins 1 and 2.
Apr 18, 2008. In this example I use an Arduino board as the bus master and have just one slave device on the I2C bus, a DS1307. You can read the DS1307 data sheet here. As I mentioned before Arduino has a library called Wire that handles all the details of the I2C protocol. Wire uses analog pin 4 for the Serial Data. Programming AVR MCUs using BASCOM - Crash Course 2012 Details about the Course: Session-01 Topics: - Introduction to Embedded Systems. Session-03 Topics: - Introduction into Bascom-AVR Instruction Set. Programming DS1307 RTC Chip.
We can also add a battery with + to pin 3 and - to pin 4. This enables the IC to keep working when the mainpower is switched off. If you don't want to use this feature, you can just connect pin 3 to pin 4 and everything will work fine. Pin 5 and pin 6 will be used to transfer the data to our microprocessor. They should be connected to the SCL and SDA pins on your microprocessor.
These lines need to be pulled high by a 4K7 pullup resistor. Bascom makes working with I2C devices easy.
You only need to know 4 commands: • I2cstart: This commant will startup I2c communications • I2cstop: This command will stop I2c communications • I2crbyte var: This command reads a byte from the device and stores it in 'var' • I2cwbyte var: This command writes the variable 'var' to the device Using the write or read command is not enough, we will also have to tell the device whether we want to write to it or read from it. We do this by using the right address. These addresses can be found in the datasheet. The write-address for the DS1307 is D0H and the read-address D1H (the H behind it tell us that these are hexadecimal figures). The DS1307 sends and wants to receive data in BCD format. This is a variation on binary for diplays where every digit is represented by four bits.
More about that. Luckily converting from BCD to decimal and visa versa is very easy in Bascom. • var = Makebcd(var) will convert decimal, hex and binary into BCD • var = Makedec(var) will convert hex, binary and BCD into decimal The data is stored on the IC in register.
You can imagine them as those oldfashioned filingcabinets. Each drawer has its number and contains some info: 00H Seconds 01H Minutes 02H Hours 03H Day 04H Date The H tell us that these are hexadecimal figures. 05H Month 06H Year 07H Control 08H to 3FH Ram If we want to read or store some data we'll first have to tell the device in which drawer we want to be. We can do this by writing the hex code for that drawer to the device. The device then will grant us acces to that drawer. After you write or read something from or to this register the device will automatically jump to the next one.
So there is no need to send the location every time Now lets put this in code: For this code you will need to dim hours as byte, minutes as byte and seconds as byte. First, we will set the clock: Seconds = Makebcd(Seconds) We convert our variables into BCD format Minutes = Makebcd(Minutes) Hours = Makebcd(Hours) reset hours.6 We reset bit 6 of the hoursbyte to make sure that our Clock runs in 24h modus. If bit 6 is 1 then the clock runs in 12h modus and bit 5 will then contain the AM/PM data. I2cstart I2cwbyte &HD0 We tell the device that we want to write a byte 2cwbyte &H00 We start at the register for seconds hex 00 I2cwbyte Seconds Adding seconds I2cwbyte Minutes Adding minutes I2cwbyte Hours Adding hours I2cstop Now our clock is set! Lets read from it now. I2cstart I2cwbyte &HD0 We tell the device that we want to write a byte.
I2cwbyte &H00 We ask the device to go to the seconds register. I2cstop I2cstart I2cwbyte &HD1 We tell the device that we want to read bytes. I2crbyte Seconds, Ack We read the data and acknowledge that we want to read the next byte too. I2crbyte Minutes, Ack I2crbyte Hours, Nack We don't ackowledge here so the device knows that we are done reading. I2cstop Hours = Hours And &B00111111 We remove bits 6 and 7 as they contain other data.
If you are in 12h modus, then you need to remove bit 5 too Hours = Makedec(Hours) We convert back to decimal format. Minutes = Makedec(minutes) Seconds = Makedec(seconds) Now we know what time it is. In the next step we will take a closer look at the DS18B20. The DS18B20 is a so-called 1wire device. Sadly, as with many things in life, this description was made up by some clever salesmen as we need at least two wires for it and in our case even three. There are two ways to set up a DS18B20: • With parasite power • With external supply To know more about these options, just check the datasheet. The data line DQ will need a 4K7 pullup resistor and can be connected to the vast majority of pins on your microcontroller.
Communication with a 1wire device is, again, not very difficult in Bascom. There are some commands but we only need three of them for this project. • 1wreset: This commands resets the communication • 1wwrite var: This command writes 'var' to the device • 1wread var: This command reads from the device into 'var' We also need to setup the 1wire bus with the following code: config 1wire = pinX.y Where X is the name of the port and y the number of the pin.
Lets try to put this all into code now: We will use the DS18B20 in 12bit mode (default setting) so every bit corresponds with 0.0625degr C or to put it easier: we will have to divide the result by 16 to get the temperature. For this code you will need to dim tempdata(9) as byte and temperature as integer. Config 1wire = portd.0 This tells the microcontroller whereto look for the device. 1wreset resets and starts the communication 1wwrite &HCC This skips transmitting the unique ROM code for the device. This code is needed when there are more devices on the same wire but we have only one so we can skip it. 1wwrite &H44 Starts the A/D convertion in the sensor and stores the data into the scratchpad waitms 750 The convertion in 10bit mode can take upto 750ms so we wait 750ms before we start to read the scratchpad.
1wreset 1wwrite &HCC 1wwrite &HBE Tells the device that we want to read the scratchpad. Tempdata(1) = 1wread(9) We read 9 bytes into tempdata(), starting from tempdata(1). If tempdata(9) = Crc8(tempdata(1), 8) Then This checks the validity of the data and Temperature = Makeint(tempdata(1), tempdata(2)) combines the 2 first bytes into an integer.
Temperature = temperature / 16 By dividing this integer by 16 we have our temperature in degr C. End If We have our sensor working now. In the next step we will talk about the buttons. To set the time we need some sort of inputdevice. In this project, we will use two buttons.
These buttons are connected to the interrupt -pins on the atmega48 (pind. Ibm Usb Serial Parallel Adapter 22p9036. 2 and pind.3). An interrupt does, as its name suggests, interrupt the program to do a little routine.
When the interrupt is done, the program continues where it was interrupted. There are lots of different interrupts triggered by internal events caused by timers, comparators. But we will use 2 external interrupts triggered by the two buttons. The buttons connect the interrupt pins with ground while a 1K5 pullup resistor keeps the pin high (the interrupt is triggered when the pin goes low). At the begining of our code, we'll need to setup the interrupts. Config INT0 = Falling The interrupt is triggered on the falling edge.
On INT0 button1 When the interrupt is triggered the program will jump to label button1. Enable INT0 Enables this interrupt config INT1 = Falling On INT1 button2 When the interrupt is triggered the program will jump to label button2.
Enable INT1 Enable interrupts Enables the use of all interrupts At the end of the code, after the End - Statement, we will put the 2 needed labels with the routine. Button1: code to set the hour Return Button2: code to set the minutes Return One important thing to remember is that you cannot trigger an interrupt inside the routine of another one! Now that we are able to set the time, we can look at our display aka the numitrons in the next step.
Step 4: The Numitrons. I bought some IV-9 numitrons rather cheaply, so this clock/thermometer was an ideal opportunity to use 4 of them. They come with long leads so they can be soldered directy onto your pcb.
The numitrons came with a very handy Russian datasheet (I really need to learn Russian.). After some testing I found out that they need between 3,5V and 4,5V and that the current per fillament is approx. Numitrons are 7 segment displays, so we need to build up our digits with these segments.
There are lots of IC´s to drive 7 segment diplays like the HEF4511 (BCD to 7 segment) but to save space on the pcb, we will drive them directly with the microcontroller. To do so, we will use portb to drive the 7 segments and to the first four pins of portc to multiplex inbetween the four numitrons. When you use multiplex numitrons, you need to use diodes on all pins, except the common one. This to prevent 'ghost digits' in other numitrons. I used the very common 1N4007 for my clock.
Contoh Telaahan Staf Polri here. Earlier, I stated that numitrons need between 3,5V and 4,5V. But when we multiplex them, you won't see anything happen. As we enable each numitron for only 5ms at a time, we'll need a higher voltage to make the fillaments glow. Any voltage between 7,5V and 12V will work fine, but I choose 7,5V because I didn't want them to be to bright. As we use a higher voltage for the numitrons than for our microcontroller, we'll need some transistors too. I used the common 2N3906 PNP-transistor to drive the segments and the BD137 NPN transistor to assist the multiplexing.
Now for some code: First of all: when we want to display time on four numitrons, we'll need to split it into 4 digits. There are numerous ways to do this, but I do it with this code: For this code you'll need to dim tube(4) as byte and temp as byte. The digits are numbered from right to left so the minutes have numitron 1 and 2 and the hours 3 and 4. Tube(2) = Mins / 10 Temp = Tube(2) * 10 Tube(1) = Mins - Temp Tube(4) = Hours / 10 Temp = Tube(4) * 10 Tube(3) = Hours - Temp So if the time is 09:24: tube(2) = 24/10 = 2 (the decimals are dropped) temp = 2*10 = 20 tube(1) = 24-20 = 4 tube(4) = 9/10 = 0 temp = 0*10 = 0 tube(3) = 9-0 = 9 Now that we have the digits, we can multiplex them: For this code, you need to dim i as byte and j as byte. For I = 1 To 4 Temp = 7seg(tube(i)) Portb = Temp J = I -1 Set Portc.j Waitms 5 Reset Portc.j Next This code selects one of the numitrons, converts its corresponding value into 7 segments and enables it to light up by setting the right pin of portc high for 5ms. As the numitrons are numbered 1 to 4 and the pins 0 to 3, variable j will be variable i substracted by 1.
Now last but not least the 7seg-function: We'll add this funtion in the code to convert the value of the digits into a 7 segment pinout for portb. First we need to declare the function. Declare Function 7seg(byval Q As Byte) As Byte Then at the end of the code we will add the code for the function.
Function 7seg(byval Q As Byte) As Byte Select Case Q Case 1: 7seg = &B01111100 Case 2: 7seg = &B00010010 Case 3: 7seg = &B00011000 Case 4: 7seg = &B00101100 Case 5: 7seg = &B00001001 Case 6: 7seg = &B00000001 Case 7: 7seg = &B01111000 Case 8: 7seg = &B00000000 Case 9: 7seg = &B00001000 Case 0: 7seg = &B01000000 End Select End Function Important here is that, as we used PNP transistors, a 0 means that the segment is activated and a 1 that the segment is deactivated. If you wire your munitrons differently to portb, you'll need to find out which bit is needed for each segment. In the next step we'll look at the brains of our contraption: the atmega48. The atmega48 is the brain of our contraption. It wil collect all the data from the clock and the thermometer and put it onto our display.
We won't use an external crystal for this project but the internal 8MHz oscillator. There are 2 reasons for that. First of all we don't need a very accurate or highspeed timing and secondly we can use portb.6 for our 7 segments.
The only 2 things that our atmega needs is power and a way to program it. For power, we hook up VCC to 5V and the 2 GND pins to ground (we also add a 100nF capacitor between VCC and GND). To connect the atmega with you ISP- programmer, you just have to connect MOSI to MOSI, MISO to MISO, SCK to SCK and reset to reset. (I added a schematic in the images) At the begin of our code, we'll need to tell the compiler a few details about our microcontroller. First of all we need to tell which microcontroller we use: $regfile = 'm48def.dat' Then we need to tell what clockspeed we use (in Hz): $crystal = 8000000 Then there are some other bits and bobs we need to discribe(I won't go into detail about them here): $hwstack = 32 $swstack = 8 $framesize = 24 After this, you can start to write your code.
In the next step, we will bring everything together. I really wanted this project to look as nice as possible, so I invested a lot of time in the overall design and building the case. I hope that this build is awesome enough to have a chance in the lasercutter contest as I would love to have one of these machines. They would allow me to make even nicer looking and more intricate cases and parts. Also making gears would be a lot easier, so I would be able to make complex mechaninical movements.
A lasercutter would be the ideal solution, as I work a lot with acrylate and other plastics. It would enable me to make designs that that a CNC-router can't make and I wouldn't have to bother my friends all the time to use theire machines. It would ofcourse also be great for my friends, who also happen to build a lot of stuff, to have access to such a device.
So it would surely boost the creativity of those people around me too ( they would surely pay me a lot more visits;) ). I have no commercial intensions with the machine, just building stuff and helping people build theire projects and ofcourse sharing everything on Instructables. Pin Connection: 1 common 2 right hand deciamal point 3 Segment (b) 4 Segment (c) 5 Segment (a) 6 Segment (f) 7 Segment (g) 8 Segment (d) I did cut pin 2 because I did't use the decimal point, So i ended up with 8 pins instead of 9. You don't need a blank out option. You can put a powerswitch on the powercord of the device.
The battery of the DS1307 will take over the power for the timekeeping and all other functions are switched off. The battery can power a DS1307 for a few years so no worries there.