<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PIC Tutorials | Teach Me Microcontrollers</title>
	<atom:link href="https://www.teachmemicro.com/category/tutorials/pic-tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.teachmemicro.com/category/tutorials/pic-tutorial/</link>
	<description>Microcontroller Tutorials and Resources</description>
	<lastBuildDate>Sun, 28 Jun 2026 01:44:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.3</generator>

<image>
	<url>https://www.teachmemicro.com/wp-content/uploads/2019/04/blue-icon-65x65.png</url>
	<title>PIC Tutorials | Teach Me Microcontrollers</title>
	<link>https://www.teachmemicro.com/category/tutorials/pic-tutorial/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to Program a PIC Microcontroller Using an Arduino</title>
		<link>https://www.teachmemicro.com/how-to-program-a-pic-microcontroller-using-an-arduino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=how-to-program-a-pic-microcontroller-using-an-arduino</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Mon, 13 Oct 2025 01:00:33 +0000</pubDate>
				<category><![CDATA[PIC Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=9416</guid>

					<description><![CDATA[<p>Programming PIC microcontrollers usually requires specialized hardware programmers like the PICkit series. But what if you don’t have one? Thanks to open-source projects like a-p-prog, you can turn an Arduino Uno or Nano into a PIC programmer that works over the In-Circuit Serial Programming (ICSP) interface. In this tutorial, we’ll walk through the steps to &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/how-to-program-a-pic-microcontroller-using-an-arduino/">How to Program a PIC Microcontroller Using an Arduino</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Programming PIC microcontrollers usually requires specialized hardware programmers like the PICkit series. But what if you don’t have one? Thanks to open-source projects like <a rel="noopener" target="_new" class="decorated-link" href="https://github.com/embhobbb/a-p-prog">a-p-prog<span aria-hidden="true" class="ms-0.5 inline-block align-middle leading-none"><svg width="20" height="20" viewbox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" data-rtl-flip="" class="block h-[0.75em] w-[0.75em] stroke-current stroke-[0.75]"><path d="M14.3349 13.3301V6.60645L5.47065 15.4707C5.21095 15.7304 4.78895 15.7304 4.52925 15.4707C4.26955 15.211 4.26955 14.789 4.52925 14.5293L13.3935 5.66504H6.66011C6.29284 5.66504 5.99507 5.36727 5.99507 5C5.99507 4.63273 6.29284 4.33496 6.66011 4.33496H14.9999L15.1337 4.34863C15.4369 4.41057 15.665 4.67857 15.665 5V13.3301C15.6649 13.6973 15.3672 13.9951 14.9999 13.9951C14.6327 13.9951 14.335 13.6973 14.3349 13.3301Z"></path></svg></span></a>, you can turn an Arduino Uno or Nano into a PIC programmer that works over the In-Circuit Serial Programming (ICSP) interface.</p>
<p>In this tutorial, we’ll walk through the steps to use an Arduino as a PIC programmer, upload code, and troubleshoot common issues.</p>
<p><span id="more-9416"></span></p>
<hr />
<h3>Why Use an Arduino to Program PICs?</h3>
<ul>
<li><strong>Low cost:</strong> Any spare Arduino Uno, Nano, or Pro Mini will do.</li>
<li><strong>Simplicity:</strong> Just a handful of jumper wires.</li>
<li><strong>Flexibility:</strong> Works with a wide range of popular 8-bit PIC microcontrollers.</li>
<li><strong>Open-source:</strong> The firmware and host software are freely available and regularly tested.</li>
</ul>
<hr />
<h3>What You’ll Need</h3>
<p><strong>Hardware</strong></p>
<ul>
<li>Arduino Uno/Nano/Pro Mini (ATmega328P-based)</li>
<li>Target PIC microcontroller (e.g., PIC16F1829, PIC12F1840 — see supported list)</li>
<li>Breadboard or target board with ICSP pins</li>
<li>Jumper wires</li>
<li>Optional: 470–1 kΩ resistors (recommended if the target is self-powered or uses 3.3 V logic)</li>
<li>USB cable for Arduino</li>
</ul>
<p><strong>Software</strong></p>
<ul>
<li>Arduino IDE</li>
<li><em>pp3</em> host utility (from the <em>a-p-prog</em> repo)</li>
<li>A compiler toolchain for PIC (e.g., MPLAB X + XC8, SDCC) to generate <em>.hex</em> files</li>
</ul>
<hr />
<h3>Step 1: Wiring Arduino to PIC (ICSP)</h3>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2025/09/arduino-pic-programmer-1.avif"><img data-dominant-color="9db8bb" data-has-transparency="false" style="--dominant-color: #9db8bb;" decoding="async" src="https://www.teachmemicro.com/wp-content/uploads/2025/09/arduino-pic-programmer-1-1024x594.avif" alt="" width="618" height="358" class="aligncenter size-large wp-image-9421 not-transparent" srcset="https://www.teachmemicro.com/wp-content/uploads/2025/09/arduino-pic-programmer-1-1024x594.avif 1024w, https://www.teachmemicro.com/wp-content/uploads/2025/09/arduino-pic-programmer-1-300x174.avif 300w, https://www.teachmemicro.com/wp-content/uploads/2025/09/arduino-pic-programmer-1-768x445.avif 768w, https://www.teachmemicro.com/wp-content/uploads/2025/09/arduino-pic-programmer-1.avif 1380w" sizes="(max-width: 618px) 100vw, 618px" /></a></p>
<p>The Arduino acts as an ICSP programmer using three main pins:</p>
<div class="_tableContainer_1rjym_1">
<div class="group _tableWrapper_1rjym_13 flex w-fit flex-col-reverse" tabindex="-1">
<table class="w-fit min-w-(--thread-content-width)">
<thead>
<tr>
<th data-col-size="sm">Arduino Pin</th>
<th data-col-size="sm">PIC Pin</th>
<th data-col-size="sm">Function</th>
</tr>
</thead>
<tbody>
<tr>
<td data-col-size="sm"><strong>A3</strong></td>
<td data-col-size="sm">MCLR</td>
<td data-col-size="sm">Reset / programming entry</td>
</tr>
<tr>
<td data-col-size="sm"><strong>A1</strong></td>
<td data-col-size="sm">PGD</td>
<td data-col-size="sm">Programming Data</td>
</tr>
<tr>
<td data-col-size="sm"><strong>A0</strong></td>
<td data-col-size="sm">PGC</td>
<td data-col-size="sm">Programming Clock</td>
</tr>
<tr>
<td data-col-size="sm"><strong>GND</strong></td>
<td data-col-size="sm">GND</td>
<td data-col-size="sm">Common ground</td>
</tr>
<tr>
<td data-col-size="sm"><strong>5V</strong></td>
<td data-col-size="sm">VDD</td>
<td data-col-size="sm">Optional power (if PIC runs at 5V)</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> If your target board is already powered, or runs at 3.3 V, add <strong>470–1 kΩ resistors</strong> in series with MCLR/PGC/PGD. This prevents back-power issues.</p>
<hr />
<h3>Step 2: Flash the Arduino Programmer Firmware</h3>
<ol>
<li>Clone or download the <a rel="noopener" target="_new" class="decorated-link" href="https://github.com/embhobbb/a-p-prog">a-p-prog repository<span aria-hidden="true" class="ms-0.5 inline-block align-middle leading-none"><svg width="20" height="20" viewbox="0 0 20 20" fill="currentColor" xmlns="http://www.w3.org/2000/svg" data-rtl-flip="" class="block h-[0.75em] w-[0.75em] stroke-current stroke-[0.75]"><path d="M14.3349 13.3301V6.60645L5.47065 15.4707C5.21095 15.7304 4.78895 15.7304 4.52925 15.4707C4.26955 15.211 4.26955 14.789 4.52925 14.5293L13.3935 5.66504H6.66011C6.29284 5.66504 5.99507 5.36727 5.99507 5C5.99507 4.63273 6.29284 4.33496 6.66011 4.33496H14.9999L15.1337 4.34863C15.4369 4.41057 15.665 4.67857 15.665 5V13.3301C15.6649 13.6973 15.3672 13.9951 14.9999 13.9951C14.6327 13.9951 14.335 13.6973 14.3349 13.3301Z"></path></svg></span></a>.</li>
<li>Open Arduino IDE.</li>
<li>Load the sketch from <em>fw/pp/pp.ino</em>.</li>
<li>Select your Arduino board and COM port, then <strong>Upload</strong>.</li>
</ol>
<p>At this point, your Arduino is no longer a normal Arduino — it’s a PIC programmer.</p>
<hr />
<h3>Step 3: Build the Host Tool</h3>
<p>The host software, <em>pp3</em>, runs on your PC and sends commands to the Arduino over USB.</p>
<p>On <strong>Linux/macOS</strong>:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">gcc -Wall pp3.c -o pp3</code></pre></pre>
</div>
<p>On <strong>Windows</strong> (using MinGW):</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">gcc -Wall pp3.c -o pp3.exe</code></pre></pre>
</div>
<p>Or simply use the prebuilt <em>pp3.exe</em> included in the repo.</p>
<p>Keep the file <em>pp3_devices.dat</em> in the same folder as <em>pp3</em> — it contains the device database.</p>
<hr />
<h3>Step 4: Test Communication</h3>
<p>Before flashing your firmware, test if the Arduino can talk to your PIC:</p>
<p><strong>Linux/macOS</strong>:</p>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">./pp3 -c /dev/ttyACM0 -p -n -t 16f1829</code></pre></pre>
</div>
<p><strong>Windows</strong>:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">pp3.exe -c COM7 -p -n -t 16f1829</code></pre></pre>
</div>
</div>
<p>Replace <em>16f1829</em> with your target device name.</p>
<p>Expected output:</p>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="sticky top-9">
<div class="absolute end-0 bottom-0 flex h-9 items-center pe-2">
<div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">Opening serial port 
Device ID 0x27E4 
Releasing MCLR</code></pre></pre>
</div>
</div>
</div>
</div>
</div>
<hr />
<h3>Step 5: Program Your HEX File</h3>
<p>Now flash your compiled PIC firmware (<em>firmware.hex</em>).</p>
<p><strong>Linux/macOS</strong>:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">./pp3 -c /dev/ttyACM0 -t 16f1829 firmware.hex</code></pre></pre>
</div>
<p><strong>Windows</strong>:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">pp3.exe -c COM7 -t 16f1829 firmware.hex</code></pre></pre>
</div>
<p>If successful, you’ll see programming and verification messages for FLASH and config memory.</p>
<hr />
<h3>Step 6: Troubleshooting</h3>
<p><strong>Problem:</strong> <em>Device ID reads 0x0000</em></p>
<ul>
<li>Check wiring (PGC <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> A0, PGD <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> A1, MCLR <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> A3).</li>
<li>Ensure target power and common ground are connected.</li>
<li>Try adding a bootloader delay:</li>
</ul>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="overflow-y-auto p-4" dir="ltr">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-bash" data-lang="Bash"><pre><code class="language-cpp">pp3.exe -c COM7 -s 1700 -t 16f1829 firmware.hex</code></pre></pre>
</div>
</div>
</div>
<p><strong>Problem:</strong> <em>Verify failed</em></p>
<ul>
<li>Add series resistors.</li>
<li>Shorten jumper wires.</li>
<li>Confirm the correct device name (<em>-t</em>).</li>
</ul>
<p><strong>Problem:</strong> <em>No COM port</em></p>
<ul>
<li>On Windows, check Device Manager for COM port.</li>
<li>On Linux/macOS, your device may appear as <em>/dev/ttyUSB0</em> or<em> /dev/ttyACM0</em>.</li>
</ul>
<hr />
<h3>Supported PIC Devices</h3>
<p>The project supports many 8-bit PIC microcontrollers, including:</p>
<ul>
<li>PIC12F1822 / 12F1840 / 12F1501 / 12F1612</li>
<li>PIC16F1455 / 16F1503 / 16F1507 / 16F1509</li>
<li>PIC16F1829 (tested extensively)</li>
<li>And more (see repo for full list)</li>
</ul>
<hr />
<h3>Tips for Reliable Programming</h3>
<ul>
<li>Keep your wiring short.</li>
<li>Always share ground between Arduino and target.</li>
<li>Use external power for large boards.</li>
<li>Add <em>-v 1</em> to <em>-v 4</em> to increase verbosity for debugging.</li>
</ul>
<hr />
<h3>Conclusion</h3>
<p>Using an Arduino as a PIC programmer is a cost-effective and educational alternative to commercial tools. With just a few jumper wires, the open-source firmware, and the <em>pp3</em> host utility, you can program many popular PIC microcontrollers right from your computer.</p>
<p>Whether you’re experimenting with PICs for the first time or just need a quick DIY programmer, this method is reliable, flexible, and well-documented by the community.</p>
<p>The post <a href="https://www.teachmemicro.com/how-to-program-a-pic-microcontroller-using-an-arduino/">How to Program a PIC Microcontroller Using an Arduino</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using a 16x2 Monochrome LCD with the PIC16F84A (Assembly Tutorial)</title>
		<link>https://www.teachmemicro.com/using-a-16x2-monochrome-lcd-with-the-pic16f84a-assembly-tutorial/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-a-16x2-monochrome-lcd-with-the-pic16f84a-assembly-tutorial</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Wed, 24 Sep 2025 00:48:52 +0000</pubDate>
				<category><![CDATA[PIC Projects]]></category>
		<category><![CDATA[PIC Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=9316</guid>

					<description><![CDATA[<p>Introduction A 16x2 monochrome LCD module is a widely used display in microcontroller projects. It can show two lines of text, each up to 16 characters long, making it ideal for simple user interfaces. These LCDs are based on the HD44780 controller (or compatible), which accepts commands and data via an 8-bit or 4-bit parallel &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/using-a-16x2-monochrome-lcd-with-the-pic16f84a-assembly-tutorial/">Using a 16x2 Monochrome LCD with the PIC16F84A (Assembly Tutorial)</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3><strong>Introduction</strong></h3>
<p>A 16x2 monochrome LCD module is a widely used display in microcontroller projects. It can show <strong>two lines of text, each up to 16 characters long</strong>, making it ideal for simple user interfaces. These LCDs are based on the <strong>HD44780 controller (or compatible)</strong>, which accepts commands and data via an 8-bit or 4-bit parallel interface.</p>
<p>The LCD works by receiving control signals (RS, R/W, E) and data signals (D0–D7 or D4–D7 for 4-bit mode). In this tutorial, we’ll use <strong>8-bit mode</strong> for simplicity. The PIC16F84A will send initialization commands to the LCD, followed by ASCII characters to be displayed.</p>
<p>Understanding the control lines:</p>
<ul>
<li><strong>RS (Register Select):</strong>
<ul>
<li>0 = Instruction/command (e.g., clear display).</li>
<li>1 = Data (character to display).</li>
</ul>
</li>
<li><strong>R/W (Read/Write):</strong>
<ul>
<li>0 = Write to LCD.</li>
<li>1 = Read from LCD (rarely needed, we’ll keep it  0.</li>
</ul>
</li>
<li><strong>E (Enable):</strong>
<ul>
<li>A high-to-low pulse latches the data/command into the LCD.</li>
</ul>
</li>
</ul>
<p>Once initialized, the LCD can display text by sending ASCII codes as data.</p>
<hr />
<h3><strong>Materials</strong></h3>
<ul>
<li>PIC16F84A microcontroller</li>
<li>16x2 HD44780-based monochrome LCD module</li>
<li>4 MHz crystal oscillator + 2 × 22pF capacitors</li>
<li>10kΩ potentiometer (for LCD contrast adjustment)</li>
<li>Breadboard and jumper wires</li>
<li>5V regulated power supply</li>
</ul>
<hr />
<h3><strong>Code (Assembly for PIC16F84A)</strong></h3>
<p>We’ll walk through the full code, then explain each part.</p>
<h4><strong>Full Program</strong></h4>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">;===========================================================
; Program: LCD 16x2 Display with PIC16F84A
;===========================================================

    list p=16F84A
    include &lt;p16f84a.inc&gt;

    __CONFIG _FOSC_HS &amp; _WDTE_OFF &amp; _PWRTE_ON &amp; _CP_OFF

;-------------------------------
; Pin connections
; LCD Data -&gt; PORTB
; RS -&gt; RA0
; RW -&gt; RA1 (tied low, write only)
; EN -&gt; RA2
;-------------------------------

    cblock 0x20
        temp
    endc

;-------------------------------
; Reset vector
;-------------------------------
    org 0x00
    goto main

;-------------------------------
; Subroutines
;-------------------------------
delay_ms
    movlw   d&#039;250&#039;
    movwf   temp
d1  nop
    nop
    decfsz  temp, f
    goto d1
    return

lcd_pulse
    bsf     PORTA,2      ; E=1
    call    delay_ms
    bcf     PORTA,2      ; E=0
    call    delay_ms
    return

lcd_cmd
    bcf     PORTA,0      ; RS=0
    movwf   PORTB        ; Send command
    call    lcd_pulse
    return

lcd_data
    bsf     PORTA,0      ; RS=1
    movwf   PORTB        ; Send data
    call    lcd_pulse
    return

lcd_init
    ; Function Set: 8-bit, 2 line, 5x8 font
    movlw   0x38
    call    lcd_cmd

    ; Display ON, Cursor OFF
    movlw   0x0C
    call    lcd_cmd

    ; Clear display
    movlw   0x01
    call    lcd_cmd

    ; Entry mode: auto-increment
    movlw   0x06
    call    lcd_cmd
    return

;-------------------------------
; Main Program
;-------------------------------
main
    bsf     STATUS, RP0
    movlw   0x00
    movwf   TRISB       ; PORTB = output
    movlw   0xF8
    movwf   TRISA       ; RA0-RA2 output, RA3-RA4 input
    bcf     STATUS, RP0

    call    lcd_init

    ; Write &quot;HELLO&quot;
    movlw   &#039;H&#039;
    call    lcd_data
    movlw   &#039;E&#039;
    call    lcd_data
    movlw   &#039;L&#039;
    call    lcd_data
    movlw   &#039;L&#039;
    call    lcd_data
    movlw   &#039;O&#039;
    call    lcd_data

endless
    goto endless

    end</code></pre></pre>
</div>
<p><strong><a class="sim-btn" href="https://picsimulator.com/?example=lcd-hello" target="_blank" rel="noopener" aria-label="Open LCD Hello example in PICSimulator"><img loading="lazy" decoding="async" class="sim-icon" src="https://picsimulator.com/favicon.png" width="20" height="20" style="width: 20px; height: 20px; vertical-align: middle; margin-right: 5px;" data-wp-editing="1" />Simulate this code in PICSimulator</a></strong></p>
<h3>Code Explanation</h3>
<h4><strong>1. Configuration and Setup</strong></h4>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">list p=16F84A
    include &lt;P16F84A.inc&gt;
    __CONFIG _FOSC_HS &amp; _WDTE_OFF &amp; _PWRTE_ON &amp; _CP_OFF</code></pre></pre>
</div>
</div>
<ul>
<li>Sets processor type and includes the register definitions.</li>
<li>Configures the microcontroller for <strong>High-Speed crystal oscillator</strong>, <strong>watchdog timer off</strong>, <strong>power-up timer on</strong>, and <strong>code protection off</strong>.</li>
</ul>
<h4><strong>2. LCD Pin Mapping</strong></h4>
<ul>
<li><strong>PORTB</strong> is used for LCD data (D0–D7).</li>
<li><strong>RA0 = RS</strong>, <strong>RA1 = R/W (grounded)</strong>, <strong>RA2 = E</strong>.</li>
<li>Only writing to the LCD is needed, so R/W is tied to ground.</li>
</ul>
<h4><strong>3. Delay Routine</strong></h4>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">delay_ms
    movlw d&#039;250&#039;
    movwf temp
d1: decfsz temp, f
    goto d1
    return</code></pre></pre>
</div>
</div>
<p>A simple software delay loop to let the LCD process commands.</p>
<h4><strong>4. LCD Enable Pulse</strong></h4>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">lcd_pulse
    bsf PORTA,2   ; E=1
    call delay_ms
    bcf PORTA,2   ; E=0
    call delay_ms
    return</code></pre></pre>
</div>
</div>
<p>The LCD latches commands/data on the <strong>falling edge of E</strong>.</p>
<h4><strong>5. Sending Commands and Data</strong></h4>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">lcd_cmd
    bcf PORTA,0   ; RS=0 (command)
    movwf PORTB
    call lcd_pulse
    return</code></pre></pre>
</div>
</div>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">lcd_data
    bsf PORTA,0   ; RS=1 (data)
    movwf PORTB
    call lcd_pulse
    return</code></pre></pre>
</div>
</div>
<p>These subroutines separate <strong>instructions (clear, cursor)</strong> from <strong>characters (ASCII)</strong>.</p>
<h4><strong>6. LCD Initialization</strong></h4>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">movlw 0x38   ; Function set: 8-bit, 2-line, 5x8 font
movlw 0x0C   ; Display ON, cursor OFF
movlw 0x01   ; Clear display
movlw 0x06   ; Entry mode: auto-increment</code></pre></pre>
</div>
</div>
<p>These commands are required at startup to prepare the LCD.</p>
<h4><strong>7. Writing Text</strong></h4>
<div class="contain-inline-size rounded-2xl relative bg-token-sidebar-surface-primary">
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-plain" data-lang="Plain Text"><pre><code class="language-cpp">movlw &#039;H&#039;
call lcd_data</code></pre></pre>
</div>
</div>
<p>Each ASCII character is written sequentially to the LCD.</p>
<hr />
<h3><strong>Conclusion</strong></h3>
<p>In this tutorial, we connected a <strong>16x2 monochrome LCD</strong> to a <strong>PIC16F84A microcontroller</strong> using an <strong>8-bit parallel interface</strong>. We wrote initialization and display routines in <strong>assembly</strong>, giving full control of the LCD at a low level.</p>
<p>This project demonstrates how to:</p>
<ul>
<li>Initialize the LCD in 8-bit mode.</li>
<li>Send commands and data separately.</li>
<li>Display custom strings of text.</li>
</ul>
<p>With this foundation, you can extend the program to display sensor data, menu options, or real-time feedback for embedded projects.</p>
<p>The post <a href="https://www.teachmemicro.com/using-a-16x2-monochrome-lcd-with-the-pic16f84a-assembly-tutorial/">Using a 16x2 Monochrome LCD with the PIC16F84A (Assembly Tutorial)</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Use Lookup Tables in PIC Assembly</title>
		<link>https://www.teachmemicro.com/use-lookup-tables-pic-assembly/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=use-lookup-tables-pic-assembly</link>
					<comments>https://www.teachmemicro.com/use-lookup-tables-pic-assembly/#comments</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Fri, 21 Jun 2019 08:27:38 +0000</pubDate>
				<category><![CDATA[PIC Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=3581</guid>

					<description><![CDATA[<p>Programming a microcontroller in assembly languages takes time and to reduce that time, embedded systems engineers often have tricks up their sleeves. One of those tricks is the use of lookup tables. In this post, I will share how I use lookup tables in assembly language for the PIC16F84A microcontroller. The RETLW Opcode Lookup tables &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/use-lookup-tables-pic-assembly/">How to Use Lookup Tables in PIC Assembly</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Programming a microcontroller in assembly languages takes time and to reduce that time, embedded systems engineers often have tricks up their sleeves. One of those tricks is the use of lookup tables. In this post, I will share how I use lookup tables in assembly language for the <a href="https://www.win-source.net/products/detail/microchip-technology/pic16f84a-04i-p.html">PIC16F84A</a> microcontroller.</p>
<p><span id="more-3581"></span></p>
<h3><strong>The RETLW Opcode</strong></h3>
<p>Lookup tables are possible in assembly primarily because of the RETLW opcode. This instruction means “return with a literal in w” and is used like this:</p>
<pre class="lang:asm decode:true"><pre><code class="language-cpp">RETLW 0x04</code></pre></pre>
<p>Here, 0x04 is the literal value placed inside the W register before returning. Since the opcode returns to something, it is usually inside a subroutine.</p>
<p>Take note that RETLW reads the stack for the address to which to return. So a GOTO followed by RETLW will result in a stack underflow error.</p>
<h3>Lookup Table Example</h3>
<p>The most common lookup table is the one for seven segment displays. Frugal engineers don’t want to use decoders in using seven segment displays and so connect them directly to PIC pins. A lookup table is used to convert the numbers to their equivalent for seven segment displays.</p>
<p>Below is an example table:</p>
<pre class="lang:asm decode:true"><pre><code class="language-cpp">table addwf PC
      retlw b’00111111’
      retlw b’00000110’
      retlw b’01011011’
      retlw b’01001111’
      retlw b’01100110’
      retlw b’01101101’
      retlw b’01111100’
      retlw b’00000111’
      retlw b’01111111’
      retlw b’01100111’</code></pre></pre>
<p>The binaries in this code are the seven-segment equivalent for digits zero to nine, assuming a common cathode displays and LSB at segment ‘a’.</p>
<p>Now if I want to display the digit seven (connected to PORTB), for example, I would do it like this:</p>
<pre class="lang:asm decode:true "><pre><code class="language-cpp">movlw 0x07
call table
movwf PORTB</code></pre></pre>
<p>What this does is move a literal value 7 to W then call the lookup table. On the table, the value 7 adds to the current value of the program counter which is the first line of the table. The program then jumps 7 lines towards</p>
<pre class="lang:asm decode:true"><pre><code class="language-cpp">retlw b’00000111’</code></pre></pre>
<p>The program now returns to the caller with W equal to the seven segment equivalent for the digit 7.</p>
<h3><strong>Example Project: Decade Counter</strong></h3>
<p>Let’s say we use two seven segment displays to count from zero to ninety-nine. One way to implement this is to assign variables to the ones and tens digits. As the ones digit go past 9, the tens digit increments by one. Using lookup tables make this project easier.</p>
<pre class="lang:asm decode:true"><pre><code class="language-cpp">#include &lt;P16F877A.inc&gt;

__CONFIG _FOSC_XT &amp; _WDTE_OFF &amp; _PWRTE_OFF &amp; _BOREN_OFF &amp; _LVP_OFF &amp; _CPD_OFF &amp; _WRT_OFF &amp; _CP_OFF

RES_VECT  CODE    0x0000         ; processor reset vector
    GOTO START                   ; go to beginning of program

INT_VECT CODE      0x0004        ; interrupt vector
    GOTO ISR                     ; go to interrupt service routine

MAIN_PROG CODE                      ; let linker place main program

CBLOCK 0x20
    micros
    ones
    tens
    count
ENDC

START
    bsf STATUS,RP0
    movlw 0x00
    movwf TRISB
    movlw 0x00
    movwf TRISC
    movlw 0x07
    movwf OPTION_REG
    bcf STATUS,RP0
    bsf INTCON,GIE
    bsf INTCON,TMR0IE
    clrf ones
    clrf tens
    clrf micros

MAIN
    movlw 0x02
    movwf PORTC
    movf ones, W
    call TABLE
    movwf PORTB
    call DELAY
    movlw 0x01
    movwf PORTC
    movf tens, W
    call TABLE
    movwf PORTB
    call DELAY
    goto MAIN
   
ISR
    bcf INTCON,GIE
    bcf INTCON,TMR0IE
    incf micros,1
    movf micros,0
    sublw 0x0F
    btfsc STATUS,Z
    goto inc_ones
    goto ret
inc_ones
    clrf micros
    incf ones, 1
    movf ones, 0
    sublw 0x0A
    btfsc STATUS,Z
    goto inc_tens
    goto ret
inc_tens
    clrf ones
    incf tens, 1
    movf tens, 0
    sublw 0x0A
    btfsc STATUS,Z
    clrf tens
    goto ret
ret bcf INTCON,TMR0IF
    bsf INTCON,GIE
    bsf INTCON,TMR0IE
    retfie

DELAY
    LOOP DECFSZ count,F
    GOTO LOOP
    RETURN
  
TABLE   addwf PCL
        retlw b&#039;00111111&#039;    ;digit 0
        retlw b&#039;00000110&#039;    ;digit 1
        retlw b&#039;01011011&#039;    ;digit 2
        retlw b&#039;01001111&#039;    ;digit 3
        retlw b&#039;01100110&#039;    ;digit 4
        retlw b&#039;01101101&#039;    ;digit 5
        retlw b&#039;01111101&#039;    ;digit 6
        retlw b&#039;00000111&#039;    ;digit 7
        retlw b&#039;01111111&#039;    ;digit 8
        retlw b&#039;01101111&#039;    ;digit 9    

    END</code></pre></pre>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2019/06/ezgif-5-a1e78ccd82da.gif"><img loading="lazy" decoding="async" class="size-full wp-image-3584 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/06/ezgif-5-a1e78ccd82da.gif" alt="Lookup Tables with PIC" width="606" height="410" /></a></p>
<p>The post <a href="https://www.teachmemicro.com/use-lookup-tables-pic-assembly/">How to Use Lookup Tables in PIC Assembly</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/use-lookup-tables-pic-assembly/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Persistence of Vision (POV) with Seven-segment Displays</title>
		<link>https://www.teachmemicro.com/pov-seven-segment-displays/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pov-seven-segment-displays</link>
					<comments>https://www.teachmemicro.com/pov-seven-segment-displays/#comments</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Tue, 23 Apr 2019 04:11:11 +0000</pubDate>
				<category><![CDATA[PIC Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=3039</guid>

					<description><![CDATA[<p>Lack of pins to use is a common challenge in designing microcontroller-based projects. This is particularly true when dealing with liquid crystal or seven-segment displays. Multiplexers and display drivers are great help but at an additional cost. Thankfully, a software-based solution exists to solve such a problem. What is POV? Persistence of vision (POV) is &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/pov-seven-segment-displays/">Persistence of Vision (POV) with Seven-segment Displays</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Lack of pins to use is a common challenge in designing microcontroller-based projects. This is particularly true when dealing with <a href="https://www.teachmemicro.com/arduino-lcd-tutorial/">liquid crystal</a> or seven-segment displays. Multiplexers and display drivers are great help but at an additional cost. Thankfully, a software-based solution exists to solve such a problem.</p>
<p><span id="more-3039"></span></p>
<h3><strong>What is POV?</strong></h3>
<p><a href="https://en.wikipedia.org/wiki/Persistence_of_vision">Persistence of vision (POV)</a> is a technique to reduce the microcontroller pins used without adding extra components. Basically, it’s a form of optical illusion wherein our perception of an object is not as fast as how the object is changing. A basic non-electronic example of POV is how a pencil seemed rubbery when wiggled.</p>
<h3><strong>POV With Seven-Segment Displays</strong></h3>
<p>I will be using common cathode (CC) seven-segment displays for this tutorial. I believe this is enough to grasp the basics of POV and lay the path for using other devices like sixteen-segment displays, dot matrices, etc.</p>
<p>Recall that a seven-segment display is wired like this:</p>
<figure style="width: 300px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="img-responsive" title="Seven segment common cathode display" src="https://www.jameco.com/jameco/workshop/techtip/working-with-seven-segment-displays-fig1.jpg" alt="Seven segment common cathode display" width="300" height="271" /><figcaption class="wp-caption-text"><em>From Jameco</em></figcaption></figure>
<p>To light up one segment, the anode of that segment must have a higher voltage than the cathode. Each segment can be assigned to a microcontroller pin and the cathode is connected to the ground.</p>
<p>Numbers are displayed by setting (make high) certain segments. If the wiring connection below is followed, then digit one is displayed when RB.1 and RB.2 of the <a href="https://www.win-source.net/products/detail/microchip-technology/pic16f84a-04i-p.html">PIC16F84A</a> are set while the rest are cleared (make low).</p>
<p id="YBoTUOd"><img loading="lazy" decoding="async" class="wp-image-3041 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe82d009867.png" alt="" width="450" height="332" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe82d009867.png 740w, https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe82d009867-300x221.png 300w" sizes="auto, (max-width: 450px) 100vw, 450px" /></p>
<p>Displaying digits 0 to 9 is done by following the table below:</p>
<table>
<tbody>
<tr>
<th>Bit Sequence</th>
<th>7-segment Digit</th>
</tr>
<tr>
<td>00111111</td>
<td>0</td>
</tr>
<tr>
<td>00000110</td>
<td>1</td>
</tr>
<tr>
<td>01011011</td>
<td>2</td>
</tr>
<tr>
<td>01001111</td>
<td>3</td>
</tr>
<tr>
<td>01100110</td>
<td>4</td>
</tr>
<tr>
<td>01101101</td>
<td>5</td>
</tr>
<tr>
<td>01111110</td>
<td>6</td>
</tr>
<tr>
<td>00000111</td>
<td>7</td>
</tr>
<tr>
<td>01111111</td>
<td>8</td>
</tr>
<tr>
<td>01100111</td>
<td>9</td>
</tr>
</tbody>
</table>
<p>But what if we use more than one seven-segment display? This is where POV comes in handy. The concept is tricking the eye as if two displays are simultaneous although they are actually just alternating.</p>
<p>Consider this connection:</p>
<p id="WtsKcst"><img loading="lazy" decoding="async" class="wp-image-3042 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe85b64167b.png" alt="" width="469" height="320" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe85b64167b.png 856w, https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe85b64167b-300x205.png 300w, https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe85b64167b-768x524.png 768w, https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe85b64167b-110x75.png 110w" sizes="auto, (max-width: 469px) 100vw, 469px" /></p>
<p>Here we see that the cathodes for the displays are now connected to a pin. The segments for both displays are connected to the same pins! We can turn on the left display if its cathode is low and turn it off if its cathode is high. The same is true for the right display.</p>
<p>Now if we want to display the digit 13 on these two displays, what we do is turn on the left display and turn off the right display. Then, we make the segments display the digit one:</p>
<p id="DjLwIQD"><img loading="lazy" decoding="async" class="wp-image-3043 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe860dc2edd.png" alt="" width="441" height="325" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe860dc2edd.png 763w, https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe860dc2edd-300x221.png 300w" sizes="auto, (max-width: 441px) 100vw, 441px" /></p>
<p>After this, we turn off the left digit and turn on the right digit. Then, we make the segments display the digit three:</p>
<p id="toGctry"><img loading="lazy" decoding="async" class="wp-image-3044 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe864d2a2f3.png" alt="" width="452" height="335" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe864d2a2f3.png 765w, https://www.teachmemicro.com/wp-content/uploads/2019/04/img_5cbe864d2a2f3-300x222.png 300w" sizes="auto, (max-width: 452px) 100vw, 452px" /></p>
<p>Now, we make this loop in a speed that is fast enough to trick the eye that they are simultaneous:</p>
<p><iframe loading="lazy" width="480" height="270" src="https://giphy.com/embed/g4IlcQyHiYTQV7IHlt" frameborder="0" class="giphy-embed" allowfullscreen="allowfullscreen"></iframe></p>
<p><a href="https://giphy.com/gifs/g4IlcQyHiYTQV7IHlt">via GIPHY</a></p>
<p>That’s POV!</p>
<h3><strong>Example Project with POV</strong></h3>
<p>We can extend this to as many seven-segment displays as our chosen microcontroller can permit. The limiting factor is the number of available pins for the cathode of each display.</p>
<p><iframe loading="lazy" width="560" height="315" src="https://www.youtube.com/embed/QczSB2fHGME" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="allowfullscreen"></iframe></p>
<p>In the video above, I used POV to create a digital clock out of six seven-segment displays and one PIC microcontroller. To further reduce the pin count, I used a BCD to seven-segment driver.</p>
<p>The post <a href="https://www.teachmemicro.com/pov-seven-segment-displays/">Persistence of Vision (POV) with Seven-segment Displays</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/pov-seven-segment-displays/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Capture and Compare with PIC16F877A</title>
		<link>https://www.teachmemicro.com/capture-compare-pic16f877a/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=capture-compare-pic16f877a</link>
					<comments>https://www.teachmemicro.com/capture-compare-pic16f877a/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Fri, 15 Feb 2019 00:28:01 +0000</pubDate>
				<category><![CDATA[PIC Tutorial]]></category>
		<category><![CDATA[asm]]></category>
		<category><![CDATA[ccp]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=2777</guid>

					<description><![CDATA[<p>The PIC16F877A microcontroller comes with a Capture Compare PWM (CCP) module which utilizes its 16-bit Timer1 module to generate or count pulses, among other things. I have already covered how to generate PWM in my previous tutorial. This time, we will look at how to implement capture and compare with PIC16F877A using the CCP module. &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/capture-compare-pic16f877a/">Capture and Compare with PIC16F877A</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The PIC16F877A microcontroller comes with a Capture Compare PWM (CCP) module which utilizes its 16-bit Timer1 module to generate or count pulses, among other things. I have already covered how to generate PWM in my <a href="https://www.teachmemicro.com/pic16-pwm/">previous tutorial</a>. This time, we will look at how to implement capture and compare with <a href="https://www.win-source.net/products/detail/microchip-technology/pic16f877a-i-p.html">PIC16F877A</a> using the CCP module.</p>
<p><span id="more-2777"></span></p>
<h3><strong>Capture Mode</strong></h3>
<p>When in capture mode, the value of Timer1 is copied to the CCPRx register when any of these four events happen:</p>
<ul>
<li>rising edge on CCP pin</li>
<li>falling edge on CCP pin</li>
<li>4th rising edge on CCP pin</li>
<li>16th rising edge on CCP pin</li>
</ul>
<p>Note that there are two CCP pins, CCP1 on RC2 and CCP2 on RC1. Each CCP pin corresponds to a CCPxCON register:</p>
<p id="dVnDoen"><img loading="lazy" decoding="async" width="621" height="438" class="alignnone size-full wp-image-2778 " src="https://www.teachmemicro.com/wp-content/uploads/2019/01/img_5c47d8afe8c13.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/01/img_5c47d8afe8c13.png 621w, https://www.teachmemicro.com/wp-content/uploads/2019/01/img_5c47d8afe8c13-300x212.png 300w" sizes="auto, (max-width: 621px) 100vw, 621px" /></p>
<p>In short, to capture on CCP1 pin (RC2) use CCP1CON. Otherwise, to capture on CCP2 pin (RC2) use CCP2CON.</p>
<p>To enable capture mode, you must follow these steps:</p>
<ol>
<li>Adjust the value of bits 3 to 0 of CCPxCON register to the desired capture mode: 0100 for every falling edge, 0101 for every rising edge, 0110 for every 4th rising edge and 0111 for every 16th rising edge.</li>
<li>Make CCP pin input by setting the corresponding TRISC pin.</li>
<li>Read the CCPRx register. Note that both Timer1 and CCPRx registers are 16-bit registers and is subdivided into TMR1H, TMR1L and CCPRxH, CCPRxL respectively.</li>
</ol>
<p>Here is an example ASM code that captures the Timer1 value and displays it on PORTB:</p>
<pre class="theme:eclipse lang:asm decode:true"><pre><code class="language-cpp">#include &lt;P16F877A.INC&gt;
    
RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    START                   ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

MAIN_PROG CODE                      ; let linker place main program

START
    MOVLW b&#039;00000100&#039;
    MOVWF CCP1CON	    ;Capture Mode, every falling edge on RC2
    BSF STATUS,RP0	    ;Bank 1
    BSF TRISC,2		    ;Make RC2 input
    CLRF TRISB		    ;Make PORTB output
    BCF STATUS,RP0	    ;Bank 0
    BSF T1CON,TMR1ON	    ;Turn on Timer1
MAIN
    BTFSS PIR1,CCP1IF
    GOTO MAIN
    MOVF CCPR1L,W
    MOVWF PORTB
    GOTO MAIN

    END</code></pre></pre>
<p>What this code does is capture the value of Timer1 every time a falling edge pulse is detected at RC2. Since Timer1 and consequently, CCPR1, are 16-bit registers, we cannot copy their values to PORTB, which is an 8-bit register. What I did here is just copy the low byte (CCPR1L) to PORTB.</p>
<h3><strong>Compare Mode</strong></h3>
<p>In compare mode, the CCPR1 value is continuously compared to the Timer1 value. When the CCPR1 value is equal to the Timer1 value, the CCP1 pin (RC2) is either driven low, high or remain unchanged but with other effects. The event on match condition can be set using the same CCP1CON register.</p>
<p>To enable compare mode, follow these steps:</p>
<ol>
<li>Adjust the value of bits 3 to 0 of CCPxCON register to the desired event on match: 1000 to set CCP pin, 1001 to clear CCP pin,  1010 to generate an interrupt and 1011 to start A/D conversion.</li>
<li>Make CCP pin output by clearing the corresponding TRISC pin.</li>
<li>Load a value to CCPRx register that will be compared to the Timer1 value.</li>
</ol>
<pre class="theme:eclipse lang:asm decode:true"><pre><code class="language-cpp">#include &lt;P16F877A.INC&gt;
    
RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    START                   ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

MAIN_PROG CODE                      ; let linker place main program

START
    MOVLW b&#039;00001000&#039;
    MOVWF CCP1CON	    ;Compare mode, set RC2 on match
    BSF STATUS,RP0	    ;Bank 1
    BCF TRISC,2		    ;Make RC2 output
    BCF STATUS,RP0	    ;Bank 0
    MOVLW 0xFF
    MOVWF CCPR1L            ;Let CCPR1 = 255
    BSF T1CON,TMR1ON	    ;Turn on Timer1
MAIN
    BTFSS PIR1,CCP1IF
    GOTO MAIN               ;Do nothing, wait for match
    BCF PORTC,2             ;Match condition, clear RC2
    END</code></pre></pre>
<p>What this code does is wait for a match between the CCP1RL (equal to 255 in this example) and the Timer1 value. When a match occurs, the RC2 pin should set. In order for us visualize the match again, the RC2 must be cleared after the match occured.</p>
<h3><strong>Practical Application of Capture and Compare</strong></h3>
<p>One good practical application of capture and compare is pulse counting. While pulse counting can be implemented using Timer0's counter mode, it is limited to 8-bit values. The 16-bit Timer1 value has a higher resolution and thus can count faster pulses.</p>
<p>An article on a frequency counter PIC project will be published detailing the practical application of capture and compare.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>The post <a href="https://www.teachmemicro.com/capture-compare-pic16f877a/">Capture and Compare with PIC16F877A</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/capture-compare-pic16f877a/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Using Buttons and LEDs on the Curiosity HPC</title>
		<link>https://www.teachmemicro.com/using-buttons-and-leds-on-the-curiosity-hpc/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-buttons-and-leds-on-the-curiosity-hpc</link>
					<comments>https://www.teachmemicro.com/using-buttons-and-leds-on-the-curiosity-hpc/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Wed, 06 Feb 2019 09:20:04 +0000</pubDate>
				<category><![CDATA[PIC Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=2878</guid>

					<description><![CDATA[<p>Last time, I showed how to get started with Microchip's Curiosity HPC board. I will now explore the use of the included buttons and LEDs on this microcontroller board. When using development boards for the first time, it's always a good idea to look at its datasheet first. The Curiosity HPC has four properly-labeled LEDs. &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/using-buttons-and-leds-on-the-curiosity-hpc/">Using Buttons and LEDs on the Curiosity HPC</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Last time, I showed how to <a href="https://www.teachmemicro.com/first-use-microchip-curiosity-hpc/">get started with Microchip's Curiosity HPC</a> board. I will now explore the use of the included buttons and LEDs on this <a href="https://www.win-source.net/category/integrated-circuits-ics/embedded/embedded-microcontrollers">microcontroller</a> board.</p>
<p><span id="more-2878"></span></p>
<p>When using development boards for the first time, it's always a good idea to look at its <a href="http://ww1.microchip.com/downloads/en/devicedoc/40001856a.pdf">datasheet</a> first. The Curiosity HPC has four properly-labeled LEDs. But I needed to make sure if they were active low or high. Also, I needed to know if the buttons are normally high or normally low.</p>
<p>The schematic of the development board shows this:</p>
<p id="EnhAeGb"><img loading="lazy" decoding="async" width="429" height="468" class="size-full wp-image-2879 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a45e191129.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a45e191129.png 429w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a45e191129-275x300.png 275w" sizes="auto, (max-width: 429px) 100vw, 429px" /></p>
<p>So I've confirmed two things: the LEDs will turn on when I <em>set</em> their corresponding pins and the buttons are normally high.</p>
<h3><strong>Controlling the On-Board LEDs</strong></h3>
<p>Now I will try to create strobe lights out of the four LEDs on the board. With the older <a href="https://www.teachmemicro.com/pic16f877a-more-microcontroller-features/">PIC16F877A</a>, I only need to manipulate TRIS and PORT registers to control the output pins of that PIC. However, for newer PICs like the PIC16F18875 on the Curiosity HPC, there is now a LAT short for "latch" register.</p>
<p>Manipulating any pin of the PIC requires the use of the LAT or PORT registers. According to the <a href="http://ww1.microchip.com/downloads/en/DeviceDoc/400001802D.pdf">datasheet</a>, writing a value to a PORT actually writes the value into its LAT register. Meanwhile, reading from a PORT returns a value that is the actual state of the I/O pins. This is a consequence of the pins following the <em>read-modify-write</em> operation: when writing to a PORT, the current states of the pins of that PORT are READ, the read values MODIFIED, and is now WRITTEN to the corresponding LAT register.</p>
<p>The existence of PORT and LAT registers is somewhat vague but I have come to understand it like this: write to LAT, read from PORT.</p>
<p>Another peculiarity is that all pins are now analog by default. The corresponding ANSEL bits should be "0" to make a pin digital. For example, writing "0" to ANSA4 makes RA4 digital.</p>
<p>So let's say we want to flash led D2 which is wired to RA4, this is now the code:</p>
<pre class="lang:c decode:true"><pre><code class="language-cpp">#define _XTAL_FREQ 4000000

#include &lt;xc.h&gt;

void main(void) {
    TRISA4 = 0;           //Make RA4 output
    ANSA4 = 0;            //and a digital I/O pin
    
    while(1){            //Make the flashing endless
        LATA4 = 1;       //Set RA4
        __delay_ms(500); //Half a second delay
        LATA4 = 0;       //Clear RA4
        __delay_ms(500); //Another half-second delay
    }
    return;
}</code></pre></pre>
<p>Here, line 7 is how you would make a pin digital. Writing "1" to LATA4 turns on the LED on RA4 and writing "0" turns it off.</p>
<p>I tried changing LATA4 to RA4 and the LED still flashed. I believe the difference between LAT and PORT will not be obvious here because I only wrote to a port, not read it. What you write to RA4 also becomes the value of LATA4.</p>
<p>Now for the strobe light code, I only needed to modify the code above and now include the rest of the LED pins:</p>
<pre class="lang:c decode:true"><pre><code class="language-cpp">#define _XTAL_FREQ 4000000

#include &lt;xc.h&gt;

void main(void) {
    TRISA4 = 0;
    TRISA5 = 0;
    TRISA6 = 0;
    TRISA7 = 0;
    ANSA4 = 0;
    ANSA5 = 0;
    ANSA6 = 0;
    ANSA7 = 0;
    
    while(1){
        LATA = 0b10000000;
        __delay_ms(500);
        LATA = 0b01000000;
        __delay_ms(500);
        LATA = 0b00100000;
        __delay_ms(500);
        LATA = 0b00010000;
        __delay_ms(500);
    }
    return;
}</code></pre></pre>
<p>&nbsp;</p>
<h3><strong>Something's Wrong with RA7</strong></h3>
<p>The code above flashes the LEDs EXCEPT for RA7! I browsed the PIC16F18875 datasheet and found this:</p>
<p id="sWlEqpt"><img loading="lazy" decoding="async" width="730" height="117" class="alignnone size-full wp-image-2882 " src="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a954ce3de5.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a954ce3de5.png 730w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a954ce3de5-300x48.png 300w" sizes="auto, (max-width: 730px) 100vw, 730px" /></p>
<p>RA7 is also a digital clock input pin (CLKIN) as seen. Based on experience, CLKIN pins tend to be current sinks by default. This may be the reason why RA7 wasn't able to drive the on-board LED.</p>
<p>More datasheet reading led me to this:</p>
<p id="PkjnWnS"><img loading="lazy" decoding="async" width="636" height="160" class="alignnone size-full wp-image-2883 " src="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a95ef28f26.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a95ef28f26.png 636w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a95ef28f26-300x75.png 300w" sizes="auto, (max-width: 636px) 100vw, 636px" /></p>
<p>This tells me that if FEXTOSC is set to OFF, then I can now use RA7 just like any other I/O pin.</p>
<p>FEXTOSC is in fact part of the configuration word for the microcontroller. To manipulate it, I needed to view the configuration bits via Run &gt; Configuration Bits. The Configuration Bits window now appears at the bottom:</p>
<p id="JyyjHNH"><img loading="lazy" decoding="async" width="911" height="537" class="alignnone size-full wp-image-2884 " src="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a96afcdffe.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a96afcdffe.png 911w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a96afcdffe-300x177.png 300w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a96afcdffe-768x453.png 768w" sizes="auto, (max-width: 911px) 100vw, 911px" /></p>
<p>The first row of the field shows FEXTOSC. I just needed to change this to OFF and click the "Generate Source Code to Output". The Config Bits Source will now appear:</p>
<p id="qNkSZVU"><img loading="lazy" decoding="async" width="913" height="539" class="alignnone size-full wp-image-2885 " src="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a970836686.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a970836686.png 913w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a970836686-300x177.png 300w, https://www.teachmemicro.com/wp-content/uploads/2019/02/img_5c5a970836686-768x453.png 768w" sizes="auto, (max-width: 913px) 100vw, 913px" /></p>
<p>&nbsp;</p>
<p>I just then copied this source to my code (right after the #insert &lt;xc.h&gt; line).</p>
<p>After that, RA7 is now flashing along with the other LEDs.</p>
<p><a href="https://gfycat.com/JoyousEssentialKinglet">https://gfycat.com/JoyousEssentialKinglet</a></p>
<h3><strong>Using the On-board Buttons</strong></h3>
<p>Now that I managed to control the on-board LEDs on the Curiosity HPC, it's time to use the two user buttons. I believe this is now a better setting for describing the difference between PORT and LAT.</p>
<p>Consider the code below:</p>
<pre class="lang:c decode:true"><pre><code class="language-cpp">void main(void) {
    TRISA4 = 0;
    TRISC5 = 1;
    ANSELA = 0;
    ANSELC = 0;
    
    LATC5 = 0;
    while(1){
       if(LATC5 ==  1){
           RA4 = 1;
       }else{
           RA4 = 0;
       }
    }
    return;
}</code></pre></pre>
<p>With this code, RA4 stays on regardless if S2 is pressed or not. Why? because I wrote a "0" to LATC5 and unless I read RC5, that pin will remain "0". LATC5 will never look at the <em>current state</em> of pin RC5. Hence, RA4 will also remain 0.</p>
<p>Now if you tweak the code above to this:</p>
<pre class="lang:c decode:true"><pre><code class="language-cpp">void main(void) {
    TRISA4 = 0;
    TRISC5 = 1;
    ANSELA = 0;
    ANSELC = 0;
    
    RC5 = 0;
    while(1){
       if(RC5 ==  1){
           RA4 = 1;
       }else{
           RA4 = 0;
       }
    }
    return;
}</code></pre></pre>
<p>This time, RA4 will turn on or off if ever I press or depress S2. Even though I wrote "0" to RC5, this bit will always be equal to the <em>current state</em> of the pin. This is how I understood LAT and PORT.</p>
<p>So much for that. Now I will modify my LED strobe code above so that the strobe will change direction if I press S1 or S2. Here's my code:</p>
<pre class="lang:c decode:true "><pre><code class="language-cpp">void main(void) {
    TRISA4 = 0;
    TRISA5 = 0;
    TRISA6 = 0;
    TRISA7 = 0;
    TRISB4 = 1;
    TRISC5 = 1;
    ANSA4 = 0;
    ANSA5 = 0;
    ANSA6 = 0;
    ANSA7 = 0;
    ANSB4 = 0;
    ANSC5 = 0;
    
    while(1){
        if(RB4==0){
            LATA = 0b10000000;
            __delay_ms(500);
            LATA = 0b01000000;
            __delay_ms(500);
            LATA = 0b00100000;
            __delay_ms(500);
            LATA = 0b00010000;
            __delay_ms(500);
        }else if(RC5==0){
            LATA = 0b00010001;
            __delay_ms(500);
            LATA = 0b00100000;
            __delay_ms(500);
            LATA = 0b01000000;
            __delay_ms(500);
            LATA = 0b10000000;
            __delay_ms(500);
        }else{
            LATA = 0x00;
            __delay_ms(500);
            LATA = 0xF0;
            __delay_ms(500);
        }
        
    }
    return;
}</code></pre></pre>
<p>And here's the result of the code above (BTW, sorry for the potato quality gif):</p>
<p><a href="https://gfycat.com/DependableFatHarlequinbug">https://gfycat.com/DependableFatHarlequinbug</a></p>
<p>That's it for using the user LEDs and buttons on the Curiosity HPC board. In my next article, I'll try to explore the mikroBUS slots.</p>
<p>The post <a href="https://www.teachmemicro.com/using-buttons-and-leds-on-the-curiosity-hpc/">Using Buttons and LEDs on the Curiosity HPC</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/using-buttons-and-leds-on-the-curiosity-hpc/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PIC16F877A - More Microcontroller Features</title>
		<link>https://www.teachmemicro.com/pic16f877a-more-microcontroller-features/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pic16f877a-more-microcontroller-features</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Wed, 11 Apr 2018 09:03:50 +0000</pubDate>
				<category><![CDATA[PIC Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?page_id=2002</guid>

					<description><![CDATA[<p>We have managed to blink an LED and use interrupts and timers with the PIC16F84A. Sadly, that’s almost all we can do with that microcontroller as it lacks features that most microcontrollers or Arduino have. From here on, we will now be using the PIC16F877A. The PIC16F877A is a 40-pin (DIP) microcontroller which Microchip describes as &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/pic16f877a-more-microcontroller-features/">PIC16F877A - More Microcontroller Features</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>We have managed to <a href="https://www.teachmemicro.com/pic16f84a-beginner-microcontroller/">blink an LED</a> and <a href="https://www.teachmemicro.com/pic-interrupt-pic16f84a/">use interrupts</a> and <a href="https://www.teachmemicro.com/pic-timer-pic16f84a/">timers</a> with the PIC16F84A. Sadly, that’s almost all we can do with that microcontroller as it lacks features that most microcontrollers or Arduino have. From here on, we will now be using the <a href="https://www.win-source.net/products/detail/microchip-technology/pic16f877a-i-p.html">PIC16F877A</a>.</p>
<p><span id="more-2002"></span></p>
<p>The PIC16F877A is a 40-pin (DIP) microcontroller which Microchip <a href="http://www.microchip.com/wwwproducts/en/PIC16F877A">describes as powerful</a> based on having a 200 nanosecond instruction speed. It’s old and Microchip itself is not recommending it for new designs but its features and price make it still a popular microcontroller.</p>
<p>&nbsp;</p>
<h3><strong>PIC16F877A Specs</strong></h3>
<p>Here are a few of its specifications:</p>
<ul>
<li>Bus width - 8 bits</li>
<li>Pin Count - 40 (PDIP, SOIC) / 44 (QFN, PLCC, TQFP)</li>
<li>Program Memory - 14.3 kilobytes</li>
<li>CPU Speed - 5 million instructions per second</li>
<li>RAM Size - 368 bytes</li>
<li>EEPROM Size - 256 bytes</li>
</ul>
<p>Obviously, the PIC16F877A trumps the PIC16F84A based on the numbers above. But what separates this microcontroller are these features:</p>
<ul>
<li>10-bit, up to 8-channel Analog-to-Digital<br />
Converter (A/D)</li>
<li>Synchronous Serial Port (SSP) with SPI<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br />
(Master mode) and I2C<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2122.png" alt="™" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (Master/Slave)</li>
<li>Universal Synchronous Asynchronous Receiver<br />
Transmitter (USART/SCI) with 9-bit address<br />
detection</li>
</ul>
<p>We will discuss each of these features as we continue with this tutorial.</p>
<h3><strong>LED Blink Code in Assembly</strong></h3>
<p>For now, we will create a simple assembly language program using the PIC16F877A.<br />
The code is very similar to the one using PIC16F84A:</p>
<pre class="theme:arduino-ide lang:asm decode:true"><pre><code class="language-cpp">#INCLUDE &lt;P16F877A.INC&gt;
    
 __CONFIG _FOSC_XT &amp; _WDTE_OFF &amp; _PWRTE_OFF &amp; _BOREN_OFF &amp; _LVP_OFF &amp; _CPD_OFF &amp; _WRT_OFF &amp; _CP_OFF
   
RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    START                   ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

    CBLOCK 0x0C
	COUNT1
	COUNT2
    ENDC
    
MAIN_PROG CODE                      ; let linker place main program

START
    BSF STATUS, RP0
    CLRF TRISB
    BSF TRISA,0
    BCF STATUS, RP0
    
MAIN
    BSF PORTA,0
    CALL DELAY
    BCF PORTA,0
    CALL DELAY
    GOTO MAIN
    
DELAY
LOOP1   DECFSZ COUNT1,1
	GOTO LOOP1
	DECFSZ COUNT2,1
	GOTO LOOP1
	RETURN
	
    END</code></pre></pre>
<p>The code above simply toggles the state of pin RB0. So when an LED is attached to this pin, it will blink. You can simulate this code in Proteus using the schematic diagram below:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2004" src="https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-1024x733.png" alt="PIC16F877A Blink a LED circuit" width="618" height="442" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-1024x733.png 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-300x215.png 300w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-768x550.png 768w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-24x17.png 24w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-36x26.png 36w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit-48x34.png 48w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_blink_led_circuit.png 1531w" sizes="auto, (max-width: 618px) 100vw, 618px" /></p>
<p>Of course, the advantage of using this microcontroller is you can attach a lot more LEDs!</p>
<h3><strong>Switch an LED in Assembly</strong></h3>
<p>For input using a switch, you can freely use any pin except those that have AN labels. These analog pins including all PORTA and PORTE pins are meant for analog-to-digital conversion and need a bit of additional code to make them digital.</p>
<p>To turn these analog pins to digital, we must write 0x07 or 0x06 to the ADCON1 register. Details about this are found in my <a href="https://www.teachmemicro.com/pic-adc/">analog-to-digital conversion</a> tutorial.</p>
<p>Here’s a code that uses a switch to RA0 to turn on/off a LED:</p>
<pre class="theme:arduino-ide lang:asm decode:true"><pre><code class="language-cpp">#INCLUDE &lt;P16F877A.INC&gt;
    
 __CONFIG _FOSC_XT &amp; _WDTE_OFF &amp; _PWRTE_OFF &amp; _BOREN_OFF &amp; _LVP_OFF &amp; _CPD_OFF &amp; _WRT_OFF &amp; _CP_OFF
   
RES_VECT  CODE    0x0000            ; processor reset vector
    GOTO    START                   ; go to beginning of program

; TODO ADD INTERRUPTS HERE IF USED

    CBLOCK 0x0C
	COUNT1
	COUNT2
    ENDC
    
MAIN_PROG CODE                      ; let linker place main program

START
    BSF STATUS, RP0
    CLRF TRISB
    MOVLW 0x07
    MOVWF ADCON1
    MOVLW 0x01
    MOVWF TRISA
    BCF STATUS, RP0
    
MAIN
    BTFSC PORTA,0
    GOTO OFF
    GOTO ON
    GOTO MAIN
    
ON  BSF PORTB,0
    GOTO MAIN  
    
OFF BCF PORTB,0
    GOTO MAIN
    
DELAY
LOOP1   DECFSZ COUNT1,1
	GOTO LOOP1
	DECFSZ COUNT2,1
	GOTO LOOP1
	RETURN
	
    END</code></pre></pre>
<p>Here’s the schematic diagram for the code above:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2005" src="https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-1024x639.png" alt="PIC16F877A LED Switch circuit" width="618" height="386" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-1024x639.png 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-300x187.png 300w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-768x479.png 768w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-24x15.png 24w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-36x22.png 36w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit-48x30.png 48w, https://www.teachmemicro.com/wp-content/uploads/2018/04/pic16f877a_switch_led_circuit.png 1636w" sizes="auto, (max-width: 618px) 100vw, 618px" /></p>
<p>Those are the basic assembly language programs we can do with the PIC16F877A. Up next, we will look at the features that separate this microcontroller from the PIC16F84A, starting with serial communication.</p>
<p>The post <a href="https://www.teachmemicro.com/pic16f877a-more-microcontroller-features/">PIC16F877A - More Microcontroller Features</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using a Water Level Sensor with Microcontrollers</title>
		<link>https://www.teachmemicro.com/water-level-sensor-microcontrollers-arduino/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=water-level-sensor-microcontrollers-arduino</link>
					<comments>https://www.teachmemicro.com/water-level-sensor-microcontrollers-arduino/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Sun, 01 Apr 2018 15:16:20 +0000</pubDate>
				<category><![CDATA[Arduino Tutorial]]></category>
		<category><![CDATA[PIC Tutorial]]></category>
		<category><![CDATA[Sensor Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=1893</guid>

					<description><![CDATA[<p>A water level sensor is a simple device used to measure the level and volume of water inside a container. This tutorial shows you how to use a water level sensor with microcontrollers like an Arduino or PIC. Introduction Water level sensors range from educational to industrial. The most common and frequently seen in stores &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/water-level-sensor-microcontrollers-arduino/">Using a Water Level Sensor with Microcontrollers</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>A water level <a href="https://www.win-source.net/category/sensors-transducers">sensor</a> is a simple device used to measure the level and volume of water inside a container. This tutorial shows you how to use a water level sensor with microcontrollers like an Arduino or PIC.</p>
<p><span id="more-1893"></span></p>
<h3><strong>Introduction</strong></h3>
<p>Water level sensors range from educational to industrial. The most common and frequently seen in stores is this one:</p>
<p><img loading="lazy" decoding="async" class="wp-image-1901 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor.jpg" alt="Water Level Sensor" width="496" height="496" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor.jpg 800w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-150x150.jpg 150w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-300x300.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-768x768.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-65x65.jpg 65w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-24x24.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-36x36.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-48x48.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/04/water-level-sensor-120x120.jpg 120w" sizes="auto, (max-width: 496px) 100vw, 496px" /></p>
<p id="jnicIDm">This is a conductive-type water level sensor, where the change in resistance of parallel wires over varying depths of water is converted to voltage. This is not ideal for high precision water level monitoring and is only suitable for hobby projects.</p>
<p>The module has three pins: + (5V), - (GND), and S (Signal). The S pin outputs voltage corresponding to water level.</p>
<h3><strong>Wiring Diagram</strong></h3>
<p>Connecting the water level sensor to a microcontroller is easy: just connect the S pin to any analog pin. Of course, you must connect the and the + and - pin to power and ground. Here's an example wiring diagram with an Arduino:</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-1895 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-1024x458.jpg" alt="Arduino Water Level Sensor Schematic" width="618" height="276" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-1024x458.jpg 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-300x134.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-768x343.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-24x11.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-36x16.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor-48x21.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/04/arduino-water-level-sensor.jpg 1704w" sizes="auto, (max-width: 618px) 100vw, 618px" /></p>
<h3>Arduino Sketch</h3>
<p>The sketch for the water level sensor is also simple:</p>
<pre class="lang:arduino decode:true "><pre><code class="language-cpp">void setup()
{
	Serial.begin(9600);
}

void loop()
{
	Serial.println(analogRead(A0));
	delay(100);
}</code></pre></pre>
<p>This sketch will display varying numbers on the serial monitor as you vary the depth of the water. You cannot display the actual levels unless you do some actual tests. I suggest you use a calibrated container like this one:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2018/04/calibrated_cup.avif"><img data-dominant-color="edeceb" data-has-transparency="false" style="--dominant-color: #edeceb;" loading="lazy" decoding="async" class="aligncenter size-full wp-image-9579 not-transparent" src="https://www.teachmemicro.com/wp-content/uploads/2018/04/calibrated_cup.avif" alt="" width="449" height="582" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/04/calibrated_cup.avif 449w, https://www.teachmemicro.com/wp-content/uploads/2018/04/calibrated_cup-231x300.avif 231w" sizes="auto, (max-width: 449px) 100vw, 449px" /></a></p>
<p>&nbsp;</p>
<p>Fill up this container with liquid up to each calibration. Then place the water level sensor, open serial monitor and record the number. Add more water reaching each label on the container then record the number again. Continue doing this until you've filled the container.</p>
<h3>PIC XC8 Code</h3>
<p>To use this water level sensor with a PIC, we can use the code I created in my PIC ADC tutorial:</p>
<pre class="lang:arduino decode:true"><pre><code class="language-cpp">#include  // include processor files - each processor file is guarded.  
#include 
#include 
#include 
void Serial_init(const long int baudrate){
    BRGH = 1;
    unsigned int x;
    x = (_XTAL_FREQ /(baudrate*16))-1;
    SPBRG = x;
    SYNC = 0;
    SPEN = 1;
    TRISC7 = 1;
    TRISC6 = 1;
    CREN = 1;
    TXEN = 1;
}
void putch(char data) {
    while(!TRMT);
    TXREG = data;
}
unsigned int ADC_read(int channel){
    ADFM = 1; //results right justified
    ADCS0 = 0; //conversion speed = 4*Tosc
    ADCS1 = 0;
    ADCS2 = 1;
    ADCON0bits.CHS = channel;  
    ADON = 1; //turn on ADC
    __delay_ms(1);  
    GO_DONE = 1;
    while(ADCON0bits.GO_DONE == 1);
    unsigned int adval = (ADRESH &lt;&lt; 8) + ADRESL; //ex 1002
    return adval;
}
void main(void) {
    Serial_init(9600);
    int adval = ADC_read(0); //read analog signal at channel 0
    char buf[5];             //buffer to hold conversion result from integer to string
    itoa(buf, adval, 10);    //convert integer ADC result to string and store to buf
    printf(&quot;\rValue: %s\n&quot;,buf);  //print through Serial port
    __delay_ms(10);
}</code></pre></pre>
<p>It is assumed that the S pin of the sensor is attached to channel AN0 of the PIC's ADC. Similar to the Arduino example, you still need to do tests and recording to acquire the levels in metric or english units of measurement.</p>
<p>The post <a href="https://www.teachmemicro.com/water-level-sensor-microcontrollers-arduino/">Using a Water Level Sensor with Microcontrollers</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/water-level-sensor-microcontrollers-arduino/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>PIR Motion Sensor</title>
		<link>https://www.teachmemicro.com/pir-motion-sensor/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pir-motion-sensor</link>
					<comments>https://www.teachmemicro.com/pir-motion-sensor/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Wed, 21 Mar 2018 13:00:29 +0000</pubDate>
				<category><![CDATA[Arduino Tutorial]]></category>
		<category><![CDATA[PIC Tutorial]]></category>
		<category><![CDATA[Sensor Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=1700</guid>

					<description><![CDATA[<p>You can in fact build your own motion sensor without spending too much. Motion sensors can be set up using ultrasonic transceivers, video cameras, or microwave signals. In this tutorial, I’ll show you how to use the PIR motion sensor with a microcontroller. PIR is short for passive infrared which describes how the sensor operates; &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/pir-motion-sensor/">PIR Motion Sensor</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>You can in fact build your own <a href="https://www.win-source.net/category/sensors-transducers/motion-sensors">motion sensor</a> without spending too much. Motion sensors can be set up using ultrasonic transceivers, video cameras, or microwave signals. In this tutorial, I’ll show you how to use the PIR motion sensor with a microcontroller.</p>
<p>PIR is short for <i>passive infrared</i> which describes how the sensor operates; passive means the device doesn’t emit any energy. Basically, the sensor detects infrared radiation emitted by anything that is warm, including a person.</p>
<p>Most PIR sensors look like this:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1704" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor.jpg" alt="HC-SR501 PIR motion sensor" width="800" height="800" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor.jpg 800w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-150x150.jpg 150w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-300x300.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-768x768.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-65x65.jpg 65w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-24x24.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-36x36.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-48x48.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-120x120.jpg 120w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>This is the HC-SR501 PIR motion sensor. The dome is called a <a href="https://en.wikipedia.org/wiki/Fresnel_lens">Fresnel lens</a> that focuses the infrared radiation towards the IR sensor in the middle. This is what the module looks like without the dome:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1703" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less.jpg" alt="HC-SR501 PIR motion sensor without lens" width="800" height="800" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less.jpg 800w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-150x150.jpg 150w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-300x300.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-768x768.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-65x65.jpg 65w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-24x24.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-36x36.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-48x48.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-dome-less-120x120.jpg 120w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>This PIR sensor has a detection range from 100 to 130 degrees and from 3 to 7 meters from the device.</p>
<p>Here’s what the underside looks like:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1702" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated.jpg" alt="HC-SR501 PIR motion sensor underside" width="800" height="800" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated.jpg 800w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-150x150.jpg 150w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-300x300.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-768x768.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-65x65.jpg 65w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-24x24.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-36x36.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-48x48.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/PIR-Motion-Sensor-underside-annotated-120x120.jpg 120w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>Here we see the three pins that would be connected to a microcontroller. The DOUT pin toggles high when a warm body is detected within the defined range. It will stay high depending on the time delay and trigger mode settings.</p>
<p>There’s the sensitivity adjust knob that can change the range from a minimum of 3 meters (fully clockwise) or a maximum of 7 meters (full counter-clockwise). The time delay knob adjusts how long will the DOUT pin stays high when the sensor is triggered. The minimum is 3 seconds (fully counter-clockwise) and the maximum is 5 minutes (fully clockwise).</p>
<p>The jumper on the left side sets the trigger mode to either repeatable or non-repeatable. When in repeatable mode, each detection resets the time delay. When in non-repeatable mode, the time delay begins immediately after detection and the next motion will be disregarded. It is worth mentioning that when the DOUT pin goes low after the time delay period, there is a <b>3 second window in which all motion will not be detected</b>.</p>
<p>Here’s an example timeline if the HC-SR501 PIR sensor is set to non-repeatable mode, with a 3 second time delay:</p>
<table>
<tbody>
<tr>
<td>Motion detected</td>
<td>Any motion here will be undetected</td>
<td>Any motion here will be undetected</td>
<td>Start of three second window. Any motion here will be undetected</td>
<td>Any motion here will be undetected</td>
<td>Any motion here will be undetected</td>
<td>Motion detected</td>
</tr>
<tr>
<td>1s</td>
<td>2s</td>
<td>3s</td>
<td>4s</td>
<td>5s</td>
<td>6s</td>
<td>7s</td>
</tr>
<tr>
<td>HIGH</td>
<td>HIGH</td>
<td>HIGH</td>
<td>LOW</td>
<td>LOW</td>
<td>LOW</td>
<td>HIGH</td>
</tr>
</tbody>
</table>
<p>Here’s an example timeline if the sensor is set to repeatable mode, with the same time delay:</p>
<table>
<tbody>
<tr>
<td>Motion detected</td>
<td>Motion</p>
<p>detected</td>
<td>Any motion here will be detected and will extend the time delay</td>
<td>Any motion here will be detected and will extend the time delay</td>
<td>Start of three second window. Any motion here will be undetected</td>
<td>Any motion here will be undetected</td>
<td>Any motion here will be undetected</td>
</tr>
<tr>
<td>1s</td>
<td>2s</td>
<td>3s</td>
<td>4s</td>
<td>5s</td>
<td>6s</td>
<td>7s</td>
</tr>
<tr>
<td>HIGH</td>
<td>HIGH</td>
<td>HIGH</td>
<td>HIGH</td>
<td>LOW</td>
<td>LOW</td>
<td>LOW</td>
</tr>
</tbody>
</table>
<h3>Arduino Implementation</h3>
<p>We only need to read the Arduino digital pin to which the DOUT pin of the HC-SR501 is connected to know if a motion is detected. Here’s an example sketch where the DOUT pin is connected to Arduino’s pin 2:</p>
<pre class="lang:arduino decode:true"><pre><code class="language-cpp">int pirPin = 2; // Input for HC-S501
int pirVal; // Place to store read PIR Value

void setup() {
   Serial.begin(9600);
   pinMode(pirPin, INPUT);  
}

void loop() {
  pirVal = digitalRead(pirPin);
  if(pirVal){
    Serial.println(“Motion detected!”);
    delay(3000);                                //wait for three seconds 
  }
}</code></pre></pre>
<h3>PIC Implementation</h3>
<p>A similar code for the PIC using XC8 can be implemented, where the DOUT pin is connected to RB0. Here, an LED connected to RB1 lights up when motion is detected:</p>
<pre class="lang:arduino decode:true"><pre><code class="language-cpp">#define _XTAL_FREQ 4000000
#include 

int main(){
    TRISB0 = 1;
    TRISB1 = 0;
    while(1){
        if(RB0){
            RB1 = RB0;
            __delay_ms(3000);
        }else{
            RB1 = 0;
        }
    }
}</code></pre></pre>
<p>The post <a href="https://www.teachmemicro.com/pir-motion-sensor/">PIR Motion Sensor</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/pir-motion-sensor/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How to Use L298N Motor Driver</title>
		<link>https://www.teachmemicro.com/use-l298n-motor-driver/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=use-l298n-motor-driver</link>
					<comments>https://www.teachmemicro.com/use-l298n-motor-driver/#comments</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Wed, 14 Mar 2018 06:26:59 +0000</pubDate>
				<category><![CDATA[Arduino Tutorial]]></category>
		<category><![CDATA[PIC Tutorial]]></category>
		<category><![CDATA[motor]]></category>
		<category><![CDATA[pwm]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=1637</guid>

					<description><![CDATA[<p>You can drive an LED on or off using a microcontroller like Arduino or PIC. There’s no problem there because the 20 mA or so current from the pins is enough. You can’t drive loads that require much more current like a motor. This is where the L298N motor controller comes in. Introduction The L298N &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/use-l298n-motor-driver/">How to Use L298N Motor Driver</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>You can drive an LED on or off using a microcontroller like <a href="https://www.teachmemicro.com/arduino-tutorials/">Arduino</a> or <a href="https://www.teachmemicro.com/pic-microcontroller-tutorials/">PIC</a>. There’s no problem there because the 20 mA or so current from the pins is enough. You can’t drive loads that require much more current like a motor. This is where the <a href="https://www.win-source.net/products/detail/stmicroelectronics/l298n.html">L298N</a> motor controller comes in.</p>
<p><span id="more-1637"></span></p>
<h3><strong>Introduction</strong></h3>
<p>The <a href="https://www.utmel.com/productdetail/stmicroelectronics-l298n-5052314">L298N</a> motor controller follows the H-bridge configuration, which is handy when controlling the direction of rotation of a DC motor. An H-bridge schematic looks like this:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-1638" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-1024x575.png" alt="H-bridge" width="618" height="347" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-1024x575.png 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-300x169.png 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-768x431.png 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-24x13.png 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-36x20.png 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge-48x27.png 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge.png 1853w" sizes="auto, (max-width: 618px) 100vw, 618px" /></p>
<p>Here, the motor rotates in the direction dictated by the switches. When S1 and S4 are on, the left motor terminal is more positive than the right terminal, and the motor rotates in a certain direction. On the other hand, when S2 and S3 are on, the right motor terminal is more positive than the left motor terminal, making the motor rotate in the other direction.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1639" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_.png" alt="H-bridge left and right" width="921" height="283" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_.png 921w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_-300x92.png 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_-768x236.png 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_-24x7.png 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_-36x11.png 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/H_bridge_operating.svg_-48x15.png 48w" sizes="auto, (max-width: 921px) 100vw, 921px" /></p>
<p>The other benefit of using an H-bridge is that you can provide a separate power supply to the motors. This is very significant, especially when using an Arduino board where the 5V power source is simply not enough for two DC motors.</p>
<h3><strong>The L298N IC</strong></h3>
<p>The L298N is an integrated circuit that follows the H-bridge concept. It comes in two IC packages: MultiWatt15 and PowerSO20. Here are the pinouts for each package:</p>
<p id="VXdDSOd"><img loading="lazy" decoding="async" width="459" height="525" class="size-full wp-image-3452 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b2cb02a15.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b2cb02a15.png 459w, https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b2cb02a15-262x300.png 262w" sizes="auto, (max-width: 459px) 100vw, 459px" /></p>
<p>&nbsp;</p>
<p style="text-align: left;">This <a href="https://www.utmel.com/category/integratedcircuitsics/pmicfullhalfbridgedrivers?cid=545">IC drives</a> two motors through two channels, A and B. For example, if a motor is using channel A, its terminals must be connected to pins <em>Out 1</em> and <em>Out 2</em>. The <em>Enable A</em> pin must be high to turn on the motor. To drive a motor to a direction, say, clockwise, the pin <em>Input 1</em> must be high while the pin <em>Input 2</em> must be low. To drive the motor counterclockwise, the pin <em>Input 1</em> is low while the pin <em>Input 2</em> is high.</p>
<p id="BbPIFzS"><img loading="lazy" decoding="async" width="668" height="293" class="size-full wp-image-3453 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b551cbce3.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b551cbce3.png 668w, https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b551cbce3-300x132.png 300w" sizes="auto, (max-width: 668px) 100vw, 668px" /></p>
<p>The diagram above shows an example diagram for using the L298N to drive one DC motor.</p>
<p>Here are the IC's ratings:</p>
<p id="TUCGuDS"><img loading="lazy" decoding="async" width="691" height="239" class="size-full wp-image-3454 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b815d086f.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b815d086f.png 691w, https://www.teachmemicro.com/wp-content/uploads/2019/05/img_5ce3b815d086f-300x104.png 300w" sizes="auto, (max-width: 691px) 100vw, 691px" /></p>
<p>The most notable feature here is its high power supply although its input pins follow lower voltage levels. This means you can power high voltage motors while controlling them with <a href="https://www.utmel.com/category/integratedcircuitsics/integratedcircuitsics-embeddedmicrocontrollers?cid=488">microcontrollers</a>.</p>
<p>More information about the L298N IC is found on its <a href="https://www.sparkfun.com/datasheets/Robotics/L298_H_Bridge.pdf">datasheet</a>.</p>
<p>For this tutorial, we will be focusing more on the L298N breakout board.</p>
<h3><strong>The L298N Motor Controller Board</strong></h3>
<p>As already mentioned, the L298N has four inputs corresponding to the four switches in the H-bridge diagram above. All you need to do is apply signals to the inputs to make the motor(s) rotate to a certain direction.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-1640" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-1024x835.jpg" alt="L298N motor controller board" width="618" height="504" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-1024x835.jpg 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-300x245.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-768x626.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-24x20.jpg 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-36x29.jpg 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated-48x39.jpg 48w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-H-Bridge-Motor-Controller-Annotated.jpg 1516w" sizes="auto, (max-width: 618px) 100vw, 618px" /></p>
<p>Using a breakout board is easier for prototyping compared to using the IC.</p>
<p>The controller board, shown above, has +12V and +5V terminals. The +12V pin is where the motor power is attached. This pin can accept voltages from +7VDC to +35VDC.</p>
<p><strong><span style="color: #ff0000;">Important note: remove the +12V jumper shown if you are using powers higher than +12V.</span></strong></p>
<p>When the +12V jumper is attached, the on-board voltage regulator is now enabled, and you can source +5V from the +5V terminal. <strong><em>This means the +5V terminal is not for powering the board but for connecting a device, say Arduino, that needs a 5V source.</em></strong></p>
<p>You have Motor A inputs and Motor B inputs. These connect to the microcontroller. The motor terminals connect to Motor Terminals 1, 2, 3, 4. Specifically, motor A connects to terminals 1 and 2 while Motor B connects to terminals 3 and 4.</p>
<p>There are also two other jumpers on the board, as shown. Remove these jumpers if you are using DC motors and keep it for <a href="https://sea.banggood.com/Nema17-59Ncm-2A-1_84-lead-48mm-Stepper-Motor-For-3D-Printer-CNC-p-1252415.html?p=RP091828734735201901&amp;custlinkid=208710">stepper motors</a>. Speed control for Motor A and Motor B is achieved via PWM on these pins. More on that later.</p>
<h3><strong>Connecting a DC Motor to the L298N Board</strong></h3>
<p>Here is a wiring diagram for connecting two DC motors to the L298N driver board.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1641" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors.png" alt="L298N board with motors attached" width="651" height="473" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors.png 651w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-300x218.png 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-24x17.png 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-36x26.png 36w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-48x35.png 48w" sizes="auto, (max-width: 651px) 100vw, 651px" /></p>
<p>Using the L298N is straightforward. If you want the left motor to rotate in one direction, apply a high pulse to IN1 and a low pulse to IN2. To reverse the direction, reverse the pulses to IN1 and IN2. The same applies to the right motor.</p>
<p>Here’s a table that summarizes the pins and corresponding motor direction. This assumes you are following the same Fritzing diagram above.</p>
<table>
<tbody>
<tr>
<td>IN1</td>
<td>IN2</td>
<td>IN3</td>
<td>IN4</td>
<td>Direction</td>
</tr>
<tr>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>Stop</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>1</td>
<td>0</td>
<td>Forward</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>Reverse</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>Left</td>
</tr>
<tr>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>Right</td>
</tr>
</tbody>
</table>
<h3><strong>Speed Control?</strong></h3>
<p>Speed control is also possible with the L298N motor driver. All you need is to feed PWM signals to the motor-enable pins. The speed of the motor will vary according to the width of the pulses. The wider the pulses, the faster the motor rotates. How fast the motor rotates for a given pulse width will vary from motor to motor even if they look the same. Thus, the actual pulse width must be derived through experiment.</p>
<h3><strong>Using the L298N with Arduino</strong></h3>
<p>An example diagram for connecting the L298N motor controller board to an Arduino is shown:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-scaled.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-4397" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-1024x524.jpg" alt="L298N Arduino Wiring Diagram" width="618" height="316" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-1024x524.jpg 1024w, https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-300x153.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-768x393.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-1536x786.jpg 1536w, https://www.teachmemicro.com/wp-content/uploads/2018/03/l298n-arduino-1-2048x1048.jpg 2048w" sizes="auto, (max-width: 618px) 100vw, 618px" /></a></p>
<p>You can attach the control pins to any digital (or even analog) pins. However, for motor speed control, the motor enable pins must be attached to a PWM-enabled pin. Here you see that the motor enable pins connect to pin 10 and pin 5, both of which are PWM pins.</p>
<p>Here’s an example Arduino sketch utilizing the diagram above:</p>
<pre class="lang:arduino decode:true "><pre><code class="language-cpp">//Motor Connections
//Change this if you wish to use another diagram
#define EnA 10
#define EnB 5
#define In1 9
#define In2 8
#define In3 7
#define In4 6


void setup()
{
  // All motor control pins are outputs
  pinMode(EnA, OUTPUT);
  pinMode(EnB, OUTPUT);
  pinMode(In1, OUTPUT);
  pinMode(In2, OUTPUT);
  pinMode(In3, OUTPUT);
  pinMode(In4, OUTPUT);
}
void goStraight()   //run both motors in the same direction
{
  // turn on motor A
  digitalWrite(In1, HIGH);
  digitalWrite(In2, LOW);
  // set speed to 150 out 255
  analogWrite(EnA, 200);
  // turn on motor B
  digitalWrite(In3, HIGH);
  digitalWrite(In4, LOW);
  // set speed to 150 out 255
  analogWrite(EnB, 200);
  delay(2000);
  // now turn off motors
  digitalWrite(In1, LOW);
  digitalWrite(In2, LOW);  
  digitalWrite(In3, LOW);
  digitalWrite(In4, LOW);
}
void loop()
{
  goStraight();
  delay(1000);
}</code></pre>
</pre>
<p>You can modify this sketch to include a function for going backward, turning left, and turning right. Just follow the table above.</p>
<h3><strong>Using the L298N with PIC </strong></h3>
<p>You can also use a PIC microcontroller with the L298N motor controller board. Here is an example diagram using the <a href="https://www.utmel.com/productdetail/microchiptechnology-pic16f877aipt-4814980">PIC16F877A</a>:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-1643 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-PIC.png" alt="L298N Board example with PIC" width="588" height="613" srcset="https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-PIC.png 588w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-PIC-288x300.png 288w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-PIC-24x24.png 24w, https://www.teachmemicro.com/wp-content/uploads/2018/03/L298N-Board-With-Motors-PIC-46x48.png 46w" sizes="auto, (max-width: 588px) 100vw, 588px" /></p>
<p>And here’s an XC8 code that does the same as the Arduino sketch above:</p>
<pre class="lang:arduino decode:true"><pre><code class="language-cpp">#define _XTAL_FREQ 4000000
#include &lt;xc.h&gt;
#include &quot;pwm.h&quot;


void goStraight(){
    //turn on motor A
    PORTBbits.RB0 = 1;
    PORTBbits.RB1 = 0;
    startPWM(1);     //pulse motor enable A      
    //turn on motor B
    PORTBbits.RB2 = 1;
    PORTBbits.RB3 = 0;
    startPWM(2);     //pulse motor enable B
    __delay_ms(2000);
    PORTBbits.RB0 = 0;
    PORTBbits.RB1 = 0;
    PORTBbits.RB2 = 0;
    PORTBbits.RB3 = 0;
    
}
void main(void) {
    
    TRISBbits.TRISB0 = 0;   //IN1
    TRISBbits.TRISB1 = 0;   //IN2
    TRISBbits.TRISB2 = 0;   //IN3
    TRISBbits.TRISB3 = 0;   //IN4
    initPWM(500, 50, 1);   //initialize PWM at 50% duty cycle, 500 Hz
    while(1){
        goStraight();
        __delay_ms(1000);
    }
    
    return;
}</code></pre></pre>
<p>You might need to read my <a href="https://www.teachmemicro.com/pic-microcontroller-tutorials/pic16-pwm/">PWM tutorial for PICs</a> to understand the code above.</p>
<p>I hope you find this tutorial helpful!</p>
<p>The post <a href="https://www.teachmemicro.com/use-l298n-motor-driver/">How to Use L298N Motor Driver</a> appeared first on <a href="https://www.teachmemicro.com">Microcontroller Tutorials</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/use-l298n-motor-driver/feed/</wfw:commentRss>
			<slash:comments>7</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: www.teachmemicro.com @ 2026-08-08 23:23:34 by W3 Total Cache
-->