PIC 16 — 7 Awesome MPLABX Projects!

Reviewing C Language Using MPLABX with PIC16F877A — #PIC_Series — Episode 0

J3
Jungletronics
18 min readJul 24, 2023

--

Hi, this project uses the PIC-DIP40 Development Board and presents 7 projects using the PIC16F877A in C Language using Microchips’ MPLABX IDE. All codes are functional! 👉GitHub

Welcome!

Let’s Get Started:

If you gave me a chance I would take it 🎺🎷💖

0#Step — Installation & Documentations:

Installation:

Run these Examples by Install MPLAB-X on WIN10:

Use: microchip_MPLABX IDE

Use: MPLAB® XC8 Compiler

Use: WaveShare Site (Chinese) — PICkit3 v3.10

Use: S.O. Windows 10

Version:
Product Version: MPLAB X IDE v6.10
Java: 1.8.0_345; OpenJDK 64-Bit Server VM 25.345-b01
Runtime: OpenJDK Runtime Environment 1.8.0_345-b01
System: Windows 10 version 10.0 running on amd64; Cp1252; pt_BR (mplab)

Documentation:

PIC16F877A

MPLAB XC8 Compiler

PICkit™ 3

PICKIT™ 3 IN-CIRCUIT DEBUGGER

0#Step —Prepare your Environment:

👍 Download the lcd.h file to run the some codes below:

Create a Directory named:

MPLABXProjects

Inside expand the Directories:

(CODE_1, CODE_2...)

Open MPLABX and Point to each Project:

PICKit3 — In All The Project folder right click it, and

Properties > Select PICKit3 > 

Tab: Power > Power target circuit PICkit3 : True
Voltage Level: 4.625 V
The PICKit3 option only enables if all drivers are properly installed. During Installation enable the MPLAB IPE Program. If you still don’t recognize it, download the standalone app for PICkit3 and most likely all drivers will be installed. For my platform, it worked… See Stackoverflow

1#Step — The First Project — Simple LED BLINK 😜:

Code 1:

