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

92986459 3 Channel IR Remote Control

Embed Size (px)

DESCRIPTION

Remote control IR

Citation preview

  • 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

  • Example how to wake-up from sleep mode when key pressed. main : SLEEP

    BTFSS CH1

    GOTO Do_CH1

    BTFSS CH2

    GOTO Do_CH2

    BTFSS CH3

    GOTO Do_CH3

    GOTO 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 "on-

    change" interrupt capability!

    #define RC5_DATA_PIN PIN_B1 /* IR sensor (SFH5110-36)

    connected to RB1 */

    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) /* timer increments every

    25.6us, */

    /* i.e. around 39 ticks per millisecond */

    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() get_timer0() /* timer0 shall be used for RC5

    decoding */

    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 plus-values 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 8-pin SMD

    (through (surface mount)

    hole) PIC12F629-I/SN

    8/PDIP 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 GPIO,0 bsf 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 status, rp0 ;Bank 1 bcf TRISIO,0 nop bsf TRISIO,0 bcf status, rp0 ;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:

    for '629 Change

    to:

    07h 27h

    08h 28h

    09h 29h

    0Ah 2Ah

    0Bh 2Bh

    0Ch 2Ch

    0Dh 2Dh

    0Eh 2Eh

    0Fh 2Fh

    10h 30h

  • 11h 31h

    12h 32h

    13h 33h

    14h 34h

    15h 35h

    16h 36h

    17h 37h

    18h 38h

    19h 39h

    1Ah 3Ah

    1Bh 3Bh

    1Ch 3Ch

    1Dh 3Dh

    1Eh 3Eh

    1Fh 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 P-Z 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 movlw 0C8h ; equal to 200 movwf fileB AA 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 gpio,0 ; put a LED on pin 7 with a 470R resistor. call _200mS bcf gpio,0 call _200mS goto On_Off 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).

  • The smallest, simplest, and latest 8-pin microcontroller chip in the PIC

    series is the PIC12F629. It has 8 pins, will accept over 1022 lines of code and can be re-programmed 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.

    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.

    Device No

    of

    pins Type

    Code

    Space I/O

    Pins ADC

    Pins ADC

    We

    use

    these:

    PIC12C508(A) 8 OTP 512 6 Data

    PIC12C509(A) 8 OTP 1024 6

    PIC12F629 8 Flash 1024 6 Data Smallest chip 1st choice

    PIC12F675 8 Flash 1024 6 4 10-bit Data

    PIC16F84(A) 18 Flash 1024 13 Data Lots of projects for this chip

    PIC16F628A 18 Flash 2048 16 Data 2nd choice

  • 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 ;bank 1

    call 3ffh ;get the calibration value

    movwf OSCCAL ;calibrate

    bcf status,rp0 ;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

    __config _WDT_OFF & _XT_OSC & _CP_ON & _CPD_ON & _BODEN_OFF &

    _MCLRE_OFF & _PWRTE_ON

    #DEFINE CH1 GPIO,0 ; CONNECT WITH TX SWITCH CHANNEL 1

    #DEFINE CH2 GPIO,1 ; CONNECT WITH TX SWITCH CHANNEL 2

    #DEFINE CH3 GPIO,3 ; CONNECT WITH TX SWITCH CHANNEL 3

    #DEFINE IR GPIO,2 ; CONNECT WITH IR LED WITH TRANSISTOR DRIVES

    #DEFINE TOG_BIT TOGGLE,0 ; TOGLE BIT NOT USE FOR THIS PROJECT

    #DEFINE CH1_CMD 0X01 ; CHANNEL 1 COMMAND

    #DEFINE CH2_CMD 0X02 ; CHANNEL 2 COMMAND

    #DEFINE CH3_CMD 0X03 ; CHANNEL 3 COMMAND

    CNT1 EQU 20H

    CNT2 EQU 21H

    CNT3 EQU 22H

    CNT4 EQU 23H

    TOGGLE EQU 24H

    CMD EQU 25H ; 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 = INPUT , GPIO 2 = OUTPUT

    MOVWF TRISIO

    BSF IOCB,IOCB0

    BSF IOCB,IOCB1

  • BSF IOCB,IOCB3

    BSF INTCON,GPIE

    BCF STATUS,RP0

    BCF INTCON,GIE

    BCF 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 CNT2,F

    GOTO $-7

    ;

    RETLW 0

    ;

    ;======================================

    ; 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 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: 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

    ; 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 ; processor reset vector goto SetUp ; go to "setting up the port as In-Out etc" ORG 0x004 nop ; processor goes here after interrupt nop ; nop = no operation = 1 cycle nop 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 b'00110111' movwf 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 GPIO,0 ;This makes the lowest line go HIGH bsf GPIO,2 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

    ;*************************************************************************

    fileA

    fileB

    fileC

    pin7

    pin6

    pin5

    pin4

    equ 20h

    equ 21h

    equ 22h

    equ 23h

    equ 24h

    equ 25h

    equ 26h

    equ 27h

    equ 28h

    equ 0

    equ 1

    equ 2

    equ 3

    ;this is the first available file

    ;delay file A

    ;delay file B

    ;delay file C

    ; bits on GPIO

    ;GP0 output to LED

    ;GP1

    ;GP2

    ;GP3

  • pin3

    pin2

    Start

    SetUp

    Del

    DelX

    Main

    equ 4

    equ 5

    org 0x0000

    nop

    nop

    nop

    nop

    nop

    nop

    nop

    bsf STATUS,rp0

    movlw b'10000110'

    movwf OPTION_REG

    movlw b'00110111'

    movwf TRISIO

    movlw 0x07

    movwf CMCON

    call 0x3ff

    movwf OSCCAL

    bcf status,rp0

    clrf GPIO

    goto Main

    movlw 40h

    movwf fileC

    decfsz fileA,1

    goto DelX

    decfsz fileB,1

    goto DelX

    decfsz fileC,1

    goto DelX

    retlw 00

    bsf GPIO,pin7

    call Del

    bcf GPIO,pin7

    call Del

    goto Main

    org 0x3ff

    retlw 0x20

    END

    ;GP4

    ;GP5

    ;program starts at location 000

    ;"org" = tells the assembler to start at this address.

    ;NOPs to get past interrupt address

    ;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

    ;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

    ;turn on LED

    ;turn off LED

    ;OSCCAL calibration value

  • 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

    DelX

    Del

    DelX

    movlw 40h

    movwf fileC

    decfsz fileA,1

    goto DelX

    decfsz fileB,1

    goto DelX

    decfsz fileC,1

    goto DelX

    retlw 00

    movlw 40h

    movwf fileC

    decfsz fileA,1

    goto $+2

    decfsz fileB,1

    goto $+2

    decfsz fileC,1

    goto DelX

    retlw 00

    ;Delay 0.5 sec

    ; ,1 denotes the result of the decrement

    ; is placed in the file

    $+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 40h

    movwf fileC

    decfsz fileA,1

    goto $+2

    decfsz fileB,1

    goto $+2

    decfsz fileC,1

    goto $-5

    retlw 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:

    nop

    nop

    nop

    nop

    -----------------------

    goto $+1

    goto $+1

    ;Delay 4 micro-seconds

    ;1 uS

    ;1 uS

    ;1 uS

    ;1 uS

    -----------------------------------------------------------------

    ;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 STATUS,RP0 ; Sel Bank 1 bcf OPTION_REG,NOT_GPPU ; enable weak pull-up bsf WPU, 5 ; enable wpu on GPIO 5 only bsf IOC, 5 ; enable Int-On-Change GPIO 5 bcf 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

    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

    ; 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

    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 ; counter flags:3 ; various flags rand:2 ; random number sensor ; 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 0A0h

    movwf 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 n,f ; move literal to file

    movlw n

    movwf f

  • 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

  • fileA

    fileB

    fileC

    pin7

    pin6

    pin5

    pin4

    pin3

    pin2

    Start

    SetUp

    Del

    DelX

    equ 22h

    equ 23h

    equ 24h

    equ 25h

    equ 26h

    equ 27h

    equ 28h

    equ 0

    equ 1

    equ 2

    equ 3

    equ 4

    equ 5

    org 0x0000

    nop

    nop

    nop

    nop

    nop

    nop

    nop

    bsf STATUS,rp0

    movlw b'10000110'

    movwf OPTION_REG

    movlw b'00110111'

    movwf TRISIO

    movlw 0x07

    movwf CMCON

    call 0x3ff

    movwf OSCCAL

    bcf status,rp0

    clrf GPIO

    goto Main

    movlw 40h

    movwf fileC

    decfsz fileA,1

    goto DelX

    decfsz fileB,1

    goto DelX

    decfsz fileC,1

    ;delay file A

    ;delay file B

    ;delay file C

    ; bits on GPIO

    ;GP0 output to LED

    ;GP1

    ;GP2

    ;GP3

    ;GP4

    ;GP5

    ;program starts at location 000

    ;"org" = tells the assembler to go to this address.

    ;NOPs to get past interrupt address

    ;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

    ;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

    goto DelX

    retlw 00

    bsf GPIO,pin7

    call Del

    bcf GPIO,pin7

    call Del

    goto Main

    org 0x3ff

    retlw 0x20

    END

    ;turn on LED

    ;turn off LED

    ;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.

    fileA

    fileB

    fileC

    pin7

    pin6

    pin5

    pin4

    pin3

    pin2

    Start

    SetUp

    equ 20h

    equ 21h

    equ 22h

    equ 23h

    equ 24h

    equ 25h

    equ 26h

    equ 27h

    equ 28h

    equ 0

    equ 1

    equ 2

    equ 3

    equ 4

    equ 5

    org 0x0000

    nop

    nop

    nop

    nop

    nop

    nop

    call 0x3ff

    bsf STATUS,rp0

    movwf OSCCAL

    movlw b'10000110'

    movwf OPTION_REG

    movlw b'00001000'

    movwf TRISIO

    bcf status,rp0

    ; globals

    ;this is the first available file

    ;delay file A

    ;delay file B

    ;delay file C

    ; bits on GPIO

    ;GP0

    ;GP1

    ;GP2

    ;GP3

    ;GP4

    ;GP5

    ;***************************************************

    ;* Start of program *

    ;***************************************************

    ;program starts at location 000

    ;"org" = tells the assembler to go to this address.

    ;NOPs to get past reset vector address

    ;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

  • Del_1

    DelX

    Main

    clrf GPIO

    goto Main

    movlw 40h

    movwf fileC

    decfsz fileA,1

    goto DelX

    decfsz fileB,1

    goto DelX

    decfsz fileC,1

    goto DelX

    retlw 00

    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

    org 0x3ff

    retlw 0x20

    END

    ;Clear GPIO of junk

    ;Delay_1 0.5sec

    ; ,1 denotes the result of the decrement

    ; is placed in the file

    ;OSCCAL calibration value

    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.

    Loop1

    MOVLW 08

    MOVWF 20h

    MOVLW 21h

    MOVWF 04

    MOVLW 8Fh

    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.

    Loop1

    MOVLW 03

    MOVWF 20h

    MOVLW 21h

    MOVWF 04

    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