<?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>8051 Tutorial Archives | Teach Me Microcontrollers!</title>
	<atom:link href="https://www.teachmemicro.com/category/8051-tutorial/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.teachmemicro.com/category/8051-tutorial/</link>
	<description>Microcontroller Tutorials and Resources</description>
	<lastBuildDate>Tue, 21 Jan 2025 01:04:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://www.teachmemicro.com/wp-content/uploads/2019/04/blue-icon-65x65.png</url>
	<title>8051 Tutorial Archives | Teach Me Microcontrollers!</title>
	<link>https://www.teachmemicro.com/category/8051-tutorial/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Interrupt Programming in 8051</title>
		<link>https://www.teachmemicro.com/interrupt-programming-in-8051/</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Tue, 21 Jan 2025 01:04:55 +0000</pubDate>
				<category><![CDATA[8051 Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=8044</guid>

					<description><![CDATA[<p>Interrupts are powerful features in microcontrollers that allow them to respond to events efficiently. The 8051 microcontroller supports several types of interrupts, enabling it to handle multiple tasks concurrently. In this tutorial, we’ll explore how to use interrupts in the 8051, including their configuration and usage, complete with an example code in C using Keil &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/interrupt-programming-in-8051/">Interrupt Programming in 8051</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400;"><a href="https://www.teachmemicro.com/arduino-interrupt-tutorial/">Interrupts</a> are powerful features in microcontrollers that allow them to respond to events efficiently. The 8051 microcontroller supports several types of interrupts, enabling it to handle multiple tasks concurrently. In this tutorial, we’ll explore how to use interrupts in the 8051, including their configuration and usage, complete with an example code in C using Keil C51.</span></p>
<p><span id="more-8044"></span></p>
<h3><b>Overview of 8051 Interrupts</b></h3>
<p><span style="font-weight: 400;">The 8051 microcontroller has five interrupt sources:</span></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>External Interrupt 0 (INT0)</b><span style="font-weight: 400;">: Triggered by a signal on pin P3.2.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Timer 0 Overflow Interrupt (TF0)</b><span style="font-weight: 400;">: Triggered when Timer 0 overflows.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>External Interrupt 1 (INT1)</b><span style="font-weight: 400;">: Triggered by a signal on pin P3.3.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Timer 1 Overflow Interrupt (TF1)</b><span style="font-weight: 400;">: Triggered when Timer 1 overflows.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Serial Communication Interrupt (RI/TI)</b><span style="font-weight: 400;">: Triggered by the completion of data reception or transmission.</span></li>
</ol>
<h4><b>Interrupt Vector Table</b></h4>
<p><span style="font-weight: 400;">Each interrupt has a specific location in the memory where its service routine begins. This is called the interrupt vector address.</span></p>
<table>
<tbody>
<tr>
<td><b>Interrupt Source</b></td>
<td><b>Vector Address</b></td>
</tr>
<tr>
<td><span style="font-weight: 400;">External Interrupt 0 (INT0)</span></td>
<td><span style="font-weight: 400;">0x0003</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Timer 0 Overflow Interrupt</span></td>
<td><span style="font-weight: 400;">0x000B</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">External Interrupt 1 (INT1)</span></td>
<td><span style="font-weight: 400;">0x0013</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Timer 1 Overflow Interrupt</span></td>
<td><span style="font-weight: 400;">0x001B</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Serial Communication Interrupt</span></td>
<td><span style="font-weight: 400;">0x0023</span></td>
</tr>
</tbody>
</table>
<h3><b>Enabling Interrupts</b></h3>
<p><span style="font-weight: 400;">The 8051 uses the Interrupt Enable (IE) and Interrupt Priority (IP) registers to control interrupt behavior.</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>IE Register</b><span style="font-weight: 400;">: Enables or disables specific interrupts.</span>
<ul>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">EA: Global enable/disable.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">ET0: Enable Timer 0 interrupt.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">EX0: Enable External Interrupt 0.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">ET1: Enable Timer 1 interrupt.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">EX1: Enable External Interrupt 1.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">ES: Enable Serial interrupt.</span></li>
</ul>
</li>
<li style="font-weight: 400;" aria-level="1"><b>IP Register</b><span style="font-weight: 400;">: Sets priority levels for interrupts.</span>
<ul>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">PT0: Priority for Timer 0.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">PX0: Priority for External Interrupt 0.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">PT1: Priority for Timer 1.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">PX1: Priority for External Interrupt 1.</span></li>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">PS: Priority for Serial interrupt.</span></li>
</ul>
</li>
</ul>
<h3><b>Writing an Interrupt Service Routine (ISR)</b></h3>
<p><span style="font-weight: 400;">An ISR is a special function that executes when an interrupt occurs. In C, the </span><span style="font-weight: 400;">interrupt</span><span style="font-weight: 400;"> keyword is used to define an ISR, followed by the interrupt vector number.</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>void timer0_ISR(void) interrupt 1 {
    // Code to execute when Timer 0 overflows
}</code></pre>
</div>
<h3><b>Example: Blinking an LED Using Timer 0 Interrupt</b></h3>
<p><span style="font-weight: 400;">In this example, we use Timer 0's interrupt to toggle an LED every 50 milliseconds.</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include &lt;reg51.h&gt;  // Include 8051 header file

void timer0_ISR(void) interrupt 1;

void main() {
    TMOD = 0x01;       // Timer 0 in Mode 1 (16-bit mode)
    TH0 = 0xFC;        // Load high byte for 50ms delay at 12 MHz
    TL0 = 0x66;        // Load low byte for 50ms delay at 12 MHz
    ET0 = 1;           // Enable Timer 0 interrupt
    EA = 1;            // Enable global interrupts
    TR0 = 1;           // Start Timer 0

    while (1) {
        // Main loop doing other tasks
    }
}

void timer0_ISR(void) interrupt 1 {
    P1 = ~P1;          // Toggle Port 1
    TH0 = 0xFC;        // Reload high byte
    TL0 = 0x66;        // Reload low byte
}</code></pre>
</div>
<h3><b>Explanation of the Code</b></h3>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>Timer Initialization</b><span style="font-weight: 400;">: Timer 0 is configured in Mode 1 (16-bit timer mode) using the </span><span style="font-weight: 400;">TMOD</span><span style="font-weight: 400;"> register.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Interrupt Enabling</b><span style="font-weight: 400;">: The </span><span style="font-weight: 400;">ET0</span><span style="font-weight: 400;"> bit enables the Timer 0 interrupt, and the </span><span style="font-weight: 400;">EA</span><span style="font-weight: 400;"> bit enables global interrupts.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>ISR</b><span style="font-weight: 400;">: The </span><span style="font-weight: 400;">timer0_ISR</span><span style="font-weight: 400;"> function toggles Port 1 every time Timer 0 overflows.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Reloading Timer</b><span style="font-weight: 400;">: The timer registers (</span><span style="font-weight: 400;">TH0</span><span style="font-weight: 400;"> and </span><span style="font-weight: 400;">TL0</span><span style="font-weight: 400;">) are reloaded in the ISR to maintain consistent timing.</span></li>
</ol>
<h3><b>External Interrupt Example</b></h3>
<p><span style="font-weight: 400;">Here’s an example of using External Interrupt 0 to turn an LED on or off based on a button press.</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include &lt;REGX51.H&gt;

void external0_ISR(void) interrupt 0;

void main() {
    IT0 = 1;          // Configure INT0 for edge-triggered mode
    EX0 = 1;          // Enable External Interrupt 0
    EA = 1;           // Enable global interrupts
    P1 = 0x00;        // Initialize Port 1 to OFF

    while (1) {
        // Main loop doing other tasks
    }
}

void external0_ISR(void) interrupt 0 {
  P1 = ~P1;         // Toggle Port 1
}</code></pre>
</div>
<h3><b>Applications of Interrupts</b></h3>
<p><span style="font-weight: 400;">Interrupts allow microcontrollers to respond to real-time events efficiently. Common applications include:</span></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>Real-Time Clock</b><span style="font-weight: 400;">: Generating periodic interrupts for timekeeping.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Input Event Handling</b><span style="font-weight: 400;">: Responding to button presses or sensor signals.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Communication</b><span style="font-weight: 400;">: Handling data transmission and reception.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Multitasking</b><span style="font-weight: 400;">: Managing concurrent tasks in embedded systems.</span></li>
</ol>
<h3><b>Conclusion</b></h3>
<p><span style="font-weight: 400;">Interrupt programming is a cornerstone of embedded system development. By understanding how to configure and use interrupts in the 8051, you can create responsive and efficient applications. Practice using different interrupt sources and experiment with priority settings to master this essential skill.</span></p>
<p>The post <a href="https://www.teachmemicro.com/interrupt-programming-in-8051/">Interrupt Programming in 8051</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Timers in 8051</title>
		<link>https://www.teachmemicro.com/using-timers-in-8051/</link>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Sat, 18 Jan 2025 01:00:11 +0000</pubDate>
				<category><![CDATA[8051 Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=7962</guid>

					<description><![CDATA[<p>Timers are among the most essential peripherals in any microcontroller, and the 8051 is no exception. With two built-in 16-bit timers (Timer 0 and Timer 1), the 8051 can perform a variety of timing tasks, such as creating delays, measuring time intervals, and generating pulses. In this tutorial, we’ll discuss the configuration and usage of &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/using-timers-in-8051/">Using Timers in 8051</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400;">Timers are among the most essential peripherals in any microcontroller, and the <a href="https://www.teachmemicro.com/8051-microcontroller-introduction/">8051</a> is no exception. With two built-in 16-bit timers (Timer 0 and Timer 1), the 8051 can perform a variety of timing tasks, such as creating delays, measuring time intervals, and generating pulses. In this tutorial, we’ll discuss the configuration and usage of these timers, complete with an example code in C using Keil C51.</span></p>
<p><span id="more-7962"></span></p>
<h3><b>Overview of 8051 Timers</b></h3>
<p><span style="font-weight: 400;">The 8051 microcontroller has two timers, Timer 0 and Timer 1. Both timers are 16-bit registers, meaning they can count from 0 to 65,535. They can operate in several modes, allowing for different functionalities:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>Mode 0</b><span style="font-weight: 400;">: 13-bit timer/counter.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Mode 1</b><span style="font-weight: 400;">: 16-bit timer/counter.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Mode 2</b><span style="font-weight: 400;">: 8-bit auto-reload timer/counter.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Mode 3</b><span style="font-weight: 400;">: Split timer mode (Timer 0 only).</span></li>
</ul>
<h3><b>Timer Registers</b></h3>
<p><span style="font-weight: 400;">Each timer has the following associated registers:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>THx</b><span style="font-weight: 400;">: High byte of the timer.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>TLx</b><span style="font-weight: 400;">: Low byte of the timer.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>TMOD</b><span style="font-weight: 400;">: Timer Mode register for selecting the mode of operation.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>TCON</b><span style="font-weight: 400;">: Timer Control register for starting, stopping, and monitoring the timer.</span></li>
</ul>
<h3><b>Configuring the Timer</b></h3>
<p><span style="font-weight: 400;">The steps to use a timer in 8051 are as follows:</span></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>Select the Mode</b><span style="font-weight: 400;">: Use the </span><span style="font-weight: 400;">TMOD</span><span style="font-weight: 400;"> register to configure the desired mode for the timer.</span>
<ul>
<li style="font-weight: 400;" aria-level="2"><span style="font-weight: 400;">When selecting a timer mode, avoid directly overwriting the </span><span style="font-weight: 400;">TMOD</span><span style="font-weight: 400;"> register, as it controls both Timer 0 and Timer 1. Instead, use a bitwise operation to preserve the settings of the other timer. For example, to set Timer 0 to Mode 1 without affecting Timer 1:</span><span style="font-weight: 400;"><br />
</span></p>
<pre><span style="font-weight: 400;">TMOD = (TMOD &amp; 0xF0) | 0x01; // Set Timer 0 to Mode 1</span></pre>
<p><span style="font-weight: 400;">Here:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="3"><span style="font-weight: 400;">(TMOD &amp; 0xF0)</span><span style="font-weight: 400;"> clears the lower 4 bits (related to Timer 0) while retaining the upper 4 bits (related to Timer 1).</span></li>
<li style="font-weight: 400;" aria-level="3"><span style="font-weight: 400;">| 0x01</span><span style="font-weight: 400;"> sets Timer 0 to Mode 1.</span></li>
</ul>
</li>
</ul>
</li>
<li style="font-weight: 400;" aria-level="1"><b>Load Initial Value</b><span style="font-weight: 400;">: Load the initial count value into the </span><span style="font-weight: 400;">THx</span><span style="font-weight: 400;"> and </span><span style="font-weight: 400;">TLx</span><span style="font-weight: 400;"> registers.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Start the Timer</b><span style="font-weight: 400;">: Set the appropriate bit in the </span><span style="font-weight: 400;">TCON</span><span style="font-weight: 400;"> register to start the timer.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Monitor or Interrupt</b><span style="font-weight: 400;">: Poll the timer overflow flag or use an interrupt to handle the overflow event.</span></li>
</ol>
<h3><b>Example: Creating a Delay Using Timer 0</b></h3>
<p><span style="font-weight: 400;">In this example, we’ll create a delay of approximately 1 millisecond using Timer 0 in Mode 1.</span></p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include &lt;reg51.h&gt;  // Include 8051 header file

void delay_ms(unsigned int ms); // this will be a new delay function using timer

void main() {
    while (1) {
        P1 = 0xFF;  // Turn ON all LEDs connected to Port 1
        delay_ms(1000);  // 1-second delay
        P1 = 0x00;  // Turn OFF all LEDs connected to Port 1
        delay_ms(1000);  // 1-second delay
    }
}

void delay_ms(unsigned int ms) {
    unsigned int i;
    for (i = 0; i &lt; ms; i++) {
        TMOD = (TMOD &amp; 0xF0) | 0x01;  // Timer 0 in Mode 1 (16-bit mode)
        TH0 = 0xFC;   // Load high byte (for 1 ms delay at 12 MHz)
        TL0 = 0x66;   // Load low byte (for 1 ms delay at 12 MHz)
        TR0 = 1;      // Start Timer 0
        while (TF0 == 0);  // Wait for overflow flag
        TR0 = 0;      // Stop Timer 0
        TF0 = 0;      // Clear overflow flag
    }
}</code></pre>
</div>
<h3><b>Explanation of the Code</b></h3>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>Timer Mode Selection</b><span style="font-weight: 400;">: The </span><span style="font-weight: 400;">TMOD</span><span style="font-weight: 400;"> register is set using bitwise operations to select Timer 0 in Mode 1 (16-bit timer mode) without affecting Timer 1.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Timer Initialization</b><span style="font-weight: 400;">: The values </span><span style="font-weight: 400;">0xFC66</span><span style="font-weight: 400;"> are loaded into </span><span style="font-weight: 400;">TH0</span><span style="font-weight: 400;"> and </span><span style="font-weight: 400;">TL0</span><span style="font-weight: 400;">, respectively. This corresponds to a delay of 1 millisecond at a 12 MHz clock frequency.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Starting and Stopping the Timer</b><span style="font-weight: 400;">: The </span><span style="font-weight: 400;">TR0</span><span style="font-weight: 400;"> bit in the </span><span style="font-weight: 400;">TCON</span><span style="font-weight: 400;"> register is used to start and stop Timer 0.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Overflow Flag</b><span style="font-weight: 400;">: The </span><span style="font-weight: 400;">TF0</span><span style="font-weight: 400;"> flag in the </span><span style="font-weight: 400;">TCON</span><span style="font-weight: 400;"> register is polled to check when the timer overflows.</span></li>
</ul>
<h3><b>Applications of Timers</b></h3>
<p><span style="font-weight: 400;">Timers in the 8051 can be used for:</span></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>Creating Time Delays</b><span style="font-weight: 400;">: As demonstrated in the example above.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Pulse Width Modulation (PWM)</b><span style="font-weight: 400;">: Generating variable-width pulses for motor control or LED dimming.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Event Counting</b><span style="font-weight: 400;">: Counting external events when configured in counter mode.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Baud Rate Generation</b><span style="font-weight: 400;">: Used in conjunction with serial communication for baud rate control.</span></li>
</ol>
<h3><b>Timer Modes in Detail</b></h3>
<ol>
<li style="font-weight: 400;" aria-level="1"><b>Mode 0</b><span style="font-weight: 400;">: A 13-bit timer that counts from 0x0000 to 0x1FFF.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Mode 1</b><span style="font-weight: 400;">: A full 16-bit timer that counts from 0x0000 to 0xFFFF.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Mode 2</b><span style="font-weight: 400;">: An 8-bit timer with auto-reload. The value in </span><span style="font-weight: 400;">THx</span><span style="font-weight: 400;"> is reloaded into </span><span style="font-weight: 400;">TLx</span><span style="font-weight: 400;"> after overflow.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Mode 3</b><span style="font-weight: 400;">: Splits Timer 0 into two 8-bit timers. Timer 1 remains inactive in this mode.</span></li>
</ol>
<h3><b>Conclusion</b></h3>
<p><span style="font-weight: 400;">Timers are versatile peripherals that greatly enhance the functionality of the 8051 microcontroller. Whether you're creating delays, measuring time intervals, or generating pulses, understanding how to configure and use timers is essential for embedded development. Experiment with different timer modes and applications to fully harness the power of the 8051 microcontroller!</span></p>
<p>&nbsp;</p>
<p>The post <a href="https://www.teachmemicro.com/using-timers-in-8051/">Using Timers in 8051</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>8051 Serial Interface Tutorial</title>
		<link>https://www.teachmemicro.com/8051-serial-interface-tutorial/</link>
					<comments>https://www.teachmemicro.com/8051-serial-interface-tutorial/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Thu, 01 Apr 2021 02:43:43 +0000</pubDate>
				<category><![CDATA[8051 Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=5048</guid>

					<description><![CDATA[<p>We continue with our series on the 8051 with a tutorial on serial transmission. Data communications via the serial port is an easy way for a microcontroller to ‘talk’ with the outside world. Examples of devices that have serial interfaces are sensors, LCDs, EEPROM, SD cards, and RTCs. Here, I will be skipping the basics &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/8051-serial-interface-tutorial/">8051 Serial Interface Tutorial</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>We continue with our series on the 8051 with a tutorial on serial transmission. Data communications via the serial port is an easy way for a microcontroller to ‘talk’ with the outside world. Examples of devices that have serial interfaces are <a href="https://www.teachmemicro.com/how-dht22-sensor-works/">sensors</a>, <a href="https://www.teachmemicro.com/arduino-i2c-lcd/">LCDs</a>, <a href="https://www.ampheo.com/blog/eeprom-vs-flash-main-differences-between-them.html">EEPROM</a>, <a href="https://www.teachmemicro.com/using-microsd-breakout-board-arduino/">SD cards</a>, and <a href="https://www.win-source.net/category/integrated-circuits-ics/clock-timing/clock-timing-real-time-clocks">RTCs</a>.</p>
<p><span id="more-5048"></span></p>
<p>Here, I will be skipping the <a href="https://www.teachmemicro.com/microcontroller-serial-communication/">basics of serial communications</a> and proceed directly on how to use it with 8051 and the C language. In particular, we will be focusing on the RS-232 protocol.</p>
<h3><strong>8051 Registers for Hardware UART</strong></h3>
<p>8051 contains a number of registers that give the <a href="https://www.ampheo.com/c/microcontrollers">microcontroller</a> a certain feature. This is also true with other MCUs like <a href="https://www.teachmemicro.com/serial-usart-pic16f877a/">PIC</a>, <a href="https://www.ampheo.com/product/stmicroelectronics-stm32mp135fae7-14714">STM32</a>, and AVR (Arduino). To be able to use the 8051’s serial port, we need to use a number of registers.</p>
<h4><strong>Serial Port Control</strong></h4>
<p>The first register is the <strong>SCON or Serial Port Control Register</strong>. It is an 8-bit register with each bit having their own use:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/SCON-register.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5049" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/SCON-register.jpg" alt="SCON register" width="846" height="570" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/04/SCON-register.jpg 846w, https://www.teachmemicro.com/wp-content/uploads/2021/04/SCON-register-300x202.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2021/04/SCON-register-768x517.jpg 768w, https://www.teachmemicro.com/wp-content/uploads/2021/04/SCON-register-110x75.jpg 110w" sizes="auto, (max-width: 846px) 100vw, 846px" /></a></p>
<p>The important bits here are <em>SM0</em> and <em>SM1</em> as they set the serial mode of 8051. There are four modes as shown above (NOTE 1).</p>
<p>For this example, we will be using Mode 1 and leave the rest of the bits as clear. However, take special note of bit T1 as we will be also using that later.</p>
<h4><strong>Timer/Counter Mode Control</strong></h4>
<p>Serial communication requires that both transmitter and receiver are in sync. For the RS232 protocol, the only way to sync is that both TX and RX have the same baud rate. The 8051 has its own baud rate generator and requires the use of one of the two timer modules.</p>
<p>And so, the next register that we need is the <strong>TMOD or Timer/Counter Mode Control register</strong>. Here are the bits of this register:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/TMOD-register.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5050" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/TMOD-register.jpg" alt="TMOD register" width="828" height="508" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/04/TMOD-register.jpg 828w, https://www.teachmemicro.com/wp-content/uploads/2021/04/TMOD-register-300x184.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2021/04/TMOD-register-768x471.jpg 768w" sizes="auto, (max-width: 828px) 100vw, 828px" /></a></p>
<p>The register is divided into two parts, depending on which timer we will use. For this tutorial, we will be using <em>Timer 1</em>. Hence, our concern is only the high byte of TMOD. We are selecting <em>Mode 2;</em> we set bit M1, and clear bit M0. More on this mode later below.</p>
<h4><strong>Power Control Register</strong></h4>
<p>Next, we have the <strong>PCON register</strong>. We only have one bit to use here and that’s the SMOD bit:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/PCON-register.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5051" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/PCON-register.jpg" alt="PCON register" width="810" height="345" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/04/PCON-register.jpg 810w, https://www.teachmemicro.com/wp-content/uploads/2021/04/PCON-register-300x128.jpg 300w, https://www.teachmemicro.com/wp-content/uploads/2021/04/PCON-register-768x327.jpg 768w" sizes="auto, (max-width: 810px) 100vw, 810px" /></a></p>
<p>When SMOD is 1, the baud rate is doubled. Otherwise, the baud rate stays the same.</p>
<h4><strong>Timer/Counter Control Register</strong></h4>
<p>Since the serial port relies on Timer 1, we need to enable it by setting the TR1 bit of the <strong>TCON register</strong>:</p>
<p><img loading="lazy" decoding="async" width="805" height="381" class="size-full wp-image-5062 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/img_606535e2e1c99.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/04/img_606535e2e1c99.png 805w, https://www.teachmemicro.com/wp-content/uploads/2021/04/img_606535e2e1c99-300x142.png 300w, https://www.teachmemicro.com/wp-content/uploads/2021/04/img_606535e2e1c99-768x363.png 768w" sizes="auto, (max-width: 805px) 100vw, 805px" /></p>
<h4><strong>Other Registers</strong></h4>
<p>Finally, we have registers TH0, TL0, TH1, and TL1. These registers represent the high byte and low byte of 16-bit timers 0 and 1. Recall that we choose Timer 1 via TMOD register. Moreover, we choose <em>Mode 2: 8-bit auto-reload</em>. This mode allows us to modify only TH1 since TL1 is loaded from TH1 at the beginning of each cycle.</p>
<p>&nbsp;</p>
<h3><strong>Baud Rate Calculation</strong></h3>
<p>The 8051 baud rate formula is:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/8051-actual-baud-formula.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5052" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/8051-actual-baud-formula.gif" alt="8051 baud rate formula" width="261" height="45" /></a></p>
<p>Where FOSC is the 8051's crystal oscillator and TH1 the high byte value of Timer 1. What we want is to specify the value of TH1 for our target baud rate. So, reversing the formula:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/TH1-formula.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5053" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/TH1-formula.gif" alt="TH1 formula" width="268" height="43" /></a></p>
<p>For example, to achieve a baud rate of 2400 with a 12 MHz crystal, your TH1 value should be (SMOD=0):</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/TH1-calculation.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5054" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/TH1-calculation.gif" alt="TH1 calculation at 2400 baud" width="242" height="41" /></a></p>
<p>Remember that TH1 is an 8-bit register and holds integers only.</p>
<p>The actual baud rate is then:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/actual-baud-calculation.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5055" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/actual-baud-calculation.gif" alt="" width="307" height="46" /></a></p>
<p>It’s not exactly 2400 but with just 0.16% of deviation, it works.</p>
<h3><strong>C Code for 8051 Serial Interfacing</strong></h3>
<p>Here’s a C code that prints out Hello World! through the serial port at 2400 baud:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include &lt;reg51.h&gt;
#include &lt;stdio.h&gt;

#define FOSC 12000000

void serial_init(unsigned long int baud)
{
  unsigned long int divisor = 256 - (FOSC/(384*baud));
  SCON = 0x40;                      
  TMOD = 0x20;                           /* TMOD: timer 1, mode 2, 8-bit reload      */
  TH1 = divisor;			 /* load divisor to Timer 1 High Byte (TH1)  */
  TR1   = 1;                             /* TR1:  timer 1 run                        */
  TI    = 1;                             /* TI:   set TI to send first char of UART  */
}
	
void main (void)
{
  serial_init(2400);
  while(1)
  {
    printf("Hello world!\n");
  }
}</code></pre>
</div>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/serial-output-hello.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5056" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/serial-output-hello.gif" alt="8051 serial output simulation" width="600" height="342" /></a></p>
<p>Here we define a function that initializes the hardware UART:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>void serial_init(unsigned long int baud) 
{ 
  unsigned long int divisor = 256 - (FOSC/(384*baud)); 
  SCON = 0x40; 
  TMOD = 0x20;       /* TMOD: timer 1, mode 2, 8-bit reload */ 
  TH1 = divisor;     /* load divisor to Timer 1 High Byte (TH1) */ 
  TR1 = 1;           /* TR1: timer 1 run */ 
  TI = 1;            /* TI: set TI to send first char of UART */ 
}</code></pre>
</div>
<p>This function is called in <em>main()</em> where its parameter is the desired baud rate:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>void main (void) 
{ 
   serial_init(2400);
   while(1) 
   {
       printf("Hello world!\n"); 
   } 
}</code></pre>
</div>
<p>Also notice that we use the function <em>printf()</em> which belongs to the <em>stdio</em> library, hence the added definition at the top of the code. Remember bit TI in SCON? The <em>printf() </em>function uses that bit to determine when to start or stop sending characters on the serial port. If TI is not set, the <em>print()</em> function will not work.</p>
<p><em><strong>While we were able to make it work at 2400 baud, other baud rates may not work. </strong></em></p>
<p>For example, choosing 9600 baud will generate the following value for TH1:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/TH1-baud-9600.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5057" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/TH1-baud-9600.gif" alt="" width="246" height="41" /></a></p>
<p>Calculating the actual baud rate using this TH1 value:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/04/baud-9600.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5058" src="https://www.teachmemicro.com/wp-content/uploads/2021/04/baud-9600.gif" alt="" width="316" height="46" /></a></p>
<p>That’s an 8.5% difference from the desired baud rate of 9600! Your options for this one would be to try changing the crystal oscillator, use a different timer and/or apply the SMOD bit.</p>
<p>You could try <a href="https://www.keil.com/products/c51/baudrate.asp">Keil’s baud rate generator</a> to determine the best oscillator value for your target baud rate. For example, using 11.0952 MHz at mode 2 and SMOD = 0 generates a rate of 9,631.25 which is at 0.33% deviation for the standard 9600 baud.</p>
<p>That's it for this tutorial! See you in the next part of this 8051 series.</p>
<p>The post <a href="https://www.teachmemicro.com/8051-serial-interface-tutorial/">8051 Serial Interface Tutorial</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/8051-serial-interface-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Interfacing Seven Segment Displays with 8051</title>
		<link>https://www.teachmemicro.com/interfacing-seven-segment-displays-8051/</link>
					<comments>https://www.teachmemicro.com/interfacing-seven-segment-displays-8051/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Thu, 18 Mar 2021 03:58:16 +0000</pubDate>
				<category><![CDATA[8051 Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=5027</guid>

					<description><![CDATA[<p>In my previous post, I showed you how to set up an 8051 microcontroller for programming using C. This tutorial will be about how to interface with seven-segment displays. Review on Seven Segment Displays A seven-segment display consists of LEDs in parallel. This way, each LED or "segment" can be turned on or off. Recall &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/interfacing-seven-segment-displays-8051/">Interfacing Seven Segment Displays with 8051</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In my <a href="https://www.teachmemicro.com/8051-microcontroller-introduction/">previous post</a>, I showed you how to set up an 8051 <a href="https://www.ersaelectronics.com/c/microcontrollers">microcontroller</a> for programming using C. This tutorial will be about how to interface with <a href="https://www.win-source.net/category/optoelectronics/display-modules/display-modules-led-character-and-numeric">seven-segment displays</a>.</p>
<p><span id="more-5027"></span></p>
<h3><strong>Review on Seven Segment Displays</strong></h3>
<p>A <a href="https://ph.banggood.com/custlink/DmGEOvpIMY">seven-segment display</a> consists of <a href="https://www.ersaelectronics.com/c/optoelectronics">LEDs</a> in parallel. This way, each LED or "segment" can be turned on or off. Recall that an LED emits light when the anode voltage is more positive than the cathode voltage.</p>
<p id="ENXAAZF">In a <em>common cathode</em> seven-segment display, each anode of the LEDs is accessible while all LED cathodes connect into one pin. The anode pins are given labels A to G. The opposite is true for a <em>common anode</em> display. Here, we will limit ourselves to common cathode displays.</p>
<p><img decoding="async" class="aligncenter" src="https://www.allaboutcircuits.com/uploads/articles/SSD_circuit_new.jpg" alt="Interface a Seven Segment Display to an Arduino - Projects" /></p>
<p id="vGebhBZ">To display a number in a seven-segment display, the correct LEDs should light up. Hence if each anode connects to a pin in the 8051 microcontroller, digits 0 to 9 corresponds to an 8-bit value of a port.</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/03/7-seg-to-8-bit.jpg"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5039" src="https://www.teachmemicro.com/wp-content/uploads/2021/03/7-seg-to-8-bit.jpg" alt="7 seg to 8-bit value" width="808" height="865" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/03/7-seg-to-8-bit.jpg 808w, https://www.teachmemicro.com/wp-content/uploads/2021/03/7-seg-to-8-bit-280x300.jpg 280w, https://www.teachmemicro.com/wp-content/uploads/2021/03/7-seg-to-8-bit-768x822.jpg 768w" sizes="auto, (max-width: 808px) 100vw, 808px" /></a></p>
<p>Here’s a table showing all 8-bit values for digits 0 to 9, assuming segment A wires to the port’s LSB.</p>
<p id="jakOiMf"><img loading="lazy" decoding="async" width="681" height="407" class="size-full wp-image-5029 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/03/img_6052c165b011c.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/03/img_6052c165b011c.png 681w, https://www.teachmemicro.com/wp-content/uploads/2021/03/img_6052c165b011c-300x179.png 300w" sizes="auto, (max-width: 681px) 100vw, 681px" /></p>
<p>Based on the table above, we create a function that accepts a digit as a parameter and returns the corresponding 8-bit value.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>int toSevenSeg(int num)
{
  switch(num){
    case 0:
        return 0x3F;
        break;
    case 1:
        return 0x06;
        break;
    case 2:
        return 0x5B;
        break;
    case 3:
        return 0x4F;
        break;
    case 4:
        return 0x66;
        break;
    case 5:
        return 0x6D;
        break;
    case 6:
        return 0x7C;
        break;
    case 7:
        return 0x07;
        break;
    case 8: 
        return 0x7F;
        break;
   case 9:
        return 0x67;
        break;
   default:
        return 0x64; //return dash if invalid
   }
}</code></pre>
</div>
<p>The function returns an integer and so we can pass it directly to any port.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>P2 = toSevenSeg(x);</code></pre>
</div>
<h3><strong>8051 Code for Interfacing with One Display</strong></h3>
<p>The example code below shows the digits 0 to 9 in succession with a second interval in between.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include&lt;reg51.h&gt;           // special function register declarations
                            // for the intended 8051 derivative

// delay subroutine
void DELAY_ms(unsigned int ms_Count)
{
    unsigned int i,j;
    for(i=0;i&lt;ms_Count;i++)
    {
        for(j=0;j&lt;100;j++);
    }
}

// seven-segment converter routine
int toSevenSeg(int num)
{
  switch(num){
    case 0:
        return 0x3F;
        break;
    case 1:
        return 0x06;
        break;
    case 2:
        return 0x5B;
        break;
    case 3:
        return 0x4F;
        break;
    case 4:
        return 0x66;
        break;
    case 5:
        return 0x6D;
        break;
    case 6:
        return 0x7C;
        break;
    case 7:
        return 0x07;
        break;
    case 8: 
        return 0x7F;
        break;
   case 9:
        return 0x67;
        break;
   default:
        return 0x64; //return dash if invalid
   }
}
// main routine
int main() 
{
    unsigned int x;
    while(1)
    {
        //display digits 0 to 9 with 1 second interval
        for(x=0;x&lt;10;x++)
        {
	    P2 = toSevenSeg(x);
	    DELAY_ms(1000);
	}
    }
    return (0);
}
</code></pre>
</div>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/03/8051-single-seven-segment.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5032" src="https://www.teachmemicro.com/wp-content/uploads/2021/03/8051-single-seven-segment.gif" alt="8051 with single seven segment display" width="540" height="406" /></a></p>
<h3><strong>8051 Code for Interfacing with Multiple Displays</strong></h3>
<p>We can use multiple seven-segment displays by connecting the common cathode pin to a microcontroller pin. This way, we can multiplex the displays using the common cathode pin as the switch. The switching should be fast enough to trick our eyes that all displays are on simultaneously instead of alternating. This is also called <em><a href="https://www.teachmemicro.com/pov-seven-segment-displays/">persistence of vision</a></em>.</p>
<p>Here is a code that uses two seven-segment displays to count from 00 to 99.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include&lt;reg51.h&gt;           // special function register declarations
                            // for the intended 8051 derivative
sbit SW1 = P3^0;
sbit SW2 = P3^1;

// speed between display switch
#define SWITCH_SPEED 40
// speed between counts
#define COUNT_SPEED 15

// delay subroutine
void DELAY_ms(unsigned int ms_Count)
{
    unsigned int i,j;
    for(i=0;i&lt;ms_Count;i++)
    {
        for(j=0;j&lt;100;j++);
    }
}

// seven-segment converter routine
int toSevenSeg(int num)
{
  switch(num){
    case 0:
        return 0x3F;
        break;
    case 1:
        return 0x06;
        break;
    case 2:
        return 0x5B;
        break;
    case 3:
        return 0x4F;
        break;
    case 4:
        return 0x66;
        break;
    case 5:
        return 0x6D;
        break;
    case 6:
        return 0x7C;
        break;
    case 7:
        return 0x07;
        break;
    case 8: 
        return 0x7F;
        break;
   case 9:
        return 0x67;
        break;
   default:
        return 0x64;  //return dash if invalid
   }
}
// main routine
int main() 
{
    unsigned int ones, tens, counter;
    ones = 0;
    tens = 0;
    counter = 0;
    while(1)
    {
	SW1 = 1;
	SW2 = 0;
	P2 = toSevenSeg(ones);
	DELAY_ms(SWITCH_SPEED);
	SW1 = 0;
	SW2 = 1;
	P2 = toSevenSeg(tens);
	DELAY_ms(SWITCH_SPEED);
	counter++;
	if(counter &gt; COUNT_SPEED)
        {
	    ones++;
	    counter = 0;
	}
	if(ones &gt; 9)
        { 
	    tens++;
	    ones = 0;
	}
	if(tens &gt; 9) tens = 0;
   }
   return (0);
}</code></pre>
</div>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/03/8051-dual-seven-segment.gif"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-5033" src="https://www.teachmemicro.com/wp-content/uploads/2021/03/8051-dual-seven-segment.gif" alt="8051 with two seven segment displays" width="540" height="355" /></a></p>
<p>The <em>SWITCH_SPEED </em>and <em>COUNT_SPEED </em>for the code above should be chosen after testing the actual physical circuit. SWITCH_SPEED is the time interval between turning on one display and then turning on the other. COUNT_SPEED is the speed of the counting.</p>
<p>For questions regarding this tutorial, please drop a comment below!</p>
<p>The post <a href="https://www.teachmemicro.com/interfacing-seven-segment-displays-8051/">Interfacing Seven Segment Displays with 8051</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/interfacing-seven-segment-displays-8051/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Introduction to 8051 Microcontroller using C</title>
		<link>https://www.teachmemicro.com/8051-microcontroller-introduction/</link>
					<comments>https://www.teachmemicro.com/8051-microcontroller-introduction/#respond</comments>
		
		<dc:creator><![CDATA[Roland Pelayo]]></dc:creator>
		<pubDate>Sat, 13 Feb 2021 00:03:42 +0000</pubDate>
				<category><![CDATA[8051 Tutorial]]></category>
		<guid isPermaLink="false">https://www.teachmemicro.com/?p=4924</guid>

					<description><![CDATA[<p>The 8051 microcontroller is much older than the ones featured here. Yes, even older than the PIC16F84A. However, being flooded by messages from students about this microcontroller tells me that universities still teach it. Hence, in line with our goal to teach microcontrollers to anyone, we decided to add the 8051 to our lineup. The &#8230;</p>
<p>The post <a href="https://www.teachmemicro.com/8051-microcontroller-introduction/">Introduction to 8051 Microcontroller using C</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>The 8051 <a href="https://www.ampheo.com/c/microcontrollers">microcontroller</a> is much older than the ones featured here. Yes, even older than the <a href="https://www.ampheo.com/product/microchip-technology-pic16f84a-04-so-22873">PIC16F84A</a>. However, being flooded by messages from students about this microcontroller tells me that universities still teach it. Hence, in line with our goal to teach microcontrollers to anyone, we decided to add the <a href="https://www.win-source.net/products/detail/silicon-labs/c8051f007-gqr.html">8051</a> to our lineup.</p>
<p>The first part of this tutorial series shows how to start programming with the 8051 using Keil's C51 compiler. Here you'll learn how to flash an LED and use a switch.<br />
<span id="more-4924"></span></p>
<h3><strong>Setting Up</strong></h3>
<ol>
<li><a href="https://www.keil.com/demo/eval/c51.htm">Download and install Keil for 8051</a></li>
<li>Open Keil, create a new project and name it. Here, we name the project <em>Blinky.</em></li>
</ol>
<p id="lOvQkGw"><img loading="lazy" decoding="async" width="317" height="166" class="size-full wp-image-4937 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1552f19.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1552f19.png 317w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1552f19-300x157.png 300w" sizes="auto, (max-width: 317px) 100vw, 317px" /></p>
<p id="KcswCvC"><img loading="lazy" decoding="async" width="797" height="138" class="size-full wp-image-4938 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1ee5c9c.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1ee5c9c.png 797w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1ee5c9c-300x52.png 300w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228a1ee5c9c-768x133.png 768w" sizes="auto, (max-width: 797px) 100vw, 797px" /></p>
<ol start="3">
<li>At this point, you can select any <a href="https://www.keil.com/support/man/docs/c51/c51_dv_8051deriv.htm">8051 derivatives</a>. We limit ourselves to those found in Proteus ISIS. One of them is <em>AT80C51RD2 </em>and so we select it.</li>
</ol>
<p id="vumFyUY"><img loading="lazy" decoding="async" width="631" height="476" class="size-full wp-image-4939 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b05e0d4a.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b05e0d4a.png 631w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b05e0d4a-300x226.png 300w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b05e0d4a-320x240.png 320w" sizes="auto, (max-width: 631px) 100vw, 631px" /></p>
<ol start="4">
<li>A dialog will ask you about including the <em>STARTUP.A51</em> file which does the register aliasing for us. Naturally, choose Yes.</li>
</ol>
<p>&nbsp;</p>
<p id="kIjhkIo"><img loading="lazy" decoding="async" width="441" height="195" class="size-full wp-image-4940 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b3476186.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b3476186.png 441w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b3476186-300x133.png 300w" sizes="auto, (max-width: 441px) 100vw, 441px" /></p>
<ol start="5">
<li>Each project requires one <em>main.c</em> file. To add such file, right-click on <em>Source Group 1</em> folder, select <em>Add New Item...</em></li>
</ol>
<p id="TFlZTsD"><img loading="lazy" decoding="async" width="494" height="302" class="size-full wp-image-4950 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60270a3a2914b.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60270a3a2914b.png 494w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60270a3a2914b-300x183.png 300w" sizes="auto, (max-width: 494px) 100vw, 494px" /></p>
<ol start="6">
<li>Select .c file extension and name the file main.c</li>
</ol>
<p>&nbsp;</p>
<p id="ByAUPFx"><img loading="lazy" decoding="async" width="696" height="445" class="size-full wp-image-4942 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b445c66b.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b445c66b.png 696w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b445c66b-300x192.png 300w" sizes="auto, (max-width: 696px) 100vw, 696px" /></p>
<ol start="7">
<li>At this point we can start coding. For first-timers, I suggest you paste the following code to main.c and save. The explanation of this code comes in the later section.</li>
</ol>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include&lt;reg51.h&gt;           // special function register declarations
                            // for the intended 8051 derivative

// delay subroutine
void DELAY_ms(unsigned int ms_Count)
{
    unsigned int i,j;
    for(i=0;i&lt;ms_Count;i++)
    {
        for(j=0;j&lt;100;j++);
    }
}


// main routine
int main()
{
    while(1)
    {
        P2 = 0x01;                 // Turn ON LED at P2.0
        DELAY_ms(500);        // 0.5 second delay

        P2 = 0x00;                 // Turn OFF LED at P2.0
        DELAY_ms(500);        // 0.5 second delay
    }
    return (0);
}</code></pre>
</div>
<p>&nbsp;</p>
<ol start="8">
<li>Go to <em>Project -&gt; Options for Target..</em> or <em>Alt + F7</em></li>
</ol>
<p id="sfFATHy"><img loading="lazy" decoding="async" width="476" height="260" class="size-full wp-image-4944 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b7200445.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b7200445.png 476w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_60228b7200445-300x164.png 300w" sizes="auto, (max-width: 476px) 100vw, 476px" /></p>
<ol start="9">
<li>Go to <em>Output</em> tab, check the <em>Create HEX file</em> checkbox and then press Ok to close.</li>
</ol>
<p><img loading="lazy" decoding="async" width="631" height="478" class="size-full wp-image-4931 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893726b2d.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893726b2d.png 631w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893726b2d-300x227.png 300w" sizes="auto, (max-width: 631px) 100vw, 631px" /></p>
<ol start="10">
<li><em>Build target</em> or Press <em>F7</em></li>
</ol>
<p><img loading="lazy" decoding="async" width="468" height="399" class="size-full wp-image-4933 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893726fb1.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893726fb1.png 468w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893726fb1-300x256.png 300w" sizes="auto, (max-width: 468px) 100vw, 468px" /></p>
<ol start="11">
<li>Look at <em>Build Output</em> for any errors</li>
</ol>
<p><img loading="lazy" decoding="async" width="379" height="123" class="size-full wp-image-4934 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_602289374bde2.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_602289374bde2.png 379w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_602289374bde2-300x97.png 300w" sizes="auto, (max-width: 379px) 100vw, 379px" /></p>
<ol start="12">
<li>If the build is successful, the hex file will be at <em>Project Name &gt; Objects &gt; Project Name.hex</em></li>
<li>It's time to simulate the code we just created. For us, we use <a href="https://www.labcenter.com/">Labcenter Electronics' Proteus ISIS</a>. Open Proteus ISIS, use the component picker to find 80C51. This is one of the many equivalent models for the <em>AT80C51RD2.</em></li>
<li>Right click on 80C51, on <em>Program File</em> field, paste the location of the .hex file</li>
</ol>
<p><img loading="lazy" decoding="async" width="933" height="558" class="size-full wp-image-4935 aligncenter" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893917e77.png" alt="" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893917e77.png 933w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893917e77-300x179.png 300w, https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893917e77-768x459.png 768w" sizes="auto, (max-width: 933px) 100vw, 933px" /></p>
<ol start="15">
<li>Press Play. Pin P2.0 should now be flashing</li>
</ol>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-4936" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/img_6022893b4a475.gif" alt="8051 microcontroller LED flash" width="921" height="596" /></p>
<h3><strong>Flashing a LED</strong></h3>
<p>The I/O pins for the 8051 microcontrollers are grouped into ports similar to PICs and AVR microcontrollers. Each pin in a port can be set or clear by writing values to the port.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>P2 = 0x01;            // Turn ON LED at P2.0         
DELAY_ms(500);        // 0.5 second delay         

P2 = 0x00;            // Turn OFF LED at P2.0
DELAY_ms(500);        // 0.5 second delay         
</code></pre>
</div>
<p>Here, we write 0x01 to set P2.0 followed by a half-second delay. We then cleared that same pin by writing 0x00.</p>
<p>The DELAY routine is needed in order for us to see the flashing. There's no built-in <em>delay()</em> function unlike in Arduino or XC8 so we had to build one:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>// delay subroutine
void DELAY_ms(unsigned int ms_Count)
{
    unsigned int i,j;
    for(i=0;i&lt;ms_Count;i++)
    {
        for(j=0;j&lt;100;j++);
    }
}</code></pre>
</div>
<p>The 8051 has an instruction cycle speed of</p>
<p><img decoding="async" class="aligncenter" src="https://latex.codecogs.com/gif.latex?T_%7Bins%7D%3D%5Cfrac%7B12%7D%7Bf_%7BMHz%7D%7D" alt="8051 instruction cycle" /></p>
<p>This means for a 12 MHz oscillator (the default oscillator for 80C51 in Proteus), each instruction is executed in 1 microsecond. In the DELAY routine above, an inner loop counts for a hundred microseconds while an outer loop counts for an interval given by the user in milliseconds. For example, if <em>ms_Count</em> is 500, and a <em>for loop</em> takes about 10 cycles, then the routine will count 500 x 100 x 10 microseconds --- equivalent to half a second.</p>
<p>Another way is to directly set or clear the pin. To do that, we need to declare a variable representing a single pin.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>sbit LED = P2^0
</code></pre>
</div>
<p>The <em>sbit</em> keyword defines a bit within a register (SFR). It may be used like any of these three:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>sbit name = sfr-name ^ bit-position;
sbit name = sfr-address ^ bit-position;
sbit name = sbit-address;
</code></pre>
</div>
<p>Here, our SFR (special function register) is P2 and the bit position is 0.</p>
<p>So to set or clear a pin, we can now use:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>LED = 1; 		// Turn ON LED at P2.0 
DELAY_ms(500);		// 0.5 second delay
            
LED = 0; 		// Turn OFF LED at P2.0
DELAY_ms(500);		// 0.5 second delay
</code></pre>
</div>
<p>To strobe LEDs, we can simply write values to the P2 register in succession.</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include &lt;reg51.h&gt;       // special function register declarations
                        // for the intended 8051 derivative

// delay subroutine
void DELAY_ms(unsigned int ms_Count)
{
    unsigned int i,j;
    for(i=0;i&lt;ms_Count;i++)
    {
        for(j=0;j&lt;100;j++);
    }
}

// main routine
int main() 
{
    while(1)
    {
        P1 = 0x01; 		// Turn ON LED at P2.0 
        DELAY_ms(500);		// 0.5 second delay
        
        P1 = 0x02; 		// Turn OFF LED at P2.0
        DELAY_ms(500);		// 0.5 second delay
			
	P1 = 0x04; 		// Turn ON LED at P2.0 
        DELAY_ms(500);		// 0.5 second delay
        
        P1 = 0x08; 		// Turn OFF LED at P2.0
        DELAY_ms(500);		// 0.5 second delay
			
	P1 = 0x10; 		// Turn ON LED at P2.0 
        DELAY_ms(500);		// 0.5 second delay
        
        P1 = 0x20; 		// Turn OFF LED at P2.0
        DELAY_ms(500);		// 0.5 second delay
			
	P1 = 0x40; 		// Turn OFF LED at P2.0
        DELAY_ms(500);		// 0.5 second delay
			
	P1 = 0x80; 				// Turn OFF LED at P2.0
        DELAY_ms(500);		// 0.5 second dela
    }
    return (0);
}</code></pre>
</div>
<p>Of course, we can also use other ports by simply replacing P1 with P0, P2, or P3.</p>
<h3><!--more--><br />
<strong>Using a Switch</strong></h3>
<p>Unlike other microcontrollers, the 8051 doesn't use <em>data direction registers</em>. Hence, you can make a pin an output or input pin directly. You can attach a switch like this:</p>
<p><a href="https://www.teachmemicro.com/wp-content/uploads/2021/02/8051-switch.bmp"><img loading="lazy" decoding="async" class="aligncenter wp-image-4952 size-full" src="https://www.teachmemicro.com/wp-content/uploads/2021/02/8051-switch.bmp" alt="8051 microcontroller switch" width="491" height="321" srcset="https://www.teachmemicro.com/wp-content/uploads/2021/02/8051-switch.bmp 491w, https://www.teachmemicro.com/wp-content/uploads/2021/02/8051-switch-300x196.jpg 300w" sizes="auto, (max-width: 491px) 100vw, 491px" /></a></p>
<p>and check its state using a simple if-else statement:</p>
<div class="hcb_wrap">
<pre class="prism undefined-numbers lang-c" data-lang="C"><code>#include &lt;reg51.h&gt; // special function register declarations 
                   // for the intended 8051 derivative 
sbit LED = P2^0;
sbit SW = P1^0; 
// delay subroutine 
void DELAY_ms(unsigned int ms_Count) { 
  unsigned int i,j;
  for(i=0;i&lt;ms_Count;i++) {
     for(j=0;j&lt;100;j++); 
  } 
} 
// main routine
int main() { 
  while(1) {
    if(SW == 0){
      LED = 1; 
    }else{ 
      LED = 0; 
    } 
  } 
  return (0); 
}</code></pre>
</div>
<p>Here, when the switch at P1.0 is closed, the LED at P2.0 turns on. Otherwise, the LED turns off.</p>
<p>That's it for a short introduction to 8051 microcontroller programming in C. On the next iteration, we'll go deeper into some registers of the 8051 and create interfacing projects using LCDs, sensors, and more!</p>
<p>The post <a href="https://www.teachmemicro.com/8051-microcontroller-introduction/">Introduction to 8051 Microcontroller using C</a> appeared first on <a href="https://www.teachmemicro.com">Teach Me Microcontrollers!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.teachmemicro.com/8051-microcontroller-introduction/feed/</wfw:commentRss>
			<slash:comments>0</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-10-15 09:10:50 by W3 Total Cache
-->