/* 
Code 1: Blink 1 LED

MCU: PIC16F877A
Dev.Board: PIC-DIP40 - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/


#include <xc.h> // Compiler library
#include <pic16f877a.h> // Include library for PIC16F877A0

// Setting the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS (High Speed) mode
#pragma config WDTE = OFF // Watchdog Timer desable
#pragma config PWRTE = OFF // Power-up Timer desable
#pragma config BOREN = ON // Brown-out Reset unable
#pragma config LVP = OFF // Disabled low voltage programming (high Vpp)


#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)
# define TRUE 1

void main(){
TRISD = 0x00;

while (TRUE){
PORTD = 0x7f; // All PORTD pins off except RD0
__delay_ms(1000); // Wait 1 sec.
PORTD = 0xff; // All PORTD pins off
__delay_ms(1000); // Wait 1 sec.
}
}

For LEDS:

In the PIC-DIP40 Development Board

> KEEP LED-EN jumper

For LCDs:

> REMOVE the LED-EN jumper

Screenshots

By keeping LED-EN jumper all LEDs on PORTD will be available. If you use LCD, remove it. Product Description: High-quality PIC microcontroller development board; (1). Reset button; (2). 4M crystal onboard, Using socket, Crystal frequency can be replaced easily at any time; (3). 4 independent push buttons, connected to RB0 RB1 RB2 RB3; (4). 8 LEDs connected to the RD port, J3 is jumpered to enable LEDs. Remove to disconnect; (5). Standard RS232 communication interface, microcontroller computer communication interface; (6). USB power supply interface; (7). External 5V DC power interface; (8). Power switch; (9). ICSP (ZR) programming interface (K150 PICKIT2 PICKIT3 ICD2 etc.); (10). VCC GND Pin power expansion interface can use for access or to 5V power supply; (11). Microcontroller IO port Pin leads for convenient expansion; (12). DS18B20 temperature sensor interface; (13). LCD1602 LCD interface; (14). LCD12864 LCD interface Package includes 1. 1 x PIC development board 2. PIC16F877A chip 3. 1 x USB cable

2#Step — Light 2 LEDs together and turn them off via KEY1:

Code 2:

/*
Code 2: Light 2 LEDs together and turn them off via KEY1
MCU: PIC16F877A
Dev.Board: PIC-DIP40 - UNINTER - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/

#include <xc.h> // Compiler library
#include <pic16f877a.h> // Library for the PIC16F877A

// Configuration of the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS mode (High Speed)
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config LVP = OFF // Low voltage programming disabled (high Vpp)

#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)
#define TRUE 1

void main() {
TRISD = 0B01111110; // Configure PORTD pins RD0 and RD7 as output
TRISB = 0B00000001; // Configure PORTB pin RB0 as an input

// Enable pull-up for RB0
OPTION_REGbits.nRBPU = 0;

PORTD = 0B11111111; // Initialize PORTD with all LEDs off (inverted logic)

while (TRUE) {
if (PORTBbits.RB0 == 0) { // Check if the KEY1 button was pressed (RB0 at low level - inverted logic)
__delay_ms(50); // Debounce - wait a short period to avoid noise
if (PORTBbits.RB0 == 0) { // Check again if the KEY1 button is pressed (inverted logic)
// Turn on the LEDs in the first and last bits of PORTD (inverted logic)
PORTDbits.RD0 = 0; // Turn on the first LED (bit 0 of PORTD - inverted logic)
PORTDbits.RD7 = 0; // Turn on the last LED (bit 7 of PORTD - inverted logic)
}
} else {
// Turn off the LEDs in the first and last bits of PORTD (inverted logic)
PORTDbits.RD0 = 1; // Turn off the first LED (bit 0 of PORTD - inverted logic)
PORTDbits.RD7 = 1; // Turn off the last LED (bit 7 of PORTD - inverted logic)
}
}
}

3#Step — Turn on LEDs in sequence:

Code 3:

/*
Code 3: Turn on LEDs in sequence
MCU: PIC16F877A
Dev.Board: PIC-DIP40 - UNINTER - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/

#include <xc.h> // Compiler library
#include <pic16f877a.h> // Include the library for PIC16F877A

// Configuration of the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS mode (High Speed)
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config LVP = OFF // Low voltage programming disabled (high Vpp)

#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)

void main() {
TRISD = 0x00; // Set all PORTD pins as output
PORTD = 0xFF; // Initialize PORTD with all LEDs off (inverted logic)

// Set Timer 0 to generate a 1 second delay
OPTION_REG = 0b11000111; // Prescaler 1:256, timer mode, rising edge on internal clock

while (1) {
// Sequence of turning the LEDs on and off
for (int i = 0; i < 8; i++) {
// Turn on the current LED (bit i) and turn off the previous LED (bit i-1)
PORTD = ~(1 << i);
__delay_ms(1000); // 1 second delay

// Turn off all LEDs
PORTD = 0xFF;
__delay_ms(1000); // 1 second delay
}
}
}

4#Step — Light 4 LEDs two by two (and turn them off) via KEY1 and KEY2:

Code 4:

/*
Code 4: Light 4 LEDs two by two (and turn them off) via KEY1 and KEY2
MCU: PIC16F877A
Dev.Board: PIC-DIP40 - UNINTER - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/

#include <xc.h> // Libraries for the compiler
#include <pic16f877a.h> // Include the library for PIC16F877A

// Configuration of the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS mode (High Speed)
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config LVP = OFF // Low voltage programming disabled (high Vpp)

#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)
#define TRUE 1


void main() {
TRISD = 0B00111010; // Configure PORTD pins RD0 and RD7 as output
TRISB = 0B00000011; // Configure PORTB pin RB0 as an input

// Enable pull-up for RB0
OPTION_REGbits.nRBPU = 0;
unsigned char flag = 0; // Button 2 control variable

PORTD = 0B11111111; // Initialize PORTD with all LEDs off (inverted logic)

while (TRUE) {
if (PORTBbits.RB0 == 0) { // Check if the KEY1 button was pressed (RB0 at low level - inverted logic)
__delay_ms(50); // Debounce - wait a short period to avoid noise
if (PORTBbits.RB0 == 0) { // Check again if the KEY1 button is pressed (inverted logic)
// Turn on the LEDs in the first and last bits of PORTD (inverted logic)
PORTDbits.RD0 = 0; // Turn on the first LED (bit 0 of PORTD - inverted logic)
PORTDbits.RD7 = 0; // Turn on the last LED (bit 7 of PORTD - inverted logic)
}
else {
// Turn off the LEDs in the first and last bits of PORTD (inverted logic)
PORTDbits.RD0 = 1; // Turn off the first LED (bit 0 of PORTD - inverted logic)
PORTDbits.RD7 = 1; // Turn off the last LED (bit 7 of PORTD - inverted logic)
}
}
if (PORTBbits.RB1 == 0 & flag == 0) {
// Checks if the KEY2 button was pressed (RB1 at low level - inverted logic) and flag lowered
__delay_ms(50); // Debounce - wait a short period to avoid noise
if (PORTBbits.RB1 == 0 & flag == 0) { // Check again
PORTDbits.RD6 = 0; // Turn on LED2 (RD6 - inverted logic)
PORTDbits.RD2 = 0; // Turn on LED6 (RD2 - inverted logic)
__delay_ms(1000); // Ignore the finger remaining on the button
flag = 1; // Raise the flag
}
}
if (PORTBbits.RB1 == 0 & flag == 1) {
__delay_ms(50); // Debounce - wait a short period to avoid noise
if (PORTBbits.RB1 == 0 & flag == 1) {
// Checks again if the KEY2 button is pressed (inverted logic) and flag raised
PORTDbits.RD6 = 1; // Turn off LED2 (RD6 - inverted logic)
PORTDbits.RD2 = 1; // Turn off LED6 (RD2 - inverted logic)
__delay_ms(1000); // Ignore the finger remaining on the button
flag = 0; // Lower the flag
}
}

}
}

5#Step — Write “Hello World!” on the LCD:

Code 5:

/*
Code 5: Write "Hello World" on the LCD
MCU: PIC16F877A
Dev.Board: PIC-DIP40 - UNINTER - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/
#include <xc.h> // libraries for compiler
#include "lcd.h" // Include library for LCD
#include <pic16f877a.h> // Include the library for PIC16F877A

// Configuration of the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS mode (High Speed)
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config LVP = OFF // Low voltage programming disabled (high Vpp)
#pragma config CP = OFF

#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)

void main() {
// LCD initialization
LCD_init();
LCD_clean();
LCD_line1();
// Write the phrase "HELLO WORLD" character by character on the first line of the display
LCD_write('H');
LCD_write('E');
LCD_write('L');
LCD_write('L');
LCD_write('O');
LCD_write(' ');
LCD_write('W');
LCD_write('O');
LCD_write('L');
LCD_write('R');
LCD_write('D');
LCD_write('!');

while (1) {
// Other operations or program logic can be added here
}
}

6#Step — Write Name AND ID on the LCD:

Code 6:

/*
Code 6: Write Name AND ID on the LCD
MCU: PIC16F877A
Dev.Board: PIC-DIP40 - UNINTER - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/

#include <xc.h> // Compiler library
#include "lcd.h" // Include library for LCD
#include <pic16f877a.h> // Include the library for PIC16F877A

// Configuration of the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS mode (High Speed)
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config LVP = OFF // Low voltage programming disabled (high Vpp)

#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)

void writeWord(); // function prototype

void writeWord(char *word) { // Function to write a word on the LCD
while (*word != '\0') {
LCD_write(*word);
word++;
}
}

void main() {
// LCD initialization
LCD_init();

// Write "Your Name" on the first line
LCD_line1(); // Position the cursor on the first line, first column
writeWord("Your Name Goes Here!");

// Write "ID: 1234567" on the second line
LCD_line2(); // Position the cursor on the second line, first column
writeWord("ID: 1234567");

while (1) {
// Other operations or program logic can be added here
}
}

7#Step — Simulates a Marquee on the LCD (to the right):

Code 7:

/*
Code 7: Simulates a Marquee on the LCD (to the right)
MCU: PIC16F877A
Dev.Board: PIC-DIP40 - UNINTER - VERSION 2
Oscillator: 4M
Ext. Modules: PIC KIT 3 - MICROCHIP
Date: AUG/2023
*/

