Vous êtes sur la page 1sur 80

REMOTE-CONTROLLED REAL-TIME CLOCK WITH DEVICE CONTROLLER\

ABSRACT :This project makes use of a TV remote control. Using RC5 coding, a real-time clock chip is set to control five different alarm settings. These settings can also be used to switch on an external device. Up to eight devices can be controlled with this project. The circuit is based on ATMEL ATmega16 microcontroller and Maxims DS1307 real-time clock chip. An LCD module allows for user interface.

Block diagram of remote-controlled real-time clock with device controller

CIRCUIT DESCRIPTION Fig. 1 shows the block diagram of the remote-controlled real-time clock with device controller. It comprises six sections, namely, IR detector remote control sensing and decoding unit, realtime clock, LCD interface, device switching unit, microcontroller and power supply unit The microcontroller unit integrates all the sub-systems and system software the circuit of the device controller. REMOTE CONTROL SECTION. This circuit makes use of a Philips TV remote for device switching and RTC parameter setting. It uses RC5 coding format, which is also known as biphase coding. In RC5-coded signal, each bit has a uniform duration. Table I shows how all the commands of RC5 remote control are encoded. The first two bits designated S are start bits, which are used to adjust and synchronise the receiver. These bits are used to calculate and analyse the bit length of other bits. The third bit is a toggle bit (T), which toggles every time a button is pressed at the remote control. This bit is used to identify whether the button is really pressed or whether

an obstacle came in between the path of the IR remote and IR receiver. Bits A4 down to A0 are used to identify the device. So a maximum of 32 devices can be interrogated to respond individually to the same type of coding without any disturbance. Bits C5 down to C0 are control/command bits. Therefore a maximum of 64 commands can be equipped in an RC5 type remote. Decimal equivalent of a few command codes used in this project are listed at Table II. Pressing any command/ control button on the remote generates code signal, which is received by IR receiver-demodulator (TSOP1738). The output of the IR demodulator is normally high, which changes to low when any of the buttons on the remote is pressed. It is fed to PD3 through the I/O interface line of the microcontroller. The microcontroller decodes the incoming RC5 data stream and subsequent actions are taken based on the this information. LCD UNIT. The LCD module (16- character2-line) is interfaced with the microcontroller. Data pins 7 through 14 of the LCD module are connected to port A (PA0 through PA7) of the microcontroller. Register-select (RS) pin 4 and enable pin (pin 6) of the LCD are interfaced with PC1 and PC2 of the microcontroller, respectively. R/W pin of the LCD (pin 5) is pulled low permanently and thus is always in writing mode. Back light of the LCD is controlled by PD0 line of the microcontroller with the help of transistor T1. All the information is displayed on the LCD, which forms the basic user interface unit. Real-time clock. IC DS1307 (IC2) from Maxim (Dallas Semiconductor) is a serial RTC chip with calendar function. This chip also incorporates 56 bytes of NV RAM. Data and address are transferred serially through I2C bidirectional bus, which obviates the need for a large number of interface lines. The bidirectional data is read and written with the help of just two I/O interface lines. In this chip, the clock operates in either 24- or 12-hour format with AM/PM indicator. In calendar mode, end of the month is automatically adjusted for the months with less than 31 days and leap year compensation is valid up to year 2100. The memory map of DS1307 (also referred toas time keeper register map) is shown in Table III. For setting the clock and calendar at power- on, the data is first written to the designated memory location of the RTC chip and, during the normal operation. It is read back from each specific memory location during the clock and calendar display functions. The alarm settings are stored in NV RAM; these can be deleted and altered at any given point of the operation. All this is achieved with the help of the system software. In the project, only five alarms have been allowed but the same can be changed as per requirement; only the alarm limits have to be changed. Clock pulse to the RTC is provided by a 32.768kHz crystal. As per the convention of I2C interface communication, the device address while writing into DS1307 chip is 0xD0 (in binary format 11010000) and while reading the data from DS1307 the device address is 0xD1 (in binary format 11010001). Due to this unique device addressing technique, a number of I2Cinterfaced chips can be attached on SCL and SDA interface lines of RTC. Thus, at a given time, only one I2C device will respond to the data on the I/ O interface lines. DEVICE CONTROL. Devices are connected to contacts of the relay and relays are controlled through the outputs of IC4. Port B of IC1 (PB0 through PB7) is interfaced with pin 8 down to pin 1 of IC4 (ULN2803) to control relays RL1 through RL8, respectively. Five out of eight devices (device 1 through 5) switch on with their respective alarm settings and the remaining three devices switch on directly. Whenever an alarm is activated for a particular setting, the respective de vice is switched on. The device can be switched off only by pressing the respective key number on the remote control. CONTROLLER. The controller unit is based on ATmega16 low-power, 8-bit CMOS microcontroller with AVR enhanced RISC architecture. This microcontroller has 16 kB of insystem programmable flash memory, 512 bytes on EEPROM, 1 kB of SRAM, two 8-bit timers, one 16-bit timer, 32 general-purpose I/O lines and 32 general-purpose working registers. It integrates all the subsystems to form a complete unit. Although this

microcontroller already has an RTC counter and I2C lines, we have used a separate RTC chip and special I2C software to show the functionality with the dedicated RTC chip, which is much easier to control and manage in terms of time keeping as well as achieving calendar functions. Regarding I2C, we wanted to show how the same can be achieved with the help of the software without alarm limits have to be changed. Clock pulse to the RTC is provided by a 32.768kHz crystal. As per the convention of I2C interface communication, the device address while writing into DS1307 chip is 0xD0 (in binary format 11010000) and while reading the data from DS1307 the device address is 0xD1 (in binary format 11010001). Due to this unique device ddressing technique, a number of I2Cinterfaced chips can be attached on SCL and SDA interface lines of RTC. Thus, at a given time, only one I2C device will respond to the data on the I/O interface lines. DEVICE CONTROL. Devices are connected to contacts of the relay and relays are controlled through the outputs of IC4. Port B of IC1 (PB0 through PB7) is interfaced with pin 8 down to pin 1 of IC4 (ULN2803) to control relays RL1 through RL8, respectively. Five out of eight devices (device 1 through 5) switch on with their respective alarm settings and the remaining three devices switch on directly. Whenever an alarm is activated for a particular setting, the respective dethe use of any specialised hardware functionality of the microcontroller; and also help the user to implement the same on any other microcontroller that does not have the dedicated facility of I2C interface. This controller unit first uses serial data received from the IR detector to get the information regarding the pressed key and then takes the appropriate action, and also updates the information on the LCD side-by-side. When in operational mode, the microcontroller reads the data from the RTC chip every one second (achieved through timer interruptscompare mode). During this 1-second interrupt, it checks for the alarm setting, controls the snooze, and also updates the time/ date information on the LCD. In between, it checks the data from the IR detector and takes action accordingly. POWER SUPPLY. Fig. 3 shows the power supply circuit. The 230V, 50HzAC mains power supply is stepped down by transformer X1 to deliver a secondary output of 15V at 500 mA.The transformer output is rectified by a full-wave bridge rectifier BR1, filtered by capacitor C6, and regulated by IC5 and IC6. IC5 and IC6 output is 5V and 12V, respectively. The regulated 12V is used for relay-driver IC4 and the rest of the circuit operates with 5V. Capacitors C7 and C8 bypass any ripple present in the regulated power supply. An actual-size, single-side PCB pattern for the remote-controlled real-tim clock with device controller (Fig. 2 and Fig. 3) is shown in Fig. 8 and its component layout in Fig. 9.

Circuit of remote-controlled real-time clock with device controller

Power supply

Actual-size, single-side PCB for the remote-controlled real-time clock with device controller

Component layout for the PCB

SOFTWARE

The system software is used to achieve integration and functionality. The software for this project is written in C language and compiled using WINAVR. WINAVR is available free of cost for Windows and Linux operating systems. It is capable of handling all the AVR functionalities like UART, timer, ADC, interrupts, etc and offers the facility of writing the program in C. The finally obtained Intel hex code file was burnt into AVRs flash memory using a suitable programmer. The microcontroller uses a 4MHz internally generated clock. To activate, fuse bytes have to be programmed as follows: Fuse low byte = D3 Fuse high byte = 99 The software for the entire project was written in modules in accordance with the functionality of each subsystem. The files used in this project are shown in Table IV. The ds1307.c file contains the codefor controlling the functions related to serial DS1307 RTC. The chip uses I2C interface, which essentially uses only two I/O interface linesSDA and SCLfor bidirectional address and data communication. This file essentially uses subroutines, which have been indicated in the I2Cmaster.h header file. Subroutines i2c_write( ) and i2c_read( ) are used for writing and reading the data to and from the RTC chip through DS1307_write( ) and DS1307_read( ), respectively. The Assembly code for the complete I2C operations and communication is written in the I2Cmaster.S file, which has been written for 4.00MHz operation, and for this reason, the microcontrollers fuses have been set to use the internal 4.00MHz clock. The data stored in the RTC chip is in BCD format. The BCD data is changed into binary format for normal processing and displaying. For this purpose, the BCD2bin( ) subroutine is used. Similarly, the user data is first converted into BCD format with bin2BCD( ) sub-routine and then written into the RTC chip. This file contains all the sub-routines that are used in rclock.c file modules. I2C-interfaced chips are initiated in a particular sequence for their proper functioning, and this has been taken care of during initialisation and reading/ writing data from/to DS1307. The user alarm settings are stored in the NV RAM of DS1307 in two fields, namely, hours and minutes. In this project, a maximum of five alarm settings have been allowed but this number can be increased by changing the variable MAX_ALARM value (in lcd.h file). Whenever the alarm setting data is to be viewed, altered, deleted or added, the program checks the user SRAM area, and based on the value stored in the ALARM_COUNT_RGST memory location, further action is permitted. While clock is functioning, the data from this SRAM area, which has now been allocated to an array, is checked and the desired action is taken when the alarm setting data matches the current time. I2CMASTER.S AND I2CMASTER.H. These files are related to control of the I2C interface communication. The details of the SCL and SDA pins and I/O interface line are defined in the i2cmaster.s file and the Assembly code file is compiled along with other code files; the parameter to be used in makefile for this file is ASRC. Lcd.C This file contains the code for control of functioning of the attached LCD module. The code controls the initialisation of the LCD, data writing on the LCD, and also the movement, characteristics and location of the cursor. It offers the facility to write data on the LCD character-by-character or string-wise. The command set used in the software is based on the command set used in the LCD based on Hitachi HD44780 ICs. Lcd.H This header file contains all the constant variable values and names of the subroutines used by various files used in the software. It clearly indicates which variable can be used as a global variable and which of the subroutines can be used across the software files. RCLOCK.C This file contains the code that integrates all the subunits together. It contains the code that will call the initialisation routines to initialise I2C chip, LCD, microcontroller ports, set timer and its IRQ, check data from the IR detector, extract information regarding the key pressed, etc. Depending upon the key pressed, the file initiates the change in RTC data like year, month, day, date, hours and minutes and also in viewing, deleting and adding new alarm settings. It takes control of the devices attached to the unit and controls their status depending upon the alarm settings. All the above-mentioned functions are implemented in this file by means of specific implementation of sub-routines and global variables wherever required. All the sub routines used in the various files are clearly marked and commented for their functionalities with codes explained. The entire project software was compiled and

