You are on page 1of 55

PIC16F887

Main Features
 Only 35 instructions to learn:
 All single-cycle instructions except branches
 Operating speed:
 DC – 20 MHz oscillator/clock input
 DC – 200 ns instruction cycle
 Interrupt capability
 8-level deep hardware stack
 Direct, Indirect and Relative Addressing modes
Main Features
 Precision Internal Oscillator:
 Factory calibrated to ±1%
 Software selectable frequency range of
 8 MHz to 31 kHz
 Software tunable
 Two-Speed Start-up mode
 Crystal fail detect for critical applications
 Clock mode switching during operation for
 Power savings
 Power-Saving Sleep mode
 Wide operating voltage range (2.0V-5.5V)
 Industrial and Extended Temperature range
 Power-on Reset (POR)
 Power-up Timer (PWRT) and Oscillator Start-up Timer
(OST)
 • Brown-out Reset (BOR) with software control Option
Main Features
 • Enhanced low-current Watchdog Timer (WDT) with on-
chip oscillator (software selectable nominal 268 seconds
with full prescaler) with software enable
 • Multiplexed Master Clear with pull-up/input pin
 • Programmable code protection
 • High Endurance Flash/EEPROM cell:
 100,000 write Flash endurance
 1,000,000 write EEPROM endurance
 Flash/Data EEPROM retention: > 40 years
 Program memory Read/Write during run time
 In-Circuit Debugger (on board)
Main Features
 Low-Power Features:
 Standby Current:
 50 nA @ 2.0V, typical
 • Operating Current:
 11 μ A @ 32 kHz, 2.0V, typical
 220 μ A @ 4 MHz, 2.0V, typical
 • Watchdog Timer Current:
 1 μ A @ 2.0V, typical
Pinout and Family Differences
I 2C
Oscillator
FOSC REGISTER
Parallel I/O (PIO) Ports
Parallel I/O (PIO) Ports
Timer 0
OPTION_REG = 0x84;
INTCON = 0xA0;

TMR0IF_bit = 0;
/*
* Project name:
LED_Blinking (Simple 'Hello World' project)
* Copyright:
(c) Mikroelektronika, 2009.
* Revision History:
20080930:
- initial release;
- 20090720 - modified by Slavisa Zlatanovic;
* Description:
This is a simple 'Hello World' project. It turns on/off LEDs connected to
PORTA, PORTB, PORTC and PORTD.
* Test configuration:
MCU: PIC16F887
http://ww1.microchip.com/downloads/en/DeviceDoc/41291F.pdf
Dev.Board: EasyPIC6
http://www.mikroe.com/en/tools/easypic6/
Oscillator: HS, 08.0000 MHz
Ext. Modules: -
SW: mikroC PRO for PIC
http://www.mikroe.com/en/compilers/mikroc/pro/pic/
* NOTES:
- Turn ON the PORT LEDs at SW9.
*/
void main() {

ANSEL = 0; // Configure AN pins as digital


ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

TRISA = 0x00; // set direction to be output


TRISB = 0x00; // set direction to be output
TRISC = 0x00; // set direction to be output
TRISD = 0x00; // set direction to be output

do {
PORTA = 0x00; // Turn OFF LEDs on PORTA
PORTB = 0x00; // Turn OFF LEDs on PORTB
PORTC = 0x00; // Turn OFF LEDs on PORTC
PORTD = 0x00; // Turn OFF LEDs on PORTD
Delay_ms(1000); // 1 second delay

PORTA = 0xFF; // Turn ON LEDs on PORTA


PORTB = 0xFF; // Turn ON LEDs on PORTB
PORTC = 0xFF; // Turn ON LEDs on PORTC
PORTD = 0xFF; // Turn ON LEDs on PORTD
Delay_ms(1000); // 1 second delay
} while(1); // Endless loop
}
/*
* Project name:
Timer0_Interrupt (Using Timer0 to obtain interrupts)
* Copyright:
(c) Mikroelektronika, 2009.
* Revision History:
20080930:
- initial release;
- 20090720 - modified by Slavisa Zlatanovic;
* Description:
This code demonstrates how to use Timer0 and it's interrupt.
Program toggles LEDs on PORTB.
* Test configuration:
MCU: PIC16F887
http://ww1.microchip.com/downloads/en/DeviceDoc/41291F.pdf
Dev.Board: EasyPIC6
http://www.mikroe.com/en/tools/easypic6/
Oscillator: HS, 08.0000 MHz
Ext. Modules: -
SW: mikroC PRO for PIC
http://www.mikroe.com/en/compilers/mikroc/pro/pic/
* NOTES:
- Turn on LEDs on PORTB (switch SW9.2).
*/
unsigned cnt;