#include <xc.h>
#include "lcd.h" // Include library for LCD
#include <pic16f877a.h> // Include the library for PIC16F877A

// Configuration of the PIC16F877A configuration bits
#pragma config FOSC = HS // External oscillator in HS mode (High Speed)
#pragma config WDTE = OFF // Watchdog Timer disabled
#pragma config PWRTE = OFF // Power-up Timer disabled
#pragma config BOREN = ON // Brown-out Reset enabled
#pragma config LVP = OFF // Low voltage programming disabled (high Vpp)

#define _XTAL_FREQ 4000000 // Oscillator frequency (4 MHz)

// function prototype
void writeWord(char *word);
int stringLength(char *str);
void LCD_shift_right(char *word);

void writeWord(char *word) { // Function to write a word on the LCD
while (*word != '\0') {
LCD_write(*word);
word++;
}
}

// Custom function to calculate string length
int stringLength(char *str) {
int len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
// Function to animate the letters to the right in the display
void LCD_shift_right(char *word) {
int len = stringLength(word); // Calculate the word length
int i, j;
// Loop to shift characters
for (i = 0; i < len + 16; i++) {
LCD_line1(); // Position the cursor on the first line, first column
for (j = 0; j < 16; j++) {
// Shift characters to the right
LCD_write(i + j < len ? word[i + j] : ' '); // Show word character or white space
}
__delay_ms(1); // Delay to control animation speed
}
}

void main() {
// LCD initialization
LCD_init();
// First line: "Your Name and Id: 1234567"
LCD_line1(); // Position the cursor on the first line, first column
LCD_shift_right("Your Name");

while (1) {
// Other operations or program logic can be added here
}
}

8#Bonus Code— Display the ADC reading on the LCD.

#include <xc.h>
#include <stdio.h>
#include "lcd.h"
#include <pic16f877a.h>

#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = ON
#pragma config LVP = OFF

#define _XTAL_FREQ 4000000

void writeWord(char *word) {
while (*word != '\0') {
LCD_write(*word);
word++;
}
}

void ADC_init() {
ADCON0 = 0x81;
ADCON1 = 0x80;
}

unsigned int ADC_read(unsigned int channel) {
unsigned int reading;
ADCON0 &= 0xC5; // 11000101, clear channels' bits
ADCON0 |= (channel << 3); // Set channel now
GO_nDONE = 1;
while (GO_nDONE);
// Retrieve the converted digital value
reading = ((ADRESH << 8) + (int)ADRESL); // Combine ADRESH and ADRESL for a 10-bit result
return reading;
}

void main() {
unsigned int reading;
char buffer[8]; // Buffer to hold the formatted ADC reading

ADC_init();
LCD_init();
// Clear the LCD before each new reading
LCD_clear();
LCD_line1();
writeWord("--ADC Reading--");

while (1) {


reading = ADC_read(0);
LCD_line2();
// Format the ADC reading as a two-digit number
//sprintf(buffer, "%u.%03u", reading / 1000, reading % 1000);
sprintf(buffer, "%02u", reading);
// Write the formatted string to the LCD
writeWord(buffer);
writeWord(" "); // Clear line2 before each new reading
}
}

Authors

@linkedin

@GitHub

Appendix

Installing MPLABX — Complete Screencast — For your Convenience

The initial screen for MPLABX IDE v6.10
Accepting the terms…
Next…
Select these three options (do not forget MPLAB IPE)
Read and just click ok…
Go to this site and download PicKit3 standalone program — If the drivers didn't work…
This is the welcome page for MPLABX v6.10

8 Fuses - FOSC, WDT, BOR, PWRT, LVP, CP, CPD, WRT:

In the context of microcontrollers and
other programmable devices,
fuses (also known as configuration bits)
are special settings that define various
hardware and software configurations.

These fuses are typically programmed during
the manufacturing process or when the
microcontroller is initially programmed.

Fuses are used to configure different
aspects of the microcontroller's behavior,
such as its clock source,
power-up behavior,
memory protection settings,
Brown-out Reset (BOR) settings,
Watchdog Timer (WDT) settings, and more.

The specific configurations available
and the number of fuses vary depending
on the microcontroller model.

Once programmed,
the fuse settings are non-volatile,
meaning they retain their values
even when power is removed
from the microcontroller.

As a result, careful consideration
is required when setting the fuses,
as changing them afterward might
not be as straightforward
as modifying the main program code.

Some common fuse settings you might
encounter in microcontrollers include:

1. Oscillator Selection (FOSC):
Configures the clock source for
the microcontroller (MC),
such as an external crystal,
internal oscillator,
or external clock.
We're using HS:
(<25M, if greater, it would be XPL).
#pragma config FOSC = HS

2. Watchdog Timer (WDT):
Enables or disables the WDT
and sets its timeout period.
WDT stands for Watchdog Timer.
It is a hardware component found
in many MCs and other embedded systems.
The primary purpose of the Watchdog Timer
is to provide a mechanism for
detecting and recovering from
system malfunctions or software errors.
The WDT operates as a separate
timer from the main system clock
and operates independently of
the main program execution.
Its main function is to monitor
the system's operation and reset
the MC if it detects
any anomalies or malfunctions.
The software can usually configure
the timeout period of the Watchdog Timer.
This determines how long the system has
to "pet" or "feed" the Watchdog Timer
before it reaches the timeout.
We are using WDT desabled:
#pragma config WDTE = OFF

3. Brown-out Reset (BOR):
Configures the voltage level at which
the MC resets to prevent
erratic behavior during power
fluctuations. It is a built-in safety
feature in many MC, including PIC devices.
Its purpose is to monitor the supply
voltage level and reset the MC when the
voltage drops bellow a certain threshold.
Often used if power may be
less predictable or prone to fluctuations.
We are using BOR desabled:
#pragma config BOREN = OFF

4 . Power-up Timer (PWRT):
Configures the delay after power-up before
the MC starts executing code.
It serves the purpose of introducing
a delay during the device's
power-up sequence. It ensures
that the device's internal
oscillators and other critical
components stabilize and become
reliable before the MC starts
executing the main program.
We are using PWRT desable:
#pragma config PWRTE = OFF

5. Low-Voltage Programming (LVP):
Enables or disables low-voltage programming
mode, which allows the MC to be programmed
using a lower programming voltage (LVP).
The LVP is a programming method
for PIC MC that allow the device to
be programmed using lower voltage level
(typically around 2 to 5 volts) than the
normal operation voltage. It is used when
high-voltage programming (typically 12-14 volts)
is not available or not desired.
We are using LVP desabled (Pickit3 provides ~12 v):
#pragma config LVP = OFF

6. Code Protection (CP):
Protects the MC's Program Memory (ROM) from
being read or copied. It saveguard the
intellectual property and prevent
unauthorized access to the program memory.
This helps protect your code from being
copied, analysed, or tempered with by
external entities.
We are using CP desabled:
#pragma config CP = OFF

7. Data Code Protection (CPD):
Prevents unauthorized read and write
access to the Data Memory (RAM) and
the Program Memory (ROM) contents. If
tried result in a reset signal.
We are using CPD desabled:
#pragma config CPD = OFF

8. Flash Memory Write Protection (WRT):
As we are desabled this feature
this means the program memory (FLASH)
can be freely written to,
Modified, or erased during the program's
execution. It allows for code modifications
and quick iterations:
#pragma WRT = OFF

Fuses are crucial in setting up the MC's
initial operating conditions and behavior,
and their values should be carefully chosen
to ensure proper and reliable operation of
the device. Incorrect fuse settings can lead
to unintended behavior or even prevent the
MC from functioning correctly.

AND & OR (ADC conversion code discussion)

       and                 or

XXXX XXXX XXXX XXX (choose 0 or 1...)
(&) 0000 1111 (|) 0000 1111
--------- ---------
(O) 0000 0000 0000 1111 (...and see the result options)
(P)
(T)
(I) dont //// //// dont
(O)
(N) care 1111 1111 care
(S)

mask to clear { and + 0 -> 0}
mask to set { or + 1 -> 1}

This means that if you use:
AND + 0 you are saying : CLEAR (RESET) THE BIT!
AND + 1 you are saying : DON'T CARE!


Otherwise, if you use:
OR + 0 you are saying : DON'T CARE!
OR + 1 you are saying : SET THE BIT!


Example:
bits index:
[7] [6] [5] [4] [3] [2] [1] [0]

Suppose this method:

void ADC_init(){
ADCON0 = 0x81;
// Other initialization code,
// if any
...
}

Latter, in another method:

ADC_read(unsigned int channel)){
ADCON0 &= 0xC5;
ADCON0 |= (channel << 3)
// Other ADC conversion code
// if any
// Return the ADC result
// if needed
...
}