debugged with WINAVR development environment, which is based on avr-gcc 3.3.1 (WinAVR-20030913). REMOTE CONTROL OPERATION The entire device operation is controlled through keys of the Philips remote control. The remote keys are used as shown in Table II. The functions of these keys are given below. Key 0 is used to change the setting of the RTC. When the RTC is functioning normally, it can be switched to setting mode by pressing the 0 key and immediately the cursor will blink on the hour field, indicating that this value can be changed through volume up and volume down keys to a desired value. Keys 1 through 8 are used, during normal operation, to control the state of the external devices. Key 1 is used to control Device 1 and so on. Devices 1 through 5 are switched on according to the alarm timing also; however, these can be switched off by pressing the respective key on the remote control itself. Keys 1 through 3 are also used in the Alarm menu. Key 1 is used to add a new alarm value to the alarm table. Key 2 is used to delete the alarm setting for the table (by changing Yes/ No field with volume up/down key). Key 3 is used to scroll through the alarm settings by use of channel up and down keys. Power key is used for deactivating the alarm and also returning one setup back in the Alarm menu. Whenever you want to return from the Alarms sub-menu (like New, Del and See), press this key. Also, this key is used to return from the Alarm menu to display screen. Mute key is used to change the field (from hour to minute to day of the week to day of the month to month of the year and, finally, the year and back to hour and so on and so forth). Volume Up and Down keys are used to change the value of a given field when setting the clock data or the alarm data. TV/AV key starts the RTC functioning once the desired settings have been made. This remote control key acts as Enter key (confirmation key). Timer key takes the user to alarm setting menu. CLOCK MODE SETTING When the RTC is switched on, the screen display is as shown in Fig. 4. The second field value shows 40 seconds. These indicated initial values have been set in subroutine i2c_initialisation( ). If some other values are required, the desired values can be written. The cursor blinking on the hour field indicates that value can be changed through volume up and down keywhich will now change the hour value from 0 to 23 hours and back to 0 again Once the desired value of the hour has been achieved, you can change to minute field by pressing Mute key. The change of field is indicated by cursor blinking on the appropriate field (here minute field). Value of minutes can be changed from 0 to 59 and again to 0. Again, after the desired value has been achieved, the field can be changed to week day by pressing Mute key. Now week days can be changed by pressing volume up and down keys. Next field-change data is related to day of the month (the date can be changed from 1 to 31) and after this, the month of the year can be changed (from January to December). The year can be changed from 00 to 99. Take care when setting the month and the days in that particular month. The process remains the same when setting the alarm value also, where only hour and minute fields are available for setting. Once the setting has been made as per the requirement, TV/AV key can be set and now the clock will start functioning with the desired settings. The functioning of the clock can be observed by change in the second field. ALARM SETTING As explained earlier, the given design allows five alarm settings with snooze facility and control of five devices only. You can enter the alarm menu by pressing Timer key. The screen at this point of operation is shown in Fig. 5. Through this menu, you can set new alarm (1New), delete alarm setting (2Del) and view alarm settings (3See). The respective menu can be activated by pressing key 1, 2 or 3. In new setting mode, if five alarm settings have been made, the same is indicated by a Full sign. In case new setting has to be made, an already exisiting alarm setting has to be deleted and then only new alarm setting will be

allowed. To return from New mode to Alarm menu, press Power key. If space is available for new alarm setting, you can change hour-field data and minute-field data by using Volume Up, Volume Down and Field keys, i.e., Mute key. Once the desired settings have been made, pressing the TV/AV key stores the alarm settings in the NV RAM of the DS1307 chip. To delete an alarm setting, first press key 2. The display will be as shown in Fig. 6.The alarm settings/values can be scrolled with the help of Channel Up and Channel Down keys. For a setting that is to be deleted, change the status of the indicator from No to Yes by Volume Up and Volume Down keys. Then delete data by pressing TV/ AV key and immediately the message Deleting Data is displayed, indicating that one alarm setting has been deleted. To view the alarm setting data, you can use key 3 in Alarm menu. The screen at this point will be as shown in Fig. 7, which indicates the total number of alarm settings in the memory (Tot:) and data being viewed. You can scroll through the data with the help of Channel Up/Down key. As you scroll though the data, the field Data: indicates the alarm setting as per the programmed sequence. The device-control field number will be the same as Data: field number. (If Data:5, the device to be controlled will be 5, and if Data:1 device 1 is attatched with this data field.) If no alarm data is found in the memory, No Alarm Data is shown on the LCD. In New and Del sub-menus of Alarm menu, TV/AV key is used to confirm the desired setting/action. To cancel settings/actions, press Power key at any time of the operation. By default, all the five alarm settings have been made initially through the software. These values can be changed in sub-routine dummy( ) found in the ds1307.c file. As soon as the alarm is activated, the LCD backlight glows periodically along with the buzzer sound. Deactivate the alarm with Power key; however, the respective-controlled device will continue to be on. The alarm can be put into snooze mode by pressing any key on the remote control. In snooze mode, the buzzer will not sound but LCD backlight will glow. The snooze delay can be changed by setting the constant snooze_delay variable (in the lcd.h file) to a desired value. No doubt the alarm time can be set in any sequence; the external device will switch on in a sorted time sequence. For example, if the alarm time is 01:21' at location-3 and 01:10' at location-5, device-5 will switch on at 01:10' and device-3 will switch on only at 01:21, even though in the alarm sequence the location of device- 3 is before device-5. When the clock is switched on, all the controlled external devices are in switched-off condition. In snooze mode, the alarm can be de-activated by pressing Power key. All the external devices can be switched off simultaneously by pressing S1. This will work only in normal functioning of the device and not during the alarm mode. The project was assembled on a general-purpose PCB.

CKT DIAGRAM

5v R6 10k R11 120

C5 20uF/25v

10

U4

R4 SW1 2.2k

Q1 SL100 R10 50 R9 10k

vcc

RESET

SW TACT-SPST pd1 pd0 15 14

11 12 13 14 15 16 17 5v 18

1 2 3 4 5 6 7 8

PB0 PB1 PB2 PB3 PB4 PB5 PB6 PB7

lcd pa0 pa1 pa2 pa3 pa4 pa5 pa6 pa7 PC2(tck) PC1(sda) PC0 Pd6 40 39 38 37 36 35 34 33 24 23 22 20 1 2 3 4 5 6 7 8

ATmega16 CRY STAL Y1 1 2 3 4 R2 10k R1 10k U8 X1 X2 VBAT GND DS1307 5v R5 220 5v R3 10k

VCC

SDA SCLK

5 18 6 19 pd4 pd5

24 23

17

11 11

17

31

31

R12 2.2k

J3 buzzer

5v

J2 I RX TSOP1738 + C1 1u/16v

Q2 SL100

Title <Title> Size A Date: Document Number <Doc> Friday , March 28, 2008 Sheet 1 of 1 Rev <Rev Code>

1 2

5v lcd

J1
16

1 2 3 4 5 6 7 8 24 23

7 8 9 2 10 11 12 13 14 CON16 6 4
1 5 1 3

15

R8 3 2 POT

Title <Title> Size A Date: Document Number <Doc> Friday , March 28, 2008 Sheet 1 of 1 Rev <Rev Code>

5v J4 2 1 CON2 U9 LM7805/TO 1 DIODE VIN VOUT 3 2 C3 1 0.1u J6 1 2 CON2 100 D2 LED 12v R14

D3

GND

12v U10 LM7812/TO 1 VIN VOUT 3

GND

Title <Title> Size A Date: Document Number <Doc> Friday , March 28, 2008 Sheet 1 of 1 Rev <Rev Code>

INTERFACING SECTION

MICROCONTROLLER (AT89S52):CRITERIA FOR CHOOSING A MICROCONTROLLER The basic criteria for choosing a microcontroller suitable for the application are: 1) The first and foremost criterion is that it must meet the task at hand efficiently and cost effectively. In analyzing the needs of a microcontroller-based project, it is seen whether an 8bit, 16-bit or 32-bit microcontroller can best handle the computing needs of the task most effectively. Among the other considerations in this category are: (a) Speed: The highest speed that the microcontroller supports. (b) Packaging: It may be a 40-pin DIP (dual inline package) or a QFP (quad flat package), or some other packaging format. This is important in terms of space, assembling, and prototyping the end product. (c) Power consumption: This is especially critical for battery-powered products. (d) The number of I/O pins and the timer on the chip. (f) How easy it is to upgrade to higher performance or lower consumption versions. (g) Cost per unit: This is important in terms of the final cost of the product in which a microcontroller is used. 2) The second criterion in choosing a microcontroller is how easy it is to develop products around it. Key considerations include the availability of an assembler, debugger, compiler, technical support. 3) The third criterion in choosing a microcontroller is its ready availability in needed quantities both now and in the future. Currently of the leading 8-bit microcontrollers, the 8051 family has the largest number of diversified suppliers. By supplier is meant a producer besides the originator of the microcontroller. In the case of the 8051, this has originated by Intel several companies also currently producing the 8051. Thus the microcontroller AT89S52, satisfying the criterion necessary for the proposed application is chosen for the task.

DESCRIPTION: The 8051 family of microcontrollers is based on an architecture which is highly optimized for embedded control systems. It is used in a wide variety of applications from
. . .

military equipment to automobiles to the keyboard. Second only to the Motorola 68HC11 in eight bit processors sales, the 8051 family of microcontrollers is available in a wide array of variations from manufacturers such as Intel, Philips, and Siemens. These manufacturers have added numerous features and peripherals to the 8051 such as I2C interfaces, analog to digital converters, watchdog timers, and pulse width modulated outputs. Variations of the 8051 with clock speeds up to 40MHz and voltage requirements down to 1.5 volts are available. This wide range of parts based on one core makes the 8051 family an excellent choice as the base architecture for a company's entire line of products since it can perform many functions and developers will only have to learn this one platform. The AT89S52 is a low-power, high-performance CMOS 8-bit microcontroller with 8K bytes of in-system programmable Flash memory. The device is manufactured using Atmels high-density nonvolatile memory technology and is compatible with the industrystandard 80C51 instruction set and pinout. The on-chip Flash allows the program memory to be reprogrammed in-system or by a conventional nonvolatile memory programmer. By combining a versatile 8-bit CPU with in-system programmable Flash on a monolithic chip, the Atmel AT89S52 is a powerful microcontroller which provides a highly-flexible and costeffective solution to many embedded control applications. In addition, the AT89S52 is designed with static logic for operation down to zero frequency and supports two software selectable power saving modes. The Idle Mode stops the CPU while allowing the RAM, timer/counters, serial port, and interrupt system to continue functioning. The Power-down mode saves the RAM con-tents but freezes the oscillator, disabling all other chip functions until the next interrupt or hardware reset.

FEATURES: The basic architecture of AT89C51 consists of the following features:


.

