Вы находитесь на странице: 1из 47

3 channel IR remote control This project is a 3-channel IR remote control with 3 output relay and easy to build.

Feature :

CPU PIC12F629 at 4MHz crystal for Tx/Rx 3 channel output relay The Tx use sleep mode for saving battery power Use Phillips RC5 protocal distance more than 7 m. Easy circuit to build and assembly small components

Basic RC5 protocal The RC5 is probably the most used by hobbyists, probably because the wide availability of cheap remote controls and easy to understand. Feature :

2 start bit always "1" 1 toggle bit but this project not use and always "0" 5 bit address and 6 bit command length Bi-phase coding (aka Manchester coding) Carrier frequency of 36kHz 25-50% duty cycle Bit time period about 1.67 ms Developt by Philips

The protocol uses bi-phase modulation (or Manchester code) of a 36kHz IR carrier frequency. All bits are of equal length of about 1.67 ms as follows figure.

Figure 1. RC5 Modulation

Figure 3. Bi-Phase coding

In figure 2,the first two pulses are the start pulses, and are both logical "1". (St1 and St2) The 3d bit is a toggle bit. This bit is inverted every time a key is released and pressed again. But this project not use this bit and always "0" (Ctrl) The next 5 bits represent the IR device address, which is sent with MSB first. (S0-S4) The next 6 bits is command and sent with MSB first too.(C0-C5) Note that a RC5 frame consists of a total of 14 bits so the total time is about 23 mS

RC5 detecting When the detect subroutine is called, it first waits for a start bit. The length of the low part of the first start bit is measured. If the low pulse of first start bit is longer than 1.020 ms or less then 800 uS the routine returns indicating error or no command received.

Figure 4. Synchronizing and Sampling of the Data

The measurement of the start bit is used to calculate two reference times, ref1 and ref2, which are used when sampling the data line. The program uses the edge in the middle of every bit to synchronize the timing. 3/4 bit length after this edge, the line is sampled. This is in the middle of the first half of the next bit (see Figure 4).The state for each bit is stored and the routine waits for the middle edge.

Tx schematic

The TX use 8 pin PIC devices, here is PIC12F629 run at 4 MHz crystal. Actualy, this device has 4MHz RC internal oscillator but not suitible for use with the project that need cirtical time as remote control.The 36KHz carrier and information bit generated by IC1.For saving power when use with battery powered we need to use this device in sleep mode when any keys not pressed and draw current <1 mA at 4MHz, 5.5V .

Example how to wake-up from sleep mode when key pressed.


main : SLEEP BTFSS GOTO BTFSS GOTO BTFSS GOTO GOTO CH1 Do_CH1 CH2 Do_CH2 CH3 Do_CH3 main

Rx schematic

The IR was recieved from Tx will demodulated by IC2 that is IR receiver Modules for Remote Control Systems.In this project I use TSOP4836 from Vishay Semiconductors that is one of TSOP48XX series. After IR demodulated it was decoded the protocal by IC1 then turn on/off appropiate channel.The out out of IC1 is toggle every time when Tx send the same command to Rx.You may be change the output drive circuit for suitible with your load.The pin 3 of IC1 must pull-up to vcc with R10K becuase it is not has weak-up internal pull-up.

RC5 Basics

Introduction The RC5 protocol was developed by Philips as consumer IR (infrared) remote control communication protocol for consumer electronics. Data Format The RC5 code is 14 bits long. Each code includes 2 start bits, 1 toggle bit, a 5 bit address (or system) and a 6 bit command. This allows for 32 systems (like TV, CD, video, etc.) and 64 commands per system.

The two start bit indicate the start of the RC5 frame. Note: After some time 64 commands per system didn't seem to be enough though, so an extra command bit was added to allow 128 commands. To maintain backward compatibility with the standard RC5, the format itself was left unchanged. The second start bit (S2) was replaced by C6. The resulting format is called Extended RC5. The toggle bit T changes each time a new command is transmitted. It allows detection if the same key is pressed twice. Since a code is being sent as long as the key is pressed, a short release of the button and again pressing it again would otherwise not be recognized.

The address bits A5..A0 specifies the system (or device) the command shall be sent to, e.g. TV, CD, Video, etc. Finally, the command bits specify the command to be performed. Modulation RC5 uses Manchester coding. Manchester coding has a transition in the middle of a bit. A logical 1 is coded as a 0 in the first half of the bit and a 1 in the second half of the bit. A logical 0 is coded as a 1 in the first half of the bit and a 0 in the second half of the bit.

Important hint: Most of the IR-Receivers (e.g. the SFH5110 or TSOP1736) have an inverted output! So a logical 1 at the output of the IR-Receiver will be represented by a 1 in the first half of the bit and a 0 in the second half, a logical 0 will be represented by 0 in the first half of the bit and a 1 in the second half. RC5 Example In the example below an example of an RC5 code which shows how the information is coded. In this example the toggle bit is 0, the address is also 0 and the command is 9, i.e. key '9' has been pressed.

Hardware

As IR-Receiver I used a SFH5110-36 which is a IR-Receiver for Remote Control Systems. Also other IR-Receivers like, a SFH506-36 or TSOP1736 will work. Important is that the IR-

Receiver is designed for a carrier frequency of 36kHz (which is the carrier frequency used by RC5). The interface to the PIC microcontroller is very simple, the output of the IR-Receiver just needs to be connected to an "interrupt on-change" pin. I used a PIC16F886 where port B has "interrupt on-change" capability, so I connected it to port pin RB1. Further I also added a pull-up resistor (according to the datasheet this is optional).

Software

The RC5 software driver is written in C language and currently is compatible to CCS C compiler and Microchip C18 compiler. Decoding The decoding happens in the interrupt service routine of the "on-change" interrupt of port B, i.e. every time the logic level on the pin changes the decoding is done. As time base for the decoding a free running hardware timer of the microcontroller is used, so the timer can also be used for other things. In my demo application, I used timer 0 of the PIC which is configured to increment every 25.6us. The resolution of 25.6us provides enough accuracy for decoding the RC5 signal (a half bit is 889us long). Timer 0 is a 8 bit timer, with a timer increment every

25.6us an overflow will occur every 25.6us * 256 = 6553us. Since the bit length is 1778us which is (much) smaller than the timer overflow time this configuration is ok for decoding the RC5 signal. RC5 Driver Configuration To use the RC5 driver in your projects, the following things need to be configured. First of all, the pin where the IR-Receiver is connect needs to be specified via the #define RC5_DATA_PIN. In the demo I used RB1. I.e. PIN_B1 needs to be replaced by the pin where the IR-Receiver is connected to. Important is that the pin which shall be used has "onchange" interrupt capability!
#define RC5_DATA_PIN connected to RB1 */ PIN_B1 /* IR sensor (SFH5110-36)

Since a hardware timer is required as time base for decoding the RC5 signal, the driver needs to know how often the timer is incremented per millisecond. In my example timer 0 is used which is configured to increment every 25.6us, hence it will increment 1000us/25.6us = 39 times per 1ms (1000us).
#define RC5_TICKS_PER_MS (1000/26) 25.6us, */ /* i.e. around 39 ticks per millisecond */ /* timer increments every

The driver also needs to know which timer is used or to be more precise how to get the current timer value. To achieve this, the macro RC5_GetTimer() needs to be defined. This macro shall return the current timer value. In the demo I used timer 0, hence it is configured to "get_timer0()" which is a CCS built in function which returns the timer 0 register value.
#define RC5_GetTimer() decoding */ get_timer0() /* timer0 shall be used for RC5

Since the RC5 driver is no properly configured, we have to include the RC5 driver itself.
#include "rc5.h" /* RC5 driver include */

Now we need to add the interrupt handler which calls the RC5 decoding function of the RC5 driver. The decoding function is RC5_InterruptHandler().
/************************************************************************** ***/ /* Interrupt_RB */ /* */ /* Port B change interrupt service routine. */ /* Used to decode RC5 IR signal. */ /************************************************************************** ***/ #INT_RB void Interrupt_RB(void)

{ RC5_InterruptHandler(); clear_interrupt(INT_RB); }

And finally, we need to configure the timer 0 which will be the time base for the RC5 decoding function and enable the "on-change" interrupt.
/* FOSC/4 is timer source */ /* FOSC = 20MHz => 5MHz, i.e. timer increment every t = 1/(FOSC/4) = 200ns */ /* with prescaler of 128 timer will increment every 25.6us */ setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128); /* configure port B interrupt on change */ set_tris_b(0xFF); /* all pins on port B are input */ input_b(); /* read port B to clear mismatch condition */ clear_interrupt(INT_RB); /* clear port B interrupt flag */ enable_interrupts(INT_RB1); /* enable RB1 interrupt on change */ /* global interrupt enable */ enable_interrupts(GLOBAL);