The two methods provided are related
to using the Analog-to-Digital Converter
(ADC) module in a microcontroller. The ADC
allows the microcontroller to convert
analog input signals (e.g., from sensors
or other analog sources) into digital values
that can be processed by the digital
circuitry of the microcontroller.

1. `void ADC_init()`

This method is used to initialize the ADC
module in the microcontroller. Let's go
through the code:

The line `ADCON0 = 0x81;` sets the
ADCON0 register to the value `0x81`.
In this context, the ADCON0 register
contains control bits that configure
the ADC module. The binary
representation of `0x81` is `10000001`.
Breaking down this binary value:

[7] [6] [5] [4] [3] [2] [1] [0]
1 0 0 0 0 0 0 1 (`0x81`)

- Bit 7 (ADON): Set to 1 to enable the ADC module.
- Bit 6 (Unimplemented): This bit is unimplemented
in the PIC16F877A and must
be kept at 0.
- Bit 5-4-3 (CHS3:CHS2:CHS0): The channel selection bits.
They are set to 000,
indicating that the ADC is configured
to use channel 0 as the
input channel initially.
- Bit 2 (GO/DONE): This bit is used to start the
ADC conversion. It is set to 0 initially,
indicating no conversion is in progress.
- Bit 1 (Unimplemented): This bit is unimplemented in
the PIC16F877A and must be kept at 0.
- Bit 0 (ADCS): This is the ADC clock selection bit.
It is set to 1 in this case,
using the Fosc/32 clock source
for the ADC conversion.