Compatible with MCS-51 Products 8K Bytes of In-System Programmable (ISP) Flash Memory 4.0V to 5.5V Operating Range Fully Static Operation: 0 Hz to 33 MHz 256 x 8-bit Internal RAM 32 Programmable I/O Lines
. .

Three 16-bit Timer/Counters Eight Interrupt Sources Full Duplex UART Serial Channel Low-power Idle and Power-down Modes Interrupt Recovery from Power-down Mode Watchdog Timer Fast Programming Time Flexible ISP Programming (Byte and Page Mode)

PIN CONFIGURATION

Fig. 4.16 Pin diagram of AT89S52

BLOCK DIAGRAM

Block diagram of the microcontroller

PIN DESCRIPTION VCC: Supply voltage. GND: Ground. Port 0: Port 0 is an 8-bit open drain bidirectional I/O port. As an output port, each pin can sink eight TTL inputs. When 1s are written to port 0 pins, the pins can be used as high-impedance inputs. Port 0 can also be configured to be the multiplexed low-order address/data bus during accesses to external program and data memory. In this mode, P0 has internal pull-ups. Port 1: Port 1 is an 8-bit bidirectional I/O port with internal pull-ups. The Port 1 output buffers can sink/source four TTL inputs. When 1s are written to Port 1 pins, they are pulled high by the internal pull-ups and can be used as inputs. As inputs, Port 1 pins that are externally being pulled low will source current (IIL) because of the internal pull-ups. In addition, P1.0 and P1.1 can be configured to be the timer/counter 2 external count input (P1.0/T2) and the timer/counter 2 trigger input (P1.1/T2EX), respectively, as shown in the following table. Port 2: Port 2 is an 8-bit bidirectional I/O port with internal pull-ups. The Port 2 output buffers can sink/source four TTL inputs. When 1s are written to Port 2 pins, they are pulled high by the internal pull-ups and can be used as inputs. As inputs, Port 2 pins that are externally being pulled low will source current (IIL) because of the internal pull-ups. Port 2 emits the high-order address byte during fetches from external program memory and during accesses to external data memory that use 16bit addresses (MOVX @ DPTR). In this application, Port 2 uses strong internal pullups when emitting 1s. During accesses to external data memory that uses 8-bit addresses (MOVX @ RI), Port 2 emits the contents of the P2 Special Function register. Port 3: Port 3 is an 8-bit bidirectional I/O port with internal pull-ups. The Port 3 output buffers can sink/source four TTL inputs. When 1s are written to Port 3 pins, they are pulled high by the internal pull-ups and can be used as inputs. As inputs, they are pulled high by the internal pull-ups and can be used as inputs. As inputs, Port 3 pins that are externally being pulled low will source current (IIL) because of the pullups. Port 3 receives some control signals for Flash programming an verification

Port 3 also serves the functions of various special features of the AT89S52, as shown in the following table. Alternate functions of Port 3:

Table 4.2 Alternate functions of Port 3 RST: Reset input. A high on this pin for two machine cycles while the oscillator is running resets the device. This pin drives high for 98 oscillator periods after the watchdog times out.

Power-On Reset circuit

Power-on reset circuit

In order for the RESET input to be effective, it must have a minimum duration of two machine cycles. ALE/PROG: Address Latch Enable (ALE) is an output pulse for latching the low byte of the address during accesses to external memory. This pin is also the program pulse input (PROG) during Flash programming. In normal operation, ALE is emitted at a constant rate of 1/6 the oscillator frequency and may be used for external timing or clocking purposes. Note, however, that one ALE pulse is skipped during each access to external data memory. If desired, ALE operation can be disabled by setting bit 0 of SFR location 8EH. With the bit set, ALE is active only during a MOVX or MOVC instruction. Otherwise, the pin is weakly pulled high. Setting the ALE-disable bit has no effect if the microcontroller is in external execution mode. PSEN: Program Store Enable (PSEN) is the read strobe to external program memory. When the AT89S52 is executing code from external program memory, PSEN is activated twice each machine cycle, except that two PSEN activations are skipped during each access to external data memory. EA: External Access Enable. EA must be strapped to GND in order to enable the device to fetch code from external program memory locations starting at 0000H up to FFFFH. Note, however, that if lock bit 1 is programmed, EA will be internally latched on reset. EA should be strapped to VCC for internal program executions. This pin also receives the 12-volt programming enable voltage (VPP) during Flash programming. XTAL1: Input to the inverting oscillator amplifier and input to the internal clock operating circuit. XTAL2: Output from the inverting oscillator amplifier.

4.4.6.2 The AT89S52 oscillator clock circuit


.

It uses a quartz crystal oscillator. We can observe the frequency on the XTAL2 pin.
.

C2 XTAL2 30pF C1 XTAL1 30pF GN D

Fig 4.19 The AT89S52 oscillator clock circuit The crystal frequency is the basic internal frequency of the microcontroller. The internal counters must divide the basic clock rate to yield standard communication bit per second (baud) rates. An 11.0592 megahertz crystal, although seemingly an odd value, yields a crystal frequency of 921.6 kilohertz, which can be divided evenly by the standard communication baud rates of 19200, 9600, 4800, 2400, 1200, and 300 hertz.

SPECIAL FUNCTION REGISTERS The Special Function Registers (SFRs) contain memory locations that are used for special tasks. Each SFR occupies internal RAM from 0x80 to 0xFF.They are 8-bits wide. The A (accumulator) register or accumulator is used for most ALU operations and Boolean Bit manipulations. Register B is used for multiplication & division and can also be used for general purpose storage. PSW (Program Status Word) is a bit addressable register PC or program counter is a special 16-bit register. It is not part of SFR. Program instruction bytes are fetched from locations in memory that are addressed by the PC.

Stack Pointer (SP) register is eight bits wide. It is incremented before data is stored during PUSH and CALL executions. While the stack may reside anywhere in on-chip RAM, the Stack Pointer is initialized to 07H after a reset. This causes the stack to begin at location 08H. DPTR or data pointer is a special 16-bit register that is accessible as two 8- bit registers: DPL and DPH, which are used to used to furnish memory addresses for internal and external code access and external data access. Control Registers: Special Function Registers IP, IE, TMOD, TCON, SCON, and PCON contain control and status bits for the interrupt system, the

Timer/Counters, and the serial port. Timer Registers: Register pairs (TH0, TL0) and (TH1, TL1) are the 16-bit Counter registers for Timer/Counters 0 and 1, respectively. 4.4.8 MEMORY ORGANIZATION MCS-51 devices have a separate address space for Program and Data Memory. Up to 64K bytes each of external Program and Data Memory can be addressed. Program Memory: If the EA pin is connected to GND, all program fetches are directed to external memory. On the AT89S52, if EA is connected to VCC, program fetches to addresses 0000H through 1FFFH are directed to internal memory and fetches to addresses 2000H through FFFFH are to external memory. Data Memory: The AT89S52 implements 256 bytes of on-chip RAM. The upper 128 bytes occupy a parallel address space to the Special Function Registers. This means that the upper 128 bytes have the same addresses as the SFR space but are physically separate from SFR space. When an instruction accesses an internal location above address 7FH, the address mode used in the instruction specifies whether the CPU accesses the upper 128 bytes of RAM or the SFR space. Instructions which use direct addressing access the SFR space. The lower 128 bytes of RAM can be divided into three segments:

1. Register Banks 0-3: locations 00H through 1FH (32 bytes). The device after reset defaults to register bank 0. To use the other register banks, the user must select them in software. Each register bank contains eight 1-byte registers R0-R7. Reset initializes the stack point to location 07H, and is incremented once to start from 08H, which is

the first register of the second register bank. 2. Bit Addressable Area: 16 bytes have been assigned for this segment 20H-2FH. Each one of the 128 bits of this segment can be directly addressed (0-7FH). Each of the 16 bytes in this segment can also be addressed as a byte. 3. Scratch Pad Area: 30H-7FH are available to the user as data RAM. However, if the data pointer has been initialized to this area, enough bytes should be left aside to prevent SP data destruction.

Fig. 4.20 Internal memory block

WATCHDOG TIMER (One-time Enabled with Reset-out) The WDT is intended as a recovery method in situations where the CPU may be subjected to software upsets. The WDT consists of a 14-bit counter and the Watchdog Timer