RC5 Decoder Demo Application Here a full demo application showing the RC5 driver usage. A full CCS C project and Microchip C18 project can be downloaded in the Download section below. The following explainations are done based on the CCS C project, but are very simialr for the C18 compiler.
/*** FILEHEADER **************************************************************** * * FILENAME: rc5demo.c * DATE: 26.07.2011 * AUTHOR: Christian Stadler * * DESCRIPTION: RC5 demo which shows usage of RC decoder driver. * *************************************************************************** ***/ /* make compiler case sensitive */ #pragma case #include #include "types.h" /* --- RC5 driver configuration --- */ #define RC5_DATA_PIN PIN_B1 /* IR sensor (SFH5110-36) connected to RB1 */ #define RC5_TICKS_PER_MS (1000/26) /* timer increments every 25.6us, */ /* i.e. around 39 ticks per millisecond */ #define RC5_GetTimer() get_timer0() /* timer0 shall be used for RC5 decoding */ #include "rc5.h" /* RC5 driver include */ /* --- macros to switch on/off LED --- */ #define Led_On() output_high(PIN_A0) #define Led_Off() output_low(PIN_A0)

/************************************************************************** ***/ /* Interrupt_RB */ /* */ /* Port B change interrupt service routine. */ /* Used to decode RC5 IR signal. */ /************************************************************************** ***/ #INT_RB void Interrupt_RB(void) { Led_On(); RC5_InterruptHandler(); clear_interrupt(INT_RB); Led_Off(); } /************************************************************************** ***/ /* main */ /* */ /* Configures timer0 as time base for RC5 decoding and enables port B */ /* interrupt on change. */ /* Main loop checks if a RC5 code has been received and writes the code */ /* to the RS232 interface. */ /************************************************************************** ***/ /* NOTE: Currently it only works if PIC is reset after programming? */ void main() { uint16 rc5code; /* FOSC/4 is timer source */ /* FOSC = 20MHz => 5MHz, i.e. timer increment every t = 1/(FOSC/4) = 200ns */ /* with prescaler of 128 timer will increment every 25.6us */ setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128); /* configure port B interrupt on change */ set_tris_b(0xFF); /* all pins on port B are input */ input_b(); /* read port B to clear mismatch condition */ clear_interrupt(INT_RB); /* clear port B interrupt flag */ enable_interrupts(INT_RB1); /* enable RB1 interrupt on change */ /* global interrupt enable */ enable_interrupts(GLOBAL); printf("**** RC5 Demo started! **** \n\r"); while(TRUE) { /* check if new data is available */ if (RC5_CodeReady()) { /* get code */ rc5code = RC5_GetCode();

printf("RC5 Code=0x%04LX DevAddr=0x%02X Toggle=%d Cmd=0x%02X\n\r", rc5code, RC5_GetDeviceAddr(rc5code), RC5_GetToggleBit(rc5code), RC5_GetCmd(rc5code)); } /* this function increments the RC5 timeout timer */ /* NOTE: Decoding will also work without calling this function, but */ /* it could happen that RC5 codes are sometimes not getting */ /* recognized because of decoding state machine stucks due */ /* to erroneous RC5 signal. */ RC5_TimeoutIncrement(); } }

Chapter 1

Chapter 2

Chapter 3
P1 P2 P3 Disassembler
Soldering and using a prototype PC board PIC12F629 Data Sheet (.pdf 4,926KB) PIC12c508A Data Sheet (.pdf 1,600KB) Instruction Set for PIC12F629 blank12F629.asm template Notepad2.zip Notepad2.exe PIC12F629.asm Chip as a "D" flip flop Library of Sub-routines "Cut and Paste" Library of routines: A-E E-P P-Z PIC12F629 Project: 2-Digit Counter PIC12F629 Project: 20 LED Display-1 10 Projects using the PIC12F629 12 FREE PIC Books Simply download the books via Rapidshare. Lots of PIC micro information on this website.

You may be asking "Why do I use a PIC chip?" The answer is simple. There is nothing else. Let me fill you in. I have been developing a range of modules similar to the talking modules and music chips in greeting cards. But these "sound" cards are so prosaic. The tunes are frightful and the speech is quite unfunny. For a person like me, who has never bought a card in his life, it is unusual to be designing electronic cards. Possibly because most of the cards on the market "fall between two stools," I have decided to design something that is a pleasure to give. I don't like gaudy, over-designed images or wording that doesn't fit the occasion. For that reason the cards I have designed are simple and uncluttered. But more important, they contain an electronics module that delivers a concept that has never been produced. For a few extra dollars you get a card that contains a gift that can keep the recipient happy for the afternoon. Some of the ideas for the modules include a Reaction Timer, a "sky writer that produces words in the air, a 20 second timer, a game of NIM and a decision-maker.

All the circuits are designed around an 8-pin microcontroller - the PIC12F629. At first glance this chip seems to be too expensive, at about 60 cents, and I was steered in the direction of the ATMIL TTtiny11. But it was soon realised this chip was going out of production and the ATtiny12 was heading the same way. The next chip in the range was ATtiny13 but the cost was higher than the PIC chip and I would have to transport my code as well as suffer a slightly reduced output drive current. Then MicroChip came to the rescue with a special chip for production-runs. Not only was it cheaper but it had additional features above the PIC12F629. The only reductions on the '629 are 2-stack (instead of 8), fewer registers and in different locations (that's why you use the "equ" statement), and no EEPROM (so data is lost when the chip is turned off). But the plusvalues include an Analogue to Digital Converter and a precision voltage reference. I also tried all the other manufacturers and nothing similar in price was available. So, the decision is made and the supply is guaranteed for quantities of 100,000. If you are thinking of designing anything for the mass-market, email me before starting anything so you don't waste time searching in the wrong direction as there are chips that are not available to the consumer market. Before reading this article, go to ICP article. It shows how to solder a surface-mount or through-hole PIC12F629 to a PC board with a programming socket that will accept In-Circuit Programming. Use the kit on the ICP page to write your first program. The article also shows how to use the PICkit-2 USB programmer.

In a nutshell, the simplest PIC chip is the PIC12C508. The PIC12C509 has twice the memory but both are only programmable ONCE. This type of chip is now HISTORY. We don't use them any more. The replacement is the PIC12F629. If you want analogue inputs, the chip to use is the PIC12F675, None of these chip has a low-voltage programming feature. For low-voltage in-circuit serial programming use PIC16F628. The PIC12F629 comes in:

8-pin (through hole) 8/PDIP

8-pin SMD (surface mount) PIC12F629-I/SN 8/SOIC package

SOIC = SOP = SMD IC = 050 (1.27mm) spacing. SOIC - pins are bent slightly at PC board SOP - pins are flat when touching PC board

Before we start:
Although the PIC12F629 is an up-grade of the PIC12C508 and '509, the program from a PIC12C508 cannot be transferred directly to a PIC12F629 as there are a number of differences between the two chips. The following items cover some of the differences.

1. The CALL Instruction


The CALL instruction for a PIC12C508,9 only works to the first 256 locations. The CALL instruction for a PIC12F629 accesses ALL MEMORY.

2. The STACK
The PIC12C508A has only a 2-CALL stack. The PIC12F629 has an 8-CALL stack. (8-level stack).

3. The In/Out Port