Overall, `ADCON0 = 0x81;` initializes the ADC module
to enable it, set the initial input channel to channel 0,
and configure the ADC clock source.

2. `ADC_read(unsigned int channel)`

This method is used to read the analog value from
a specific ADC channel. The input parameter `channel`
indicates which ADC channel to read.
Let's go through the code:

The two lines within this method manipulate the
`ADCON0` register to select the desired ADC channel:

[7] [6] [5] [4] [3] [2] [1] [0]
1 1 0 0 0 1 0 1 (`0xC5`)

- `ADCON0 &= 0xC5;`: This bitwise AND operation clears
specific bits in the `ADCON0` register.
The binary representation of `0xC5` is `11000101`.
The bits being cleared are:
- Bit 1(Unimplemented): by setting it to 0.
- Bit 5-4-3 (CHS3:CHS2:CHS0): These clear the channel
selection bits, setting them to 000.
The bits being ignored are (see previous item):
- Bits 0-2-6-7: DON'T CARE! already been set.

- `ADCON0 |= (channel << 3);`: This bitwise OR operation
sets specific bits in the `ADCON0` register based on the
`channel` input parameter. The value of `channel` is
left-shifted by 3 positions, as the channel
selection bits start at bit 3 of `ADCON0`.
This action sets the appropriate
bits to select the desired ADC channel.