Reset (WDTRST) SFR. The WDT is defaulted to disable from exiting reset. To enable the WDT, a user must write 01EH and 0E1H in sequence to the WDTRST register (SFR location 0A6H). When the WDT is enabled, it will increment every machine cycle while the oscillator is running. The WDT timeout period is dependent on the external clock frequency. There is no way to disable the WDT except through reset (either hardware reset or WDT overflow reset). When WDT over-flows, it will drive an output RESET HIGH pulse at the RST pin. 4.4.10 TIMERS AND COUNTERS Many microcontroller applications require the counting of external events such as the frequency of a pulse train, or the generation of precise internal time delays between computer actions. Both of these tasks can be accomplished using software techniques, but software loops for counting or timing keep the processor occupied so that, other perhaps more important, functions are not done. Hence the better option is to use interrupts & the two 16bit count- up timers. The microcontroller can programmed for either of the following: 1. Count internal - acting as timer 2. Count external - acting as counter All counter action is controlled by the TMOD (Timer Mode) and the TCON (Timer/Counter Control) registers. TCON Timer control SFR contains timer 1& 2 overflow flags, external interrupt flags, timer control bits, falling edge/low level selector bit etc. TMOD timer mode SFR comprises two four-bit registers (timer #1, timer #0) used to specify the timer/counter mode and operation. The timer may operate in any one of four modes that are determined by modes bits M1 and M0 in the TMOD register: TIMER MODE-0: Setting timer mode bits to 00b in the TMOD register results in using the TH register as an 8-bit counter and TL as a 5-bit counter. Therefore mode0 is a 13-bit counter. TIMER MODE-1: Mode-1 is similar to mode-0 except TL is configured as a full 8-bit counter when the mode bits are set to 01b in TMOD. TIMER MODE-2: Setting the mode bits to 10b in TMOD configures the timer to use only the TL counter as an 8-bit counter. TH is used to hold a value that is loaded into TL every time TL overflows from FFh to 00h. The timer flag is also set when TL overflows.

TIMER MODE-3: In mode-3, timer-1 simply hold its count, where as timer 0 registers TL0 and TH0 are used as two separate 8-bit counters. TL0 uses the Timer-0 control bits. TH0 counts machine cycles and takes over the use of TR1 and TF1 from Timer-1.

INTERRUPTS A computer has only two ways to determine the conditions that exist in internal and external circuits. One method uses software instructions that jump to subroutines on the states of flags and port pins. The second method responds to hardware signals, called interrupts that force the program to call a subroutine. The AT89S52 has a total of six interrupt vectors: two external interrupts (INT0 and INT1), three timer interrupts (Timers 0, 1, and 2), and the serial port interrupt. Each of these interrupt sources can be individually enabled or disabled by setting or clearing a bit in Special Function Register IE. IE also contains a global disable bit, EA, which disables all interrupts at once. Each interrupt forces the processor to jump at the interrupt location in the memory. The interrupted program must resume operation at the instruction where the interrupt took place. Program resumption is done by storing the interrupted PC address on to stack. RETI instruction at the end of ISR will restore the PC address.

p i n d e t a i l s

POWER SUPPLY SECTION

POWER SUPPLY SECTION:The power supply section consists of step down transformers of 230V primary to 9V and 12V secondary voltages for the +5V and +12V power supplies respectively. The stepped down voltage is then rectified by 4 1N4007 diodes. The high value of capacitor 1000 F charges at a slow rate as the time constant is low, and once the capacitor charges there is no resistor for capacitor to discharge. This gives a constant value of DC. IC 7805 is used for regulated supply of +5 volts and IC 7812 is used to provide a regulated supply of +12 volts in order to prevent the circuit ahead from any fluctuations. The filter capacitors connected after this IC filters the high frequency spikes. These capacitors are connected in parallel with supply and common so that spikes filter to the common. These give stability to the power supply circuit. As can be seen from the above circuit diagrams, the rectified voltage from the 4 diodes is given to pin 1 of the respective regulators. Pin 2 of the regulators is connected to ground and pin 3 to Vcc. With adequate heat sinking the regulator can deliver 1A output current. If internal power dissipation becomes too high for the heat sinking provided, the thermal shutdown circuit takes over preventing the IC from overheating.

+5V Power supply circuit


1 Vin

7805
GND 2

Vout

1000uf 230V, 50Hz 10uf 1uf

+12V Power supply Circuit

LIQUID CRYSTAL DISPLAY:-

A liquid crystal display (LCD) is a thin, flat display device made up of any number of color or monochrome pixels arrayed in front of a light source or reflector. Each pixel consists of a column of liquid crystal molecules suspended between two transparent electrodes, and two polarizing filters, the axes of polarity of which are perpendicular to each other. Without the liquid crystals between them, light passing through one would be blocked by the other. The liquid crystal twists the polarization of light entering one filter to allow it to pass through the other. Many microcontroller devices use 'smart LCD' displays to output visual information. LCD displays designed around Hitachi's LCD HD44780 module, are inexpensive, easy to use, and it is even possible to produce a readout using the 8x80 pixels of the display. They have a standard ASCII set of characters and mathematical symbols. For an 8-bit data bus, the display requires a +5V supply plus 11 I/O lines. For a 4-bit data bus it only requires the supply lines plus seven extra lines. When the LCD display is not enabled, data lines are tri-state and they do not interfere with the operation of the microcontroller. Data can be placed at any location on the LCD. For 162 LCD, the address locations are:
First line Second line 80 C0 81 C1 82 C2 83 C3 84 C4 85 C5 86 C6 through 8F

through CF

Address locations for a 2x16 line LCD

SIGNALS TO THE LCD The LCD also requires 3 control lines from the microcontroller: 1) Enable (E) This line allows access to the display through R/W and RS lines. When this line is low, the LCD is disabled and ignores signals from R/W and RS. When (E) line is high, the LCD checks the state of the two control lines and responds accordingly. 2) Read/Write (R/W) This line determines the direction of data between the LCD and microcontroller.

When it is low, data is written to the LCD. When it is high, data is read from the LCD. 3) Register select (RS) With the help of this line, the LCD interprets the type of data on data lines. When it is low, an instruction is being written to the LCD. When it is high, a character is being written to the LCD. Logic status on control lines: . Writing and reading the data from the LCD: Writing data to the LCD is done in several steps: 1) Set R/W bit to low 2) Set RS bit to logic 0 or 1 (instruction or character) 3) Set data to data lines (if it is writing) 4) Set E line to high 5) Set E line to low Read data from data lines (if it is reading): 1) Set R/W bit to high 2) Set RS bit to logic 0 or 1 (instruction or character) 3) Set data to data lines (if it is writing) 4) Set E line to high 5) Set E line to low E - 0 Access to LCD disabled - 1 Access to LCD enabled R/W - 0 Writing data to LCD - 1 Reading data from LCD RS - 0 Instruction

PIN DESCRIPTION Most LCDs with 1 controller has 14 Pins and LCDs with 2 controller has 16 Pins (two pins are extra in both for back-light LED connections).

Pin diagram of 2x16 line LCD

Pin description of the LCD

SOFTWARE SECTION

INTRODUCTION TO KEIL SOFTWARE:Keil MicroVision is an integrated development environment used to create software to be run on embedded systems (like a microcontroller). It allows for such software to be written either in assembly or C programming languages and for that software to be simulated on a computer before being loaded onto the microcontroller.

WHAT IS Vision3? Vision3 is an IDE (Integrated Development Environment) that helps write, compile, and debug embedded programs. It encapsulates the following components: A project manager. A make facility. Tool configuration. Editor.

A powerful debugger.

STEPS FOLLOWED IN CREATING AN APPLICATION IN uVision3: To create a new project in uVision3: 1. Select Project - New Project. 2. Select a directory and enter the name of the project file. 3. Select Project Select Device and select a device from Device Database. 4. Create source files to add to the project 5. Select Project - Targets, Groups, and Files. Add/Files, select Source Group1, and add the source files to the project. 6. Select Project - Options and set the tool options. Note that when the target device is selected from the Device Database all-special options are set automatically. Default memory model settings are optimal for most applications. 7. Select Project - Rebuild all target files or Build target To create a new project, simply start MicroVision and select Project=>New Project from the pulldown menus. In the file dialog that appears, choose a name and base
.

directory for the project. It is recommended that a new directory be created for each project, as several files will be generated. Once the project has been named, the dialog shown in the figure below will appear, prompting the user to select a target device. In this lab, the chip being used is the AT89S52, which is listed under the heading Atmel.

Window for choosing the target device Next, MicroVision must be instructed to generate a HEX file upon program compilation. A HEX file is a standard file format for storing executable code that is to be loaded onto the microcontroller. In the Project Workspace pane at the left, rightclick on Target 1 and select Options for Target 1 .Under the Output tab of the resulting options dialog, ensure that both the Create Executable and Create HEX File options are checked. Then click OK as shown in the two figures below.

Project Workspace Pane

Project Options Dialog

Next, a file must be added to the project that will contain the project code. To do this, expand the Target 1 heading, rightclick on the Source Group 1 folder, and select Add files Create a new blank file (the file name should end in .asm), select it, and click Add. The new file should now appear in the Project Workspace pane under the Source Group 1 folder. Double-click on the newly created file to open it in the editor. All code for this lab will go in this file. To compile the program, first save all source files by clicking on the Save All button, and then click on the Rebuild All Target Files to compile the program as shown in the figure below. If any errors or warnings occur during compilation, they will be displayed in the output window at the bottom of the screen. All errors and warnings will reference the line and column number in which they occur along with a description of the problem so that they can be easily located. Note that only errors indicate that the compilation failed, warnings do not (though it is generally a good idea to look into them anyway).

Save All and Build All Target Files Buttons

When the program has been successfully compiled, it can be simulated using the integrated debugger in Keil MicroVision. To start the debugger, select Debug=>Start/Stop Debug Session from the pulldown menus. At the left side of the debugger window, a table is displayed containing several key parameters about the simulated microcontroller, most notably the elapsed time (circled in the figure below). Just above that, there are several buttons that control code execution. The Run button will cause the program to run continuously until a breakpoint is reached, whereas the Step Into button will execute the next line of code and then pause (the current position in the program is indicated by a yellow arrow to the left of the code).

Vision3 Debugger window

Breakpoints can be set by doubleclicking on the grey bar on the left edge of the window containing the program code. A breakpoint is indicated by a red box next to the line of code.

Reset, Run and Step into options The current state of the pins on each I/O port on the simulated microcontroller can also be displayed. To view the state of a port, select Peripherals=>I/O Ports=>Port n from the pulldown menus, where n is the port number. A checked box in the port window indicates a high (1) pin, and an empty box indicates a low (0) pin. Both the I/O port data and the data at the left side of the screen are updated whenever the program is paused. The debugger will help eliminate many programming errors, however the simulation is not perfect and code that executes properly in simulation may not always work on the actual microcontroller.
.

DEVICE DATABASE A unique feature of the Keil Vision3 IDE is the Device Database, which contains information about more than 400 supported microcontrollers. When you create a new Vision3 project and select the target chip from the database, Vision3 sets all assembler, compiler, linker, and debugger options for you. The only option you must configure is the memory map. PERIPHERAL SIMULATION The Vision3 Debugger provides complete simulation for the CPU and on-chip peripherals of most embedded devices. To discover which peripherals of a device are supported, in Vision3 select the Simulated Peripherals item from the Help menu. You may also use the web-based Device Database. We are constantly adding new devices and simulation support for on-chip peripherals so be sure to check Device Database often.

PROGRAMMER The programmer used is a powerful programmer for the Atmel 89 series of microcontrollers that includes 89C51/52/55, 89S51/52/55 and many more. It is simple to use & low cost, yet powerful flash microcontroller programmer for the Atmel 89 series. It will Program, Read and Verify Code Data, Write Lock Bits, Erase and Blank Check. All fuse and lock bits are programmable. This programmer has intelligent onboard firmware and connects to the serial port. It can be used with any type of computer and requires no special hardware. All that is needed is a serial communication port which all computers have. All devices also have a number of lock bits to provide various levels of software and programming protection. These lock bits are fully programmable using this programmer. Lock bits are useful to protect the progam to be read back from microcontroller only allowing erase to reprogram the microcontroller. Major parts of this programmer are Serial Port, Power Supply and Firmware microcontroller. Serial data is sent and received from 9 pin connector and converted to/from

TTL logic/RS232 signal levels by MAX232 chip. A Male to Female serial port cable, connects to the 9 pin connector of hardware and another side connects to back of computer. All the programming intelligence is built into the programmer so you do not need any special hardware to run it. Programmer comes with window based software for easy programming of the devices.

ProLoad PROGRAMMING SOFTWARE ProLoad is a software working as a user friendly interface for programmer boards from Sunrom Technologies. Proload gets its name from Program Loader term, because that is what it is supposed to do. It takes in compiled HEX file and loads it to the hardware. Any compiler can be used with it, Assembly or C, as all of them generate compiled HEX files. ProLoad accepts the Intel HEX format file generated from compiler to be sent to target microcontroller. It auto detects the hardware connected to the serial port. It also auto detects the chip inserted and bytes used. The software is developed in Delphi and requires no overhead of any external DLL. The programmer connects to the computers serial port (Comm 1, 2, 3 or 4) with a standard DB9 Male to DB9 Female cable. Baud Rate - 57600, COMx Automatically selected by window software. No PC Card Required. After making the necessary selections, the Auto Program button is clicked as shown in the figure below which burns the selected hex file onto the microcontroller.