The IN/OUT port on a PIC12F629 is file 05h. This port corresponds to pins 7, 6, 5, 4, 3, and 2 for GP0, GP1, GP2, GP3 GP4 and GP5. Remember: GPIO,3 (GP3) (pin 4) is an INPUT-ONLY pin. When writing a program, use GPIO,0 GPIO,1 GPIO,2 GPIO,3 GPIO,4 GPIO,5 in your program and the compiler will do the rest. (GPIO = General Purpose Input/Output). For instance, If you want to SET (make HIGH) pin 7, you must do two things: 1. Make sure GPIO,0 is an OUTPUT bit by making the corresponding bit in the TRISIO register "0." This is done via the following instructions: Remember: "0" = output, "1" = input bsf status, rp0 ;bank 1 movlw b'xxxxxxx0' ;(x= don't care = does not matter) movwf TRISIO ;the lowest bit will be an OUTPUT bcf status, rp0 ;bank 0 2. Make the lowest bit of the output port = 1 (HIGH). This is done via the following instruction: bsf GPIO,0

Do not set more than one bit at a time in the GPIO (in/out) port. In other words, do not create two instructions such as: bsf bsf GPIO,0 GPIO,2

If you need to clear or set two or more output lines, perform the operation via a single instruction, thus: movlw b'xxxxx1x1' movwf GPIO You need to know the state of all the outputs and include this in the value you are going to load into GPIO via movlw b'xxxxxxxx' etc. As can be seen from the above, the six lower bits of file 05 are connected to 6 pins of the chip

to connect the microprocessor to the outside world. This file is like all the other files (from 20h to 5F - 64 files) as it can be operated-upon (incremented, decremented, shifted left or right, plus the other operations). The only difference is the contents of file 05 can be exported to the outside world and the outside world can influence the file. When any of the bits of file 05 are configured as "out," the value of the bit will make the corresponding pin of the chip either HIGH or LOW. When it is "set" (=1), the pin will be HIGH. When it is "clear" (=0), the pin will be LOW.

READING AN INPUT LINE


When any of the bits of file 05 are configured as "input," (this is done via the TRISIO instruction) the HIGH or LOW on the pin of the chip (this HIGH or LOW will be created by something in the outside world making the line HIGH or LOW) will be read by the micro as a HIGH or LOW, (when the file is read via an instruction such as btfss GPIO,1 or btfsc GPIO,1 bit test1 in file 05h, skip if set or bit test1 file 05h, skip if clear). This "reading process" can also be done when the contents of file 05 (GPIO) is moved to W. The instruction to do this is movf 05h,0 This instruction tells the micro to move the in/out port to the working register. The working register is called "W" and has the destination "0" - a file has the destination "1." The contents can also be shifted, incremented, plus other instructions. Here are some instructions to read the input bit: In most cases, the first bit (or line) to use in a program is pin 4 as this line is INPUT ONLY. It corresponds to GPIO,3. Using the instructions from above, we have GPIO,3 as an INPUT and all other lines are OUTPUT. We are looking for a HIGH on the input line. To read the bit, use the following instructions: btfsc GPIO,3 ;This will test the input bit and if it is LOW, the micro goes to movlw xx GOTO PhaseA ;This instruction takes the micro to a new sub-routine movlw xx If you don't know the state of some of the bits (or don't want to alter them - by mistake), you can use the XOR instruction. For example, to turn ON bits 0, 1 and 2, the instructions can be: bsf GPIO,0 b'00000001' bsf GPIO,1 b'00000010' bsf GPIO,2 b'00000100' But this will result in only the third instruction being carried out. We mentioned above, not to use multiple bit-setting as it will fail to work. The answer is to use the XOR instruction Combine the 3 instructions to get: b'00000111' movlw 07h xorwf GPIO Only the three lowest outputs will go HIGH. To turn OFF the three lowest outputs, repeat the same instructions: movlw 07h xorwf GPIO Only the three lowest outputs will go LOW. Actually, the bits will TOGGLE. The in/out port (file 05h for PIC12F629) is shown in RED in the following map. It is called GPIO:

Voltage on an Input line


Most input lines are classified as TTL and the voltage must be above 2v (for 5v rail) for the chip to detect a HIGH. GP2 is Schmitt Trigger input a it TMR0 clock input. This line requires 2.5v to detect a HIGH and 1.75v to detect a LOW. The TTL input have a very small gap between HIGH and LOW and to make sure the input line detects correctly, the input voltage must be much higher or much lower than the detection-point.

4. Reading the Input Port


