Professional Documents
Culture Documents
3 Channel IR Remote Control
3 Channel IR Remote Control
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.
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
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
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 */
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()
Since the RC5 driver is no properly configured, we have to include the RC5 driver itself.
#include "rc5.h"
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);
/**************************************************************************
***/
/* 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();
Chapter 1
Chapter 2
Chapter 3
P1
P2 P3
Disassembler
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.
8-pin
(through
hole)
8/PDIP
8-pin SMD
(surface mount)
PIC12F629-I/SN
8/SOIC package
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.
2. The STACK
The PIC12C508A has only a 2-CALL stack.
The PIC12F629 has an 8-CALL stack. (8-level stack).
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.
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
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.
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
SOME APPLICATIONS:
Although the PIC12F629 is the simplest device in the PIC range, it can can carry out
operations such as monitoring and controlling:
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
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
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.
Device
No
Code I/O ADC ADC
of
Type
Space Pins Pins
pins
PIC12C508(A) 8
OTP 512
PIC12C509(A) 8
OTP 1024
PIC12F629
Flash 1024
PIC12F675
Flash 1024
We
use
these:
Data
Data
Smallest chip
1st choice
10-bit Data
18
Flash 1024
13
Data
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.
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
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
CNT1 EQU
CNT2 EQU
CNT3 EQU
CNT4 EQU
TOGGLE
CMD EQU
20H
21H
22H
23H
EQU
25H
ORG
000
24H
; IR COMMAND BUFFER
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
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
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 "__"
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
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.
ORG 0x000
goto SetUp
ORG
nop
nop
nop
0x004
SetUp
instruction goes here
instruction goes here
goto Main
;**********************************************************************
;Tables
;***********************************************************************
;**********************************************************************
;Sub-routines
;***********************************************************************
Main
instruction goes here
instruction goes here
end
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
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"
fileA
fileB
fileC
equ 20h
equ 21h
equ 22h
equ 23h
equ 24h
equ 25h
equ 26h
equ 27h
equ 28h
;delay file A
;delay file B
;delay file C
; bits on GPIO
pin7
pin6
pin5
pin4
equ 0
equ 1
equ 2
equ 3
pin3
pin2
equ 4
equ 5
Start
org
nop
nop
nop
nop
nop
nop
nop
;GP4
;GP5
0x0000
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
Del
DelX
Main
call
0x3ff
movwf OSCCAL
bcf
status,rp0
clrf
GPIO
goto
Main
movlw
movwf
decfsz
goto
decfsz
goto
decfsz
goto
retlw
40h
fileC
fileA,1
DelX
fileB,1
DelX
fileC,1
DelX
00
bsf
call
bcf
call
goto
GPIO,pin7
Del
GPIO,pin7
Del
Main
;turn on LED
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
Del
40h
fileC
fileA,1
$+2
fileB,1
$+2
fileC,1
DelX
00
movlw
movwf
DelX decfsz
goto
decfsz
goto
decfsz
goto
retlw
The Delay Routine above can be written with only one Label.
Del
movlw
movwf
decfsz
goto
decfsz
goto
decfsz
goto
retlw
40h
fileC
fileA,1
$+2
fileB,1
$+2
fileC,1
$-5
00
;Delay 4 micro-seconds
nop
nop
nop
nop
;1 uS
;1 uS
;1 uS
;1 uS
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
; goto sleep.
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
; 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
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
movlf
macro
movlw
movwf
n,f
n
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:
;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"
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
Start
org
nop
nop
nop
nop
nop
nop
nop
0x0000
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
Del
DelX
call
0x3ff
movwf OSCCAL
bcf
status,rp0
clrf
GPIO
goto
Main
movlw
movwf
decfsz
goto
decfsz
goto
decfsz
40h
fileC
fileA,1
DelX
fileB,1
DelX
fileC,1
Main
goto
retlw
DelX
00
bsf
call
bcf
call
goto
GPIO,pin7
Del
GPIO,pin7
Del
Main
;turn on LED
;turn off LED
org
0x3ff
retlw 0x20
END
;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
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
SetUp call
0x3ff
bsf
STATUS,rp0
movwf OSCCAL
movlw b'10000110'
movwf OPTION_REG
movlw b'00001000'
movwf TRISIO
bcf
status,rp0
clrf
goto
Del_1 movlw
movwf
DelX decfsz
goto
decfsz
goto
decfsz
goto
retlw
Main
GPIO
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
MOVLW 21h
MOVWF 04
MOVLW 8Fh
MOVWF 00
The animation below shows how the information passes to the files:
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
DECFSZ 20h
GOTO Loop1
RETLW 00
P1
P2 P3