MAIN PROGRAM
/********************************************************************/ /******************** Main File for the Project*********************/ /* D.S.oberoi & Harinder Dhingra */ /********************************************************************/ #include <avr/signal.h> #include <inttypes.h> #include <avr/interrupt.h> #include "lcd.h" // Function declarations unsigned int rc5decode( void ); // Remote RC5 decoding void remoteSelection(unsigned int remote_val); // remote selection routine void change_year(unsigned int remote_value); // change the year routine void change_month(unsigned int remote_value); // change the month routine void change_day(unsigned int remote_value); // change the day routine void change_date(unsigned int remote_value); // change the date routine void change_min(unsigned int remote_value); // change the minutes routine void change_hour(unsigned int remote_value); // change the hour routine void alarmSetting(void); // Check and set the alarm routine char viewAlarmSetting(unsigned int remote_value ); // View alarm settings void addAlarmSetting(unsigned int remote_value); // Add alarm setting routine void init(void); // Initialization routine void device1_control(void); // Device 1 to 8 control routine void device2_control(void); // first 5 attached to their respctive time setting void device3_control(void); void device4_control(void); void device5_control(void); void device6_control(void); void device7_control(void); void device8_control(void);

void deleteAlarmSetting(unsigned int remote_value); /* module global variables */ static volatile uint8_t timerflag; char previous_min, snooze, alarm, mode , next_field, ir_disable; unsigned int snooze_tick, previous_sec; unsigned int rc5data, rc5c; char device_status=0; char key_status=0; /************* MAIN STARTS HERE *********************/ int main(void) { // Start the initialization process mode = SETTING_MODE; next_field= 0; // next field device_status= 0; alarm = 0;

ir_disable = 0; snooze= 0; snooze_tick= 0; outp(device_status, PORTB); // all external devices switched OFF init(); cbi(BUZZER_PORT,BUZZER_PIN); // disable alarm cbi(BACK_LITE_PORT, BACK_LITE_PIN); // disable backlight // I2C intialization i2c_initialization(); // LCD Initialization process lcd_init(); lcdCmdWrite(0x01);

// Start the display of clock - details at proper locations hour = display_hour(4, 1); min = display_min(7, 1); sec = display_sec(10, 1); day = display_day(0, 2); date = display_date(6, 2); month = display_month(9, 2); year = display_year(13, 2); readAlarmValues(); for(;;) // loop forever- main routine starts here { if (mode == 1 && next_field== 0) { lcd_gotoxy(5,1); // Setting on Power ON cursorBlinkOn(); } // CHECK for the REMOTE operation here while ( RC5BitHigh() ) // wait until RC5 code received { ; if(alarm ==0 && mode == DISPLAY) { outp(0xF0, DDRD); delay(100); cbi(PORTD, PIND0); delay(100); // check here if the Push Button is pressed and then // de-activate the device control signal key_status = inp(PIND) & 0x02; if (key_status == 2 ) { outp(0x00, PORTB); // disable all the PORTB device Device 1 to 8 device_status = 0 ; lcdcls(); delay(600); lcd_gotoxy(0,1); cli(); lcd_puts("Devices Disabled"); for(char op=0; op<=20; op++) // delay for viewing delay(60000); lcdcls(); sei();

} key_status =0; } } rc5data = rc5decode(); // separate the address and the command- in RC5 code if ( rc5data & 0x2000 ) { rc5c = rc5data & 0x003f; remoteSelection(rc5c); } } } /*****************************--END HERE-********************************************/

/*****************************************************************************************/ /****************************** Device Control section starts here ***********************/ /*****************************************************************************************/ // Device 1 control routine here void device1_control() { if ( mode == DISPLAY) { switch(device_status & 0x01) { // if OFF then change to ON case 0: sbi(DEVICE1_PORT, DEVICE1_PIN); device_status = device_status | 0x01; break; // if ON then change to OFF case 1: cbi(DEVICE1_PORT, DEVICE1_PIN); device_status = device_status & 0xFE; } } } // Device 2 control routine here void device2_control() { if ( mode == DISPLAY) { switch(device_status & 0x02 ) { // if OFF then change to ON case 0: sbi(DEVICE2_PORT, DEVICE2_PIN); device_status = device_status | 0x02; break; // if ON then change to OFF case 2: cbi(DEVICE2_PORT, DEVICE2_PIN); device_status = device_status & 0xFD; } } } // Device 3 control routine here void device3_control() { if ( mode == DISPLAY)

{ switch(device_status & 0x04 ) { // if OFF then change to ON case 0: sbi(DEVICE3_PORT, DEVICE3_PIN); device_status = device_status | 0x04; break; // if ON then change to OFF case 0x04: cbi(DEVICE3_PORT, DEVICE3_PIN); device_status = device_status & 0xFB; } } } // Device 4 control routine here void device4_control() { if ( mode == DISPLAY) { switch(device_status & 0x08 ) { // if OFF then change to ON case 0: sbi(DEVICE4_PORT, DEVICE4_PIN); device_status = device_status | 0x08; break; // if ON then change to OFF case 0x08: cbi(DEVICE4_PORT, DEVICE4_PIN); device_status = device_status & 0xF7; } } } // Device 5 control routine here void device5_control() { if ( mode == DISPLAY) { switch(device_status & 0x10 ) { // if OFF then change to ON case 0: sbi(DEVICE5_PORT, DEVICE5_PIN); device_status = device_status | 0x10; break; // if ON then change to OFF case 0x10: cbi(DEVICE5_PORT, DEVICE5_PIN); device_status = device_status & 0xEF; } } } // Device 6 control routine here void device6_control() { if ( mode == DISPLAY) { switch(device_status & 0x20 ) { // if OFF then change to ON case 0: sbi(DEVICE6_PORT, DEVICE6_PIN); device_status = device_status | 0x20; break; // if ON then change to OFF

case 0x20: cbi(DEVICE6_PORT, DEVICE6_PIN); device_status = device_status & 0xDF; } } } // Device 7 control routine here void device7_control() { if ( mode == DISPLAY) { switch(device_status & 0x40 ) { // if OFF then change to ON case 0: sbi(DEVICE7_PORT, DEVICE7_PIN); device_status = device_status | 0x40; break; // if ON then change to OFF case 0x40: cbi(DEVICE7_PORT, DEVICE7_PIN); device_status = device_status & 0xBf; } } } // Device 8 control routine here void device8_control() { if ( mode == DISPLAY) { switch(device_status & 0x80 ) { // if OFF then change to ON case 0: sbi(DEVICE8_PORT, DEVICE8_PIN); device_status = device_status | 0x80; break; // if ON then change to OFF case 0x80: cbi(DEVICE8_PORT, DEVICE8_PIN); device_status = device_status & 0x7F; } } }

/*****************************************************************************************/ /*****************************************************************************************/ /***** Based on the pressed Remote key - action is decided here **************************/ /*****************************************************************************************/ void remoteSelection(unsigned int remote_val) { char s ; /************* Setting Mode **************/ if (alarm == 0) { // normal functioning , when numeric keys of the remote are pressed switch (remote_val) { case 1: device1_control(); break; case 2: device2_control(); break;

case 3: device3_control(); break; case 4: device4_control(); break; case 5: device5_control(); break; case 6: device6_control(); break; case 7: device7_control(); break; case 8: device8_control(); break; } if (mode == SETTING_MODE) // action taken , when clock is in setting mode { if (next_field== 0) // Blink The cursor at Hour Location { lcd_gotoxy(6,1); cursorBlinkOn(); } if ( remote_val == FIELD_CHANGE) // change the field { ++next_field; if ( next_field> 5 ) next_field = 0; } switch(next_field) // Change the respective field Values { case 0: change_hour(remote_val); break; case 1: change_min(remote_val); break; case 2: change_day(remote_val); break; case 3: change_date(remote_val); break; case 4: change_month(remote_val); break; case 5: change_year(remote_val); } if (remote_val == AV) // Write new values to RTC { mode = DISPLAY ; // set mode to enable the display writeChangeValues(); } } // action taken when clock is in normal Display mode if ( mode == DISPLAY) // Normal functioning { if ( remote_val == SETTING_CODE ) { mode = SETTING_MODE;// entered the setting mode once again next_field= 0; } if ( remote_val == SLEEP) // Alarm setting

{ lcdcls(); cursorOff(); mode = ALARM_MENU; } } // action taken when clock is in alarm mmode if (mode == SEE_ALARM_MENU) // View alarm setting { cursorOff(); s = viewAlarmSetting(remote_val); } if (mode == DELETE_ALARM_MENU) // Delete Alarm setting { cursorOff(); //deleteAlarmSetting(remote_val); deleteAlarmSetting(0); } if (mode == ALARM_MENU) // alarm new display { cursorOff(); alarmSetting(); if (remote_val == 1 ) // Add alarm data { mode = NEW_ALARM_MENU; //s = addAlarmSetting(remote_val); addAlarmSetting(remote_val); alarmSetting(); } if (remote_val == 2 ) // Delete Alarm Data { mode = SEE_ALARM_MENU; deleteAlarmSetting(0); alarmSetting(); } if (remote_val == 3 ) // View alarm data { mode = SEE_ALARM_MENU; s = viewAlarmSetting(remote_val); alarmSetting(); } if ( remote_val == AV || remote_val == POWER) // Return to Display Menu { lcdCmdWrite(0x01); mode = DISPLAY; } } remote_val = 0; }

// if alarm is active then POWER key will put disable the alarm if (alarm == 1 || alarm == 2) { if (remote_val == POWER ) { cbi(BUZZER_PORT, BUZZER_PIN); remote_val = 0;

alarm = 0; // to enable the remote again ir_disable = 1; cbi(BACK_LITE_PORT, BACK_LITE_PIN); outp(0xF0, DDRD); for (char x=0; x<=10; x++) delay(600); // delay to prevent to go from alarm disable into setting mode key 47 is pressed }

// press any key to go in snooze mode if (remote_val != 0 ) { remote_val = 0; cbi(BUZZER_PORT, BUZZER_PIN); alarm = 2; // to enable the remote again for (char x=0; x<=10; x++) delay(600); // delay to prevent to go from alarm disable into setting mode key 47 is pressed } }

remote_val = 0; for (char x=0; x<=10; x++) delay(60000); pressed