After these operations, the `ADCON0` register
is properly configured to select the desired
ADC channel for the upcoming ADC conversion.

The code snippet does not contain the actual
ADC conversion process and result retrieval,
as that part is specific to the microcontroller
and ADC library being used.
The returned value (if any) would typically
represent the digital value obtained from
the analog input signal
on the specified ADC channel.

Hope that helps!
What is the diferrence between 
set x reset
clear x don't care?

In the context of digital electronics
and microcontrollers,"set," "reset,"
"clear," and "don't care" are terms
used to describe the states of individual
bits or signals in registers, memory
locations, or control logic.

These terms refer to the actions or
conditions that can be applied to these
bits to change their values or behavior.

Let's define each term:

Set: Setting a bit means changing
its value from 0 to 1.
It "sets" the bit to 1. Typically,
this action is done
to enable or activate
a particular function or feature.

Reset: Resetting a bit means changing
its value from 1 to 0.
It "resets" the bit to 0.
This action is commonly used
to disable or deactivate a
specific function or to
initialize a component or register
to its default state.

Clear: Clearing a bit is similar to
resetting it, And the terms
are often used interchangeably.
It means changing the
bit's value from 1 to 0,
just like in the case of resetting.

Don't Care: "Don't care" refers to a
situation in which the value
of a particular bit is irrelevant
or inconsequential. It indicates
that the value of the bit can
be either 0 or 1, and it does not
affect the system's behavior
or operation.

