Nerdegutta's logo

nerdegutta.no

PIC16F690 - Day 1: Project setup & basic I/O

29.07.25

Embedded

Day 1: Project Setup & Basic I/O

Goal: Set up MPLAB X, create a project, and control LEDs using PORTB.
Concepts: Configuration bits, TRIS/PORT/LAT registers
Code 1: Toggle RB0 with delays using __delay_ms() (high-level)
Code 2: Direct register manipulation to toggle RB0 (low-level)

Goal

Setup MPLAB X project
Toggle an LED connected to RB0
Two approaches:
High-level using __delay_ms()
Low-level using direct register manipulation
Hardware: Connect an LED (with resistor) to RB0. Assume a 4 MHz internal oscillator.

Preparation

Before coding:
Create a new project for PIC16F690 in MPLAB X.
Set XC8 as the compiler.
Enable internal oscillator: Use MPLAB X > Window > PIC Memory Views > Configuration Bits. Set:
FOSC = INTRCIO

WDT = OFF

MCLR = OFF
Generate configuration bits and paste them at the top of your code.
Code 1: High-Level Approach (with __delay_ms())
// File: main.c
#define _XTAL_FREQ 4000000  // Required for __delay_ms()

#include < xc.h > // Remove extra spaces

// CONFIG
#pragma config FOSC = INTRCIO   // Internal RC oscillator, I/O function on RA6/7
#pragma config WDTE = OFF       // Watchdog Timer disabled
#pragma config PWRTE = OFF      // Power-up Timer disabled
#pragma config MCLRE = OFF      // MCLR disabled
#pragma config BOREN = OFF      // Brown-out Reset disabled
#pragma config CP = OFF         // Code protection off
#pragma config CPD = OFF        // Data code protection off

void main(void) {
    TRISB0 = 0;     // Set RB0 as output
    ANSEL = 0;      // Disable analog inputs
    ANSELH = 0;
    PORTB = 0;      // Clear PORTB

    while(1) {
        RB0 = 1;               // LED ON
        __delay_ms(500);
        RB0 = 0;               // LED OFF
        __delay_ms(500);
    }
}
Code 2: Low-Level Approach (Bit Manipulation, No Delay Macros)
// File: main.c
#define _XTAL_FREQ 4000000

#include < xc.h > // Remove extra spaces

// CONFIG (same as above)
#pragma config FOSC = INTRCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config CP = OFF
#pragma config CPD = OFF

void delay_approx_500ms(void) {
    for (unsigned int i = 0; i < 500; i++) {
        for (unsigned int j = 0; j < 120; j++) {
            NOP();  // Fine-tune if needed
        }
    }
}

void main(void) {
    TRISB &= ~(1 << 0);  // Clear bit 0: RB0 output
    ANSEL = 0;
    ANSELH = 0;
    PORTB &= ~(1 << 0);  // Start with LED off

    while(1) {
        PORTB |= (1 << 0);     // Set RB0 high
        delay_approx_500ms();
        PORTB &= ~(1 << 0);    // Set RB0 low
        delay_approx_500ms();
    }
}
LED on RB0 should blink every 500ms.

Try modifying the delay or using other PORTB pins.