// delay to prevent to go from alarm disable into setting mode key 47 is

} /*****************************************************************************************/ /*************************Alarm delete setting - routine ********************************/ /*****************************************************************************************/ void deleteAlarmSetting(unsigned int remote_value) { signed char i, x=1, set_alarm_hour, set_alarm_min; static signed char opt = 0; i= ALARM_START_RGST; lcdCmdWrite(0x01); alarm_count= DS1307_Read(ALARM_COUNT_RGST); alarm_count= BCD2bin(alarm_count); while (alarm_count > 0) { data_count = 0; lcd_gotoxy(0,1); printf("Tot:%d", alarm_count); data_count = 0; lcd_gotoxy(13, 2); lcd_puts("No "); lcd_gotoxy(14, 2);cursorBlinkOn(); while(data_count < alarm_count * 2 ) // check the limit of the data scroll here { remote_value = 0; lcd_gotoxy(10,1); lcd_puts("Delete"); // read the data from the RAM set_alarm_hour = BCD2bin(DS1307_Read(ALARM_START_RGST + data_count)); set_alarm_min = BCD2bin(DS1307_Read( ALARM_START_RGST + data_count+1)); // print the data lcd_gotoxy(5, 2); if (set_alarm_hour < 10) printf("0%d", set_alarm_hour);

else printf("%d", set_alarm_hour); lcd_puts(":"); lcd_gotoxy(8, 2); if (set_alarm_min < 10) printf("0%d", set_alarm_min); else printf("%d", set_alarm_min); // move cursor and Blink Postition if (opt == 0) lcd_gotoxy(14, 2); else lcd_gotoxy(15, 2); // Check Remote Setting while ( RC5BitHigh() ) // wait until RC5 code received ; rc5data = rc5decode(); if ( rc5data & 0x2000 ) remote_value = rc5data & 0x003f; // separate Address and Command lcd_puts(" "); // Change Delete Options if ( remote_value == VOLUME_UP) { opt++; if (opt > 1 ) opt = 0; lcd_gotoxy(13,2); switch(opt) { case 0: lcd_puts("No "); break; case 1: lcd_puts("Yes"); } lcd_gotoxy(14, 2); cursorBlinkOn(); }

if ( remote_value == VOLUME_DOWN) { opt--; if (opt < 0) opt = 1; lcd_gotoxy(13,2); switch(opt) { case 0: lcd_puts("No "); break; case 1: lcd_puts("Yes"); } lcd_gotoxy(13, 2); cursorBlinkOn(); } // Scroll thru the Alrm Data

if (remote_value == CHANNEL_UP) { data_count+=2; ++x; if (data_count > alarm_count* 2 ) data_count = 0; if (x > alarm_count ) x = 1; } if (remote_value == AV) // Delete the Data and update RTC Alarm Registers { // AND RETURN TO previous menu if ( opt == 1) { updateAlarmData_Delete(data_count, alarm_count); opt = 0; } lcdCmdWrite(0x01); mode = ALARM_MENU; return ; } // Scroll thru alarm data if (remote_value == CHANNEL_DOWN ) { data_count-=2; --x; if (data_count < 0) data_count = (alarm_count*2) - 2; if (x < 1 ) x = alarm_count; } if (remote_value == POWER) // return to previous menu { // without any update lcdCmdWrite(0x01); mode = ALARM_MENU; return ; } } }

// If no data present in the RAM while (alarm_count == 0) { lcd_gotoxy(1,1);lcd_puts("No Alarm Data"); // when no alarm data is present while ( RC5BitHigh() ) // wait until RC5 code received ; // separate the address and the command rc5data = rc5decode();

if ( rc5data & 0x2000 ) { remote_value = rc5data & 0x003f; if (remote_value == AV ) { lcdCmdWrite(0x01); mode = ALARM_MENU; return ; } if (remote_value == POWER) // return to previous menu { // with no update lcdCmdWrite(0x01); mode = ALARM_MENU;

return ; } } } }

/*****************************************************************************************/ /****************Adding new data into ALARM setting **************************************/ /*****************************************************************************************/ void addAlarmSetting(unsigned int remote_value) { signed char i, set_alarm_hour=0, set_alarm_min=0; static char fc= 0; i= ALARM_START_RGST; lcdCmdWrite(0x01); alarm_count= DS1307_Read(ALARM_COUNT_RGST); alarm_count= BCD2bin(alarm_count) ; // data less than 6 setting lcd_gotoxy(6,2); lcd_puts("00:"); lcd_gotoxy(9,2); lcd_puts("00");// lcd_gotoxy(7,2); cursorBlinkOn(); while (alarm_count< MAX_ALARM ) { data_count = 0; lcd_gotoxy(0,1); printf("Tot:%d", alarm_count); if ( remote_value == FIELD_CHANGE) { fc++; if (fc > 1) fc = 0; } if ( fc == 0) { // change hour

lcd_gotoxy(7,2); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++set_alarm_hour; if (set_alarm_hour> 23 ) set_alarm_hour = 0; }

if ( remote_value == VOLUME_DOWN) { set_alarm_hour--; if (set_alarm_hour< 0 ) set_alarm_hour = 23; } lcd_gotoxy(6,2); if (set_alarm_hour< 10) printf("0%d", set_alarm_hour); else printf("%d", set_alarm_hour);

lcd_gotoxy(7, 2); cursorBlinkOn();

} if ( fc ==1 ) { // change minutes

lcd_gotoxy(9,2); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++set_alarm_min; if (set_alarm_min> 59 ) set_alarm_min = 0; }

if ( remote_value == VOLUME_DOWN) { set_alarm_min--; if (set_alarm_min < 0 ) set_alarm_min = 59; } lcd_gotoxy(9,2); if (set_alarm_min < 10) printf("0%d", set_alarm_min); else printf("%d", set_alarm_min); lcd_gotoxy(10, 2); cursorBlinkOn();

while ( RC5BitHigh() ) // wait until RC5 code received ; // separate the address and the command rc5data = rc5decode();

if ( rc5data & 0x2000 ) { remote_value = rc5data & 0x003f;

if (remote_value == AV) // return to previous menu { lcdCmdWrite(0x01); // should ipdate the alarm time updateAlarmData( set_alarm_hour, set_alarm_min, (alarm_count+1)); mode = ALARM_MENU; return ; } if (remote_value == POWER) // return to previous menu

// with no update lcdCmdWrite(0x01); mode = ALARM_MENU; return ;

} } } // data more than 6 setting while (alarm_count >= MAX_ALARM) { lcd_gotoxy(1,1);lcd_puts(" Alarm Setting"); lcd_gotoxy(5, 2); lcd_puts(" Full "); cursorOff(); while ( RC5BitHigh() ) // wait until RC5 code received ; // separate the address and the command rc5data = rc5decode();

if ( rc5data & 0x2000 ) { remote_value = rc5data & 0x003f;

if (remote_value == AV || remote_value == POWER ) { lcdCmdWrite(0x01); mode = ALARM_MENU; return ; } } } }

// return to previous menu

/*****************************************************************************************/ /************** alarm menu and arranagement***********************************************/ /*****************************************************************************************/ void alarmSetting( void ) { lcdcls(); cursorOff(); lcd_gotoxy(5,1); lcd_puts("Alarm"); lcd_gotoxy(0,2); lcd_puts("1New 2Del 3See"); }

/*****************************************************************************************/ /************** View Alarm settings ***********************************************/ /*****************************************************************************************/ char viewAlarmSetting(unsigned int remote_value) { signed char i, x=1, set_alarm_hour, set_alarm_min; //static char datacount=0; i= ALARM_START_RGST;

lcdCmdWrite(0x01); alarm_count= DS1307_Read(ALARM_COUNT_RGST); alarm_count= BCD2bin(alarm_count) ; while (alarm_count> 0) { data_count = 0; lcd_gotoxy(0,1); printf("Tot:%d", alarm_count);

data_count = 0; while(data_count < alarm_count * 2 ) // check the limit of the data scroll here { remote_value = 0; lcd_gotoxy(8,1); if (x<10) printf("Data:0%d", x); else printf("Data:%d", x); // read the data from the RAM set_alarm_hour = BCD2bin(DS1307_Read(ALARM_START_RGST + data_count)); set_alarm_min = BCD2bin(DS1307_Read( ALARM_START_RGST + data_count+1)); // print the data lcd_gotoxy(5, 2); if (set_alarm_hour < 10) printf("0%d", set_alarm_hour); else printf("%d", set_alarm_hour); lcd_puts(":"); lcd_gotoxy(8, 2); if (set_alarm_min < 10) printf("0%d", set_alarm_min); else printf("%d", set_alarm_min); while ( RC5BitHigh() ) // wait until RC5 code received ; // separate the address and the command rc5data = rc5decode(); if ( rc5data & 0x2000 ) remote_value = rc5data & 0x003f; if (remote_value == CHANNEL_UP) // increment the viewing data { data_count+=2; ++x; if (data_count > alarm_count* 2 ) data_count = 0; if (x > alarm_count ) x = 1; } if (remote_value == AV || remote_value == POWER) { lcdCmdWrite(0x01); mode = ALARM_MENU; return 0; } if (remote_value == CHANNEL_DOWN ) { data_count-=2; --x; // return to the previous menu

// decrement the view data

if (data_count < 0) data_count = (alarm_count * 2) - 2; if (x < 1 ) x = alarm_count; } } }

// if no data present in the RAM while (alarm_count == 0) { lcd_gotoxy(1,1);lcd_puts("No Alarm Data"); // when no alarm data is present while ( RC5BitHigh() ) // wait until RC5 code received ; // separate the address and the command rc5data = rc5decode();

if ( rc5data & 0x2000 ) { remote_value = rc5data & 0x003f; if (remote_value == AV || POWER) { lcdCmdWrite(0x01); mode = ALARM_MENU; return 0 ; } } } return 0; }

/*****************************************************************************************/ /************** Change Year Settings ****************************************************/ /*****************************************************************************************/ void change_year(unsigned int remote_value) { lcd_gotoxy(15, 2); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++year; if (year > 99 ) year= 0; }

if ( remote_value == VOLUME_DOWN) { year--; if (year< 0 ) year = 99; }

lcd_gotoxy(14,2); if (year < 10) printf("0%d", year); else printf("%d", year); lcd_gotoxy(15, 2); cursorBlinkOn(); } /*****************************************************************************************/ /************** Change Day settings ******************************************************/ /*****************************************************************************************/ void change_month(unsigned int remote_value) { lcd_gotoxy(9, 2); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++month; if (month > 12) month= 1; }

if ( remote_value == VOLUME_DOWN) { month--; if (month< 1 ) month= 12; } lcd_gotoxy(9,2); switch(month) { case 1: lcd_puts("Jan."); break; case 2: lcd_puts("Feb."); break; case 3: lcd_puts("Mar."); break; case 4: lcd_puts("Apr."); break; case 5: lcd_puts("May."); break; case 6: lcd_puts("Jun."); break; case 7: lcd_puts("Jul."); break; case 8: lcd_puts("Aug."); break; case 9: lcd_puts("Sep."); break; case 10:lcd_puts("Oct."); break; case 11:lcd_puts("Nov."); break; case 12:lcd_puts("Dec.");

} lcd_gotoxy(12, 2); cursorBlinkOn(); } /*****************************************************************************************/ /************** Change Day settings ******************************************************/ /*****************************************************************************************/ void change_day(unsigned int remote_value) { lcd_gotoxy(0,2); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++day; if (day > 7 ) day = 1; }

if ( remote_value == VOLUME_DOWN) { day--; if (day < 1 ) day = 7; } lcd_gotoxy(0, 2); switch(day) { case 1: lcd_puts("Sun."); break; case 2: lcd_puts("Mon."); break; case 3: lcd_puts("Tue."); break; case 4: lcd_puts("Wed."); break; case 5: lcd_puts("Thu."); break; case 6: lcd_puts("Fri."); break; case 7: lcd_puts("Sat."); break; } lcd_gotoxy(3, 2); cursorBlinkOn(); } /*****************************************************************************************/ /************** Change date settings *****************************************************/ /*****************************************************************************************/ void change_date(unsigned int remote_value) { lcd_gotoxy(7 , 2); cursorBlinkOn();

if ( remote_value == VOLUME_UP) { ++date; if (date > 31 ) date = 1; }

if ( remote_value == VOLUME_DOWN) { date--; if (date < 1 ) date = 31; } lcd_gotoxy(6,2); if (date < 10) printf("0%d", date); else printf("%d", date ); lcd_gotoxy(7, 2); cursorBlinkOn(); } /*****************************************************************************************/ /************** Change Minute Settings ***************************************************/ /*****************************************************************************************/ void change_min(unsigned int remote_value) { lcd_gotoxy(7,1); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++min; sec = 0; if (min > 59 ) min = 0; }

