Professional Documents
Culture Documents
Contents:
1. Introduction
2. What is the 12F675 ?
3. Front-end setup
4. Blink!
5. Making Music
6. In Circuit Serial Programming (ICSP)
7. Analog to Digital Converters (ADCs)
8. Sleeping
9. Interrupt on Change
10. Lost Calibration Code
11. Feedback and Acknowledgements
Page 1
Page 1
Page 2
Page 3 - 4
Page 5 - 6
Page 7- 9
Page 10-14
Page 15
Page 16-20
Page 21
Page 22
1. Introduction
I have been using the PIC12F675 for the past three years. During that time I have made many
mistakes, sometimes more than once. These notes were prepared to assist me in future applications
using this small but mighty microcontroller. Hopefully you will also find them useful.
Be sure to check the PIC12F629/12F675 datasheet at Microchip for detailed information.
(See: www.microchip.com)
All of my source code is written for Micro Engineering Labs PIC Basic Pro (PBP) Compiler and the
chip is programmed using MELabs EPIC Plus Programmer.
The only serious limitations are the number of ports and amount of memory.
Ian Burn
1
V5.0
12F675 Pin-out
Vdd = +2.0 to 5.5 VDC
Vss = power ground
GP0 to GP5 are the six GPIO ports with all but GPIO.3 (pin 4) being either inputs or
outputs. GPIO.3 can be either an input port or MCLR port.
3. Front-End Setup
As with most PICs, a number of initial setting must be placed at the beginning of the program.
With some PICs, such as the 16F84, one can write a simple program to blink a LED by using all the
default settings and no front-end statements are required. Not so with the 12F675.
The following lines of code are used in many of my 12F675 projects and are described as follows:
ansel=0
cmcon=7
Sets the ADC inputs as digital when not using the ADCs.
Turns the comparator OFF when using ports digitally
These two statements are critical to digital operation such as the flashing LEDs.
Next one would normally configure the GPIO ports as either inputs or outputs. GPIO.3 (pin 4) is the
MCRL pin or can be used as an input BUT not as an output. If used as an input, MCLR must be
turned OFF in the configuration line below. If it is turned ON, it must have an external pull-up resistor
of 4.7k to 10k. You would also likely want a reset button connecting the MCLR pin to ground (Vss)
via a 100 ohm resistor.
TRISIO =%000000 is the binary equivalent of TRISIO=0 which sets all ports as outputs
The Compiler seems to sense that GPIO.3 must be an input and adjusts for this incorrect code.
If all the ports except GPIO.3 are going to be outputs, a preferred code would be:
TRISIO=%001000 which is the binary equivalent of TRISIO=8
If all ports except GPIO.0 are inputs, for example, you would use either
TRISIO=%111110 or TRISIO=62
Ian Burn
V5.0
Setting the 12F675 configuration codes (sometimes called fuses) can be done at the programmer or,
for most settings, by way of an @DEVICE statement in the code.
For example:
@ Device PIC12F675,WDT_ON,PWRT_ON,PROTECT_OFF,MCLR_ON,BOD_OFF
This defines the PIC as a 12F675
The watchdog timer (WDT) is turned ON (usually only OFF if using the @SLEEP command as
the WDT keeps waking up the PIC)
Power-on reset (PWRT) is turned ON
Code protect (PROTECT) is turned OFF
MCLR is turned on so an external pull-up resistor is needed
Brown out detect (BOD) is turned OFF (this reduces sleep current)
Other front-end statements will be introduced as required.
4. Blink!
The standard test for successfully programming any PIC is to blink a LED.
This circuit uses three AA batteries
for a 4.5 volt supply. A 0.1 mfd
capacitor is connected between
pins 1 and 8 as close as possible
to the pins.
DONT omit this capacitor!
BAT1
4V5
C1
0.1
U1
1
R1
10k
4
Vdd/+
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
GP3/MCLR
GP2/AN2
R2
1k
D2
LED
PIC12F675
R3
SW1
Ian Burn
100
V5.0
The PIC BasicPro code to blink the LED when using the MCLR RESET is as follows:
Blinking a LED with a PIC 12F675
January 25, 2005
The LED will blink 10 times then turn off until the PIC is reset
Front-end setup
@ Device PIC12F675,WDT_ON,PWRT_ON,PROTECT_OFF,MCLR_ON,BOD_OFF
this statement is explained under item 3. above
ANSEL=0
Sets the ADC inputs as digital when not using the ADCs.
CMCON=7
Turns the comparator OFF when using ports digitally
TRISIO=8
All ports are outputs except MCLR - if a port is not used, set it as an output
Define Variables
LED VAR GPIO.0
x VAR BYTE
Program
FOR x = 1 to 10
LED = 1
PAUSE 500
LED = 0
PAUSE 500
NEXT x
END
The same result would occur if the MCLR was turned OFF and R1, R3 and SW1 were omitted.
GPIO.3 then becomes an input port.
I connect the GPIO.3 port to ground or to Vdd if I am not using it as in input, otherwise it will pick up
noise and prevents a deep SLEEP if using this command.
The configuration line would become:
@ Device PIC12F675,WDT_ON,PWRT_ON,PROTECT_OFF,MCLR_OFF,BOD_OFF
4V5
C1
0.1
U2
1
Vdd/+
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
GP3/MCLR
GP2/AN2
R2
Blinking LED
without RESET
1k
D1
LED
PIC12F675
Ian Burn
V5.0
5. Making Music
I have had a lot of fun making music with PICs. This is a case where the 12F675 is a bit limiting
because of its memory size but one or two tunes are possible.
One application was to blink the nose of a reindeer that played the tune, Rudolph the Red Nosed
Reindeer. Others have included musical clocks and door chimes.
Although the PIC cannot get the exact audio frequency for musical notes, it can come quite close.
The key command used is:
SOUND pin, [tone #, tone duration, tone #, tone duration, ..]
pin is the port used to put out the sound [I usually define the port such as: MPIN VAR GPIO.1]
tone # is a value between 0 and 127 with 0 being silence (127 is about 10,000 Hz)
tone duration is the length of the tone in 12 millisecond increments
The following tables can be used to equate tone # values to approximate musical notes:
Tone #
1
6
13
20
26
31
37
42
47
51
56
60
64
67
71
74
77
80
83
85
Note
Ds2
E2
F2
Fs2
G2
Gs2
A2
As2
B2
C3
Cs3
D3
Ds3
E3
F3
Fs3
G3
Gs3
A3
As3
Tone #
88
90
92
94
96
98
99
101
102
104
105
107
108
109
110
111
112
113
114
115
Note
B3
C4
Middle C
Cs4
D4
Ds4
E4
F4
Fs4
G4
Gs4
A4
As4
B4
C5
Cs5
D5
Ds5
E5
F5
Fs5 missing
G5
Ian Burn
V5.0
I did find one problem when using the 12F675 for music.
When using the 12F675s internal oscillator (may not be significant) and operating at lower voltages (3
to 4.5) distortion of the higher notes can occur if the coupling capacitor is 10 mfd. This may also be a
function of the speaker used. By dropping the
cap to 3.3 mfd the problem was eliminated
3 AA BATTERIES
and it worked down to 3V.
In the Sound Example circuit the 12F675 is
normally in SLEEP mode and draws less
than 1 microamp. SW1 operates the RESET
on the MCLR pin and wakes up the PIC,
starting the music.
R1
10k
4V5
C2
U1
0.1
Vdd/+
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
C1
4
GP3/MCLR
GP2/AN2
3.3 mfd
PIC12F675
SPEAKER
SW1
R2
8 Ohms
100
A Sound Example
'A Sound Example - January 27, 2005
The tune, Shave and a Haircut is played and then the 12F675 goes to sleep toconserve the batteries
sleep current is less than I microamp
MCLR reset is used to wake up the 12F675
Front-end Seup
@ Device PIC12F675,WDT_OFF,PWRT_OFF,PROTECT_OFF,MCLR_ON,BOD_OFF
sets configurations
ADCON0=0
'no ADC used
ANSEL=0
'no ADC input - IMPORTANT if using ports in digital mode
CMCON=7
' turns off comparator function - IMPORTANT if using ports in digital mode
TRISIO= 8
Sets GPIO.3 as input, all others as outputs. Equivalent to TRISIO =%001000
Define variables
MPIN VAR GPIO.2
y VAR BYTE
Program
START:
y=4
set delay between notes = 4 x 12 mSec = 28 mSec
Sound MPIN, [109,40,0,y,102,20,0,y,102,20,0,y,105,40,0,y,102,20,0,y,0,40,108,40,0,y,109,40,0,y]
@ SLEEP
assembler sleep forever command
Pause 100
give PIC time to wakeup
GOTO START
End
music
171 words
Ian Burn
V5.0
HINT: If memory space becomes critical, you can save a few words by using
LED=0 and LED=1
each use 1 word of memory
instead of:
Low LED and High LED each use 3 words of memory
HINT: Constantly moving a PIC between a test circuit breadboard and the chip
programmer can lead to pin damage. One way to minimize this damage is to
mount the PIC in a machine pin socket and move the complete unit back and
forth. I know, you do that already!!
What is ICSP?
ICSP, as I have been using it, is the normal high voltage programming usually done with the PIC
mounted in the programmer only in this case it is left in the circuit with the other components attached.
Five lines run from the programmer to the PIC and associated circuit. These are:
+5VDC (Vdd)
Ground (Vss)
Data line
Clock line
Vpp/MCLR programming line
Ideally one would have a jack mounted on the circuit board or breadboard that would accept the 5
lines via a plug and cable connected to the programmer. This allows the programming lines to be
easily removed while the program is running.
Design requirements
The Microchip data sheet indicates that the external circuitry connected to the CLOCK , DATA and
MCLR ports must be done via a resistor so as not to load down the programming voltages. Similarly
the capacitance on these ports must be limited for the same reason.
Ian Burn
V5.0
To normal circuit
PIC
Connections
from Programmer
Vdd (+5V)
Vdd (+5V)
Vss (gnd)
Vss (gnd)
Clock
Clock
Data
Data
Vpp
MCLR/Vpp
R1
R2
R3
10k
Vdd
To normal circuit
D2
+4.5 VDC
0.1
U1
1
D4
DIODE
D3
LED
Vss/Gnd
GP5
GP0/AN0
D1 LED
2
D5
LED
Vdd/+
R2 470
D6 LED
3
GP4/AN3
GP1/AN1
GP3/MCLR
GP2/AN2
R3 470
C1 3.3 mfd
DIODE
R1
470
SPEAKER
PIC12F675
R4
470
8 Ohms
GND
Vdd
VPP
Vcc
Data Clock
PROGRAMMER
2k
Ian Burn
V5.0
I was able to blink LEDs D1, D4 and D5 and have a tone at the speaker. I was even able to leave the
programmer connected and send in new programming data to the 12F675 with the circuit under power.
But as soon as LED D6 was added I ran into trouble if the programmer was connected and I tried to
run the circuit. Within the EPIC Programmer there is an effective resistance of 2K between the
CLOCK and DATA lines such that the outputs from the PIC at these two ports were effectively
connected together causing the LEDs to interfere with each other. This problem is obviously
eliminated by disconnecting the programmer lines when the circuit is operating.
I also could NOT get the PIC to sleep properly with the programmer connected.
I next tried to use the external MCLR resistor (MCLR=ON) and found that I could not run the circuit
with the programmer Vpp/MCLR line left connected.
The best practice is to disconnect the programmer once the programming has been completed.
Again, a convenient plug/jack would be helpful.
Ian Burn
V5.0
BAT1
4V5
C1
U1
0.1
Vdd/+
R1
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
GP3/MCLR
GP2/AN2
10k
4
DEFINE ADC_BITS 10
PIC12F675
BAT1
Vref+
R1
4V5
C1
U1
0.1
Vdd/+
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
10k
4
CMCON=7
GP3/MCLR
GP2/AN2
Vref+
PIC12F675
10
V5.0
ADCON selects the output format, the reference voltage and which ADC inputs you wish to use.
In the example that follows we want the following:
Right justified output therefore
BIT 7 = 1
Reference voltage at Vdd therefore BIT 6 = 0
Bit 5 and 4 are not used and set at 0
One ADC input, GPIO.4 is used (AN3) therefore
BIT 3 = 1
BIT 2 = 1
The ADC input will start right away and always be on therefore
BIT 1 = 1
BIT 0 = 1
This results in an ADCON0=10001111 for the 8 bits but this must be expressed as a decimal number
which is 143, therefore
ADCON0=143
Ian Burn
11
V5.0
The ANSEL register is used to set the timing and to set the ADC pin.
In the example that follows, timing was set at Fosc/2 (see Microchip Datasheet for details) therefore:
BIT 7 = 0 Unimplemented
BIT 6 = 0
BIT 5 = 0
BIT 4 = 0
We are selecting GPIO.4 or AN3 for the ADC input line, therefore:
BIT 3 = 1
BIT 2 = 0
BIT 1 = 0
BIT 0 = 0
ANSEL = 00001000
ANSEL=8
Ian Burn
12
V5.0
or TRISIO=24
The previous ADC circuits are fine except it would be useful to have some form of output.
The following example will use a variable voltage input into AN3 (GPIO.4) with the range being
between ground and the supply voltage, Vss and Vdd. This will provide ADC values from 0 to 1023.
The outputs will be a LED that turns on if ADC is above 500 and sound ranging from note values of
1 to 120, corresponding to ADC values of 0 to 1023.
The MCLR will be turned OFF, making GPIO.3 an input. To prevent noise entering this un-used port,
it will be connected to Vss.
3 AA BATTERIES
4V5
C2
U1
1
0.1
Vdd/+
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
GP3/MCLR
GP2/AN2
D1
2
R1
R2
470
10k
LED
SPEAKER
C1
4
3.3 mf d
PIC12F675
8 Ohms
Ian Burn
13
V5.0
'ADC Example #1
'A variable voltage is applied to AN3, GPIO.4 The range will be Vss to Vdd
'The LED will come on if the ADC value equals or exceeds 500
'Sound output, a 120 mSec beep, will have a frequency proportional to the input voltage.
'A #120 tone is used at the top end as the higher audio frequencies sometimes distort
'depending upon the speaker. A 0.001 mfd cap across the speaker may allow use of up to #127
'Front-end setup
@ Device PIC12F675,WDT_ON,PWRT_ON,PROTECT_OFF,MCLR_OFF,BOD_OFF
'sets configuration
ADCON0=143
'set AN3 ON ie GPIO.4
ANSEL=8
'sets Fosc/2 and GPIO.4 [AN3] as ADC input
CMCON=7
'turns off comparator function
TRISIO=%011000
'sets GPIO.4 as in input and all others as outputs could also use TRISIO=24
DEFINE OSCCAL_1K 1
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50
' Set OSCCAL for 1K device - calibrates the internal oscillator - not really needed here
'ADC settings
'ADC settings
'ADC settings
Define variables
RDG VAR WORD
MPIN VAR GPIO.2
LED VAR GPIO.0
TONE VAR WORD
'Initial settings
LED=0
'Program
START:
LED=0
ADCIN 3, RDG
Pause 100
IF RDG =>500 Then LED=1
TONE = 1+(rdg/10)*119/102
Sound MPIN,[TONE,20]
GoTo START
End
'277 words
HINT: ADC circuits frequently have a voltage divider across the battery, constantly
drawing current. Depending upon how often ADC readings are needed, you can
conserve battery life by supplying the ADC reference voltage from an unused port.
Make the port high just prior to taking an ADC reading then return it to low when
finished. You will still be using the Vdd as reference, not the Vref+ option.
For example a thermistor used in a divider to monitor a deepfreeze temperature may
require a reading every 10 minutes - no need to be drawing current all the time.
Ian Burn
14
V5.0
8. Sleeping
Many of my 12F675 circuits operate on 3 AAA or AA batteries. If the circuits operate continuously
there is often an opportunity to have the PIC SLEEP during a major part of its operating cycle.
The typical sleep current for the 12F675 is less than 1 microamp. I am not sure how much less as my
meters dont go low enough, but the current will be close to the shelf life of the battery!
The two SLEEP commands that I use are:
@SLEEP
and
SLEEP period
@SLEEP is an assembler sleep instruction which puts the PIC to sleep until it is awakened by:
the watchdog timer because you forgot to turn it off!!
an interrupt (eg interrupt on change)
a reset of the MCLR if it is used
A Pause 100 after the @SLEEP command allows time for the PIC to wakeup
SLEEP period is a PBP Compiler statement where period is the number of seconds between 1 and
65535 - a range of from 1 second to 18.2 hours. Longer periods have to be accomplished by using
loops. (eg for x= 1 to 10; SLEEP 64800; next x .= 18 hours x 10 =180 hours). This command uses
the watchdog timer which must be turned ON, unlike the @SLEEP command.
Many things can influence the sleep current, including:
Brown out detection - turn off to minimize sleep current ie BOD_OFF in the configuration
Set all unused ports as outputs. If GPIO.3 is not used as MCLR, connect to either Vss or Vdd
Tie the unused ports to Vdd using the internal weak pull-up (see page 19)
If using the POT command, set the POT port low before going to sleep, bring high on
awakening
Turn off the ADC reference voltage by using the statement : VRCON=0
turn off watchdog timer is using @SLEEP ie WDT_OFF in configuration
input data must not be changing.
HINT: Continually changing data entering an INPUT port will prevent the 12F765
from reaching minimum SLEEP current. Depending upon the input circuitry, you might
convert the port in question to an OUTPUT during the SLEEP part of the program. Be
sure to change it back to an INPUT on awakening. eg TRISIO.4=0..then..TRISIO.4=1
Ian Burn
15
V5.0
9. Interrupt-on-Change
A useful way to wake up a sleeping PIC is by using an interrupt-on-change.
For example if a battery powered 12F675 is meant to start some sequence of outputs after receiving an
incoming pulse, it is likely a good idea for it to be in SLEEP mode until the pulse arrives.
The Interrupt-on-Change (IOC) can be set for either a positive or negative going pulse and can be
allocated to any GPIO pins by setting the IOCB Register . The GPIE variable must be set in the
INCON Register and the falling edge option
is set in the OPTION Register.
+
BAT1
4V5
U1
1
R2
Vdd/+
Vss/Gnd
GP5
GP0/AN0
GP4/AN3
GP1/AN1
10k
3
GP3/MCLR
GP2/AN2
R1
1k
D1
PIC12F675
SW1
Interrupt on Change
16
IOCB = 16
January 31, 2005
V5.0
We arent dealing with a lot of the information here. We only need to enable the GPIE variable.
Bit 7 = 0
Bit 6, 5 and 4 = 0
Bit 3 = 1
Bit 2 and 1 = 0
Bit 0 = 0
Ian Burn
INTCON = 8
17
V5.0
One other key item is to turn off the GPIF, Bit 0, of INTCON just prior to the @SLEEP command.
This can be done by using INTCON.0=0
Two items of interest are in this register - Bit 6 and Bit 7 both of which need to set at 0
by using:
OPTIONS_REG.6=0
OPTIONS_REG.7=0
However, all the bits could be set at 0 without a problem so we could also use:
OPTION_REG=0
Ian Burn
18
V5.0
GPIO ports 1, 2 and 5 are not used and can be tied to Vdd using the weak pull-up resistors
therefore WPU=%00100110 or WPU = 38
'Initial settings
LED=0
Ian Burn
19
V5.0
'Program
START:
INTCON.0=0
Pause 100
@ Sleep
Pause 100
For x= 1 TO 10
LED=1
Pause 300
LED=0
Pause 300
Next x
GoTo start
End
'90 Words
HINT: When building a circuit with a sleep component, removing the power from the
circuit doesnt necessarily turn off the PIC. The charged 0.1 mfd bypass capacitor can
keep a sleeping PIC operating for awhile after the power is removed. To be sure it has
reset, short out Vdd to Vss once the power is removed.
The other option is to use the MCLR with a reset button.
HINT: Using the internal weak pull-up resistors can eliminate external pull-up resistor
on switched inputs.
Ian Burn
20
V5.0
Use the 12F675 in applications where timing isnt critical and omit the
DEFINE OSCCAL_1K 1 statement.
IF you know the last two hex digits of the calibration code you can insert them directly
into the OSCCAL register using:
OSCCAL=$xx
For example if the code is 34a8, use:
OSCCAL=$a8
DO NOT use the DEFINE OSCCAL_1K 1 statement as there is no calibration code to read
and then transfer to the OSCCAL register.
If you DO NOT know the calibration code (as in my case, with two 12F675's!!!)
use OSSCAL $80 as a starting point. (do not use DEFINE OSCCAL_1K 1 )
Connect a scope or frequency counter to Pin 3 (GPIO.4/OSC2/CLKOUT).
When programming the chip, set the Oscillator Configuration to "INTRC Clockout".
This must be done within the programmer software not the @DEVICE codes.
You will get a square wave at 1/4 of the oscillators frequency ie 1 MHz on Pin 3
Here are my results:
OSSCAL= $80
OSSCAL= $90
OSSCAL= $85
OSSCAL= $89
OSSCAL= $8c
OSSCAL= $8d
Freq=966 kHz
Freq=1001 kHz
Freq=977 kHz
Freq=991 kHz
Freq=998 kHz
Freq=1000 kHz
Ian Burn
21
V5.0
Special thanks to Melinda Burn and Angus Cameron in assisting with PDF conversions and
editing suggestions.
Ian Burn
22
V5.0