void interrupt() {
if (TMR0IF_bit) {
cnt++; // Increment counter
TMR0IF_bit = 0; // Clear TMR0IF
TMR0 = 96;
}
}

void main() {
OPTION_REG = 0x84; // Assign prescaler to TMR0
ANSEL = 0; // Configure AN pins as digital
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
TRISB = 0; // PORTB is output
PORTB = 0xFF; // Initialize PORTB
TMR0 = 96; // Timer0 initial value
INTCON = 0xA0; // Enable TMRO interrupt
cnt = 0; // Initialize cnt

do {
if (cnt >= 400) {
PORTB = ~PORTB; // Toggle PORTB LEDs
cnt = 0; // Reset cnt
}
} while(1);
}
unsigned cnt;

void interrupt() {
if (TMR0IF_bit) {

TMR0IF_bit = 0; // Clear TMR0IF


TMR0 = 255;
PORTB = ~PORTB;
}
}

void main() {
OPTION_REG = 0x80; // Assign prescaler to TMR0
ANSEL = 0; // Configure AN pins as digital
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
TRISB = 0; // PORTB is output
PORTB = 0xFF; // Initialize PORTB
TMR0 = 255; // Timer0 initial value
INTCON = 0xA0; // Enable TMRO interrupt
cnt = 0; // Initialize cnt

}
_interrupt:
MOVWF R15+0
SWAPF STATUS+0, 0
CLRF STATUS+0
MOVWF ___saveSTATUS+0
MOVF PCLATH+0, 0
MOVWF ___savePCLATH+0
CLRF PCLATH+0

;Timer0_Interrupt.c,28 :: void interrupt() {


;Timer0_Interrupt.c,29 :: if (TMR0IF_bit) {
BTFSS TMR0IF_bit+0, BitPos(TMR0IF_bit+0)
GOTO L_interrupt0
;Timer0_Interrupt.c,31 :: TMR0IF_bit = 0; // Clear TMR0IF
BCF TMR0IF_bit+0, BitPos(TMR0IF_bit+0)
;Timer0_Interrupt.c,32 :: TMR0 = 255;
MOVLW 255
MOVWF TMR0+0
;Timer0_Interrupt.c,33 :: PORTB = ~PORTB;
COMF PORTB+0, 1
;Timer0_Interrupt.c,34 :: }
L_interrupt0:
;Timer0_Interrupt.c,35 :: }
L_end_interrupt:
L__interrupt2:
MOVF ___savePCLATH+0, 0
MOVWF PCLATH+0
SWAPF ___saveSTATUS+0, 0
MOVWF STATUS+0
SWAPF R15+0, 1
SWAPF R15+0, 0
RETFIE
; end of _interrupt
Single Cycle Instruction 8 Dual Cycle Instructions
foscillator 8,000,000
foscillator/4 2,000,000
prescaler/2 1,000,000
Ton/Toff 500,000 500,000

Intructions
Loading Tmr0 2 2
Overflowing 1 1
Interrupt 12 20
15 23

Output Frequency 33,333 21,739

Osciloscope
Divisions 4.60
us per/div 5
23

fout 21,739
CAPTURE/COMPARE/PWM
MODULES (CCP1 AND CCP2)
 This device contains one Enhanced
Capture/Compare/PWM (CCP1) and
Capture/Compare/PWM module(CCP2).
 The CCP1 and CCP2 modules are identical in
operation, with the exception of the Enhanced
PWM features available on CCP1 only.
 CCPRx and CCPx refer to CCPR1 or CCPR2 and