if ( remote_value == VOLUME_DOWN) { min--; sec = 0; if (min < 0 ) min= 59; } lcd_gotoxy(7,1); if (min < 10) printf("0%d", min); else printf("%d", min); lcd_gotoxy(8,1); cursorBlinkOn(); } /*****************************************************************************************/

/************** Change Hour settings *****************************************************/ /*****************************************************************************************/ void change_hour(unsigned int remote_value) { lcd_gotoxy(4,1); cursorBlinkOn(); if ( remote_value == VOLUME_UP) { ++hour; sec = 0; if (hour > 23 ) hour = 0; }

if ( remote_value == VOLUME_DOWN) { hour--; sec = 0; if (hour < 0 ) hour = 23; } lcd_gotoxy(4,1); if (hour < 10) printf("0%d", hour); else printf("%d", hour); lcd_gotoxy(5,1); cursorBlinkOn(); } /*****************************************************************************************/ /************** Initialization of Port and Registers *************************************/ /*****************************************************************************************/ void init(void) { // Initial Port Setting outp(0xFF, DDRA); // Port A o/p outp(0x03, DDRC); // Port B o/p DDRB = 0xff; // use all pins on port B for output PORTB = 0xff; DDRA = 0xff; PORTA = 0xff; DDRD = 0xf0; // use all pins on port D for input PORTD = 0xff; // enable internal pull-up resistors outp(0x00, TCNT1H); // Initial display_data of the Timer-1 outp(0x00, TCNT1L); outp(device_status, PORTB); // set devices to output mode outp(0, TCCR1A); outp(0x0c, TCCR1B); outp(0x3D,OCR1AH); outp(0x09, OCR1AL);

// Set the prescaling to 256 // 0x3D value Compare value to generate 1-second pulse

sbi(TIMSK, OCIE1A); sei();

// Enable the compare mode

/*** Decoded RC5 data is returned, or 0x0000 if RC5 data not recognized */ /********** Written BY and used for purpose with Permission of ***************/ /********** Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury **************/ unsigned int rc5decode( void ) { unsigned int rc5data; unsigned char timer, i; // init timer/Counter0 TCCR0 = TMC8_CK8; TCNT0 = TIMER_0_CNT; TIMSK = _BV(TOIE0);

// use CLK/8 prescale // set timer T/16 = 111us // enable TCNT0 overflow interrupt

// measure startbit timerflag = 0; timer = 0; while ( RC5BitLow() && (timer < RC5BITREF2) ) { WAITFORTIMER(); timer++; } if ( (timer > RC5BITREF1) && (timer < RC5BITREF2) ) { // startbit ok, decode // wait T/4: synchronize in the middle of first half of second bit while ( timer < RC5BITREF3 ) { WAITFORTIMER(); timer++; } // read the remaining bits rc5data = 1; for (i=0; i<13; i++) { rc5data <<= 1; if ( RC5BitHigh() ) { rc5data |= 0x0001; // wait max T/2 for H->L transition (middle of next bit) timer = 0; while ( RC5BitHigh() && (timer < 16) ) { WAITFORTIMER(); timer++; } }else{ rc5data &= ~0x00001; // wait max T/2 for L->H transition (middle of next bit) timer = 0; while ( RC5BitLow() && (timer < 16) ) { WAITFORTIMER(); timer++; } } if ( timer == 16 ) { rc5data = 0x0000; // error, next bit not found break; } // wait 3/4 T: await next bit for ( timer=0; timer < 12 ; timer++) WAITFORTIMER(); }

}else { rc5data = 0x0000; // error, invalid RC-5 code } TCCR0 = TMC8_STOP; sbi(TIMSK, OCIE1A); return (rc5data); } // stop timer0 // Enable the compare mode Once Again

/************ Signal handler for timer0 overflow interrupt****************/ SIGNAL(SIG_OVERFLOW0) { timerflag = 1; // set global variable TCNT0 = TIMER_0_CNT; } // reset counter to get this interrupt again

/****************** Compare IRQ ********************/ // Check for alarm and also update the LCD SIGNAL(SIG_OUTPUT_COMPARE1A) { cli(); // disable IRQ int i; if (mode == DISPLAY ) // Display Time Data; in display mode { lcd_gotoxy(0,1);lcd_puts(" "); hour = display_hour(4, 1); min = display_min(7, 1); sec = display_sec(10, 1); lcd_gotoxy(12,1); lcd_puts(" "); day = display_day(0, 2); date = display_date(6, 2); month = display_month(9, 2); year = display_year(13, 2); // convert the time into minutes format and then compare to the alarm values i = hour * 60; i = i + min; // check for alarm, get alarm data if ( alarm == 0 && ir_disable == 0 && alarm_count > 0) { for (int x = 1; x <= alarm_count; x++) { if ( i == alarm_value[x]) // if matched found { alarm = 1; // Set alarm status for further processing previous_min = min; switch (x) // based on where the matched meets the case will switch on the device { // Maximum five devices , can be increased accordingly case 1: sbi(DEVICE1_PORT, DEVICE1_PIN); device_status = device_status | 0x01; break; case 2: sbi(DEVICE2_PORT, DEVICE2_PIN);

device_status = device_status | 0x02; break; case 3: sbi(DEVICE3_PORT, DEVICE3_PIN); device_status = device_status | 0x04;// let to user to add port here break; case 4: sbi(DEVICE4_PORT, DEVICE4_PIN); device_status = device_status | 0x08; break; case 5: sbi(DEVICE5_PORT, DEVICE5_PIN); device_status = device_status | 0x10; break; } } } }

//Alarm in beeping mode if (alarm == 1 && ir_disable == 0) { outp(0xF1, DDRD); if ((sec & 0x01) == 1) { sbi(BUZZER_PORT,BUZZER_PIN); // BUzzer in sound mode sbi(BACK_LITE_PORT, BACK_LITE_PIN); // back light of LCD ON } else { cbi(BUZZER_PORT,BUZZER_PIN); // In OFF mde cbi(BACK_LITE_PORT, BACK_LITE_PIN); } } // snooze mode now if (alarm == 2 && ir_disable == 0) { outp(0xF1, DDRD); // for back light led full glow if (previous_sec != sec ) // change in second value snooze_tick++; if ((sec & 0x01) == 1) cbi(BACK_LITE_PORT, BACK_LITE_PIN); else sbi(BACK_LITE_PORT, BACK_LITE_PIN); previous_sec = sec; } if (snooze_tick > SNOOZE_DELAY * 60) { cbi(BUZZER_PORT,BUZZER_PIN); alarm = 1; // sound the buzzer , in normal alarm mode' snooze_tick = 0; sbi(BACK_LITE_PORT, BACK_LITE_PIN); outp(0xF0, DDRD); // put D0 in input mode once again } // if in IR disable mode, check if excape key is pressed within the same minute then alarm should not sound again if (ir_disable == 1 && previous_min != min) { ir_disable = 0;

alarm = 0; snooze_tick = 0; previous_min = min; previous_sec = sec; cbi(BACK_LITE_PORT, BACK_LITE_PIN); // disable back lighting outp(0xF0, DDRD); } } sei(); }

// Enable IRQ

I2C PROGRAM
/*********************************************************************/ /**********File Related to usage of I2C DS1307 RTC Chip***************/ /*********************************************************************/ // Include the file for using I2C IC /********** I2cmaster.S Used for purpose with Permission of********/ /********** Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury **************/ #include "i2cmaster.h" #include "lcd.h"

// Read Second Data and display the same char display_sec(char x, char y) { char tempv; tempv = DS1307_Read(RTC_SECOND); tempv = BCD2bin(tempv); lcd_gotoxy(x, y); if (tempv < 10) printf("0%d", tempv); else printf("%d", tempv); return tempv; } // Read Minute Data and display the same char display_min(char x, char y) { char tempv; tempv= DS1307_Read(RTC_MINUTE); tempv= BCD2bin(tempv); lcd_gotoxy(x, y); if (tempv < 10) printf("0%d:", tempv); else printf("%d:", tempv); return tempv; } // Display Hour char display_hour(char x, char y) { char tempv; tempv= DS1307_Read(RTC_HOUR); tempv= BCD2bin(tempv);

lcd_gotoxy(x, y); if (tempv < 10) printf("0%d:", tempv); else printf("%d:", tempv); return tempv; } // Read Year Data and display the same char display_year(char x, char y) { char tempv; tempv = DS1307_Read(RTC_YEAR); tempv = BCD2bin(tempv); lcd_gotoxy(x,y); if ( tempv < 10) printf(" 0%d", tempv); else printf(" %d", tempv); cursorOff(); return tempv; } // Read Date Data and display the same char display_date(char x, char y) { char tempv; tempv = DS1307_Read(RTC_DATE); tempv = BCD2bin(tempv); lcd_gotoxy(x,y); if (tempv < 10) printf("0%d", tempv); else printf("%d", tempv); return tempv ; } // Read Month Data and display the same char display_month(char x, char y) { char tempv; tempv = DS1307_Read(RTC_MONTH); tempv= BCD2bin(tempv); switch(tempv) // convert the numeric month data into a Months Name { case 1: lcd_gotoxy(x, y);lcd_puts("Jan."); break; case 2: lcd_gotoxy(x, y);lcd_puts("Feb."); break; case 3: lcd_gotoxy(x, y);lcd_puts("Mar."); break; case 4: lcd_gotoxy(x, y);lcd_puts("Apr."); break; case 5: lcd_gotoxy(x, y);lcd_puts("May."); break; case 6: lcd_gotoxy(x, y);lcd_puts("Jun."); break; case 7: lcd_gotoxy(x, y);lcd_puts("Jul."); break; case 8: lcd_gotoxy(x, y);lcd_puts("Aug."); break; case 9: lcd_gotoxy(x, y);lcd_puts("Sep."); break; case 10: lcd_gotoxy(x, y);lcd_puts("Oct."); break; case 11: lcd_gotoxy(x, y);lcd_puts("Nov."); break;

case 12: lcd_gotoxy(x, y);lcd_puts("Dec."); break; default: lcd_gotoxy(x, y);lcd_puts("Err."); break; } return tempv; }

// Read Day Data and display the same char display_day(char x, char y) { char tempv; tempv = DS1307_Read(RTC_DAY); switch(tempv) // convert numeric day data into Day Name { case 1: lcd_gotoxy(x, y);lcd_puts("Sun."); break; case 2: lcd_gotoxy(x, y);lcd_puts("Mon."); break; case 3: lcd_gotoxy(x, y);lcd_puts("Tue."); break; case 4: lcd_gotoxy(x, y);lcd_puts("Wed."); break; case 5: lcd_gotoxy(x, y);lcd_puts("Thu."); break; case 6: lcd_gotoxy(x, y);lcd_puts("Fri."); break; case 7: lcd_gotoxy(x, y);lcd_puts("Sat."); break; default:lcd_gotoxy(x, y);lcd_puts("Err."); } return tempv; }