These terms are commonly encountered
when working with control registers,
configuration bits, and flags in microcontrollers
or digital circuits. By manipulating these
bits using set, reset, or clear operations,
developers can controlthe behavior of the
microcontroller or digital system.
Additionally, there are cases where
certain bits in registers may not be
used or have no impact on the
current operation, and their values
are considered "don't care."

Understanding the states of individual bits
is essential for proper configuration
and programming of microcontrollers
and other digital systems. It ensures
that the systemoperates as intended and
takes advantage of the various features
and functionalities provided by the hardware.
FLOATING PIN - Set Pull-Up Resistor 

(Codes 2 and 4).

When using RB0 / RB1 as an input for the
button (Codes 2 and 4),
it's essential to enable
the internal pull-up resistor
to avoid floating input issues.

To update the code to set the
internal pull-up resistor for PORTB,
TYPE:

// Enable pull-up for RB0
OPTION_REGbits.nRBPU = 0;

We added the line OPTION_REGbits.nRBPU = 0;
to enable the pull-up resistor for RB0-7.

With the internal pull-up enabled,
the button will read logic high (1)
when it's not pressed,
and logic low (0) when it's pressed,
as expected for the code logic.

The LEDs will still light up when
the button is pressed.

License

MIT

This is my setup! 😘

Related Posts

00#Episode — PIC_Series — PIC 16–7 Awesome MPLABX Projects! — Reviewing C Language Using MPLABX with PIC16F877A (this one)

01#Episode — PIC_Series — 8-bit Microcontroller MEMORY — Harvard Architecture — Separate Program & Data Memory Spaces

--

--

J3
Jungletronics

Hi, Guys o/ I am J3! I am just a hobby-dev, playing around with Python, Django, Ruby, Rails, Lego, Arduino, Raspy, PIC, AI… Welcome! Join us!