CCP1 or CCP2, respectively.
Pinout and Family Differences
/*
* Project name:
PWM (PWM library Demonstration)
* Copyright:
(c) MikroElektronika, 2008.
* Revision History:
- 2008. - initial release;
- 20090720 - modified by Slavisa Zlatanovic;
* Description:
This is a simple demonstration of PWM library, which is being used for
control of the PIC's CCP module. The module is initialized and started,
after which the PWM1 and PWM2 Duty Ratios can be adjusted by means of 4 buttons
connected to pins RA0, RA1, RA2 and RA3. The changes can be monitored on the CCP
output pins (RC1 and RC2).
* Test configuration:
MCU: PIC16F887
http://ww1.microchip.com/downloads/en/DeviceDoc/41291F.pdf
Dev.Board: EasyPIC6
http://www.mikroe.com/en/tools/easypic6/
Oscillator: HS, 08.0000 MHz
Ext. Modules: -
SW: mikroC PRO for PIC
http://www.mikroe.com/en/compilers/mikroc/pro/pic/
* NOTES:
- Pull-down PORTA and connect button jumper (J17) to Vcc.
- Turn on LEDs on PORTC SW9.3.
*/
unsigned short current_duty, current_duty1;

void InitMain() {
ANSEL = 0; // Configure AN pins as digital
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

PORTA = 255;
TRISA = 255; // Configure PORTA pins as input
PORTB = 0; // Set PORTB to 0
TRISB = 0; // Designate PORTB pins as output
PORTC = 0; // Set PORTC to 0
TRISC = 0; // Designate PORTC pins as output
PWM1_Init(5000); // Initialize PWM1 module at 5KHz
PWM2_Init(5000); // Initialize PWM2 module at 5KHz
}