// Data Read Routine from DS1307 char DS1307_Read(char address) { char tempv; // sec data i2c_start_wait(DS1307+I2C_WRITE); // set device address and write mode i2c_write(address); // write address i2c_rep_start(DS1307+I2C_READ); // set device address and read mode tempv = i2c_readNak(); // read one byte i2c_stop(); // stop i2c communcation return tempv ; } // Write Data to the DS1307 routine char DS1307_Write(char address, char value) { char tempv=0; i2c_start(DS1307+I2C_WRITE); // set device address and write mode /* issuing start condition ok, device accessible */ i2c_write(address); // write first the address and then the valsu i2c_write(value); i2c_stop(); return tempv ; } // Convert BCD number to a binary character unsigned char BCD2bin (unsigned char value) {

unsigned char tempv; tempv = (value & 0xF0)>>4; tempv = tempv * 10; value = value & 0x0F; tempv = tempv + value; return tempv; }

// shift to separate the higher nibble // higher nibble multiplied by 10 // and lower nibble added

// Convert Binary number to BCD unsigned char bin2BCD (unsigned char value ) { char tempv; tempv = 0; while (value > 9) { tempv = tempv + 0x10; value = value - 10; } tempv = tempv + value ; return tempv; }

// Write the latest data in the Alarm RAM and update the alarm count after addition routine void updateAlarmData(int sah, int sam, int acc) { char temp; temp= bin2BCD(sah); DS1307_Write(ALARM_START_RGST + ((acc-1) *2), temp); temp= bin2BCD(sam); DS1307_Write(ALARM_START_RGST + ((acc-1) *2) + 1 ,temp); temp= bin2BCD(acc); DS1307_Write(0x3f, temp); readAlarmValues(); }

// Update the alarm data after deletion routine void updateAlarmData_Delete(char dc, char tc) { signed char alarm_start_address = ALARM_START_RGST + dc ; signed char alarm_end_address = ALARM_START_RGST + ((tc-1) *2); char t, i; for (i= alarm_start_address ; i <= alarm_end_address; ) { t= DS1307_Read(i+2); // read hour from one position down DS1307_Write(i, t); // write t= DS1307_Read(i+3); DS1307_Write(i+1, t); i= i+2; } t= bin2BCD(tc -1 ); // decrement total count now DS1307_Write(0x3f, t); lcdCmdWrite(0x01); lcd_puts(" Deleting Data"); for (int x= 0; x < 200; x++) delay(6000); // read the alarm setting readAlarmValues(); } // read min and write

// Read Alarm values and convert to the Minutes format void readAlarmValues(void)

{ signed char i, xx = 1; alarm_count = DS1307_Read(ALARM_COUNT_RGST); alarm_count = BCD2bin(alarm_count) ; // read the alarm setting after the changes and take in new value for (i=0; i < (alarm_count * 2); i=i+2) { alarm_value[xx] = BCD2bin(DS1307_Read(ALARM_START_RGST + i )) * 60; alarm_value[xx] = alarm_value[xx] + BCD2bin(DS1307_Read( ALARM_START_RGST + (i+1) )); xx++; } }

// Write new values to the RTC void writeChangeValues(void) { char temp; DS1307_Write(0x00, 0x80);

// disable the RTC

temp = bin2BCD(min); DS1307_Write(RTC_MINUTE, temp ); temp = bin2BCD(hour); DS1307_Write(RTC_HOUR , temp); temp = bin2BCD(day); DS1307_Write(RTC_DAY , temp); temp = bin2BCD(date); DS1307_Write(RTC_DATE , temp); temp = bin2BCD(month); DS1307_Write(RTC_MONTH, temp); temp= bin2BCD(year); DS1307_Write(RTC_YEAR, temp); DS1307_Write(RTC_SECOND, 0x00); } /******************** RTC Initialization ********************/ void i2c_initialization(void) { char temp, i; i2c_init(); // init I2C interface DS1307_Write(RTC_CONTROL, 0x90); // Set the ControlRgst value // set initial time // Set the Initial value and Ch bit6 DS1307_Write(RTC_SECOND, 0x00); temp = bin2BCD(40) ; // changes to be made here only for testing DS1307_Write(RTC_SECOND, temp); // Initial screen display time as 00:00:50; 50 indicates temp = bin2BCD(0); // evrything is worling fine DS1307_Write(RTC_MINUTE, temp ); // can be set to any value for initial setup or temp = bin2BCD(0); // debugging DS1307_Write(RTC_HOUR , temp); temp = bin2BCD(1); // initial date and day setting DS1307_Write(RTC_DAY , temp); temp = bin2BCD(1); DS1307_Write(RTC_DATE , temp); temp = bin2BCD(1); DS1307_Write(RTC_MONTH, temp); temp= bin2BCD(0); // write second value i.e. = 0

DS1307_Write(RTC_YEAR, temp); for (i = ALARM_START_RGST; i <= ALARM_END_RGST; i++) DS1307_Write(i, 0xFF); // from 0x08 to 0x3E // Alarm count as zero DS1307_Write(ALARM_COUNT_RGST, 0x00); dummy(); } // dummy data to write into Alarm RAM, to check the functioning //can be delete, helps in de-bugging // Write 0xFF into all user RAM area

// Dummy data, written into Alarm RAM area, used for de-bugging purpose // These value are used to check alarm setting and display will indicate // that everything is working properly void dummy(void ) { char temp ; temp= bin2BCD(0); DS1307_Write(0x08, temp); temp= bin2BCD(1); DS1307_Write(0x09, temp); temp= bin2BCD(0); DS1307_Write(0x0a, temp); temp= bin2BCD(3); DS1307_Write(0x0b, temp); temp= bin2BCD(0); DS1307_Write(0x0c, temp); temp= bin2BCD(21); DS1307_Write(0x0d, temp); temp= bin2BCD(0); DS1307_Write(0x0e, temp); temp= bin2BCD(15); DS1307_Write(0x0f, temp); temp= bin2BCD(0); DS1307_Write(0x10, temp); temp= bin2BCD(10); DS1307_Write(0x11, temp);

//alarm 1 value

//alarm 2 value

//alarm 3 value

////alarm 4 value

//alarm 5 value

temp= bin2BCD(5);

// total alarm count // RAM also holds the total number alarm setting // Maximum is 5, limits can be changed

DS1307_Write(0x3f, temp);

PCB DESIGN & FABRICATION

Design of a PCB plays an important role in the performance & reliability of the electronic circuit. The productivity of the PCB & its assembly & serviceability depends on the design. All these factors finally get reflected in the piece of the electronic equipment. From this, it is evident that the task of PCB design is not simple or always straight forward. The schematic is

followed by the genetic of artwork low out design is the stage where engineering capacity combined with creativity are the governing input whose practical skill combined with technical commonsense have to be predominant in artwork preparation.

GENERAL GUIDE LINES The points to be remembered whole designing a PCB are the width of copper track, its spacing, number of layers used, & the material used for making PCB etc. The width is related to the power requirement of the circuit. For the supply track we have to provide high enough spacing as for the requirement. Also for high frequency ckt such as crystal oscillator, we provide smaller to reduce stray capacitance. It also requires project grounding to avoid noise problems. Without project grounding noise voltages will seriously affect the device which result in erroneous output. Hence project grounding is an important step in PCB & in such case the glass epoxy boards are the right choice.

THE DESIGN SOFTWARE Orcad is a low cost feature rich package for designing electronic circuits. The various tools in orcad & their implementation in designing the PCB are discussed briefly in the next session.

EDA With the advent of powerful computing system & interactive software several stages in the design & the development of an electronic circuit or product has undergone automations. Thus the software & hardware tools, which enable this automation, are collectively know as EDA tools. Example of automation application include PCB design, IC design, circuit stimulator etc. These tools help us in such away we can draw the circuit, test the functioning of the ckt in response to test input in a stimulation software & after successful stimulating the ckt we can get the PCB artwork done by the placing & roofing software. In our project we have made use of EDA tools for PCB design. The design automation tools are read for window, which include. ORCAD CAPTURE For creating ckt diagrams schematic & net list. ORCAD LAYOUT For creating PCB artwork. PCB design produces consist of the following steps. 1. DRAWING THE CIRCUIT SCHEMATICThis is done in orcad schematic capture software. It includes many libraries & thousands of component symbols. We can select the required component form library & place it on the schematic page. After placing the component symbol, we can complete the interconnection using wire bar tools. A ckt diagram can be broken up into several schematic pages. In this case the connection between two pages has to be established using off page connector with some reference. After drawing the schematic the following operation has to be done. (a)ASSIGNING THE PART REFERENCE Each component or part should have a unique name or reference to identify it. It can be done manually or automatically. (b) ASSIGNING PART VALUES

Each component can be assigned a part value i.e. the commercial name or number of the part. This is optional. 1. ASSIGNING THE FOOT PRINTS Each component or part has to be assigned a foot print or PCB pattern name. The foot print gives the actual physical representation of the component on PCB artwork. The corresponding PCB foot print can be obtained from the orcad manual. The notepad files as that of the schematic file. 2. DESIGN RULE CHECK (DRC) & NETLIST CREATION. After the circuit the schematic is ready with all required information such as part, reference & footprint, DRC tool can be used for checking errors in the design. It will check for electrical rules, missing connection etc. And report the errors fount correcting the final operation to be done before starting the PCB artwork is the net-list creation. A net list is the description of the components & their inter connection along with other information such as foot prints track widths etc. A net-list generation software or tools can take the circuit. Schematic as input & generate the net list are net list can be used as an information source for remaining stages.

CREATING THE PCB ARTWORK

In automated design the net list obtained from the previous stages is used for creating the PCB.

SCREEN SHORT OF LAYOUT

SCREEN SHORT OF ASSEMBLY SCREEN

SCREEN SHORT OF ORCAD CAPTURE

LIST OF COMP

Item Number Quantity Value 1 1 1u/16v 2 1 0.1u 3 1 20uF/25v 4 1 LED 5 1 DIODE 6 1 CON16 7 1 I RX TSOP1738 8 1 buzzer 9 1 CON2 10 1 CON8 11 1 CON2 12 1 SL100 13 1 SL100 14 1 10k 15 1 10k 16 1 10k 17 1 2.2k 18 1 220 19 1 10k 20 1 POT 21 1 10k 22 1 50 23 1 120 24 1 2.2k 25 1 100

Description Part Number Part Reference C1 C3 C5 D2 D3 J1 J2 J3 J4 J5 J6 Q1 Q2 R1 R2 R3 R4 R5 R6 R8 R9 R10 R11 R12 R14

26 27 28 29 30 31

1 1 1 1 1 1

SW TACT-SPST ATmega16 DS1307 LM7805/TO LM7812/TO CRYSTAL

SW1 U4 U8 U9 U10 Y1

Vous aimerez peut-être aussi