To read the individual pins of the input port of a PIC12F629, use one of the following instructions. (GPIO,3 (GP3) (pin 4) is an INPUT-ONLY pin and this pin is the first to use. If the input pin is normally low and goes HIGH when a signal is sent to the micro, use one of the following: btfsc 05h,0 (This the same as: btfsc GPIO,0) btfsc 05h,1 btfsc 05h,2 btfsc 05h,3 - this is pin 4 - GPIO,3 - use first in your program btfsc 05h,4

btfsc 05h,5 The next instruction will be: goto task1 - input has been detected It may be difficult to read the same input bit further down a program. This is solved by setting and clearing the bit, thus: bsf bcf nop bsf bcf status, rp0 TRISIO,0 TRISIO,0 status, rp0 ;Bank 1

;bank 0

5. The General Purpose Files - called GPR's (General Purpose Registers)


The General Purpose Files are the files you use in your program for sub-routines such as delays, comparison, incrementing, decrementing, etc. A program can start by loading a value into GPIO and outputting it to the outside world (such as a LED). A value (called a literal) is loaded into a file (a General Purpose File) and decremented until it is zero. This allows the LED to be viewed. In the diagram above, you can see the 25 General Purpose Files in a PIC12C508/9 do not match up with the 64 files in a PIC12F629. This means any program written for a '508 will not work in a PIC12F629. The solution is to add 20h to the files that have been used in a '508 program to move them so they align with the PIC12F629 files. The following table shows the result:

Old '508 file:


07h 08h 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh 10h

for '629 Change to:

27h 28h 29h 2Ah 2Bh 2Ch 2Dh 2Eh 2Fh 30h

11h 12h 13h 14h 15h 16h 17h 18h 19h 1Ah 1Bh 1Ch 1Dh 1Eh 1Fh

31h 32h 33h 34h 35h 36h 37h 38h 39h 3Ah 3Bh 3Ch 3Dh 3Eh 3Fh

6. Incrementing a File
When incrementing a file such as: incf 2Ah,1 The result is placed in the file and the working register "W" is not affected. With the instruction: incf 2Ah,0 only the working register "W" contains the result. In other words, the file is NOT INCREMENTED!!! With the instruction: incf 2Ah the assembler assumes ",1" and increments the file. But it is best to always include the directive. In the above, W=0 and f=1 where W is the working register and f is the file being incremented.

7. Current of an Output Line


The maximum current of an output line is 25mA. In the following diagram, no current-limiting resistors have been included and the current through the red LED will be more than 25mA as the voltage across the LED is 1.7v and theoretically the current will be as high as the battery can deliver. The chip will provide some current-limiting but the flow will be higher than 25mA and the chip may be damaged.

Two 47R resistors are needed as shown in the schematic below:

8. Driving a LOAD
The output current of each line of a microcontroller is very small. It is only 25mA. The only two items that can be driven directly from an output are a LED and a mini piezo diaphragm. The following diagram shows how these items can be connected (interfaced).

For a current greater than 25mA, a transistor will be needed. A transistor will be able to deliver about 500mA to 1Amp. This is assuming the transistor has a gain of 20 - 40 and this about the capability of a transistor - called a small-signal transistor. For larger currents, a MOSFET will be needed. These devices will deliver 20 amps or more to a load. There are two ways to describe the requirement of "driving a load." You can say you want to "drive the transistor as an amplifier" or "drive the transistor as a switch." When a transistor is used in an analogue situation, there is a big difference between these

two statements. In an audio amplifier, when the transistor is amplifying the signal, the output is a faithful reproduction of the input, but with a larger amplitude. Or the shape of the signal will be identical but with a larger current capability. But if the transistor in an audio amplifier is driven as a switch, the output will rise very high as soon as the input waveform starts to rise. In most audio cases this will create distortion. But with a microcontroller we are dealing with a digital circuit and the output is either 0v or rail volts (5v). Any transistor connected to the microcontroller can only have two states. When the output is zero, the transistor is turned off. This is called CUTOFF. When the output is high, the transistor is turned ON fully. This is called SATURATION. These two states are called SWITCHING STATES. When a transistor is in either of these two states, it dissipates the least amount of heat. When a transistor is CUTOFF it is obvious that the heat dissipation is low as it is zero. When a transistor is SATURATED, it has the lowest voltage across it and although the current flow is the highest, the heat dissipated is the lowest as the heat loss is multiplication of current and voltage. Suppose we want to drive a wailing siren from a microcontroller. If the microcontroller delivers the varying tone to the speaker, we say the transistor is acting as an amplifier. It is acting as a DIGITAL AMPLIFIER. It is being switched ON and OFF at different rates and the result is a wailing sound. When we refer to the transistor as a SWITCH, we often require it to turn on a device for a long period of time - such as a relay or LED.

9. GP3 - pin 4

Driving a LOAD

GP3 is an INPUT Only and cannot be used to drive a load. The only drive-lines for PIC12f series are: GP 0 - pin 7 GP 1 - pin 6 GP 2 - pin 5 GP 4 - pin 3 GP 5 - pin 2

10. 100n across the micro


Don't forget the 100n across the power rails. Place it near the micro. It stops the micro starting-up half-way through the program! Without the capacitor, the micro can start anywhere down the program and create all sorts of unusual effects.

SOME APPLICATIONS:
Although the PIC12F629 is the simplest device in the PIC range, it can can carry out operations such as monitoring and controlling:

Battery Monitoring and Voltage Detection

Watchdog Timing

Circuit Resetting

Voltage Detecting There are many specially-designed chips for these applications, but they must be purchased in large quantities. To keep your inventory down, you can use a PIC chip with a few external components to perform the operation. All you have to do is design the circuit (the detection

section) and program the chip.

READING A PIC CHIP


If you have a PIC12C508/9 chip and want to get the program and convert it to suit a PIC12F629, you will need to fit it into the socket of our Multi Chip Programmer and read it via ICProg. To do this you will need to pick PIC12C508 from the list of microprocessors from the "drop down" menu. You will also need disasm.dll or the Disassembler link above. For disasm.dll, use the "lightening" symbol to import the code from the chip. It will appear in the frame on the screen. Use the "A" button (next to the "H" button) to see the disassembled program. You can then copy and save the program in Notepad. Only chips that are not Code Protected, can be read. We only have some information on reading chips that are Code Protected: Cracking a PIC Chip If you have the .hex file, you can get the assembly file via disasm.zip as explained above. Once you have the assembly file, you can change the files as shown above.

SOME PROGRAMMING TRICKS:


The author has found problems with some instructions. The PIC12F629 does not like setting a bit on the in/out port and then setting or clearing another bit in the next instruction. The problem instructions are something like this: bsf 05,2 bsf 05,4 The micro does not set the second bit when it is executing the program. The answer is to work out the value in file 05 before the two instructions, add the value of the bits and place the value in the in/out port via the following two instructions: movlw xxh movwf 05h Alternatively, a meaningless instruction can be inserted between the two "bsf" instructions. This MAY work but is not as guaranteed as the method above. bsf 05,2 nop bsf 05,4 Each new program or modification MUST be saved with a new name as either MPASM or IC_Prog will not detect the changes and you will get the old program burnt into the chip and wonder why the changes did not fix the problem!

USING A SIMULATOR AND DEBUGGER


To help developers get a program to work successfully, a number of programming tools have been created. Two of these are a SIMULATOR and a DE-BUGGER. These are software programs and a simulator runs your program and lets you know if it will work. It seems to be the answer to a dream. But a simulator has many limitations. It assumes any hardware devices connected to the program are "ideal devices." For example, it will assume a switch has no "contact bounce" and is pressed and released very quickly. This does not happen in real life, so your program must be re-tested in actuality. Also, any output to LEDs etc assume the items are connected around the correct way. You will still have to test the actual circuit and make sure the current is within the limits of the micro. A de-bugger is also another piece of software that tries to locate a fault in your code. It has a "single step mode" in which it shows the contents of each register after an operation. Sometimes these program will assist but let me assure you that they can also lead you "down

the garden path" and in the wrong direction. I have used them and concluded that they create more frustration than assistance. The best method is to start with a small number of instructions and make sure the program works. Add a few more instructions and re-test the program. Re-name the file each time you add instructions and slowly build up the program. This is the best way to avoid frustration. We have provided explanations and helpful advice in our Library of routines: A-E E-P PZ and provided a number of programs for you to analyse and use. The main thing is not to use an instruction unless you know exactly what it does. Do not try any "clever" programming, with exotic instructions as the result can be completely different to what you expect. The first thing to do create a subroutine called a delay. Call it "_200mS" for 200milliseconds delay. _200mS AA movlw 0C8h ; equal to 200 movwf fileB decfsz fileA,1 goto AA decfsz fileB,1 goto AA retlw 00

Create a routine to turn a LED "on" and "off" using the delay. such as: On_Off bsf call bcf call goto gpio,0 _200mS gpio,0 _200mS On_Off ; put a LED on pin 7 with a 470R resistor.

If you want to see if the micro has advanced down a program to a particular location, put: goto On_Off and the LED will blink.

SOME CIRCUIT TRICKS:


The author has found the PIC12F629 chip must be fitted to a circuit when the voltage on the rail is ZERO. If a voltage is present, some of the files in the chip will get corrupted and the program will not run correctly. For example, some of the outputs will not go HIGH when required. The remedy is to turn off the project and wait for the electrolytics to discharge. You can also remove and replace the chip if you find it is performing incorrectly. The addition of a 10k resistor across the power rails will discharge the electrolytics to zero and help solve this problem. Also, the addition of a 100n (very close to the chip rails) will provide stability for the chip and allow the internal oscillator to work correctly and prevent outside spikes from upsetting the chip.

THE PIC12F629 - some preliminary points:


The PIC12F629 is an 8 pin chip that can be re-programmed up to 1,000 times. It is an up-grade of the PIC12C508 and '509 as it can be re-programmed. (The PIC12F629 does not have analogue inputs - the PIC12F675 has 4 analogue inputs.) For more details on PIC chips, see our Chip Data Ebook. Here is a list of the chips we suggest for the beginner to microcontroller programming. Start with the 8-pin 12F629 if you have only 1 to 5 items to "drive" (GP3 is input only). Or use the PIC16F628A if you want to drive up to 15 items (RA5 is input only).

Device

No Code I/O ADC ADC of Type Space Pins Pins pins OTP 512 OTP 1024 6 6 Data

We use these:

PIC12C508(A) 8 PIC12C509(A) 8

PIC12F629

Flash 1024

Data

Smallest chip 1st choice

PIC12F675

Flash 1024

10-bit Data

Lots of projects The smallest, for this chip simplest, and latest 8-pin 2nd choice PIC16F628A 18 Flash 2048 16 Data microcontr oller chip in the PIC series is the PIC12F629. It has 8 pins, will accept over 1022 lines of code and can be reprogrammed over 1,000 times. It has 6 in/out lines (GP3 is input only) and will deliver about 25mA on each output. Programs and projects written for the PIC12C508 and '509 can be converted to PIC12F629 by using our blank12F629.asm template. The only items that have to be converted are: (a) The config values. ( __config) The configuration values that turn things on or off, such as the watchdog timer, internal oscillator, plus others, to suit the PIC12F629. (b) The GPIO values. GPIO for PIC12C508A is location 06h GPIO for PIC12F629 is location 05h To convert a PIC12C508 assembly program to 12F629, the in/out instructions (such as 06,0 06,1 etc) are converted to GPIO,0 GPIO,1 etc. In one of our articles we explained how to produce a program in a PIC16F84A and when the project is working perfectly, the program can be burnt into a PIC12C508A. This was necessary as the PIC12C508A was One-Time Programmable device. The GPIO's for PIC12C508A are in location 06h. This is Port B for a PIC16F84A or 06h. (Port A for a PIC16F84A is 05h). If you use the PIC12F629, you do not have to create your program in a PIC16F84A as the PIC12F629 can be programmed up to 1,000 times. (c) The TRISIO for a PIC12F629 is address 85h in bank 1. Use the instruction TRISIO when programming a PIC12F629. For a PIC12C508, the instruction is TRIS. It has no address. PIC16F84(A) 18 Flash 1024 13 Data

IDENTIFYING THE PINS


The pinout of the PIC12F629 is the same as the PIC12C508A and all projects using a '508A can be converted to PIC12F629 by fitting a PIC12F629 and turning the project on. All you have to do is burn the '508A program into the PIC12F629 before fitting it. Only a few lines of the program and a few instructions are different for the PIC12F629 - these are the setting-up instructions and the location of the GPIO file. The differences have been discussed above.

Many of the pins have a dual function and the first thing to do is decide on the function of each pin. In most cases you will want to use the oscillator inside the chip and this will allow you to use all the 6 in/out lines. The functions for the chip will be simplified to:

The setting-up of the pins, plus the other functions of the chip, is done via an instruction called "__CONFIG." - Note the double under-bar: __ This instruction also determines a number of other things for the chip, such as code protection, and watchdog timer. During experimenting, turn Code Protection OFF and Watchdog Timer OFF. This will allow you to read a chip. Before marketing the final design, the code protection is turned on and the chip is "protected." If the watchdog timer is turned off, you will not have to include instructions in your program to keep resetting the timer. This is a complex thing to do and will be discussed later. Keep things simple for the moment.

MCLR
Pin 4 can be configured as an "Input line" (GP3) or "Master Clear." To configure Pin 4 as MCLR (also written as /MCLR or /MCLRE ) the configuration bit setting is: _MCLRE_ON When this pin is configured as /MCLRE, the pin resets the chip when it is taken LOW. To configure Pin 4 as GP3, the configuration bit setting is: _MCLRE_OFF This instruction tells the PIC to use its internal MCLR circuitry (to keep /MCLRE high), and leaves pin 4 free as an Input line. Note: MCLR pin (GP3) is INPUT ONLY.

OSCILLATOR CALIBRATION VALUE


Calibration of the oscillator is only necessary when you need precise timing, as for serial communication. In most cases you will not have to worry about this. The oscillation calibration value can be changed from the value supplied in the chip by adding the following instructions to the end of your program, (BEFORE the "end" instruction

of the program).

;**************************************************************** ;* OSCCAL calibration value * ;**************************************************************** org 0x3ff retlw 0x20 END

During the programming of the chip, the above instruction will cause the burner to go to location 3FF and insert the value 20h as well as the instruction "return with the value 20h in W." To create the maximum frequency, use: 3fh Centre frequency = 20h Minimum frequency = 00h During the running of the program (when the chip is in the project), this value is put into the OSCCAL location, to adjust the frequency of the internal oscillator. To get the micro to do this, the following instructions are added to your program:

;**************************************************************** ;* Calibrating the internal oscillator * ;**************************************************************** bsf status,rp0 call 3ffh movwf OSCCAL bcf status,rp0 ;bank 1 ;get the calibration value ;calibrate ;bank 0

The location of the oscillator calibration register is 90h. This is in Bank 1 and is identified in your program by writing: "OSCCAL" It is a 6-bit register, with values from 00h to 3fh.

P2 P3

;-----------------------------------------------------; PROJECT : 3 CHANNEL TX IR REMOTE ; CRYSTAL 4 MHz

; MPLAB : 7.11 , Assembly ; RC5 FORMAT @38KHz , 35% DUTY CYCLE ; ADDRESS = 0X0B 0000 1011 you may change ; CH1 = 0X01 ; CH2 = 0X02 ; CH3 = 0X03 ; NOT USE TOGGLE ALWAY = 0 ; WWW.SIXCA.COM ; 4-JULY 2005 ; ; FREE TO USE FOR PERSONAL OR EVEN COMERCIAL PRODUCT ;-----------------------------------------------------list P=12F629 #include <P12F629.INC> __config _WDT_OFF & _XT_OSC & _CP_ON & _CPD_ON & _BODEN_OFF & _MCLRE_OFF & _PWRTE_ON #DEFINE #DEFINE #DEFINE #DEFINE #DEFINE #DEFINE #DEFINE #DEFINE CH1 GPIO,0 ; CONNECT WITH TX SWITCH CHANNEL 1 CH2 GPIO,1 ; CONNECT WITH TX SWITCH CHANNEL 2 CH3 GPIO,3 ; CONNECT WITH TX SWITCH CHANNEL 3 IR GPIO,2 ; CONNECT WITH IR LED WITH TRANSISTOR DRIVES TOG_BIT TOGGLE,0 ; TOGLE BIT NOT USE FOR THIS PROJECT CH1_CMD 0X01 ; CHANNEL 1 COMMAND CH2_CMD 0X02 ; CHANNEL 2 COMMAND CH3_CMD 0X03 ; CHANNEL 3 COMMAND 20H 21H 22H 23H EQU 25H

CNT1 EQU CNT2 EQU CNT3 EQU CNT4 EQU TOGGLE CMD EQU

24H ; IR COMMAND BUFFER

ORG

000

BCF IR ;BSF STATUS,RP0 ;CALL 0X3FF ;MOVWF OSCCAL ;BCF STATUS,RP0 CALL DEBOUNCE ; MOVLW 0X07 MOVWF CMCON ; MAKE ALL GPIO TO DIGITAL I/O BSF STATUS,RP0 BCF OPTION_REG,7 ; ENABLE WEAK PULL-UP BCF WPU,2 ; DISABLE WEAK PULL-UP FOR GPIO2 MOVLW B'00001011' ; GPIO<0,1,3> = INPUT , GPIO 2 = OUTPUT MOVWF TRISIO BSF IOCB,IOCB0 BSF IOCB,IOCB1

BSF BSF BCF BCF BCF

IOCB,IOCB3 INTCON,GPIE STATUS,RP0 INTCON,GIE TOG_BIT

;-----------------------------------; MAIN LOOP MAIN: SLEEP ; GOTO SLEEP MODE(I a sleepy! and need to save my energy) BTFSS CH1 GOTO DO_CH1 BTFSS CH2 GOTO DO_CH2 BTFSS CH3 GOTO DO_CH3 GOTO MAIN ;-----------------------------------DO_CH1: CALL DEBOUNCE BTFSC CH1 GOTO MAIN MOVLW CH1_CMD ; LOAD COMMANE FOR CHANNEL 1 MOVWF CMD CALL SEND_RC5 ; BTFSS CH1 GOTO $-1 ; WAIT FOR SWITCH RELEASED ; CALL DEBOUNCE ; DELAY AFTER SWITCH RELEASED GOTO MAIN ;-----------------------------------DO_CH2: CALL DEBOUNCE BTFSC CH2 GOTO MAIN MOVLW CH2_CMD ; LOAD COMMANE FOR CHANNEL 1 MOVWF CMD CALL SEND_RC5 ; BTFSS CH2 GOTO $-1 ; WAIT FOR SWITCH RELEASED ; CALL DEBOUNCE ; DELAY AFTER SWITCH RELEASED GOTO MAIN ; ;-----------------------------------DO_CH3: CALL DEBOUNCE BTFSC CH3 GOTO MAIN MOVLW CH3_CMD ; LOAD COMMANE FOR CHANNEL 1 MOVWF CMD CALL SEND_RC5 ; BTFSS CH3 GOTO $-1 ; WAIT FOR SWITCH RELEASED ;

CALL DEBOUNCE ; DELAY AFTER SWITCH RELEASED GOTO MAIN ; ;====================================== ; SEND LOGIC 0 ;====================================== LOGIC0: MOVLW .32 ; 1 MOVWF CNT1 ; 1 ; LOG0_1: BSF IR ; 1 MAKE IR HIGH 35% Duty cycle = 9 uS GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 ; ;=================================== BCF IR ; 1 MAKE IR LOW 17 uS GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 NOP ; 1 ; DECFSZ CNT1,F ; 1/2 GOTO LOG0_1 ; 2 26 uS ; CALL DELAY_OFF RETURN ; 2 ; ;====================================== ; SEND LOGIC 1 ;====================================== LOGIC1: CALL DELAY_OFF ; DELAY 899 uS MOVLW .32 ; 1 MOVWF CNT1 ; 1 ; LOG1_1: BSF IR ; 1 MAKE IR HIGH 35% Duty cycle = 9 uS GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 ; ;=================================== BCF IR ; 1 MAKE IR LOW 17 uS GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 GOTO $+1 NOP ; 1 ; DECFSZ CNT1,F ; 1/2 GOTO LOG1_1 ; 2

; RETURN ; 2 ; ;====================================== ; DELAY FOR NO CARRAIR ; DELAY ABOUT 835 uS ;====================================== DELAY_OFF: MOVLW 5 ; 1 MOVWF CNT3 ; 1 MOVLW .54 ; 1 MOVWF CNT4 ; 1 DECFSZ CNT4,F ; 1/2 GOTO $-1 ; 2 DECFSZ CNT3,F ; 1/2 GOTO $-5 ; 2 RETURN ; 2 ;====================================== ; SEND RC5 TO REMOTE ; INPUT : CMD (6 BIT IR COMMAND) ;====================================== SEND_RC5: ; SEND 2 START BIT CALL LOGIC1 CALL LOGIC1 ; SEND TOGGLE BIT BTFSS TOG_BIT GOTO $+3 CALL LOGIC1 GOTO $+2 CALL LOGIC0 ; SEND ADDRESS 5 BIT FIX AT 01011 (0X0B) IT MAY BE CHANGED BY YOU CALL LOGIC0 ; 0 MSB FIRST BIT 4 CALL LOGIC1 ; 1 CALL LOGIC0 ; 0 CALL LOGIC1 ; 1 CALL LOGIC1 ; 1 LSB BIT 0 ; ; SEND COMMAND 6 BIT(00HH LLLL) MSB FIRST BCF STATUS,C RLF CMD,F ; AFTER FIRST ROTAGE 0HHL LLL0 RLF CMD,F ; AFTER SECOND ROTAGE HHLL LL00 ; MOVLW 6 MOVWF CNT2 ; RLF CMD,F ; SEND MSB FIRST BTFSS STATUS,C GOTO $+3 CALL LOGIC1 GOTO $+2 ; CALL LOGIC0

DECFSZ GOTO $-7 ; RETLW 0 ;

CNT2,F

;====================================== ; DEBOUNCE SWITCH ; DELAY 15 mS ;====================================== DEBOUNCE: MOVLW .1 ; 1 MOVWF CNT1 ; 1 DEL_1: MOVLW .20 MOVWF CNT2 ; 1 DEL_2: CLRF CNT3 ; 1 DEL_3: DECFSZ CNT3,F ; 1/2 GOTO DEL_3 ; 2 DECFSZ CNT2,F ; 1/2 GOTO DEL_2 ; 2 DECFSZ CNT1,F ; 1/2 GOTO DEL_1 ; 2 RETLW 0 ; 2 END

P1

P2 P3

Disassembler

Soldering and using a prototype PC board PIC12F629 Data Sheet (.pdf 4,926KB) INSTRUCTION SET for PIC12F629 blank12F629.asm template Library of Sub-routines "Cut and Paste" Library of routines: A-E E-P P-Z

WRITING A PROGRAM
Before starting to write a program, there are a number of things you need to know about laying it out. Let's start: Anything you write on the page is interpreted by an ASSEMBLER. The assembler will convert anything it understands to MACHINE CODE. Any comments you write on the page are placed after the ";" symbol. A program is written in a set of columns. Anything in the first column is called a LABEL. If you leave more than 2 spaces, the next item is interpreted as an INSTRUCTION and the next column contains your comments ( ";" is needed before any comments). Start by giving a name to the program, and revision number plus date. the ;************************************ simply creates a separator. The next line identifies the type of microcontroller. #include <p12f629.inc> The assembler will need to have this file in the same directory as the assembler program so it can identify some of the words you have used in your program. See: <p12f629.inc> The next line is the configuration code. It tells the assembler if you want the Code Protection ON or OFF, and other things such as Watchdog Timer, and Internal 4MHz RC Oscillator. The configuration line starts with double underbar "__"

NAMING THE FILES


One of the first things you will need to do is "list" or "name" or "equate" the files. This is the process of matching each file to a number, so the compiler can compile your program. The PIC12F629 has 64 general purpose registers or files, starting at 20h (this is two-oh-hex) and is actually 32 files from the start: (1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,10h,11h,12h,13h,14h,15h,16h,17h,18h,1h,1A,1B,1C,1D,1E,1F) 20h. The 64 files are: 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh,30h,31h,32h,33h,34h 35h,36h,37h,38h,39h,40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh, 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh. These can be used to store values during the running of the program. For instance, file 20h can be one of the files in the delay routine. We can call it delay1. The next file can be delay2. The next file is part of a tone routine, we will call it tone1 The next file is tone2. These files are called "Variables" and are placed at the beginning of the program. Each name such as delay1 has to be assigned to a file. For instance, delay1 will be file 20h delay2 will be file 21h etc. This process is called "equates." You are equating a name to a file. ;********************************************************************** ;Equates ;********************************************************************** delay1 equ 20h delay2 equ 21h tone1 equ 22h tone2 equ 23h

Instead of writing the word "equ" for each file, there is a short-cut: It is called "CBLOCK" - for "naming a block for the named constants." The first line of the short-cut is: cblock and then a number that refers to the beginning of the files for the block. The number: 0x20 is the same as saying 20h. The following cblock is the same as the above. The short-cut ends: "endc" ********************************************************************** ;Variables ;********************************************************************** cblock 0x20 ;20h is the first file of the General Purpose Registers delay1 delay2 tone1 tone2 endc

Another method of defining our files allows 2 or more files with the same name. For instance, the following allows 3 flag files. These are identified as "flags," "flags+1," "flags+2," in your program. rand is identified as "rand" and "rand+1" in your program. You can also identify similar names for files on the same line, such as: temp1, temp2. In the following, 13 files have been identified and will be given the file numbers: 20h, 21h, 22h, 23h, 24h, 25h, 26h, 27h, 28h, 29h, 2Ah, 2Bh, 2Ch. To give a name such as "flags" more than one file, it is written flags:3 or flags:4 etc. It can also be written flags1, flags2, flags3, etc. ;********************************************************************** ;File Register usage ;********************************************************************** cblock 0x20 count ; counter flags:3 ; various flags rand:2 ; random number sensor ; sensor reading servo1, servo2 ; servo positions speed1, speed2 ; motor speeds temp1, temp2 ; timers endc

The next statement is called START. It is the beginning of the program. The program starts with the statement ORG 000 or ORG 0x000. Or you can make the ORIGIN of your program 0x004 or 0x34. This tells the assemble to put the first instruction in the program at location 000 in the program memory, or at location 4 or at location 34hex. This is called a DIRECTIVE and is information for the assembler. The first instruction in our example is "goto SetUp" The sub-routine at SetUp, sets the port bits as IN or OUT. The port is actually a file and has the name GPIO (for General Purpose In Out) and is file 05. All files have 8 bits but only the lowest 6 bits of file 05 are used. These are called GPIO,0 GPIO,1 GPIO,2 GPIO,3 GPIO,4 GPIO,5

These can be called "lines" and any or all of them can be configured as input, but only GPIO,0 GPIO,1 GPIO,2 GPIO,4 GPIO,5 can be used at output as GPIO,3 (GP3) (pin 4) is an INPUT-ONLY pin. To get a pin to "work," two things must be done. Firstly the micro must be told if the pin is to be an input or output and them it must be made HIGH or LOW if it is an output pin. Any pin can be changed at any time during the running of a program but it is normal to set up the pins in Set-Up if they are not going to be altered. We discuss setting up the "lines" a little further down the article. Set-Up is placed at the 7th program location. There is a reason for this. Location 04 is where the microcontroller will return when it is "interrupted." For instance, it may be asleep, and is waiting for one of the inputs to change state. The microcontroller can be programmed to go to location 04 after an interrupt and the instructions at 04 will be carried out. We will leave three lines for three instructions, at 04, 05, 06. Location 07 is now available for your program.

At the end of SetUp, the microcontroller goes to Main. Main is always located at the end of your program and all the subroutines are placed before Main, in alphabetical order. This allows you to easily find each sub-routine. Any tables are placed before the sub-routines. Here is how the program is laid out: ;********************************************************************** ; SPINNING SIGN Colin Mitchell rev 2 19-9-2007 ;********************************************************************** list p=12f629 #include <p12f629.inc> ; Set configuration register for: ; Code protection off ; Code protection DATA off ; Brown-out detect off ; MCLR disabled (use pins for InOut) ; Watch Dog timer disabled ; Power on reset delay enabled ; Enable Internal Clock Osc, (all pins for InOut) ; __CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT ;********************************************************************** ;Variables ;********************************************************************** cblock 0x20 ;20h is the first file of the General Purpose Registers delay1 delay2 tone1 tone2 endc ;********************************************************************** ;Start ;**********************************************************************

ORG 0x000 goto SetUp ORG nop nop nop 0x004

; processor reset vector ; go to "setting up the port as In-Out etc"

; processor goes here after interrupt ; nop = no operation = 1 cycle

SetUp instruction goes here instruction goes here goto Main ;********************************************************************** ;Tables ;***********************************************************************

;********************************************************************** ;Sub-routines ;***********************************************************************

Main instruction goes here instruction goes here end

SETTING UP THE "LINES':


The "lines" are the input/out pins or "lines." These are called GPIO,0 GPIO,1 GPIO,2 GPIO,3 GPIO,4 GPIO,5 Any or all of them can be configured as input, but only GPIO,0 GPIO,1 GPIO,2 GPIO,4 GPIO,5 can be used at output as GPIO,3 (GP3) (pin 4) is an INPUT-ONLY pin. The first thing to do is work out which pins are needed to be input and output. An input pin will be given the value "1" for Input and "0" for output. Two instructions are needed, are are highlighted: bsf STATUS,rp0 movlw b'00110111' movwf TRISIO bcf status,rp0 These instructions must be placed between two instructions: bsf STATUS,rp0 and bcf status,rp0 so your instructions are placed in the chip at a special location. These instructions are placed in a file (or register) called the TRISIO file. The movlw b'00110111' instruction is a binary number that directly represents each line you want to make input or output. The chip has only 6 lines so the instruction is really: movlw b'xx110111' as the two highest bits do not have a corresponding line. They can be 0 or 1 as they have no effect. The lowest line is called "line 0" or "bit 0" or "GPIO,0" and to make it an input we place a '1' as follows: b'xx - - - - - 1' To make it an output: b'xx - - - - - 0' We have already said GPIO,3 is INPUT-ONLY so the instruction starts: b'xx - - 1 - - -' Once you have worked out if each line is to be input or output, the next decision is to make an output line HIGH or LOW. (If you make an input line high or low, it does not have any effect on the line. It will only function at detecting the voltage applied to it from the outside world.)

To make an output line HIGH, one or two instructions are needed, depending how it is done. To make any or all the lines HIGH, this can be done with two instructions. This is called "Byte Setting" as the whole byte is acted on in a single operation: movlw movwf b'00110111' GPIO

If you want to make a line HIGH, you can use "Bit Setting:" bsf GPIO,0

You cannot set more than one bit at a time, the micro does not like the following: bsf bsf GPIO,0 GPIO,2 ;This makes the lowest line go HIGH

To set more than one line at a time, read: The In/Out Port.

;blink12F629.asm ;This program will blink a LED connected to pin 7 ;17-9-2007

list p=12F629

;microcontroller identity ; 0x033 or 33h = hex value include "p12f629.inc"

__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT ;********************************************************************** ;Variables ;************************************************************************* equ 20h equ 21h equ 22h equ 23h equ 24h equ 25h fileA fileB fileC equ 26h equ 27h equ 28h ;this is the first available file

;delay file A ;delay file B ;delay file C ; bits on GPIO

pin7 pin6 pin5 pin4

equ 0 equ 1 equ 2 equ 3

;GP0 output to LED ;GP1 ;GP2 ;GP3

pin3 pin2

equ 4 equ 5

;GP4 ;GP5

Start

org nop nop nop nop nop nop nop

0x0000

;program starts at location 000 ;"org" = tells the assembler to start at this address.

;NOPs to get past interrupt address

SetUp bsf STATUS,rp0 movlw b'10000110' movwf OPTION_REG movlw b'00110111' movwf TRISIO movlw 0x07 movwf CMCON

;Bank 1 ;Turn off T0CKI, prescaler for TMR0 = 1:128 ;Set GP0 (pin 7) as output ;turn comparator off ; comparator off =111 ;calibrating the internal oscillator

call 0x3ff movwf OSCCAL bcf status,rp0 clrf GPIO goto Main Del DelX movlw movwf decfsz goto decfsz goto decfsz goto retlw bsf call bcf call goto 40h fileC fileA,1 DelX fileB,1 DelX fileC,1 DelX 00 GPIO,pin7 Del GPIO,pin7 Del Main

;get the calibration value ;calibrate oscillator ;bank 0 ;Clear GPIO of junk. This is file 05.

;Delay 0.5 sec ; ,1 denotes the result of the decrement ; is placed in the file

Main

;turn on LED ;turn off LED

;OSCCAL calibration value org 0x3ff retlw 0x20 END

THE TEMPLATE LAYOUT:


The template above consists of 6 different areas: The first area contains the CONFIGURATION values. The second area contains the "equates" or "variables." The third area contains the SET UP instructions The fourth area contains all the sub-routines. These are placed in alphabetical order, so you can easily find them when the program gets lengthy. The fifth area contains the MAIN routine. The last area sets the calibration value for the oscillator and the "end" instruction. The micro will commence at location 000 and execute the Set Up instructions. It will then go to Main. In "Main" it will find instructions to "call" sub-routines and return. In this way it will constantly loop "Main" and use sub-routines as required. If you keep to this form of layout, you will be able to follow programs written by others and be able to come back to your own programs and easily modify them.

Delay Routine
There are two ways to write a Delay Routine (and other routines). The program above uses instructions found in List of Instructions for PIC12F629. The following Delay Routine uses "$+2" to advance the micro down the program:

Del

movlw movwf DelX decfsz goto decfsz goto decfsz goto retlw

40h fileC fileA,1 DelX fileB,1 DelX fileC,1 DelX 00

;Delay 0.5 sec ; ,1 denotes the result of the decrement ; is placed in the file

Del

movlw movwf DelX decfsz goto decfsz goto decfsz goto retlw

40h fileC fileA,1 $+2 fileB,1 $+2 fileC,1 DelX 00

$+2 sends the micro to: goto $+2 below $+2 sends the micro to: goto DelX

The Delay Routine above can be written with only one Label.

;Delay 0.5 sec

Del

movlw movwf decfsz goto decfsz goto decfsz goto retlw

40h fileC fileA,1 $+2 fileB,1 $+2 fileC,1 $-5 00

$+2 sends the micro to: goto $+2 below $+2 sends the micro to: goto goto $-5 $-5 sends the micro to: decfsz fileA,1

Creating 4 micro-second delay:

;Delay 4 micro-seconds nop nop nop nop ;1 uS ;1 uS ;1 uS ;1 uS

----------------------- ----------------------------------------------------------------goto $+1 goto $+1 ;2 uS, $+1 sends the micro to the next instruction ;2 uS, $+1 sends the micro to the next instruction

SLEEP
To put the micro to sleep, a number of things must be done. This routine allows the micro to go to SLEEP when it comes to the SLEEP instruction. The micro wakes up from sleep when it detects a change on GPIO,5 (pin 2). Pin 2 must have a pull-up resistor for the following program to work and a push-switch to create the change on the pin. The pull-up resistor can be external (about 47k) and a push switch to take the pin low to take the micro out of SLEEP. Or, to turn on the weak internal 47k pull-up resistor, place the following instructions in SetUp: bsf bcf bsf bsf bcf STATUS,RP0 ; Sel Bank 1 OPTION_REG,NOT_GPPU ; enable weak pull-up WPU, 5 ; enable wpu on GPIO 5 only IOC, 5 ; enable Int-On-Change GPIO 5 STATUS,RP0 ; Sel Bank 0

In a sub-routine, place the following instruction: goto sleep ; goto sleep.

The following sub-routine is suitable to create a sleep condition:

Sleep movf

GPIO,W

; Read GPIO clears Int-On-Change flag. Must read ; into W not back to F as it reads port not the output ; latch which may result in output data being ; inadvertently altered. ; Sel bank 1 ; Setup W for TRISIO all input ; Write to TRISIO. Reduce power in sleep mode ; Go to sleep ; ; Wake from sleep and set ; TRISIO for input and output for your project ; Sel Bank 0 ; Read GPIO register ; and clear GPIF flag in interrupt register

bcf INTCON,GPIF bsf STATUS,RP0 movlw 0xFF movwf TRISIO sleep nop movlw b'11101000' movwf TRISIO bcf STATUS,RP0 movf GPIO,W bcf INTCON,GPIF

CREATING A MACRO
Suppose you want to create an instruction the assemble does not understand, such as:

movlf 0A0h,sensor

In the instruction above you want to move the value A0h into file 26h (by referring to the list above: count flags:3 rand:2 sensor ; counter ; various flags ; random number ; sensor reading

count will be allotted file 20h, flags will be allotted file 21h, flags+1 will be give 22h, flags+2 will be give file 23h, rand will be 24h, rand+1 will be 25h and sensor will be 26h. But the assembler does not have an instruction of the above. It requires two instructions:

movlw movwf

0A0h sensor

Creating your own instructions for the assembler is called a "macro." To tell the assembler how to handle an instruction in which the value 0Ah (called a "constant" or "literal") is to be moved to file 26h (the "sensor" file), a macro can be written to allow any "literal" to be written to any "file:"

movlf

macro movlw movwf

n,f n f

; move literal to file

endm

When the assembler sees the instruction: movlf it looks to see if a macro has been produced. The instructions in the macro are then added to the program (called the "source"). The macro is written with a label in the first column. The word "macro" is then written to tell the assembler the next instructions are "macro instructions." On the same line we write the parameters that will be used in the macro. The macro ends with "endm."

START HERE
If you will want to burn a chip and make sure it works in a test circuit. To help you, we have written a simple program, called "blink12F629.asm". This will blink a LED on Pin 7. The circuit for this is:

Click .asm and .hex for blink12F629.asm files.

;blink12F629.asm ;This program will blink a LED connected to pin 7 ;17-12-2005

list p=12F629

;microcontroller identity ; 0x033 or 33h = hex value include "p12f629.inc"

__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT ;Internal osc.

equ 20h equ 21h

; globals ;this is the first available file

equ 22h equ 23h equ 24h equ 25h fileA fileB fileC equ 26h equ 27h equ 28h ;delay file A ;delay file B ;delay file C ; bits on GPIO pin7 pin6 pin5 pin4 pin3 pin2 equ 0 equ 1 equ 2 equ 3 equ 4 equ 5 ;GP0 output to LED ;GP1 ;GP2 ;GP3 ;GP4 ;GP5

Start

org nop nop nop nop nop nop nop

0x0000

;program starts at location 000 ;"org" = tells the assembler to go to this address.

;NOPs to get past interrupt address

SetUp bsf STATUS,rp0 movlw b'10000110' movwf OPTION_REG movlw b'00110111' movwf TRISIO movlw 0x07 movwf CMCON

;Bank 1 ;Turn off T0CKI, prescaler for TMR0 = 1:128 ;Set GP0 (pin 7) as output ;turn comparator off ; comparator off =111 ;calibrating the internal oscillator

call 0x3ff movwf OSCCAL bcf status,rp0 clrf GPIO goto Main Del DelX movlw movwf decfsz goto decfsz goto decfsz 40h fileC fileA,1 DelX fileB,1 DelX fileC,1

;get the calibration value ;calibrate oscillator ;bank 0 ;Clear GPIO of junk. This is file 05.

;Delay 0.5 sec ; ,1 denotes the result of the decrement ; is placed in the file

goto retlw Main bsf call bcf call goto

DelX 00 GPIO,pin7 Del GPIO,pin7 Del Main

;turn on LED ;turn off LED

org 0x3ff retlw 0x20 END

;OSCCAL calibration value

YOUR FIRST PROGRAM:


We are now ready to start writing a program. You will need the INSTRUCTION SET for the PIC12F629 Below is the blank12F629.asm template: The instructions for your program are arranged in three columns. The first column contains the "labels." They identify the address of the first instruction for a sub-routine. The second column contains the "instructions" - called the mnemonics. The "half-computer" "half-English" instructions that both computer and micro understands. The third column contains the "comments." It must have a ";" before each line so that they are not assembled - so they don't appear in the final .hex file! Click .asm and .hex for "blank12F629.asm" files. The .asm file is used by your compiler (MPASM) to produce a .hex file for your ICProg burner program.

;blank12F629.asmm ;Template for PIC12F629 microcontroller 17-12-2005 ;CONFIG defines internal oscillator, code-protection OFF, pin 4 is GP3, ; watchdog timer OFF. list p=12F629 ;microcontroller identity

; 0x033 or 33h = hex value include "p12f629.inc" __CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT ;Internal osc.

equ 20h equ 21h equ 22h equ 23h equ 24h equ 25h fileA fileB fileC equ 26h equ 27h equ 28h

; globals ;this is the first available file

;delay file A ;delay file B ;delay file C ; bits on GPIO

pin7 pin6 pin5 pin4 pin3 pin2

equ 0 equ 1 equ 2 equ 3 equ 4 equ 5

;GP0 ;GP1 ;GP2 ;GP3 ;GP4 ;GP5

;*************************************************** ;* Start of program * ;***************************************************

Start

org nop nop nop nop nop nop

0x0000

;program starts at location 000 ;"org" = tells the assembler to go to this address.

;NOPs to get past reset vector address

SetUp call 0x3ff bsf STATUS,rp0 movwf OSCCAL movlw b'10000110' movwf OPTION_REG movlw b'00001000' movwf TRISIO bcf status,rp0

;get the calibration value ;Bank 1 ;calibrate oscillator ;Turn off T0CKI, prescaler for TMR0 = 1:128 ;Set GP0's as output, GP3 = input. ;bank 0

clrf goto

GPIO Main

;Clear GPIO of junk

Del_1 movlw movwf DelX decfsz goto decfsz goto decfsz goto retlw Main

40h fileC fileA,1 DelX fileB,1 DelX fileC,1 DelX 00

;Delay_1 0.5sec ; ,1 denotes the result of the decrement ; is placed in the file

your instruction goes here your instruction goes here your instruction goes here call Del_1 your instruction goes here your instruction goes here your instruction goes here goto Main

;OSCCAL calibration value org 0x3ff retlw 0x20 END

BURNING YOUR PROGRAM


The first program you will burn will be "blink12F629.asm" Open Notepad.exe or Unzip Notepad.zip in our Programming folder on the left-side of the screen and load it with the blink12F629.asm file by sliding it into Notepad. It will then show in Notepad. You can now make any changes to the program. Save the result in a folder called PIC12F629Pgms (programs). To burn blink12F629.asm into a PIC12F629, you will need to assemble the .asm file in MPASM to create a .hex file. To do this, place MPASM in a folder (or unzip MPASM.zip in the folder) and create a shortcut to desktop. Click on MPASM on your desktop and it will open. Locate blink12F629.asm in PIC12F629Pgms folder and load it into MPASM. Use: Radix: Default, Warning Level: Default, Hex Output: Default, Generated Files: Error File and List file, Do not tick: Case Sensitive, Macro Expansion: Default, Processor PIC12F629, Tab Size: 8, Tick: Save settings on exit. Click: Assemble. Your blink12F629.hex file will be put into the same folder. To burn a PIC12F629, you will need the Multi Chip Programmer. Make sure the programmer

is the latest version with 628 on the underside of the PCB. Connect it to your computer via the serial cable supplied in the kit and the green LED will illuminate. Install IC Prog on your desktop or unzip IC Prog.zip Click on the folder on the top left-hand side and locate Expt-1.hex Make sure you have selected PIC12F629 before loading the .hex file. The configuration settings will be automatically set according to the configuration value supplied in the program - or you can change anything before burning the new program. Fit a chip into the programmer and click on the "lightening" icon. The programmer will now burn the program into the chip. The LEDs on the Multi-Chip Programmer will show the action taking place. When the chip is "burnt," place it in the socket on the project and the LED will flash. This might seem a lot of work to create a simple effect, but the same amount of work will produce a compete project - it's just the size of the program will be different.

WRITING YOUR PROGRAM


Writing a program consists of creating small routines called sub-routines. The basic layout of a program has already been shown above. It is now a matter of creating subroutines that perform a function. When these are executed at high-speed, the program performs a task. The most interesting subroutines carry out an operation that appears to have "intelligence." These type of subroutines can be found in a game, where the player is pitted against the computer. The basics behind an "intelligent" sub-routine is simple. You simply provide an answer for ALL the possible combinations. When this sub-routine is executed in the program, it creates the illusion of intelligence. This type of sub-routine is interesting and challenging to create. There are a number of very common games played with matches and marbles or markers, that can be converted to a program. Once you master the technique of writing a sub-routine that solves a problem, all other routines will be easy to create.

HERE ARE SOME PROGRAMMING HINTS:


Before we start, the PIC12F629 has only 5 output lines and this prevents it from directly driving a 7-digit display. We have designed a project called 2-Digit Counter that shows how to expand the outputs to drive the displays. 1. Indirect Addressing One of the things you may want to do is access a list of values from a table. A number of files can be addressed by a sub-routine and the information can be moved into each file or read from each file. The files must be a group. Suppose we have 8 files and need to read the contents and output it to a display. The files are: 21h, 22h, 23h, 24h, 25h, 26h, 27h, and 28h. There are two special files that allow a sub-routine to be created to look at the 8 files and read the contents. They are: INDF and FSR The INDF file is not a real file. It is like a Robot Arm. It reaches down the list of files and picks up the contents or delivers the contents of a file to the programmer. The file it reaches is determined by the value in FSR. FSR is loaded with the address of the file you wish to read or write. This arrangement has an advantage. By loading FSR with a value, you can reach a file and by incrementing FSR, you can reach the next file etc. If you load a value into INDF, you will actually load the value into the file pointed to by FSR. If you read INDF, you will actually read the contents of the file pointed to by FSR. You can consecutively read 8, 10 or 20 files or clear 20 files or load into 20 or more files with a simple looping sub-routine. It's a very powerful feature. The following instructions put a value of 8Fh into file 21h.

MOVLW 21h MOVWF 04 MOVLW 8Fh MOVWF 00

;Load W with start of 8 files ;Load 21h into FSR ;Put 8F into W ;Put 8Fh into file 21h

The animation below shows how the information passes to the files:

Using INDF and FSR


The following instructions put a value of 8Fh into files 21h, 22h, 23h, 24h, 25h, 26h, 27h and 28h. MOVLW 08 MOVWF 20h MOVLW 21h MOVWF 04 MOVLW 8Fh Loop1 MOVWF 00 INCF 04 DECFSZ 20h GOTO Loop1 RETLW 00 ;8 loops of the program ;File 20h is the decrementing file ;Load W with start of 8 files ;Load 21h into FSR ;Put 8F into W ;Put 8Fh into file 21h ;Increment FSR to make INDF go to next file

The following instructions read files 21h, 22h and 23h, and outputs to GPIO. MOVLW 03 MOVWF 20h MOVLW 21h MOVWF 04 Loop1 MOVF 00,0 MOVWF GPIO CALL Delay INCF 04 ;3 loops of the program ;File 20h is the decrementing file ;Load W with start of 3 files ;Load 21h into FSR ;Copy file 21h (or next file) into W ;Move W to output GPIO ;Show value on set of 3 LEDs

DECFSZ 20h GOTO Loop1 RETLW 00

;Increment FSR to make INDF go to next file

P1

P2 P3

Вам также может понравиться