PWM2_Init(5000 seem to override PWM1_Init(5000


void main() {
InitMain();
current_duty = 30; // Initial value for current_duty
current_duty1 = 30; // Initial value for current_duty1

PWM1_Start(); // Start PWM1


PWM2_Start(); // Start PWM2
PWM1_Set_Duty(current_duty); // Set current duty for PWM1
PWM2_Set_Duty(current_duty1); // Set current duty for PWM2

while (1) { // Endless loop


if (RA0_bit) { // Button on RA0 pressed
Delay_ms(40);
current_duty++; // Increment current_duty
PWM1_Set_Duty(current_duty);
}

if (RA1_bit) { // Button on RA1 pressed


Delay_ms(40);
current_duty--; // Decrement current_duty
PWM1_Set_Duty(current_duty);
}

if (RA2_bit) { // Button on RA2 pressed


Delay_ms(40);
current_duty1++; // Increment current_duty1
PWM2_Set_Duty(current_duty1);
}

if (RA3_bit) { // Button on RA3 pressed


Delay_ms(40);
current_duty1--; // Decrement current_duty1
PWM2_Set_Duty(current_duty1);
}
if (RA5_bit) { // Button on RA3 pressed
PORTC.B0 = ~ PORTC.B0;
// current_duty = 255 - current_duty;
PWM1_Set_Duty(current_duty);
Delay_ms(1000);
}

Delay_ms(5); // Slow down change pace a little


}
}
/*
* Project name:
Button (Demonstration of using Button Library)
* Copyright:
(c) Mikroelektronika, 2009.
* Revision History:
20080110:
- initial release;
- 20090720 - modified by Slavisa Zlatanovic;
* Description:
This program demonstrates usage on-board button as PORTB input.
On every RB0 one-to-zero transition PORTC is inverted.
* Test configuration:
MCU: PIC16F887
http://ww1.microchip.com/downloads/en/DeviceDoc/41291F.pdf
Dev.Board: EasyPIC6
http://www.mikroe.com/en/tools/easypic6/
Oscillator: HS, 08.0000 MHz
Ext. Modules: -
SW: mikroC PRO for PIC
http://www.mikroe.com/en/compilers/mikroc/pro/pic/
* NOTES:
- Turn ON the PORTC LEDs.
- Put button jumper (J17) into VCC position and pull-down PORTB.
*/
bit oldstate; // Old state flag

void main() {

ANSEL = 0; // Configure AN pins as digital I/O


ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;

TRISB0_bit = 1; // set RB0 pin as input


TRISB = 0b00000011;
PORTB = 0x00;

TRISC = 0x00; // Configure PORTC as output


PORTC = 0xAA; // Initial PORTC value
oldstate = 0;

do {
if (Button(&PORTB, 0, 1, 1)) { // Detect logical one
oldstate = 1; // Update flag
}
if (oldstate && Button(&PORTB, 0, 1, 0)) { // Detect one-to-zero transition
PORTC = ~PORTC; // Invert PORTC
oldstate = 0; // Update flag
}
if (RB1_bit == 1) { // Detect one-to-zero transition
PORTC = ~PORTC; // Invert PORTC
}
} while(1); // Endless loop
}
Switch + LED
(SWITCH12)
 void main ()
 {
 ADPCFG = 0xFFFF;
 TRISF=0b000001;
 PORTF=0x00;
 while(1)
 {
 if((PORTF&0b000001)==1) // Switch at PORTF Bit 0
 {PORTF.F1=PORTF.F1^1;} // Toggles PORTF Bit 1
 }
 }
Key DEBOUNCING
Key DEBOUNCING – 1
(SWITCH2)
 void main ()


{
int i;
Adapted from 123 PIC


const int Tenms = 16667;
ADPCFG = 0xFFFF;
Experiments for the EVIL


TRISF=0b000001;
PORTF=0x00;
GENIOUS by MYKE PREDKO
 while(1)
 {
 i = 0; // Wait 10 ms for Button Up
 while (i < Tenms)
 {
 if (1 == PORTF.F0) // Button Down/Start over
 {
 i = 0;
 }
 else // Button Up/Increment Count
 {
 i = i + 1;
 } //
 } //

 i = 0; // Wait 10 ms for Button Down


 while (i < Tenms)
 {
 if (0 == PORTF.F0 ) // Button Up/Start over
 i = 0;
 else // Button Down/Increment Count
 i = i + 1;
 }

 PORTF.F1=PORTF.F1^1; // Toggle LED to Turn ON/OFF LED

 }
 }
Key DEBOUNCING – 1
(SWITCH2)
 ;SWITCH2.c,24 :: while (i < Tenms)
 $0144 $ L_main_6:
 $0144 $470060 ADD W14, #0, W0
 $0146 $780110 MOV [W0], W2
 $0148 $4700E2 ADD W14, #2, W1
 $014A $510011 SUB W2, [W1], W0
 $014C $3D000D BRA GE L_main_7, L_main_7
 ;SWITCH2.c,25 :: if (0 == PORTF.F0) // Button Up/Start over
 $014E $801700 MOV PORTF, W0
 $0150 $6000E1 AND W0, #1, W1
 $0152 $108060 SUBR W1, #0, W0
 $0154 $3A0004 BRA NZ L_main_8, L_main_8
 ;SWITCH2.c,26 :: i = 0;
 $0156 $200000 MOV #0, W0
 $0158 $780F00 MOV W0, [W14]
 $015A $040164 GOTO L_main_9 80,000,000
 $015E $ L_main_8: f   20,000,000
4
 ;SWITCH2.c,28 :: i = i + 1;
1
 $015E $200011 MOV #1, W1 T(ms)   0.00000005
 $0160 $470060 ADD W14, #0, W0 f
 $0162 $408810 ADD W1, [W0], [W0] 10ms
Intructions   200,000
 $0164 $ L_main_9: T(ms)
 $0164 $040144 GOTO L_main_6 N  200,000/12  16,667
 $0168 $ L_main_7:
 ;SWITCH2.c,30 :: PORTF.F1=PORTF.F1^1; // Toggle LED to Turn
Capture Mode
Compare Mode
PWM
Period in multiples of 4/fosc
Resolution in multiples of 1/fosc
Least significant bits of extended TMR2
Change at oscillator frequency
void InitMain() {
ANSEL = 0; // Configure AN pins as digital
ANSELH = 0;
C1ON_bit = 0; // Disable comparators
C2ON_bit = 0;
PORTC = 0; // Set PORTC to 0
TRISC = 0; // Designate PORTC pins as output
}

void main() {
InitMain();
PR2 = 0x65;
T2CON = 0X04;
CCP2CON = 0X3F;
CCPR2L = 0X0F;
}
PWM
PWM Frequency
Divisions 5.10
us per div 10.00
Period in us 51.00
Frequency 19,607.84

Pulse duration 0.80


us per div 10.00
Duration in us 8.00
d 15.69%
RxL:CCPxCON<5:4> 1 1 1 1 1 1
32 16 8 4 2 1 63
RxL:CCPxCON<5:4> *Tosc 7.88E-06
PR2 0x65 101
(PR2 + 1)* 4*Tosc *TMR2prescale Value 5.10E-05
fpwm 19,607.84
d 15.44%

You might also like