<?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>Embedded Lab</title>
	<atom:link href="https://embedded-lab.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://embedded-lab.com/blog</link>
	<description>Embedded Systems tutorials, projects, and more ...</description>
	<lastBuildDate>
	Tue, 20 Feb 2024 21:04:54 +0000	</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.1.19</generator>
	<item>
		<title>Mastering the SiLabs C8051 Microcontroller</title>
		<link>https://embedded-lab.com/blog/mastering-the-silabs-c8051-microcontroller/</link>
				<comments>https://embedded-lab.com/blog/mastering-the-silabs-c8051-microcontroller/#comments</comments>
				<pubDate>Wed, 24 May 2023 10:02:34 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[8-bit Microcontroller]]></category>
		<category><![CDATA[8051]]></category>
		<category><![CDATA[C8051]]></category>
		<category><![CDATA[C8051F330]]></category>
		<category><![CDATA[microcontroller]]></category>
		<category><![CDATA[mikroC]]></category>
		<category><![CDATA[MikroC for 8051]]></category>
		<category><![CDATA[mikroelektronika]]></category>
		<category><![CDATA[SiLabs]]></category>
		<category><![CDATA[Silicon Laboratories]]></category>
		<category><![CDATA[Silicon Labs]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">https://embedded-lab.com/blog/?p=15170</guid>
				<description><![CDATA[In a world where upgrades and advancements are constant, it is easy to overlook older technology in favour of newer, more advanced options. However, the case of 8051 microcontrollers defies this trend. Despite being considered relics of the past, there is still a significant demand for these microcontrollers. Manufacturers have revitalized the proven 8051 architecture by incorporating modern features such as ADCs and communication modules, transforming them into powerful, reliable and versatile devices. Silicon Laboratories (SiLabs) is an American semiconductor-manufacturing company, similar to Microchip and STMicroelectronics. They are renowned for producing a wide range of semiconductor components, including both 8]]></description>
								<content:encoded><![CDATA[
<p>In a world where upgrades and advancements are constant, it is easy to overlook older technology in favour of newer, more advanced options. However, the case of 8051 microcontrollers defies this trend. Despite being considered relics of the past, there is still a significant demand for these microcontrollers. Manufacturers have revitalized the proven 8051 architecture by incorporating modern features such as ADCs and communication modules, transforming them into powerful, reliable and versatile devices.</p>



<div class="wp-block-image"><figure class="aligncenter is-resized"><img src="https://embedded-lab.com/blog/wp-content/uploads/2023/05/image.png" alt="" class="wp-image-15171" width="342" height="320" /></figure></div>



<p><a href="https://www.silabs.com/">Silicon
Laboratories (SiLabs)</a> is an American semiconductor-manufacturing company,
similar to Microchip and STMicroelectronics. They are renowned for producing a
wide range of semiconductor components, including both 8 and 32-bit
microcontrollers. Notably, SiLabs is highly regarded for its RF chips and
USB-Serial converters such as CP2102.</p>



<p>In terms of their 8-bit MCU product line-up, SiLabs
offers microcontrollers based on the well-established 8051 architecture.
However, their MCUs go beyond being simple, traditional 8051 devices. Like
other manufacturers like Nuvoton and STC, SiLabs enhances their MCUs with
additional modern hardware components such as DACs and communication
peripherals. </p>



<p>SiLabs C8051 microcontrollers are recognized for their good performance, reliability, and scalability. They cater to the evolving needs of the embedded systems industry, whether it&#8217;s in the realm of consumer electronics, industrial automation, or smart home applications. These microcontrollers serve as a solid foundation for various projects, providing developers with a dependable and flexible platform.</p>


]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/mastering-the-silabs-c8051-microcontroller/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
							</item>
		<item>
		<title>Inductance-Capacitance Measurement using PIC18 Microcontroller</title>
		<link>https://embedded-lab.com/blog/inductance-capacitance-measurement-using-pic18-microcontroller/</link>
				<comments>https://embedded-lab.com/blog/inductance-capacitance-measurement-using-pic18-microcontroller/#comments</comments>
				<pubDate>Wed, 24 Aug 2022 06:07:19 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[PIC Projects]]></category>
		<category><![CDATA[PIC18F]]></category>
		<category><![CDATA[frequency measurement]]></category>
		<category><![CDATA[LC meter]]></category>
		<category><![CDATA[Microchip]]></category>
		<category><![CDATA[PIC]]></category>
		<category><![CDATA[PIC18]]></category>
		<category><![CDATA[PIC18F452]]></category>

		<guid isPermaLink="false">https://embedded-lab.com/blog/?p=15077</guid>
				<description><![CDATA[When designing or debugging an electrical or electronics device, it is very important to know the values of the components that have been used on board. With a multimeter most of the components can be easily measured and identified but most ordinary multimeters do not have options to measure inductors and capacitors as this is rarely needed. However, without capacitors there are literally no circuits while complex circuits may have inductors in them. A LCR (inductor-capacitor-resistor) measurement meter can be used to determine the aforementioned components but usually such meters are pretty expensive. Here, I will share a method with]]></description>
								<content:encoded><![CDATA[
<p>When designing or debugging an electrical or electronics device, it is very important to know the values of the components that have been used on board. With a multimeter most of the components can be easily measured and identified but most ordinary multimeters do not have options to measure inductors and capacitors as this is rarely needed. However, without capacitors there are literally no circuits while complex circuits may have inductors in them. A LCR (inductor-capacitor-resistor) measurement meter can be used to determine the aforementioned components but usually such meters are pretty expensive. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-20.png" alt="" class="wp-image-15103" /></figure></div>



<span id="more-15077"></span>



<p>Here, I will share a method with which we can measure inductors and
capacitors with some degree of accuracy. For the purpose, we can use a common
8-bit microcontroller. I have used a PIC18F452. Of course, any other
microcontroller will be equally suitable for the purpose as long as the
calculations and procedures are maintained. We will also need a small external
analogue circuit based on LM393 dual analogue comparator. This circuit is a
simple <a href="https://en.wikipedia.org/wiki/Hartley_oscillator">Hatley
oscillator</a>. The idea is to measure the frequency or time period of the
oscillator. When a new component such an inductor introduced to the oscillator,
its frequency and therefore time period changes. We can then back-calculate
component value. &nbsp;</p>



<p>PIC18F452 is an 8-bit PIC18F series microcontroller. In terms of hardware is much more capable than the popular PIC16F877A or PIC16F887. However, we do not need any other hardware apart from a capture compare module (CCP) and a timer. The main reason to use a PIC18F is its operating clock speed which is 40MHz.</p>



<h2>Schematic</h2>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-1.png" alt="" class="wp-image-15079" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-1.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-1-580x463.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-1-768x613.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<h2>Components</h2>



<p>As shown in the circuit diagram all the components would be needed. Components L2 to L6 and C4 to C8 are test components. These are present only in simulation and not physically. Rotary switches SW1 and SW2 are only use in simulation schematic and are physically not present. A 2&#215;16 alphanumerical LCD is used for displaying info. And a button connected to pin C0 is used for mode selection. </p>



<h2>Code</h2>



<pre class="wp-block-preformatted"> #include &lt;18F452.h&gt;  <br> &nbsp;<br> #device *=16<br> &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> #fuses NOWDT, PUT, H4, BROWNOUT, BORV42<br> #fuses NOLVP, NODEBUG, NOCPB, STVREN, CPD<br> #fuses PROTECT, NOWRT, NOWRTB, NOWRTC<br> #fuses NOWRTD, NOEBTR, NOEBTRB, NOOSCSEN<br> &nbsp;<br> #use delay(clock = 40M) &nbsp; &nbsp;<br>  <br>  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> #include "lcd.c" &nbsp; &nbsp;<br> &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> #define mode_button &nbsp; &nbsp; &nbsp;input(pin_C0) &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> #define C_cal_in_nF &nbsp; &nbsp; &nbsp; &nbsp; 100.0 <br> #define L_cal_in_uH &nbsp; &nbsp; &nbsp; &nbsp; 100.0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> #define pi &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.142 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> #define cal_delay &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;1000 &nbsp; <br><br> #define scaling_factor_c &nbsp; &nbsp;((10.0 / (4.0 * pi * pi * L_cal_in_uH))) &nbsp; &nbsp;<br> #define scaling_factor_l &nbsp; &nbsp;&nbsp;((10.0 / (4.0 * pi * pi * C_cal_in_nF))) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> unsigned int32 overflow_count = 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> unsigned int32 pulse_ticks = 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> unsigned int16 start_time = 0; &nbsp;<br> unsigned int16 end_time = 0; &nbsp; &nbsp;<br> &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> void setup(void); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp;<br> #int_TIMER1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> void TMR_ISR(void) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp;overflow_count++; &nbsp; &nbsp; &nbsp;<br> } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br><br><br> #int_CCP1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> void CCP_ISR(void)<br> {<br> &nbsp; &nbsp;end_time = CCP_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp;pulse_ticks = ((65536 * overflow_count) + end_time - start_time);<br> &nbsp; &nbsp;start_time = end_time; <br> &nbsp; &nbsp;overflow_count = 0;<br> }<br> &nbsp;<br> void main(void) &nbsp;<br> {<br> &nbsp; &nbsp; short calibration_done = 0; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; unsigned char mode = 0; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; unsigned long t = 0; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; double ref = 0.0; <br> &nbsp; &nbsp; double value = 0.0;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   <br> &nbsp; &nbsp; setup(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> &nbsp; &nbsp; while(TRUE) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> &nbsp; &nbsp; &nbsp; &nbsp; t = (pulse_ticks); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; value = ((double)t * (double)t);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; if(mode_button == FALSE)<br> &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;delay_ms(60); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;while(mode_button == FALSE); &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;calibration_done = 0; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mode++;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(mode &gt; 1)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mode = 0;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; if(calibration_done == 0) <br> &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("\f"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Calibrating...."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Place no part."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay_ms(cal_delay); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("\f"); &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(mode == 0)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref = (value * scaling_factor_c); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("C.ref/nF:"); &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(lcd_putc, "%3.1g &nbsp; ", ref); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(mode == 1) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref = (value * scaling_factor_l);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("L.ref/uH:"); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(lcd_putc, "%3.1g &nbsp; ", ref); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay_ms(cal_delay); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("\f");<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; calibration_done = 1;<br> &nbsp; &nbsp; &nbsp; &nbsp; } <br> &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; else<br> &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(mode)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 1:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value = (value * scaling_factor_c); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Ind./uH:"); &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value = (value * scaling_factor_l); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Cap./nF:"); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value -= ref;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if((value &lt; 0) || (value &gt; 1000)) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;value = 0;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(lcd_putc, "%3.1g &nbsp; &nbsp; &nbsp; &nbsp; ", value); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; delay_ms(100); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; }; <br> }<br> &nbsp;<br> void setup(void) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; <br> { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; setup_wdt(WDT_OFF); &nbsp;<br> &nbsp; &nbsp; setup_adc(ADC_OFF);<br> &nbsp; &nbsp; setup_adc_ports(NO_ANALOGS); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; setup_spi(SPI_DISABLED); &nbsp; &nbsp;<br> &nbsp; &nbsp; setup_psp(PSP_DISABLED); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; setup_ccp1(CCP_CAPTURE_RE);<br> &nbsp; &nbsp; setup_ccp2(CCP_OFF);<br> &nbsp; &nbsp; setup_low_volt_detect(LVD_43); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; setup_timer_0(T0_OFF | T0_8_BIT); <br> &nbsp; &nbsp; setup_timer_1(T1_INTERNAL); &nbsp;<br> &nbsp; &nbsp; setup_timer_2(T2_DISABLED, T2_DIV_BY_1, 16); <br> &nbsp; &nbsp; setup_timer_3(T3_DISABLED); &nbsp;<br> &nbsp; &nbsp; set_timer0(0);<br> &nbsp; &nbsp; set_timer1(0); &nbsp;<br> &nbsp; &nbsp; set_timer2(0); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; set_timer3(0);<br> &nbsp; &nbsp; enable_interrupts(INT_CCP1); &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; enable_interrupts(INT_TIMER1);<br> &nbsp; &nbsp; enable_interrupts(global); &nbsp;<br> &nbsp; &nbsp; lcd_init();<br> &nbsp; &nbsp; lcd_putc("\f"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> } &nbsp; &nbsp; &nbsp; &nbsp; </pre>



<h2>Theory </h2>



<p>We know that:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-4.png" alt="" class="wp-image-15082" /></figure></div>



<p>For a known set of L and C the equation above becomes:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-3.png" alt="" class="wp-image-15081" /></figure></div>



<p>We also know that the inductance of inductors adds when connected in series:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-2.png" alt="" class="wp-image-15080" /></figure></div>



<p>Similarly, the total capacitance of capacitors sums up when connected in parallel:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-5.png" alt="" class="wp-image-15083" /></figure></div>



<p>The above equation can be rearranged as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-6.png" alt="" class="wp-image-15084" /></figure></div>



<p>We also know that:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-7.png" alt="" class="wp-image-15085" /></figure></div>



<p>Thus, the above equation for unknown capacitor becomes:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-8.png" alt="" class="wp-image-15086" /></figure></div>



<p>The same is equation also holds true for unknown inductor too:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-9.png" alt="" class="wp-image-15087" /></figure></div>



<p>Thus,
by knowing two different frequencies or time periods, the value of any unknown
capacitor or inductor can be determined. </p>



<p>A PIC18F452’s CCP1 module along with Timer 1 is used to capture the oscillations coming out of a Hartley oscillator. With nothing unknown connected except the 100nF and 100µH reference capacitor and inductor respectively, the reference oscillation frequency is about 50kHz (about 20µs time period). Whenever a new component is added this frequency changes. </p>



<h2>Explanation</h2>



<p>Basing on the theory discussed, we would need PIC18’s high processing speed along with a timer and capture module. We would also need an LCD to display results. The setup function shown below highlights these modules and their settings. </p>



<pre class="wp-block-preformatted"> void setup(void) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> …<br> &nbsp; &nbsp; setup_ccp1(CCP_CAPTURE_RE);<br> …<br> &nbsp; &nbsp; setup_timer_1(T1_INTERNAL); &nbsp;<br> …<br> &nbsp; &nbsp; set_timer1(0); &nbsp;<br> …<br> &nbsp; &nbsp; enable_interrupts(INT_CCP1); &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; enable_interrupts(INT_TIMER1);<br> &nbsp; &nbsp; enable_interrupts(global); &nbsp;<br> &nbsp; &nbsp; lcd_init();<br> &nbsp; &nbsp; lcd_putc("\f"); &nbsp; &nbsp; &nbsp;<br> } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </pre>



<p>CCP1 module is
set for rising edge capture. This means that CCP1 will capture Timer 1’s count
whenever it senses rising edges. CCP modules in PIC microcontrollers usually
work Timer 1 module and so its count is captured. Capturing two consecutive
rising edges result in period measurement of incoming waveform. This is what we
would need the most. </p>



<p>To further make thing work apparently in concurrent manner, interrupts are used. CCP1 interrupt is triggered when there is a rising edge capture and Timer 1 interrupt is used to keep track of timer overflows. The current and previous capture counts are stored while taking care of Timer 1 overflow. These would be used to determine time period. Timer 1 will rarely overflow because it would only overflow if the incoming waveform has very low frequency and this would literally never happen. &nbsp;</p>



<pre class="wp-block-preformatted"> #int_TIMER1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> void TMR_ISR(void) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> { &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp;overflow_count++; &nbsp; &nbsp; &nbsp;<br> } &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> <br> #int_CCP1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> void CCP_ISR(void)<br> {<br> &nbsp; &nbsp;end_time = CCP_1; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp;pulse_ticks = ((65536 * overflow_count) + end_time - start_time);<br> &nbsp; &nbsp;start_time = end_time; <br> &nbsp; &nbsp;overflow_count = 0;<br> } </pre>



<p>PIC18’s PLL is used to upscale an external 10 MHz crystal oscillator clock to 40 MHz. This is reflected in the fuse bit and clock settings.</p>



<pre class="wp-block-preformatted"> #fuses H4 ….<br> &nbsp;<br> #use delay(clock = 40M) &nbsp; &nbsp; </pre>



<p>However, PICs usually take 4 clock cycles per instruction and so the effective system clock frequency is 10 MHz.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-10.png" alt="" class="wp-image-15088" /></figure></div>



<p>Thus, one tick of Timer 1 is: </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-11.png" alt="" class="wp-image-15089" /></figure></div>



<p>Thus, at the base frequency of 50 kHz (20 µs), Timer 1 would count:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-12.png" alt="" class="wp-image-15090" /></figure></div>



<p>Since the reference inductor and capacitor values are know the following equations simply as:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-13.png" alt="" class="wp-image-15091" /></figure></div>



<p>The same applies for inductor measurement too and the formula simplifies as shown below:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-14.png" alt="" class="wp-image-15092" /></figure></div>



<p>The fixed constants are defined in definitions on top of the code</p>



<pre class="wp-block-preformatted"> #define C_cal_in_nF &nbsp; &nbsp; &nbsp; &nbsp; 100.0 <br> #define L_cal_in_uH &nbsp; &nbsp; &nbsp; &nbsp; 100.0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> #define pi &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3.142 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> #define cal_delay &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1000 &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> #define scaling_factor_c &nbsp; &nbsp;((10.0 / (4.0 * pi * pi * L_cal_in_uH))) &nbsp; &nbsp;<br> #define scaling_factor_l &nbsp; &nbsp;((10.0 / (4.0 * pi * pi * C_cal_in_nF))) &nbsp; &nbsp; &nbsp; </pre>



<p>Now let’s say we want to measure 220nF. So, for this amount of capacitance, the oscillator frequency would be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-15.png" alt="" class="wp-image-15093" /></figure></div>



<p>Timer 1 would count 355 counts while
capturing this frequency from the oscillator. </p>



<p>Now if we back-calculate using the formulae shown previously, the capacitor is found to be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-16.png" alt="" class="wp-image-15094" /></figure></div>



<p>Yes, the
reading is a bit off from actual value but close enough to actual value. The error
occurs because timer counts cannot be anything other than integers. This error can
be smartly compensated in code. </p>



<p>The push button connected to pin C0 is used to select either inductance or capacitance measurement mode. Every time the mode is changed, calibration would be needed. The calibration procedure is simple. We just have to leave our meter with nothing connected except the reference capacitor and inductor as shown the following circuit diagram. This is the Hartley oscillator and the core part of the entire device. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-17.png" alt="" class="wp-image-15095" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-17.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-17-580x371.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/image-17-768x491.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p>During this
time, the reference component value is measured and saved. This value would be
deducted during unknown component measurement. During calibration, the meter’s display
would show instruction for not placing any external component. </p>



<p>After the calibration is completed, unknown components can be placed and measured accordingly. These are all what the program’s main loop does.</p>



<pre class="wp-block-preformatted">     while(TRUE) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  <br> &nbsp; &nbsp; &nbsp; &nbsp; t = (pulse_ticks); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; value = ((double)t * (double)t);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; if(mode_button == FALSE)<br> &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;delay_ms(60); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;while(mode_button == FALSE); &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;calibration_done = 0; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mode++;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(mode &gt; 1)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mode = 0;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; if(calibration_done == 0) <br> &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("\f"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Calibrating...."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Place no part."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay_ms(cal_delay); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("\f"); &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(mode == 0)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref = (value * scaling_factor_c); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("C.ref/nF:"); &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(lcd_putc, "%3.1g &nbsp; ", ref); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(mode == 1) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref = (value * scaling_factor_l);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("L.ref/uH:"); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(lcd_putc, "%3.1g &nbsp; ", ref); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay_ms(cal_delay); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("\f");<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; calibration_done = 1;<br> &nbsp; &nbsp; &nbsp; &nbsp; } <br> &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; else<br> &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 1); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(mode)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case 1:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value = (value * scaling_factor_c); &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Ind./uH:"); &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default:<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value = (value * scaling_factor_l); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_putc("Cap./nF:"); &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value -= ref;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if((value &lt; 0) || (value &gt; 1000)) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;value = 0;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lcd_gotoxy(1, 2); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf(lcd_putc, "%3.1g &nbsp; &nbsp; &nbsp; &nbsp; ", value); &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; &nbsp; &nbsp; delay_ms(100); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br> &nbsp; &nbsp; };  </pre>



<p>Some time-proven
good-old tricks have been applied in this code:</p>



<ol><li>Instead of measuring frequency, time period is
measured. This saved one calculation step because frequency is inverse of time
period. </li></ol>



<ul><li>Rather than using math library, some values that
need to raised by some power, is simply repeated multiplied. For example, the
time period needs to be squared but instead it is multiplied by itself. </li></ul>



<ul><li>Definitions have been used in order to identify some
important constant values and reduce calculation.</li></ul>



<ul><li>The use of global variables has been kept to a minimum.
Although the code is nothing compared to the memory resources of the PIC18 microcontroller.</li></ul>



<ul><li>Interrupt methods have been employed to make the
program efficient and as less blocking as possible.</li></ul>



<ul><li>Unused hardware peripherals have been reinitialized
to reduce power consumption and other issues. </li></ul>



<h2>Demo</h2>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-1024x576.jpg" alt="" class="wp-image-15100" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-1024x576.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-580x326.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-768x432.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13005120-1024x576.jpg" alt="" class="wp-image-15098" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13005120-1024x576.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13005120-580x326.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13005120-768x432.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011057-1024x576.jpg" alt="" class="wp-image-15099" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011057-1024x576.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011057-580x326.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011057-768x432.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-1024x576.jpg" alt="" class="wp-image-15100" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-1024x576.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-580x326.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/08/IMG_20220823_13011941-768x432.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="PIC18 LC Meter - Measurement of Inductance and Capacitance" width="860" height="484" src="https://www.youtube.com/embed/R6ZhQxcOhSo?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>All files related to this project can be found <a href="https://github.com/sshahryiar/PIC-Microcontroller-Projects/tree/main/LC%20Meter">here</a>.</p>



<p>Happy coding.</p>



<p><em>Author: Shawon M. Shahryiar</em></p>



<p><a href="https://www.facebook.com/groups/microarena">https://www.facebook.com/groups/microarena</a></p>



<p><a href="https://www.facebook.com/MicroArena?ref=hl"><em>https://www.facebook.com/MicroArena</em></a><em> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</em></p>



<p><em>23.08.2022</em></p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/inductance-capacitance-measurement-using-pic18-microcontroller/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
							</item>
		<item>
		<title>A Simple Solar Irradiation Measurement Technique</title>
		<link>https://embedded-lab.com/blog/a-simple-solar-irradiation-measurement-technique/</link>
				<comments>https://embedded-lab.com/blog/a-simple-solar-irradiation-measurement-technique/#comments</comments>
				<pubDate>Mon, 28 Feb 2022 11:07:16 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Nuvoton]]></category>
		<category><![CDATA[Sensors]]></category>
		<category><![CDATA[Solar Power]]></category>
		<category><![CDATA[8051]]></category>
		<category><![CDATA[Irradiation]]></category>
		<category><![CDATA[N76E003]]></category>
		<category><![CDATA[Renewable Energy]]></category>
		<category><![CDATA[solar]]></category>

		<guid isPermaLink="false">https://embedded-lab.com/blog/?p=14986</guid>
				<description><![CDATA[A pyranometer or solar irradiation tester is measurement tool that is a must-have for every professional in renewable energy sector. However, owing one is not easy because it is both expensive and rare. It is expensive because it uses highly calibrated components and it is rare because it is not an ordinary multi-meter that is available in common hardware shops. Personally, I have a long professional career in the field of LED lighting, renewable energy (mainly solar), Lithium and industrial battery systems, electronics and embedded-systems. I have been at the core of designing, testing, commissioning and analyzing some of the]]></description>
								<content:encoded><![CDATA[
<p> A pyranometer or solar irradiation tester is measurement tool that is a must-have for every professional in renewable energy sector. However, owing one is not easy because it is both expensive and rare. It is expensive because it uses highly calibrated components and it is rare because it is not an ordinary multi-meter that is available in common hardware shops.  </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image.png" alt="" class="wp-image-14987" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image.png 783w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-580x295.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-768x390.png 768w" sizes="(max-width: 783px) 100vw, 783px" /></figure></div>



<hr class="wp-block-separator" />



<p>Personally, I
have a long professional career in the field of LED lighting, renewable energy
(mainly solar), Lithium and industrial battery systems, electronics and
embedded-systems. I have been at the core of designing, testing, commissioning
and analyzing some of the largest solar power projects of my country – a
privilege that only a few enjoyed. In many of my solar-energy endeavors, I
encountered several occasions that required me to estimate solar isolation or
solar irradiation. Such situations included testing solar PV module
efficiencies, tracking solar system performance with seasons, weather, sky
conditions, dust, Maximum Power Point Tracking (MPPT) algorithms of solar
inverters, chargers, etc. </p>



<p>I wanted a
simply way with which I can measure solar irradiance with some degree of
accuracy. Having the advantage of working with raw solar cells, tools that test
cells and complete PV modules combined with theoretical studies, I found out a
rudimentary method of measuring solar irradiation.</p>



<p>In simple terms, solar insolation&nbsp;is defined as the amount of solar radiation incident on the surface of the earth in a day and is measured in kilowatt-hour per square meter per day (kWh/m²/day).&nbsp;Solar irradiation, on the other hand, is the&nbsp;<a href="https://en.wikipedia.org/wiki/Power_(physics)">power</a>&nbsp;per unit area received from the&nbsp;<a href="https://en.wikipedia.org/wiki/Sun">Sun</a>&nbsp;in the form of&nbsp;<a href="https://en.wikipedia.org/wiki/Electromagnetic_radiation">electromagnetic radiation</a>&nbsp;as measured in the&nbsp;<a href="https://en.wikipedia.org/wiki/Wavelength">wavelength</a>&nbsp;range of the measuring instrument. It is measured in&nbsp;<a href="https://en.wikipedia.org/wiki/Watt">watt</a>&nbsp;per square meter (W/m²). The solar insolation is, therefore, an aggregate of solar irradiance over a day. &nbsp; Sun energy collection by solar photovoltaic (PV) modules is depended on solar irradiance and this in turn has impact on devices using this energy. For example, in a cloudy day a solar battery charger may not be able to fully charge a battery attached to it. Likewise, in a sunny day the opposite may come true. </p>



<h2>Solar PV Cells</h2>



<p>For making a solar irradiation meter we would obviously need a solar cell. In terms of technology, there are three kinds of cells commonly available in the market and these are shown below. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-1.png" alt="" class="wp-image-14988" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-1.png 639w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-1-580x532.png 580w" sizes="(max-width: 639px) 100vw, 639px" /></figure></div>



<h1>Basic Solar Math</h1>



<p>Typically, Earth-bound solar irradiation is about 1350 W/m². About 70 &#8211; 80% of this irradiation makes to Earth’s surface and rest is absorbed and reflected. Thus, the average irradiation at surface is about 1000 W/m². Typical cell surface area of a poly crystalline cell having dimensions 156 mm x 156 mm x 1mm is:  </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-2.png" alt="" class="wp-image-14989" /></figure></div>



<p>The theoretical or ideal wattage of such a cell should be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-3.png" alt="" class="wp-image-14990" /></figure></div>



<p>However, the present-day
cell power with current technology somewhere between 4 – 4.7 Wp. It is safe to
assume an average wattage of a typical poly crystalline cell to be 4.3 Wp.



Therefore, cell efficiency is calculated to be: 



</p>



<p>  </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-4.png" alt="" class="wp-image-14991" /></figure></div>



<p>72 cells of 4.3 Wp capacity will
form a complete solar PV module of 310Wp.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-5.png" alt="" class="wp-image-14992" /></figure></div>



<p>Likewise, the approximate area of a 310 Wp solar panel having dimensions (1960 mm x 991 mm x 40 mm) is:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-6.png" alt="" class="wp-image-14993" /></figure></div>



<p>The theoretical wattage that we should be getting with 1.942 m² area panel is found to be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-7.png" alt="" class="wp-image-14994" /></figure></div>



<p>Therefore, module/panel efficiency is calculated to be: </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-8.png" alt="" class="wp-image-14995" /></figure></div>



<p> Cell efficiency is always higher than module efficiency because in a complete PV module there are many areas where energy is not harvested. These areas include bus-bar links, cell-to-cell gaps, guard spaces, aluminum frame, etc. As technology improves, these efficiencies also improve.  </p>



<p>Monocrystalline cells have same
surface are but more wattage, typically between 5.0 to 5.5 Wp. We can assume an
average cell wattage of 5.2 Wp.</p>



<p>Therefore, cell efficiency is calculated to be: </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-9.png" alt="" class="wp-image-14997" /></figure></div>



<p>Typically, monocrystalline PV modules consist of 60 cells and so 60 such cells are arranged then the power of a complete PV module is calculated to be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-10.png" alt="" class="wp-image-14998" /></figure></div>



<p>The area of that PV module having dimensions 1650 mm x 991 mm x 38 mm would be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-11.png" alt="" class="wp-image-14999" /></figure></div>



<p>The theoretical wattage that we should be getting with 1.635 m² area panel is found to be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-12.png" alt="" class="wp-image-15000" /></figure></div>



<p>Therefore, module/panel efficiency is calculated to be: </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-13.png" alt="" class="wp-image-15001" /></figure></div>



<p>These calculations prove the
following points:</p>



<ul><li>Monocrystalline PV modules can harvest the same amount of energy as their polycrystalline counterparts with lesser area.</li><li>Monocrystalline cells are more efficient than poly crystalline cells.</li><li>Monocrystalline PV modules are more efficient than polycrystalline PV modules. </li><li>156 mm x 156 mm cell dimension is typical but there are also cells of other dimensions like 125 mm x 125 mm x 1 mm.</li><li>Though I compared monocrystalline and polycrystalline cells and modules here the same points are true for thin film or amorphous cells.</li><li>Currently, there are more efficient cells and advanced technologies, and thus higher power PV modules with relatively smaller area. For instance, at present there are PV modules from Tier 1 manufacturers that have powers well above 600W but their physical dimensions are similar to 300Wp modules. </li></ul>



<p>Solar PV modules can be generally categorized in four categories based on the number of solar cells in series and they usually have the following characteristics:</p>



<p><strong><em>36 Cells </em></strong></p>



<ul><li>36
x 0.6 V = 21.6V (i.e., 12V Panel)</li><li>VOC
= 21.6V</li><li>VMPP
= 16 – 18V</li><li>For
modules from 10 &#8211; 120 Wp </li></ul>



<p><strong><em>60 Cells</em></strong></p>



<ul><li>60
x 0.6 V = 36V </li><li>VOC
= 36V</li><li>VMPP
= 25 – 29V</li><li>For
modules from 50 – 300+ Wp </li></ul>



<p><strong><em>72 Cells</em></strong></p>



<ul><li>72
x 0.6 V = 43.2V (i.e., 24V Panel)</li><li>VOC
= 43.2V</li><li>VMPP
= 34 – 38V</li><li>For
modules from 150 – 300+ Wp </li></ul>



<p><strong><em>96 Cells</em></strong></p>



<ul><li>96
x 0.6 V = 57.6V (i.e., 24V Panel)</li><li>VOC
= 57.6V</li><li>VMPP
= 42 – 48V</li><li>For
modules from 250 – 300+ Wp </li><li>Rare</li></ul>



<p>One cell may not be fully used and could be cut with laser scribing machines to meet voltage and power requirements. Usually, the above-mentioned series connections are chosen because they are the standard ones. Once a cell series arrangement is chosen, the cells are cut accordingly to match required power. A by-cut cell has lesser area and therefore lesser power. Cutting a cell reduces its current and not its voltage. Thus, power is reduced.  36 cell modules are also sometimes referred as 12V panels although there is no 12V rating in them and this is because such modules can directly charge a 12V lead-acid battery but cannot charge 24V battery systems without the aid of battery chargers. Similarly, 72 cell modules are often referred as 24V panels.  </p>



<h2>Important Parameters of a Panel/Cell</h2>



<p><strong>Open Circuit Voltage (Voc)</strong> –no load/open-circuit voltage of cell/panel.&nbsp; </p>



<p><strong>Short Circuit Current (Isc)</strong> – current that will flow when the panel/cell is shorted in full sunlight.</p>



<p><strong>Maximum Power Point Voltage (VMPP)</strong> &#8211; output voltage of a panel at maximum power point or at rated power point of the cell’s/panel’s characteristics curve.</p>



<p><strong>Maximum Power Point Current (IMPP)</strong> &#8211; output current of a panel at maximum power point or at rated power point of the cell’s/panel’s characteristics curve.</p>



<p><strong>Peak Power (Pmax)</strong> – the product of VMPP and IMPP. It is the rated power of a cell’s/PV module at STC. Its unit is watt-peak (WP) and not watts because this is the maximum or peak power of a cell/module. </p>



<p><strong>Power Tolerance</strong> – percentage deviation of power. </p>



<p><strong>STC </strong>stands for Standard Temperature Condition or simply lab conditions (25°C).</p>



<p><strong>AM</strong> stands for Air Mass – This can be used to help characterize the solar spectrum after&nbsp;<a href="https://en.wikipedia.org/wiki/Solar_radiation">solar radiation</a>&nbsp;has traveled through the atmosphere.</p>



<p><strong>E</strong> stands for Standard Irradiation of 1000 W/m².</p>



<p>Shown below is the technical specification sticker of a 320 Wp JA Solar PV Module:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-14.png" alt="" class="wp-image-15002" /></figure></div>



<p>According to the sticker the PV module has the following
specs at STC and irradiation, E = 1000 W/m²:</p>



<p><strong>V</strong><strong>OC = 46.12 V </strong></p>



<p><strong>V</strong><strong>MPP = 37.28 V</strong></p>



<p><strong>Isc = 9.09 A</strong></p>



<p><strong>I</strong><strong>MPP = 8.58 A</strong></p>



<p><strong>Pmax = 320 W</strong><strong>P</strong><strong></strong></p>



<p>From these specs we can estimate and deduce the followings:</p>



<p>VMPP-by-VOC ratio:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-15.png" alt="" class="wp-image-15003" /></figure></div>



<p>This value is always between 76 – 86%.</p>



<p>Similarly, IMPP-by-ISC ratio:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-16.png" alt="" class="wp-image-15004" /></figure></div>



<p>This value is always between 90 &#8211; 96%.</p>



<p>The product of these ratios should be as high as possible. Typical values range between 0.74 – 0.79. This figure represents fill-factor (FF) of a PV module or a PV cell.&nbsp; </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-17.png" alt="" class="wp-image-15005" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-17.png 679w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-17-580x296.png 580w" sizes="(max-width: 679px) 100vw, 679px" /></figure></div>



<p>An ideal
PV cell/module should have a characteristics curve represented by the green
line. However, the actual line is represented by the blue one. Fill-Factor is
best described as the percentage of ideality. Thus, the greater it is or the
closer it is to 100 % the better is the cell/module.&nbsp;&nbsp; </p>



<p>In this case, the FF is calculated to be <strong><em>0.94 x 0.81 = 0.76 or 76%.</em></strong></p>



<p>Number of cells is calculated to be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-18.png" alt="" class="wp-image-15006" /></figure></div>



<p>Therefore, each cell has an open circuit voltage (VOC) of:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-19.png" alt="" class="wp-image-15007" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-19.png 423w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-19-420x98.png 420w" sizes="(max-width: 423px) 100vw, 423px" /></figure></div>



<p><em>I</em><em>MPP</em> is 8.58 A and<em>
I</em><em>SC</em><em> </em>is 9.09 A. </p>



<p>Cell power is calculated as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-20.png" alt="" class="wp-image-15008" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-20.png 650w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-20-580x220.png 580w" sizes="(max-width: 650px) 100vw, 650px" /></figure></div>



<p>Efficiencies are deduced as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-21.png" alt="" class="wp-image-15009" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-22.png" alt="" class="wp-image-15010" /></figure></div>



<p>The I-V curves of the PV module shown below show the effect of solar irradiation on performance. It is clear that with variations in solar irradiation power production varies. The same is shown by the power curve. Voltage and current characteristics follow a similar shape.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-23.png" alt="" class="wp-image-15011" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-23.png 609w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-23-580x446.png 580w" sizes="(max-width: 609px) 100vw, 609px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-24.png" alt="" class="wp-image-15012" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-24.png 591w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-24-580x433.png 580w" sizes="(max-width: 591px) 100vw, 591px" /></figure></div>



<p>The I-V curve shown below demonstrates the effect of temperature on performance. We can see that power production performance deteriorates with rise in temperature. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-25.png" alt="" class="wp-image-15013" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-25.png 650w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-25-580x407.png 580w" sizes="(max-width: 650px) 100vw, 650px" /></figure></div>



<p>The characteristics curves of the
320 Wp JA Solar PV module are shown above. From the curves above we can clearly
see the following points:</p>



<ul><li>Current changes with irradiation but voltage changes slightly and so power generation depends on irradiation and current. </li><li>Current changes slightly with temperature but voltage changes significantly. At high temperatures, PV voltage decreases and this leads to change in Maximum Power Point (MPP) point. Thus, at high temperatures power generation decreases and vice-versa. </li><li>Vmpp-by-Voc ratio remains pretty much the same at all irradiation levels. </li><li>The curves are similar to that of a silicon diode and this is so because a cell is essentially a light sensitive silicon diode. </li></ul>



<h2>Impacts of Environment on PV</h2>



<h4>Effect of Temperature</h4>



<p>Let us now see how temperature affects solar module performance. Remember that a solar cell is just like a silicon diode and we know that a silicon diode’s voltage changes with temperature. This change is about -2 mV/°C. Thus, the formula below demonstrates the effect of temperature:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-26.png" alt="" class="wp-image-15014" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-26.png 634w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-26-580x41.png 580w" sizes="(max-width: 634px) 100vw, 634px" /></figure></div>



<p>Suppose the ambient temperature is 35°C and let us consider the same 320 Wp PV module having:</p>



<p style="text-align:center"><strong>V</strong><strong>OC</strong><strong> at STC = 46.12V</strong></p>



<p style="text-align:center"><strong>V</strong><strong>MPP</strong><strong> at STC = 37.28V</strong></p>



<p>Therefore, the temperature difference from STC is:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-64.png" alt="" class="wp-image-15061" /></figure></div>



<p>Under such
circumstance the VMPP
should be about 35V but it gets decreased more and fill-factor is ultimately
affected. </p>



<p>So clearly there is a shift in VMPP which ultimately affects output power. This is also shown in the following graph:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-27.png" alt="" class="wp-image-15015" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-27.png 698w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-27-580x420.png 580w" sizes="(max-width: 698px) 100vw, 698px" /></figure></div>



<h4>Effect of Shading, Pollution and Dust</h4>



<p>Power generation is also affected by shades, i.e., obstruction of
sunlight. Obstacles can be anything from a thin stick to a large tree. Dust and
pollution also contribute to shading on microscopic level. However, broadly
speaking, shading can be categorized in two basic categories – Uniform Shading
and Non-uniform Shading. </p>



<p>Uniform shading is best described as complete shading of all PV modules
or cells of a solar system. This form of shading is mainly caused by dust,
clouds and pollution. In such shading conditions, PV current is affected
proportionately with the amount of shading, yielding to decreased power
collection. However, fill-factor and efficiencies are literally unaffected. </p>



<p>Non-uniform shading, as its name suggests, is partial shading of some PV modules or cells of a solar system. Causes of such shading include buildings, trees, electric poles, etc. Non-uniform shading must be avoided because cells that receive less radiation than the others behave like loads, leading to formation of hotspots in long-run. Shadings as such result in decreased efficiency, current and power generation because of multiple wrong MPP points.</p>



<h4>Effect of Other Variables</h4>



<p>There are several other variables that have effect on solar energy collection. Variables and weather conditions like rain, humidity, snow, clouds, etc. affect energy harvest while cool, windy and sunny conditions have positive impact on energy harvest. These factors are region and weather dependent and cannot be generalized. </p>



<h2>Basic Solar Geometry</h2>



<p>Some basics of solar geometry is needed to be realized to efficiently design solar systems and how sun rays are reach earth. Nature follows a mathematical pattern that it never suddenly or abruptly alters. The movement of the sun and its position on the sky at any instance can be described by some simple trigonometric functions.  The Earth not just orbits the Sun but it tilts and revolves about its axis. The daily rotation of the Earth about the axis through its North and South poles (also known as celestial poles) is perpendicular to the equator point, however it is not perpendicular to the plane of the orbit of the Earth. In fact, the measure of tilt or obliquity of the axis of the Earth to a line perpendicular to the plane of its orbit is currently about 23.5°.  </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-28.png" alt="" class="wp-image-15017" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-28.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-28-580x399.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-28-768x528.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p><strong><em>The plane of the Sun </em></strong>is the plane parallel to the Earth’s celestial equator and through the center of the sun. The Earth passes alternately above and below this plane making one complete elliptic cycle every year. </p>



<p>In summer solstice, the Sun shines down most directly on the Tropic of Cancer in the northern hemisphere, making an angle δ = 23.5° with the equatorial plane. Likewise, in winter solstice, it shines on the Tropic of Capricorn, making an angle δ = -23.5° with the equatorial plane. In equinoxes, this angle δ is 0°. Here δ is called the angle of declination. In simple terms the angle of declination represents the amount of Earth’s tilt or obliquity.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-29.png" alt="" class="wp-image-15018" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-29.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-29-580x192.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-29-768x254.png 768w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-29-420x140.png 420w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p>The angle of declination, <strong><em>δ</em></strong>, for Nth day of a year can be deduced using the following formula:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-30.png" alt="" class="wp-image-15019" /></figure></div>



<p>Here, N = 1
represents 1<sup>st</sup> January. </p>



<p>The angle of
declination has effect on day duration, sun travel path and thus it dictates
how we should tilt PV modules with respect to ground with seasonal
changes.&nbsp; </p>



<p>The next most important thing to note is the geographical location in terms of GPS coordinates (longitude, <strong><em>λ</em></strong> East and latitude, <strong><em>ϕ</em></strong> North). This is because geo location also has impact on the aforementioned. Northern and Southern Hemispheres have several differences.</p>



<p>Shown below is
a graphical representation of some other important solar angles. Here:</p>



<ul><li>The angle of solar elevation, <strong><em>ά</em></strong>,
is the angular measure of the Sun’s rays above the horizon. </li></ul>



<ul><li>The&nbsp;solar zenith angle, <strong><em>Z</em></strong>,&nbsp;is
the angle between an imaginary point directly above a given location, on the
imaginary&nbsp;<a href="https://en.wikipedia.org/wiki/Celestial_sphere">celestial
sphere</a>. and the center of the&nbsp;<a href="https://en.wikipedia.org/wiki/Sun">Sun</a>&#8216;s disc. This is
similar to tilt angle.</li></ul>



<p>



The azimuth angle, <strong><em>A</em></strong>, is a local
angle between the direction of due North and that of the perpendicular projection
of the Sun down onto the horizon line measured clockwise.



</p>



<p>&nbsp; </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-31.png" alt="" class="wp-image-15020" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-31.png 1006w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-31-580x353.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-31-768x468.png 768w" sizes="(max-width: 1006px) 100vw, 1006px" /></figure></div>



<p>The angle of solar elevation, <strong><em>ά</em></strong>, at noon for location on Northern Hemisphere can be deduced as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-32.png" alt="" class="wp-image-15021" /></figure></div>



<p>Similarly, for location on Southern Hemisphere, the angle of solar elevation at noon can be deduced as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-33.png" alt="" class="wp-image-15022" /></figure></div>



<p>Here <strong><em>ϕ</em></strong> represents latitude and <strong><em>δ</em></strong> represents angle of declination. Zenith/Tilt angle is found to be: </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-34.png" alt="" class="wp-image-15023" /></figure></div>



<p>Determining azimuth angle is not simple as additional info are needed. The first thing that we will need is to the sunrise equation. This is used to determine the local time of sunrise and sunset at a given latitude, ϕ at a given solar declination angle, δ. The sunrise equation is given by the formula below:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-35.png" alt="" class="wp-image-15024" /></figure></div>



<p>Here ω is the hour angle. ω is between -180° to 0° at
sunrise and between 0° to 180° at sunset. </p>



<p><em>If [tan(ϕ).tan(δ)] </em><em>≥
1, there is no sunset on that day. Likewise, if [tan(ϕ).tan(δ)] </em><em>≤
-1, there is no sunrise on that day.</em></p>



<p>The hour angle, ω is the
angular distance between the meridian of the observer and the meridian whose</p>



<p>plane contains the sun. When the sun reaches its highest point in the sky at noon, the hour angle is zero. At this time the Sun is said to be ‘due south’ (or ‘due north’, in the Southern Hemisphere) since the meridian plane of the observer contains the Sun. On every hour the hour angle increases by 15°.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-36.png" alt="" class="wp-image-15025" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-36.png 974w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-36-580x361.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-36-768x478.png 768w" sizes="(max-width: 974px) 100vw, 974px" /></figure></div>



<p>From hour angle, we can determine the local sunrise and sunset times as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-37.png" alt="" class="wp-image-15026" /></figure></div>



<p>For a given location, hour angle and date the angle of solar elevation can be expressed as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-38.png" alt="" class="wp-image-15027" /></figure></div>



<p>Since we have the hour angle info along with sunrise and sunset times, we can now determine the azimuth angle. It is expressed as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-39.png" alt="" class="wp-image-15028" /></figure></div>



<p>Solving the above equation for <strong><em>A </em></strong>will yield in azimuth angle.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-40.png" alt="" class="wp-image-15029" /></figure></div>



<p>Knowing azimuth and solar elevation angles help us determine the length and location of the shadow of an object. These are important for solar installations.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-41.png" alt="" class="wp-image-15030" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-41.png 1000w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-41-580x397.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-41-768x526.png 768w" sizes="(max-width: 1000px) 100vw, 1000px" /></figure></div>



<p>The length of the shadow is as in the figure above is found to be: </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-42.png" alt="" class="wp-image-15031" /></figure></div>



<p>From the geometric analysis, it can be shown that solar energy harvest will increase if PV modules can be arranged as such to follow the Sun. This is the concept of solar tracking system. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-43.png" alt="" class="wp-image-15032" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-43.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-43-580x435.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-43-768x576.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p>If the Sun can be tracked according to these math models, the maximum possible harvest can be obtained. However, some form of solar-tracking structures will be needed. An example of sun tracking system is shown above. This was designed by a friend of mine and myself back in 2012. He designed the mechanical section while I added the intelligence in form of embedded-system coding and tracking controller design. </p>



<p>Here’s a photo of the sun tracking controller that I designed. It used a sophisticate algorithm to track the sun.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-44-848x1024.png" alt="" class="wp-image-15033" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-44-848x1024.png 848w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-44-538x650.png 538w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-44-768x928.png 768w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-44.png 975w" sizes="(max-width: 848px) 100vw, 848px" /></figure></div>



<h2>Building the Device</h2>



<p>In order to
build the solar irradiance meter, we will need a solar cell or a PV module of
known characteristics. Between a single cell and module, I would recommend for
a cell because:</p>



<ul><li>Cells have lower power than complete modules.</li><li>Cells have almost no framing structure.</li><li>Cells are small and light-weight.</li><li>Cells are individual and so there is no need to
take account of series-parallel combination. </li></ul>



<p>We would see
why these are important as we move forward.</p>



<p>For the project, I used a cheap amorphous solar cell as shown in the photo below. It looks like a crystalline cell under my table lamp but actually it is an amorphous one. It can be purchased from AliExpress, Amazon or similar online platform.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-45.png" alt="" class="wp-image-15034" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-45.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-45-580x322.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-45-768x426.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p>With a cell test machine, it gave a characteristic curve and data as shown below:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-46.png" alt="" class="wp-image-15035" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-46.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-46-580x368.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-46-768x487.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p>From this I-V characteristics curve, we can see its electrical parameters. The cell has a physical dimension of 86mm x 56mm and so it has an area of 0.004816m².</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-47.png" alt="" class="wp-image-15036" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-47.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-47-580x285.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-47-768x377.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-48.png" alt="" class="wp-image-15037" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-48.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-48-580x338.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-48-768x447.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<p>From the calculation which I
already discussed, irradiation measurement needs two known components – the
total cell area and the maximum power it can generate. We know both of these
data. Now we just have to formulate how we can use these data to measure
irradiation. </p>



<p>Going back to a
theory taught in the first year of electrical engineering, <a href="https://en.wikipedia.org/wiki/Maximum_power_transfer_theorem#:~:text=In%20electrical%20engineering%2C%20the%20maximum,viewed%20from%20its%20output%20terminals.">the
maximum power transfer theorem</a>, we know that to
obtain&nbsp;maximum&nbsp;external power from a source with a finite&nbsp;<a href="https://en.wikipedia.org/wiki/Internal_resistance">internal resistance</a>, the resistance of the load
must equal the resistance of the source as viewed from its output terminals.
This is the theory behind my irradiation measurement. </p>



<p>From the cell
electrical characteristics data, we can find the ideal resistance that is
needed to make this theory work. </p>



<p>It is important to note that we would just be focusing on maximum power point data only and that is because this is the maximum possible output that the cell will provide at the maximum irradiation level of 1000W/m². The ideal resistance is calculated as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-49.png" alt="" class="wp-image-15038" /></figure></div>



<p>and so does the electric current. The voltage that would be induced across RMPP is proportional to this current because according to Ohms law:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-50.png" alt="" class="wp-image-15039" /></figure></div>



<p>The equivalent circuit is as shown below:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/schema-1-1024x563.jpg" alt="" class="wp-image-15040" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/schema-1-1024x563.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/schema-1-580x319.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/schema-1-768x422.jpg 768w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/schema-1.jpg 1123w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>The boxed
region is the electrical equivalent of a solar cell. At this point it may look
complicated but we are not digging inside the box and so it can be considered
as a mystery black box.</p>



<p>We know that:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-51.png" alt="" class="wp-image-15041" /></figure></div>



<p>We know the value of resistance and all we have to do is to measure the voltage (V) across the cell. We also know the area of the cell and so we can deduce the value of irradiation, E incident on the cell according to the formula:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-52.png" alt="" class="wp-image-15042" /></figure></div>



<h2>Schematic</h2>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-53.png" alt="" class="wp-image-15043" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-53.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-53-580x268.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-53-768x355.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<h2>Code</h2>



<pre class="wp-block-preformatted">#include "N76E003.h"<br>#include "SFR_Macro.h"<br>#include "Function_define.h"<br>#include "Common.h"<br>#include "Delay.h"<br>#include "soft_delay.h"<br>#include "LCD_2_Wire.h"<br><br>#define Vmpp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5.162F<br>#define Impp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0.056F<br>#define R_actual &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(Vmpp / Impp)<br>#define R_fixed &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 100.0F // &nbsp; &nbsp;<br>#define R_Error &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (R_fixed / R_actual)<br>#define ADC_Max &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4095.0F<br>#define VDD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3.3F<br>#define scale_factor &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2.0F<br><br>#define cell_efficiency &nbsp; &nbsp; &nbsp; &nbsp; 0.065F // 6.5% (Typical Amorphous Cell Efficiency)<br>#define cell_length &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0.0854F // 85.4mm as per inscription on the cell<br>#define cell_width &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0.0563F // 56.3mm as per inscription on the cell<br>#define effective_area_factor &nbsp; 0.90F // Ignoring areas without cell, i.e. boundaries, frames, links, etc<br>#define cell_area &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (cell_length * cell_width) // 0.004816 sq.m &nbsp;<br>#define effective_cell_area &nbsp; &nbsp; (cell_area * effective_area_factor * cell_efficiency) // 0.000281736 sq.m<br><br>void setup(void);<br>unsigned int ADC_read(void);<br>unsigned int ADC_average(void);<br>void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned int value);<br><br>void main(void)<br>{<br>&nbsp; unsigned int ADC = 0;<br>&nbsp; float v = 0;<br>&nbsp; float V = 0;<br>&nbsp; float P = 0;<br>&nbsp; float E = 0;<br>&nbsp; <br>&nbsp; setup();<br>&nbsp; <br>&nbsp; while(1)<br>&nbsp; {<br>&nbsp; &nbsp; &nbsp; ADC = ADC_average();<br>&nbsp; &nbsp; &nbsp; v = ((VDD * ADC) / ADC_Max); &nbsp; &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; V = (v * scale_factor);<br>&nbsp; &nbsp; &nbsp; P = (((V * V) / R_fixed) * R_Error);<br>&nbsp; &nbsp; &nbsp; E = (P / effective_cell_area);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; lcd_print(12, 0, (unsigned int)(P * 1000.0));<br>&nbsp; &nbsp; &nbsp; lcd_print(12, 1, (unsigned int)E);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; delay_ms(100);<br>&nbsp; };<br>}<br><br>void setup(void)<br>{ <br>&nbsp; LCD_init();<br>&nbsp; LCD_clear_home(); <br>&nbsp; LCD_goto(0, 0); <br>&nbsp; LCD_putstr("PV PWR mW:");<br>&nbsp; LCD_goto(0, 1); <br>&nbsp; LCD_putstr("E. W/sq.m:");<br>&nbsp; <br>&nbsp; Enable_ADC_AIN0;<br>}<br><br>unsigned int ADC_read(void)<br>{<br>&nbsp; register unsigned int value = 0x0000;<br>&nbsp; <br>&nbsp; clr_ADCF;<br>&nbsp; set_ADCS; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; while(ADCF == 0);<br>&nbsp; <br>&nbsp; value = ADCRH;<br>&nbsp; value &lt;&lt;= 4;<br>&nbsp; value |= ADCRL;<br>&nbsp; <br>&nbsp; return value;<br>}<br><br>unsigned int ADC_average(void)<br>{<br>&nbsp; &nbsp; signed char samples = 16;<br>&nbsp; &nbsp; unsigned long value = 0;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; while(samples &gt; 0)<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; value += ((unsigned long)ADC_read());<br>&nbsp; &nbsp; &nbsp; &nbsp; samples--;<br>&nbsp; &nbsp; };<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; value &gt;&gt;= 4;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; return ((unsigned int)value);<br>}<br><br>void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned int value)<br>{ &nbsp;<br>&nbsp; unsigned char ch = 0;<br><br>&nbsp; &nbsp; if((value &gt; 999) &amp;&amp; (value &lt;= 9999))<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; ch = (((value % 10000) / 1000) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto(x_pos, y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = (((value % 1000) / 100) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 1), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = (((value % 100) / 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 2), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = ((value % 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 3), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; else if((value &gt; 99) &amp;&amp; (value &lt;= 999))<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; ch = 0x20;<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto(x_pos, y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = (((value % 1000) / 100) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 1), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = (((value % 100) / 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 2), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = ((value % 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 3), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; else if((value &gt; 9) &amp;&amp; (value &lt;= 99))<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; ch = 0x20;<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto(x_pos, y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = 0x20;<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 1), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = (((value % 100) / 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 2), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = ((value % 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 3), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; ch = 0x20;<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto(x_pos, y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = 0x20;<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 1), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = 0x20;<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 2), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; ch = ((value % 10) + 0x30);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_goto((x_pos + 3), y_pos);<br>&nbsp; &nbsp; &nbsp; &nbsp; LCD_putchar(ch);<br>&nbsp; &nbsp; } &nbsp; <br>}<br></pre>



<h2>Explanation</h2>



<p>This project is
completed with a Nuvoton N76E003 microcontroller. I chose this microcontroller because
it is cheap and features a 12-bit ADC. The high-resolution ADC is the main reason
for using it because we are dealing with low power and thus low voltage and
current. The solar cell that I used is only about 300mW in terms of power. If
the reader is new to Nuvoton N76E003 microcontroller, I strongly suggest going
through my tutorials on this microcontroller <a href="https://embedded-lab.com/blog/tag/n76e003/">here</a>. </p>



<p>Let us first see what definitions have been used in the code. Most are self-explanatory.</p>



<pre class="wp-block-preformatted">#define Vmpp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5.162F<br>#define Impp &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0.056F<br>#define R_actual &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(Vmpp / Impp)<br>#define R_fixed &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 100.0F // &nbsp; &nbsp;<br>#define R_Error &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (R_fixed / R_actual)<br>#define ADC_Max &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4095.0F<br>#define VDD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3.3F<br>#define scale_factor &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2.0F<br><br>#define cell_efficiency &nbsp; &nbsp; &nbsp; &nbsp; 0.065F // 6.5% (Typical Amorphous Cell Efficiency)<br>#define cell_length &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0.0854F // 85.4mm as per inscription on the cell<br>#define cell_width &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0.0563F // 56.3mm as per inscription on the cell<br>#define effective_area_factor &nbsp; 0.90F // Ignoring areas without cell, i.e. boundaries, frames, links, etc<br>#define cell_area &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (cell_length * cell_width) // 0.004816 sq.m &nbsp;<br>#define effective_cell_area &nbsp; &nbsp; (cell_area * effective_area_factor * cell_efficiency) // 0.000281736 sq.m </pre>



<p>Obviously VMPP and IMPP are needed to calculate RMPP and this is called here as <strong><em>R_actual</em></strong>. <strong><em>R_fixed</em></strong> is the load resistor that is put in parallel to the solar cell and this is the load resistor needed to fulfill maximum power transfer theorem. Practically, it is not possible to get 92.18Ω easily and so instead of 92.18Ω ,a 100Ω (1% tolerance) resistor is placed in its place. The values are close enough and the difference between these values is about 8%. This difference is also taken into account in the calculations via the definition <strong><em>R_Error</em></strong>.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-54.png" alt="" class="wp-image-15044" /></figure></div>



<p>Thus, during calculation this amount of difference should be compensated for.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-55.png" alt="" class="wp-image-15045" /></figure></div>



<p><strong><em>ADC_Max</em></strong> and <strong><em>VDD</em></strong> are maximum ADC count and supply voltage values respectively. These would be needed to find the voltage resolution that the ADC can measure.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-56.png" alt="" class="wp-image-15046" /></figure></div>



<p>Since 806µV
is a pretty small figure, we can rest assure that very minute changes in solar
irradiance will be taken into account during measurement. </p>



<p><strong><em>scale_factor</em></strong> is the voltage divider ratio. The cell gives a maximum voltage output of 5.691V but N76E003 can measure up to 3.3V. Thus, a voltage divider is needed. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-57.png" alt="" class="wp-image-15047" /></figure></div>



<p>This
is the maximum voltage that N76E003 will see when the cell reaches open-circuit
voltage. Thus, the ADC input voltage needs to be scaled by a factor of 2 in
order to back-calculate the cell voltage, hence the name <strong><em>scale_factor</em></strong>.</p>



<p>The next definitions are related to the cell that is used in this project. Cell length and width are defined and with these the area of the cell is calculated. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-58.png" alt="" class="wp-image-15048" /></figure></div>



<p>The physical
cell area does not represent the total area that is sensitive to solar irradiation.
There are spaces within this physical area that contain electrical links, bezels
or frame, etc. Thus, a good estimate of effective solar sensitive cell area is
about 90% of the physical cell area. This is defined as the <strong><em>effective_area_factor</em></strong>.
&nbsp;&nbsp;&nbsp;</p>



<p>Lastly, we have to take account of cell efficiency because we have seen that in a given area not all solar irradiation is absorbed and so the <strong><em>cell_efficiency</em></strong> is also defined. Typically, a thin film cell like the one I used in this project has an efficiency of 6 – 7% and so a good guess is 6.5%. All of the above parameters lead to effective cell area and it is calculated as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-59.png" alt="" class="wp-image-15049" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-59.png 623w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-59-580x103.png 580w" sizes="(max-width: 623px) 100vw, 623px" /></figure></div>



<p>So now the aforementioned equation becomes as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-60.png" alt="" class="wp-image-15050" /></figure></div>



<p>The equations
suggest that only by reading ADC input voltage we can compute both the power
and solar irradiance. </p>



<p>The code initializes by initializing the I2C LCD, printing some fixed messages and enabling ADC pin 0. </p>



<pre class="wp-block-preformatted">void setup(void)<br>{ <br>&nbsp; LCD_init();<br>&nbsp; LCD_clear_home(); <br>&nbsp; LCD_goto(0, 0); <br>&nbsp; LCD_putstr("PV PWR mW:");<br>&nbsp; LCD_goto(0, 1); <br>&nbsp; LCD_putstr("E. W/sq.m:");<br>&nbsp; <br>&nbsp; Enable_ADC_AIN0;<br>} </pre>



<p>The core components of the code are the functions related to ADC reading and averaging. The code below is responsible for ADC reading.</p>



<pre class="wp-block-preformatted">unsigned int ADC_read(void)<br>{<br>&nbsp; register unsigned int value = 0x0000;<br>&nbsp; <br>&nbsp; clr_ADCF;<br>&nbsp; set_ADCS; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; while(ADCF == 0);<br>&nbsp; <br>&nbsp; value = ADCRH;<br>&nbsp; value &lt;&lt;= 4;<br>&nbsp; value |= ADCRL;<br>&nbsp; <br>&nbsp; return value;<br>}  </pre>



<p>The following code does the ADC averaging part. Sixteen samples of ADC reading are taken and averaged. Signal averaging allows for the elimination of false and noisy data. The larger the number of samples, the more is the accuracy but having a larger sample collection lead to slower performance.</p>



<pre class="wp-block-preformatted">unsigned int ADC_average(void)<br>{<br>&nbsp; &nbsp; signed char samples = 16;<br>&nbsp; &nbsp; unsigned long value = 0;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; while(samples &gt; 0)<br>&nbsp; &nbsp; {<br>&nbsp; &nbsp; &nbsp; &nbsp; value += ((unsigned long)ADC_read());<br>&nbsp; &nbsp; &nbsp; &nbsp; samples--;<br>&nbsp; &nbsp; };<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; value &gt;&gt;= 4;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; return ((unsigned int)value);<br>} &nbsp;</pre>



<p> In the main, the ADC average is read and this is converted to voltage. The converted voltage is then upscaled by applying the <strong><em>scale_factor</em></strong> to get the actual cell voltage. With the actual voltage, power and irradiation are computed basing on the math aforementioned. The power and irradiation values are displayed on the I2C LCD and the process is repeated every 100ms.  </p>



<pre class="wp-block-preformatted">ADC = ADC_average();<br>v = ((VDD * ADC) / ADC_Max); &nbsp; &nbsp; &nbsp;  <br>V = (v * scale_factor);<br>P = (((V * V) / R_fixed) * R_Error);<br>E = (P / effective_cell_area);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>lcd_print(12, 0, (unsigned int)(P * 1000.0));<br>lcd_print(12, 1, (unsigned int)E);<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>delay_ms(100); </pre>



<p>I have tested the device against a SM206-Solar solar irradiation meter and the results are fairly accurate enough for simple measurements.</p>



<h2>Demo</h2>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-61.png" alt="" class="wp-image-15051" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-61.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-61-580x308.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-61-768x408.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-62.png" alt="" class="wp-image-15052" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-62.png 975w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-62-580x316.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-62-768x418.png 768w" sizes="(max-width: 975px) 100vw, 975px" /></figure></div>



<h3>Demo video links: <br></h3>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Solar Pyranometer with N76E003 and Mini Solar Cell" width="860" height="484" src="https://www.youtube.com/embed/j86mO_6Vdmc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<figure class="wp-block-embed-youtube aligncenter wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Solar Insolation Measurement with Nuvoton N76E003 and a Mini Solar Cell" width="860" height="484" src="https://www.youtube.com/embed/X3ipnicPN6U?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<h2>Improvements and Suggestions</h2>



<p>Though this device is not a professional solar irradiation measurement meter, it is fair enough for simple estimations. In fact, SMA – a German manufacturer of solar inverter, solar charger and other smart solar solution uses a similar method with their <strong><em>SMA Sunny Weather Station</em></strong>. This integration allows them to monitor their power generation devices such as on-grid inverters, multi-cluster systems, etc. and optimize performances. &nbsp;</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-63.png" alt="" class="wp-image-15053" srcset="https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-63.png 607w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-63-150x150.png 150w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-63-580x580.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2022/02/image-63-90x90.png 90w" sizes="(max-width: 607px) 100vw, 607px" /></figure></div>



<p>There are rooms for lot of improvements
and these are as follows:</p>



<ul><li>A temperature sensor can be mounted on the backside of the solar cell. This sensor can take account of temperature variations and thereby compensate readings. We have seen that temperature affects solar cell performance and so temperature is a major influencing factor.</li><li>A smaller cell would have performed better but it would have needed additional amplifiers and higher resolution ADCs. A smaller cell will have lesser useless areas and weight. This would make the device more portable. </li><li>Using filters to filter out unnecessary components of solar spectrum. </li><li>Adding a tracking system to scan and align with the sun would result in determining maximum irradiation. </li></ul>



<p>Project Code can be found <a href="https://github.com/sshahryiar/Nuvoton-8-bit-MCU-Projects/tree/main/Solar%20Irradiation%20Meter">here</a>.</p>



<p>Happy coding.</p>



<p><em>Author: Shawon M. Shahryiar</em></p>



<p><a href="https://www.facebook.com/groups/microarena">https://www.facebook.com/groups/microarena</a></p>



<p><a href="https://www.facebook.com/MicroArena?ref=hl"><em>https://www.facebook.com/MicroArena</em></a><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</em></p>



<p><em>28.02.2022</em></p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/a-simple-solar-irradiation-measurement-technique/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
							</item>
		<item>
		<title>Exploring STC 8051 Microcontrollers &#8211; Coding</title>
		<link>https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers-coding/</link>
				<comments>https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers-coding/#comments</comments>
				<pubDate>Fri, 03 Dec 2021 09:15:37 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[Embedded Lessons]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[STC8051]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[8051]]></category>
		<category><![CDATA[Chinese Microcontroller]]></category>
		<category><![CDATA[STC]]></category>
		<category><![CDATA[STC Microcontroller]]></category>
		<category><![CDATA[STC8A8K64S4A12]]></category>

		<guid isPermaLink="false">https://embedded-lab.com/blog/?p=14763</guid>
				<description><![CDATA[About STC8A8K64S4A12 Microcontroller and its Development Board This is the continuation of my first post on STC 8051 Microcontrollers here. Many Chinese microcontroller manufacturers develop awesome and cheap general-purpose MCUs using the popular 8051 architecture. There are many reasons for that but most importantly the 8051 architecture is a very common one that has been around for quite a long time. Secondly, manufacturing MCUs with 8051 DNA allows manufacturers to focus less on developing their own proprietary core and to give more effort in adding features. Holtek, Nuvoton, STC, etc are a few manufacturers to name. Rather than mastering a]]></description>
								<content:encoded><![CDATA[
<h2>About STC8A8K64S4A12
Microcontroller and its Development Board</h2>



<p style="text-align:left"></p>



<p>This is the continuation of my first post on STC 8051 Microcontrollers <a href="https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers/">here</a>.</p>



<p></p>



<p>Many Chinese microcontroller manufacturers develop awesome and cheap general-purpose MCUs using the popular 8051 architecture. There are many reasons for that but most importantly the 8051 architecture is a very common one that has been around for quite a long time. Secondly, manufacturing MCUs with 8051 DNA allows manufacturers to focus less on developing their own proprietary core and to give more effort in adding features. Holtek, Nuvoton, STC, etc are a few manufacturers to name. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2021/12/Untitled.jpg" alt="" class="wp-image-14769" srcset="https://embedded-lab.com/blog/wp-content/uploads/2021/12/Untitled.jpg 250w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/Untitled-150x150.jpg 150w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/Untitled-90x90.jpg 90w" sizes="(max-width: 250px) 100vw, 250px" /></figure></div>



<span id="more-14763"></span>



<p>Rather than mastering a good old 8051-based microcontroller like the AT89C52 or similar, it is better to learn something new that has many similarities with that architecture. As mentioned earlier, STC has various flavour of microcontrollers based on 8051 cores. STC8A8K64S4A12 of the STC8 family is one such example. Here for this documentation, I will be using this MCU specifically. In short, it is a beast as it offers lot of additional hardware that are usually not seen in regular 8051s. Some key features are listed below. The red box highlights the STC8A8K64S4A12 micro in particular.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image.png" alt="" class="wp-image-14764" srcset="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image.png 940w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-580x420.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-768x556.png 768w" sizes="(max-width: 940px) 100vw, 940px" /></figure></div>



<p>I chose STC8A8K64S4A12 for this tutorial for all of its rich features. My favourite features include 12-bit ADC, multiple timers, reduced EMI feature and PCA module.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-1.png" alt="" class="wp-image-14765" srcset="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-1.png 617w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-1-543x650.png 543w" sizes="(max-width: 617px) 100vw, 617px" /></figure></div>



<p>Now let’s see the naming convention of STC microcontrollers. The figure below shows us what the name of a STC8 micro means:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-2.png" alt="" class="wp-image-14766" /></figure></div>



<p>The name STC8A8K64S4A12 is quite a mouthful
and given the nomenclature info, STC8A8K64SA412 is actually a STC8 series micro
with on-chip 12-bit ADC, 8kB SRAM, 64kB code space and 4 hardware serial (UART)
ports. Apart from these hardware thingies, the naming convention does not
reveal other cool features, for if it had been so, the device name would be
even longer.&nbsp; &nbsp;</p>



<p>Initially I wanted to make this tutorial with the STC15F(L)204EA microcontroller but later I changed my mind because STC8A8K64S4A12 is much richer in hardware peripheral terms than STC15F(L)204EA, not to mention several similar hardware are present in both models of microcontroller. Since I planned to use STC8A8K64S4A12, I waited for the arrival of the board shown below before completing this work. Although this development board is an official board, it has been smartly designed for fast learning and rapid deployment of projects. As a matter of fact, if someone learns about this micro with this board, he/she will rule over all of STC’s 8051-based line-up.</p>



<figure class="wp-block-image"><img src="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-3.png" alt="" class="wp-image-14767" srcset="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-3.png 931w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-3-580x375.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-3-768x497.png 768w" sizes="(max-width: 931px) 100vw, 931px" /></figure>



<p>This board has the following schematic and it will be needed throughout this tutorial. </p>



<div class="wp-block-image"><figure class="aligncenter"><img src="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-4.png" alt="" class="wp-image-14768" srcset="https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-4.png 940w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-4-580x385.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2021/12/image-4-768x510.png 768w" sizes="(max-width: 940px) 100vw, 940px" /></figure></div>



<p>On board, we have connectors for OLED display, GLCD, LCD, TFT Display, nRF24L01 transceiver, ESP8266 Wi-Fi module, etc. We also have on board W25x16 flash, 24C04 EEPROM, RS485 communication bridge and a CH340G USB-serial converter that doubles as an on-board programmer. </p>


]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers-coding/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
							</item>
		<item>
		<title>Elecrow launches Crowbits: Electronic Blocks for STEM Education</title>
		<link>https://embedded-lab.com/blog/elecrow-launches-crowbits-electronic-blocks-for-stem-education/</link>
				<comments>https://embedded-lab.com/blog/elecrow-launches-crowbits-electronic-blocks-for-stem-education/#respond</comments>
				<pubDate>Fri, 05 Mar 2021 03:02:48 +0000</pubDate>
		<dc:creator><![CDATA[R-B]]></dc:creator>
				<category><![CDATA[Internet of Things]]></category>

		<guid isPermaLink="false">http://embedded-lab.com/blog/?p=14757</guid>
				<description><![CDATA[With the grand success of CROWPI2, an all-in-one portable Raspberry Pi Laptop development platform, Elecrow has now come up with Crowbits: easy-to-use electronic building blocks for young inventors. Crowbits include more than 80 modules that can be easily snapped through built-in magnets to create projects. It also incorporates a graphical programming software -Letsocde, where users can simply drag and drop blocks to develop applications.]]></description>
								<content:encoded><![CDATA[
<p>With the grand success of <strong><a href="http://embedded-lab.com/blog/meet-crowpi2-an-all-in-one-portable-raspberry-pi-laptop-for-steam-learning-and-rapid-prototyping/">CROWPI2</a></strong>, an all-in-one portable Raspberry Pi Laptop development platform, Elecrow has now come up with <strong><a href="https://www.kickstarter.com/projects/elecrow/crowbits-electronic-blocks-for-stem-education-at-any-level">Crowbits: easy-to-use electronic building blocks</a></strong> for young inventors. Crowbits include more than 80 modules that can be easily snapped through built-in magnets to create projects. It also incorporates a graphical programming software -Letsocde, where users can simply drag and drop blocks to develop applications.</p>



<p> </p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2021/03/crowbit1.png" alt="" class="wp-image-14759" srcset="https://embedded-lab.com/blog/wp-content/uploads/2021/03/crowbit1.png 680w, https://embedded-lab.com/blog/wp-content/uploads/2021/03/crowbit1-580x327.png 580w" sizes="(max-width: 680px) 100vw, 680px" /><figcaption>Crowbits: <strong><a href="https://www.kickstarter.com/projects/elecrow/crowbits-electronic-blocks-for-stem-education-at-any-level">easy-to-use electronic building blocks</a></strong> for young inventors</figcaption></figure>



<p></p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/elecrow-launches-crowbits-electronic-blocks-for-stem-education/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Meet CrowPi2: An all-in-one portable Raspberry Pi laptop for STEAM learning and rapid prototyping</title>
		<link>https://embedded-lab.com/blog/meet-crowpi2-an-all-in-one-portable-raspberry-pi-laptop-for-steam-learning-and-rapid-prototyping/</link>
				<comments>https://embedded-lab.com/blog/meet-crowpi2-an-all-in-one-portable-raspberry-pi-laptop-for-steam-learning-and-rapid-prototyping/#respond</comments>
				<pubDate>Wed, 17 Jun 2020 00:30:18 +0000</pubDate>
		<dc:creator><![CDATA[R-B]]></dc:creator>
				<category><![CDATA[Raspberry Pi]]></category>
		<category><![CDATA[Raspberry Pi kit]]></category>
		<category><![CDATA[Raspberry Pi laptop]]></category>

		<guid isPermaLink="false">http://embedded-lab.com/blog/?p=14728</guid>
				<description><![CDATA[When it comes to STEAM (Science, technology, engineering, art and math) education, the Raspberry Pi is perhaps the most affordable, powerful, and versatile learning tool for all ages and skill levels. The versatility of this little computer comes from its incredible interconnectivity feature that offers direct connection of sensors and electromechanical components, thereby allowing the users to learn embedded hardware and programming in a very simple and engaging way. Since it first came out in 2012, the Raspberry Pi has been the most adventurous tool of teachers in the classroom to foster learning, awareness of computer programming, and extend the]]></description>
								<content:encoded><![CDATA[
<p>When it comes to STEAM (Science, technology, engineering, art and math) education, the Raspberry Pi is perhaps the most affordable, powerful, and versatile learning tool for all ages and skill levels. The versatility of this little computer comes from its incredible interconnectivity feature that offers direct connection of sensors and electromechanical components, thereby allowing the users to learn embedded hardware and programming in a very simple and engaging way. Since it first came out in 2012, the Raspberry Pi has been the most adventurous tool of teachers in the classroom to foster learning, awareness of computer programming, and extend the computer capabilities to multiple domains of education.  The best way to learn Raspberry Pi is by doing projects. There are tons of starter kits available in the market for Raspberry Pi to satisfy both the programming and hardware needs. Elecrow’s has just announced a <strong><a href="https://www.kickstarter.com/projects/elecrow/crowpi2-steam-education-platformand-raspberry-pi-laptop" target="_blank" rel="noreferrer noopener" aria-label="kickstarter campaign (opens in a new tab)">kickstarter campaign</a></strong> for their latest CrowPi2, which is an unique development platform combining the power of the Raspberry Pi computer with a bunch of sensors, displays, and software applications in a form of portable laptop suitable for easy learning and rapid prototyping. </p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2020/06/48d648801580188b66932566cd20ef6a_original-598x1024.jpg" alt="" class="wp-image-14736" srcset="https://embedded-lab.com/blog/wp-content/uploads/2020/06/48d648801580188b66932566cd20ef6a_original-598x1024.jpg 598w, https://embedded-lab.com/blog/wp-content/uploads/2020/06/48d648801580188b66932566cd20ef6a_original-379x650.jpg 379w, https://embedded-lab.com/blog/wp-content/uploads/2020/06/48d648801580188b66932566cd20ef6a_original.jpg 680w" sizes="(max-width: 598px) 100vw, 598px" /><figcaption>CrowPi2: An all-in-one laptop and prototyping device based on Raspberry Pi</figcaption></figure>



<p><strong>For more details on the introduction pricing and onboard features of CrowPi2, visit the <a href="https://www.kickstarter.com/projects/elecrow/crowpi2-steam-education-platformand-raspberry-pi-laptop" target="_blank" rel="noreferrer noopener" aria-label="Kickstarter page (opens in a new tab)">Kickstarter page</a>.</strong></p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/meet-crowpi2-an-all-in-one-portable-raspberry-pi-laptop-for-steam-learning-and-rapid-prototyping/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
							</item>
		<item>
		<title>Tinkering TI MSP430F5529</title>
		<link>https://embedded-lab.com/blog/tinkering-ti-msp430f5529/</link>
				<comments>https://embedded-lab.com/blog/tinkering-ti-msp430f5529/#comments</comments>
				<pubDate>Wed, 29 Jan 2020 15:58:00 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[Embedded Lessons]]></category>
		<category><![CDATA[MCU develeopment tools]]></category>
		<category><![CDATA[MSP430 Launchpad]]></category>
		<category><![CDATA[Texas Instruments]]></category>
		<category><![CDATA[TI]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[launchpad]]></category>
		<category><![CDATA[Launchpad kit]]></category>
		<category><![CDATA[MSP430]]></category>
		<category><![CDATA[MSP430F5529]]></category>
		<category><![CDATA[MSP430F5529 USB]]></category>
		<category><![CDATA[ti]]></category>
		<category><![CDATA[TI MSP]]></category>
		<category><![CDATA[TI MSP430 Microcontrollers]]></category>

		<guid isPermaLink="false">http://embedded-lab.com/blog/?p=14523</guid>
				<description><![CDATA[In my past tutorials on MSP430s, I demonstrated how to get started with MSP430 general purpose microcontrollers from Texas Instruments (TI). Those tutorials covered most aspects of low and mid-end MSP430G2xxx series microcontrollers. For those tutorials, TI’s official software suite – Code Composer Studio (CCS) – an Eclipse-based IDE and GRACE – a graphical peripheral initialization and configuration tool similar to STM32CubeMX were used. To me, those low and mid-end TIs chips are cool and offer best resources one can expect at affordable prices and small physical form-factors. I also briefly discussed about advanced MSP430 microcontrollers and the software resources]]></description>
								<content:encoded><![CDATA[
<p>In my <a href="http://embedded-lab.com/blog/introducing-ti-msp430-microcontrollers/">past tutorials on MSP430s</a>, I demonstrated how to get started with MSP430 general purpose microcontrollers from <strong><em>Texas Instruments (TI)</em></strong>. Those tutorials covered most aspects of low and mid-end MSP430G2xxx series microcontrollers. For those tutorials, TI’s official software suite – <strong><em>Code Composer Studio (CCS)</em></strong> – an Eclipse-based IDE and <strong><em>GRACE</em></strong> – a graphical peripheral initialization and configuration tool similar to STM32CubeMX were used. To me, those low and mid-end TIs chips are cool and offer best resources one can expect at affordable prices and small physical form-factors. I also briefly discussed about advanced MSP430 microcontrollers and the software resources needed to use them effectively. Given these factors, now it is high time that we start exploring an advanced 16-bit TI MSP430 microcontroller using a combination of past experiences and advanced tools. MSP430F5529 is such a robust high-end device and luckily it also comes with an affordable Launchpad board dedicated for it. </p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2020/01/launchpad.jpg" alt="" class="wp-image-14524" srcset="https://embedded-lab.com/blog/wp-content/uploads/2020/01/launchpad.jpg 945w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/launchpad-580x438.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/launchpad-768x579.jpg 768w" sizes="(max-width: 945px) 100vw, 945px" /></figure>



<span id="more-14523"></span>



<p>First of all, MSP430F5529 is a monster microcontroller because it offers large memory spaces– 128kB of flash and 8kB of RAM. Secondly, it is a 16-bit RISC microcontroller that host several advanced features like USB, DMA, 12-bit SAR ADC, analogue comparator, a real time clock (RTC), several sophisticated timers with multiple capture-compare I/O channels, etc. There is an on-chip hardware multiplier apart from several bidirectional general-purpose digital input-output (DIO/GPIO) pins, multipurpose communication peripherals (USCIs) and a highly complex clock and power system that can be tweaked to optimize the speed-power performances. The MSP430F5529LP microcontroller featured on-board MSP430F5529 Launchpad is a low power energy-efficient variant of MSP430F5529 and hence the <em>LP</em> designation at the end of the part naming. It can run at low voltage levels like 1.8V. In short, it is a hobbyist wildest dream come true. </p>



<h2>MSP-EXP430F5529LP Launchpad Board</h2>



<p>The MSP-EXP430F5529LP Launchpad board is just like other Launchpad boards, having similar form-factor and layout. Unlike the previously seen MSP-EXP430G2 Launchpads, its header pins are brought out using dual-sided male- female rail-connectors. These allow us to stack <strong><em>BoosterPacks</em></strong> on both sides.</p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529-Launchpad-1024x555.jpeg" alt="" class="wp-image-14526" srcset="https://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529-Launchpad-1024x555.jpeg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529-Launchpad-580x314.jpeg 580w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529-Launchpad-768x416.jpeg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Shown above and below are the pin maps of this Launchpad board.</p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529LP-Launchpad-Pin-Map.png" alt="" class="wp-image-14525" srcset="https://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529LP-Launchpad-Pin-Map.png 1007w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529LP-Launchpad-Pin-Map-580x253.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/MSP430F5529LP-Launchpad-Pin-Map-768x335.png 768w" sizes="(max-width: 1007px) 100vw, 1007px" /></figure>



<p>The first pin map is useful for <strong><em>Energia</em></strong> users and the second one is useful for CCS users. I use a combination of both.  Like other Launchpad boards, this Launchpad comes with a separable MSP-FET USB programmer and debugger interface. Since MSP430F5529 micro has USB hardware embedded in it, the on-board micro USB port can act as a physical USB port when developing USB-based hardware. The micro USB port isn’t, however, directly connected with the chip. Instead of that, the same USB port is connected to the on-board FET programmer and the MSP430F5529 chip via an on-board USB hub. The micro USB port also provides power to the board. The on-board MSP430 chip is powered by 3.3V LDO regulator. This LDO is not meant for driving large loads. There are sufficient power rail pins to hook-up low-power external devices like sensors, LCDs, etc without the need of power rail extenders.&nbsp;&nbsp;&nbsp; </p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2020/01/Board.png" alt="" class="wp-image-14527" srcset="https://embedded-lab.com/blog/wp-content/uploads/2020/01/Board.png 789w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/Board-580x440.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/Board-768x583.png 768w" sizes="(max-width: 789px) 100vw, 789px" /></figure>



<p>MSP430F5529 is not a low pin count micro and it has a sophisticated clock system that can be feed with both internal and external clock sources. Thus, unlike MSP430G2xxx Launchpads, this Launchpad comes with two external crystals – a 4MHz and a 32.768kHz crystal that are physically connected with GPIO pins. There are two user buttons and two LEDs also. Additionally, there are dedicated buttons for USB bootstrap loader and hardware reset. There are few jumpers that can be for measurements, debugging, programming, etc.</p>



<p>Shown below is the schematic of MSP430F5529LP Launchpad board:</p>



<figure class="wp-block-image"><img src="http://embedded-lab.com/blog/wp-content/uploads/2020/01/Schematic-756x1024.png" alt="" class="wp-image-14530" srcset="https://embedded-lab.com/blog/wp-content/uploads/2020/01/Schematic-756x1024.png 756w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/Schematic-480x650.png 480w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/Schematic-768x1041.png 768w, https://embedded-lab.com/blog/wp-content/uploads/2020/01/Schematic.png 1039w" sizes="(max-width: 756px) 100vw, 756px" /></figure>



<h2>TI MSP430Ware Driver Library and Other Stuffs</h2>



<p>Like with other advanced microcontrollers from TI,
there is no GRACE-like support that can be found for MSP430F5529 and similar
devices. In fact, GRACE only supports few low-end and mid-end MSP430
microcontrollers and for some reason TI stopped updating this great tool since
2013. One probably reason may be the difficulty in developing a GUI-based
application that can be used across all computer platforms (Windows, Linux, Mac
OS, etc) while maintaining support for all ever-growing families of MSP430
devices. </p>



<p>Instead of upgrading GRACE, TI invested on something called <strong><em>MSP430Ware Driver Library</em></strong> or simply <strong><em>Driverlib</em></strong>. Driverlib replaces traditional register-level coding with a set of dedicated hardware libraries that reduces learning and implementation curves. These libraries consist of functions, variables and constants that have meaningful names. A sample code is shown below:</p>



<pre class="wp-block-preformatted">Timer_A_outputPWMParam outputPWMParam = {0}; 
outputPWMParam.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; outputPWMParam.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_2; outputPWMParam.timerPeriod = 20000; 
outputPWMParam.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1; outputPWMParam.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET; outputPWMParam.dutyCycle = 0; 
Timer_A_outputPWM(TIMER_A2_BASE, &amp;outputPWMParam);</pre>



<p>Note that there is no register-level coding involved
and that’s the beauty. Here all the settings of a timer in PWM mode are being
set. Each parameter is named with a meaningful name instead of some meaningless
magic numbers and coding jargon.</p>



<p>Initially, I was doubtful and hesitant about using
Driverlib because it hides away all the good-old register-level coding and at
the same time it lacks good documentations. Comparing Driverlib documentation
with the documentation of other manufacturers like STMicroelectronics or
Microchip, I would say that Driverlib documentation is somewhat incomplete,
clumsy and difficult to perceive. Adding to this is the fact that TI while
developing and updating Driverlib made some changes to some function and
definition names. This creates further confusion unless you are using the right
version of documentation alongside the right Driverlib version. </p>



<p>Here’s one example. Both are correct and the compiler won’t throw any unexpected error but the first one is seen in older documentations while the second is used more often now. </p>



<pre class="wp-block-preformatted">Timer_A_startCounter(__MSP430_BASEADDRESS_T0A5__, TIMER_A_CONTINUOUS_MODE);

or

Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_CONTINUOUS_MODE);</pre>



<p>Issues like this one discussed above may not always
be that simple and when it comes to older codes/examples, thing may become very
ugly.</p>



<p>Another disadvantage that comes along with stuffs
like Driverlib is resource management. Indeed, Driverlib reduces coding efforts
a lot but at the expense of valuable and limited memory resources. Performance
is also a bit compromised as execution speed is reduced due to additional
hidden coding. </p>



<p>Despite these facts, I decided to go along with
Driverlib because like other coders I didn’t want to spend time going through register-by-registers.
In present day’s embedded system arena, people like the easy, effective and
quick paths. It happened to me that after few trials I was able to master
Driverlib and could also pinpoint issues with documentation and even practically
get rid of the issues. As of this moment, I am enjoying it a lot and this whole
tutorial is based on it. </p>



<p>Use <strong><em>Resource Explorer</em></strong> of Code Composer
Studio (CCS) IDE or visit the following link:</p>



<figure class="wp-block-embed"><div class="wp-block-embed__wrapper">
http://www.ti.com/tool/MSPWARE
</div></figure>



<p>to get access to MSP430Ware. MSP430Ware contains lot
example codes, libraries and other stuffs.</p>



<p>The rest of the software suite and hardware tools
will be same as the ones used before. Grace support is unavailable and so it
won’t be used. </p>



<p>Please also download MSP430F5529 <a href="https://www.ti.com/product/MSP430F5529/technicaldocuments">documentations</a> and Launchpad board <a href="http://www.ti.com/tool/MSP-EXP430F5529LP">resources</a>. </p>


]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/tinkering-ti-msp430f5529/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
							</item>
		<item>
		<title>Making a SPL dB Meter</title>
		<link>https://embedded-lab.com/blog/making-a-spl-db-meter/</link>
				<comments>https://embedded-lab.com/blog/making-a-spl-db-meter/#comments</comments>
				<pubDate>Wed, 19 Jun 2019 15:01:36 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[Display]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[PIC Projects]]></category>
		<category><![CDATA[PIC18F]]></category>
		<category><![CDATA[Product Review]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[8-bit Microcontroller]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[dB Meter]]></category>
		<category><![CDATA[Grove]]></category>
		<category><![CDATA[microphone]]></category>
		<category><![CDATA[Sound]]></category>
		<category><![CDATA[Spectrum]]></category>
		<category><![CDATA[SPL]]></category>

		<guid isPermaLink="false">http://embedded-lab.com/blog/?p=14471</guid>
				<description><![CDATA[In the 1980s, there was no internet as like today and so the sources of entertainment were televisions, radios and cassette players. When I was a kid, we had an audio cassette player. We used it to play songs but my imagination was always fixed to its VU meter display with its fancy readings as shown below. It changed with the volume of the speakers and matched rhythmically with the sound coming out of it. During my engineering career, I got to know about the Decibel scale and sound pressure measurement. It soon became a goal for me to design]]></description>
								<content:encoded><![CDATA[
<p class="has-drop-cap">In the 1980s, there was no internet as like today and so the sources of entertainment were televisions, radios and cassette players. When I was a kid, we had an audio cassette player. We used it to play songs but my imagination was always fixed to its VU meter display with its fancy readings as shown below. It changed with the volume of the speakers and matched rhythmically with the sound coming out of it. During my engineering career, I got to know about the Decibel scale and sound pressure measurement. It soon became a goal for me to design an audio dB meter and recreate my child memories. In this tutorial, I will show how to make a dB meter that is accurate enough for general uses.</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/vu-meter.png" alt="" class="wp-image-14474" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/vu-meter.png 595w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/vu-meter-580x290.png 580w" sizes="(max-width: 595px) 100vw, 595px" /></figure></div>



<span id="more-14471"></span>



<h2>Background and Application</h2>



<p>Sound needs a medium
for propagation or travel. It can’t travel in vacuum. Normally air is that
medium but sound can also propagate in liquids and other states of matter. I am
not going to lecture on how sound travels and its properties as Wikipedia details
everything well <a href="https://en.wikipedia.org/wiki/Sound">here</a>. Everything
we see around us has a measurement and a unit. In case of sound pressure, the
unit is decibel. Our basic requirement is to be able to measure <strong><em>Sound
Pressure Level (SPL)</em></strong> in decibel scale with a typical 8-bit microcontroller,
an ordinary microphone and without involving complex algorithms. </p>



<p>Measurement of sound has a number of uses. For instance, monitoring sound pollution, security system, monitoring the quality of an amplifier, detecting sound profile of an environment, etc. </p>



<h2>Selecting Microphone</h2>



<p>For the ease of work and for known parameters, I selected <a href="http://wiki.seeedstudio.com/Grove-Sound_Sensor">Seeedstudio’s Grove Sound Sensor</a> which happens to have the following specs:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/Grove-sensor.png" alt="" class="wp-image-14478" /></figure></div>



<p><a href="https://www.seeedstudio.com/">Seeedstudio</a> – a Shenzhen, China-based
component manufacturer and global component supplier, has a good reputation in
the hobby-electronics community, particularly amongst Arduino and Raspberry Pi users.
It is one of the most reliable electronics partners that make quality items at
reasonable price tags.</p>



<p>The <a href="http://www.seeedstudio.com/Grove-Sound-Sensor-p-752.html">Grove microphone module</a> that Seeedstudio sells under the <a href="http://wiki.seeedstudio.com/Grove">Grove</a> product family banner consists of an electret microphone and a pair of general-purpose op-amps in non-inverting configuration that increase the gain roughly by 100 times. The sensor I used was an old version one and the main difference is an additional potentiometer to alter gain. Shown below is the schematic of the current version of the sensor:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/amp-1-1024x441.png" alt="" class="wp-image-14485" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/amp-1-1024x441.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/amp-1-580x250.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/amp-1-768x330.png 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/amp-1.png 1211w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<p>The microphone module is itself very small. The Grove header and connector are simple and all products of Grove family share the same pin/header layout. The headers bring out power pins and signal pin(s). Grove connectors connect with these headers in one way only and the connectors have properly colored-wires. Thus, there is literally no chance of accidental wrong connections. The same type of header brings out the needed connections from the microphone module. We just have to connect them to our host microcontroller and power supply. </p>



<h2>The Math</h2>



<p>The
specs of the microphone in the Grove Sound Sensor suggests that it has a
sensitivity of 52 &#8211; 48dB at 1kHz spectrum. Therefore, it is best to consider an
average sensitivity of 50dB.&nbsp;</p>



<p>The formula for sensitivity is as follows:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/image.png" alt="" class="wp-image-14486" /></figure></div>



<p>where Output AREF is typically 1000 mV/Pa (1 V/Pa)
reference output ratio.</p>



<p>Thus, the sensitivity of the microphone in mv/Pa is found by going on the other side of the formula as shown in the following steps:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/image-1.png" alt="" class="wp-image-14487" /></figure></div>



<p>Going back to the schematic of the microphone module, we see that the original signal is amplified by about 100 times and so the actual sensitivity of the microphone is calculated to be:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/image-2.png" alt="" class="wp-image-14488" /></figure></div>



<p>Microphone sensitivity is typically measured with a 1kHz sine wave at a 94dB&nbsp;sound pressure level (SPL), or with 1Pa pressure. This is a reference value. Thus, the SPL value is given by the following formula:</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/image-3.png" alt="" class="wp-image-14489" /></figure></div>



<p>where 94 is the base value.</p>



<p>A dB reading of 40 represents near quietness while a dB reading of 95 represents the while of a train.</p>



<h2>Schematic</h2>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/sch.png" alt="" class="wp-image-14473" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/sch.png 732w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/sch-580x544.png 580w" sizes="(max-width: 732px) 100vw, 732px" /></figure></div>



<p>As can be seen, the above schematic was designed with Proteus VSM. There is no model for Grove Sound Sensor and so to mimic it, an interactive potentiometer was used in its place. Additionally, power and additional GLCD pins have been ignored in the schematic. However, those pins are present physically.</p>



<h2>Coding</h2>



<p>The code was written with CCS PIC
C compiler and a PIC18F242 microcontroller was used for the project due to its
large memories. CCS PIC C compiler’s coding style is similar to that of Arduino’s
and so I guess nobody would be having any issue understanding the code. </p>



<p>The coding has two major parts. First is data collection and processing, and secondly, the graphical presentation of the collected data on a <strong><em>Graphical Liquid Crystal Display (GLCD)</em></strong>. </p>



<pre class="wp-block-preformatted">#include                                    #device *= 16  #device ADC=10 #fuses HS, PUT, NOWDT, PROTECT, CPD, BROWNOUT, BORV45 #fuses NOSTVREN, NOLVP, NODEBUG, NOCPB, NOWRT, NOWRTC #fuses NOWRTB,  NOWRTD, NOEBTR, NOEBTRB, NOOSCSEN        #use delay (clock = 10MHz)                              #define LARGE_LCD                               #define ref_SPL  94  #define sensitivity    3.16                                                                               #include  #include "HDM64GS192.c"              #include "graphics.c"        #include "background_art.c"                                                                                                                                unsigned char txt_dB_msg[30] = {"SPL Meter"}; unsigned char txt_dB_current[30]; unsigned char txt_dB_max[30];    unsigned char txt_dB_min[30];     unsigned char txt_dB_avg[30];                                      unsigned char x = 17;              float dB_max = 0.0; float dB_min = 100.0; float dB_avg = 0.0;              float dB_current = 0.0;                                                                                                                                          void setup(); void draw_background();                                                         float adc_rms();     void read_SPL(); void display_redings();             void plot_data();  float map(float value, float x_min, float x_max, float y_min, float y_max);                               void main()                                                                                 {                             setup();      draw_background();          while(TRUE)                 {         read_SPL();         display_redings();         plot_data();              delay_ms(400);     }                              }                                                                                                                                                                                              void setup()                                                                    {                                                   disable_interrupts(global);          setup_WDT(WDT_off);        setup_spi(spi_ss_disabled|spi_disabled);        setup_timer_0(T0_internal);                                      setup_timer_1(T1_disabled);                                                                                 setup_timer_2(T2_disabled, 255, 1);             set_timer0(0);        set_timer1(0);             set_timer2(0);        setup_ccp1(ccp_off);               setup_ccp2(ccp_off);        setup_ADC_ports(AN0);                                setup_ADC(ADC_clock_div_32);          set_ADC_channel(0);        glcd_init(on);           glcd_fillscreen(0);                    memset(txt_dB_current, 0, 30);             memset(txt_dB_max, 0, 30);         memset(txt_dB_min, 0, 30);            memset(txt_dB_avg, 0, 30);                                                                  glcd_text57(130, 4, txt_dB_msg, 1, ON);  }                                void draw_background()  {                                unsigned long n = 0;                          unsigned char i = 0;    unsigned char j = 0;    unsigned char cs = 0;                for(i = 0; i &lt; 8; ++i)           {                  output_low(GLCD_DI);                                 glcd_writeByte(GLCD_LEFT, 0x40);              glcd_writeByte(GLCD_RIGHT, 0x40);                  glcd_writeByte(GLCD_MID, 0x40);                                     glcd_writeByte(GLCD_LEFT,(i | 0xB8));           glcd_writeByte(GLCD_RIGHT,(i | 0xB8));            glcd_writeByte(GLCD_MID,(i | 0xB8));                output_high(GLCD_DI);                                    for(j = 0; j = 0) &amp;&amp; (j  0)     {         read_adc(adc_start_only);         while(!adc_done());         rms = read_adc(adc_read_only);           tmp += (rms * rms);               samples--;           }                          tmp &gt;&gt;= 4;                                rms = (sqrt(tmp));          rms *= 0.004875;           if(rms &lt;= 0)     {      rms = 0.004875;     }          return rms;                     }                                          void read_SPL()  {    dB_current = adc_rms();    db_current = (ref_SPL + 20 * log10(db_current / sensitivity));         if(db_current &gt;= 99)    {        dB_current = 99;    }                                                      if(x &gt; 125)     { db_max = 0.0; db_min = 100.0;     x = 17;                }        if(dB_current &gt; dB_max)          {      db_max = dB_current;      }                      if(dB_current &lt; dB_min)          {                     db_min = dB_current;    }                           dB_avg = ((db_max + dB_min) * 0.5);    }                                                                                        void display_redings()  {                                                               glcd_text57(130, 20, txt_dB_current, 1, OFF);       sprintf(txt_dB_current, "Cr:%2.1g dB", db_current);         glcd_text57(130, 20 , txt_dB_current, 1, ON);                                                     glcd_text57(130, 30, txt_dB_max, 1, OFF);              sprintf(txt_dB_max, "Mx:%2.1g dB", dB_max);     glcd_text57(130, 30 , txt_dB_max, 1, ON);               glcd_text57(130, 40, txt_dB_min, 1, OFF);              sprintf(txt_dB_min, "Mn:%2.1g dB", dB_min);     glcd_text57(130, 40 , txt_dB_min, 1, ON);                             glcd_text57(130, 50, txt_dB_avg, 1, OFF);              sprintf(txt_dB_avg, "Av:%2.1g dB", dB_avg);     glcd_text57(130, 50, txt_dB_avg, 1, ON);  }                                                                                                                   void plot_data()                                 {                                        unsigned char l = 0;                                l = map(dB_current, 40, 99, 61, 2);         glcd_line(x, 2, x, 61, YES);       glcd_line(x, l, x, 61, NO);         x += 2; }                                         float map(float value, float x_min, float x_max, float y_min, float y_max)    {                              return (y_min + (((y_max - y_min) / (x_max - x_min)) * (value - x_min))); }          </pre>



<h2>Explaining the Code</h2>



<p>To efficiently collect data, the Root-Mean-Square (RMS) value of 16 raw output samples from the Grove Sound Sensor is taken and the value is converted from ADC counts to voltage. This way of sampling data ensures cancellation of unnecessary noise and glitches. </p>



<pre class="wp-block-preformatted">float adc_rms()
{                         
    unsigned char samples = 16;
    register unsigned long long tmp = 0;
    register float rms = 0.0;          
                      
    while(samples &gt; 0)
    {
        read_adc(adc_start_only);
        while(!adc_done());
        rms = read_adc(adc_read_only);  
        tmp += (rms * rms);      
        samples--;      
    }                     
    tmp &gt;&gt;= 4;                           
    rms = (sqrt(tmp));     
    rms *= 0.004875; 
    
    if(rms &lt;= 0)
    {
        rms = 0.004875;
    }
    
    return rms;                    
}</pre>



<p>The RMS voltage value from the sensor is then put to the derived formula discussed earlier. However, a microcontroller is not your ordinary calculator and it will behave erratically rather than showing an error symbol as in your calculator when it is forced to do a wrong calculation like dividing a value by zero. To avoid such incidents, the readings are checked for upper and lower hardware limits and confined if necessary, before processing and graphical representation. &nbsp;</p>



<p>Further data processing is done to
determine the maximum, minimum and average SPL values.</p>



<pre class="wp-block-preformatted">void read_SPL() <br> {<br>    dB_current = adc_rms();<br>    db_current = (ref_SPL + 20 * log10(db_current / sensitivity)); <br> if(db_current &lt;= 40)    {        dB_current = 40;    }    if(dB_current &gt;= 99)<br>    {<br>        dB_current = 99;<br>    }<br> if(x &gt; 125) <br>    {<br>       db_max = 0.0;<br>       db_min = 100.0;    <br>       x = 17;            <br>    }<br> if(dB_current &gt; dB_max)      <br>    {     <br>       db_max = dB_current;  <br>    }              <br> if(dB_current &lt; dB_min)      <br>    {                    <br>       db_min = dB_current;<br>    }                   <br> dB_avg = ((db_max + dB_min) * 0.5);   <br> } </pre>



<p>Now with the data processed, the data is ready for graphical presentation. The GLCD used here had a resolution of 192 x 64 pixels. It had three regions represented by three chip select (CS) pins. The first two regions were used for graphics while the third or the last region was used for text data. </p>



<p>Every graphical presentation has two components – one is the static background part and the other is the dynamic foreground part. In this code, the static part is the dB scale and the enclosure where the SPL bars graph is to be shown. This part as shown below is loaded only once right after initialization. The dynamic part changes with SPL values in the form of thin vertical bar graphs. &nbsp;</p>



<div class="wp-block-image"><figure class="aligncenter"><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/bmp-1024x512.png" alt="" class="wp-image-14476" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/bmp-1024x512.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/bmp-580x290.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/bmp-768x384.png 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/bmp.png 1025w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>



<pre class="wp-block-preformatted">void display_redings() 
{                                                          
    glcd_text57(130, 20, txt_dB_current, 1, OFF);  
    sprintf(txt_dB_current, "Cr:%2.1g dB", db_current);    
    glcd_text57(130, 20 , txt_dB_current, 1, ON);     
                                          
    glcd_text57(130, 30, txt_dB_max, 1, OFF);         
    sprintf(txt_dB_max, "Mx:%2.1g dB", dB_max);
    glcd_text57(130, 30 , txt_dB_max, 1, ON);     
    
    glcd_text57(130, 40, txt_dB_min, 1, OFF);         
    sprintf(txt_dB_min, "Mn:%2.1g dB", dB_min);
    glcd_text57(130, 40 , txt_dB_min, 1, ON); 
                      
    glcd_text57(130, 50, txt_dB_avg, 1, OFF);         
    sprintf(txt_dB_avg, "Av:%2.1g dB", dB_avg);
    glcd_text57(130, 50, txt_dB_avg, 1, ON); 
}                                
                                                                             
void plot_data()                                
{                                    
   unsigned char l = 0;
                           
   l = map(dB_current, 40, 99, 61, 2); 
   
   glcd_line(x, 2, x, 61, YES);   
   glcd_line(x, l, x, 61, NO); 
   
   x += 2;
}     

                                  
float map(float value, float x_min, float x_max, float y_min, float y_max)   
{                         
    return (y_min + (((y_max - y_min) / (x_max - x_min)) * (value - x_min)));
}      
</pre>



<p>As shown above the first function is responsible for displaying text data. The second function is responsible for plotting the bar graph. The region where a bar is to be plotted is cleared before plotting. This allows us not to fully refresh the screen. The map function is a straight-line equation solver and it comes useful in quickly translating from one range to another. For instance, in this case, the map function translates dB readings from 40 – 99 dB to 61 – 2 Y-coordinate position of the GLCD. Over 100 bars (X-coordinate points) together show the dB trend plot. </p>



<h2>Improvements</h2>



<p>A number of improvements can be made
to the project. Some of these include:</p>



<ul><li>Using
a more sensitive and professional microphone.</li><li>Using
a larger GLCD/TFT display.</li><li>Using
a faster chip for faster data processing.</li><li>Adding
a computer or mobile-phone application.</li><li>Adding
features like FFT data processing, spectrum display, etc.</li><li>Adding
a temperature and pressure sensor to take care of changes in medium with
temperature and air pressure variations.</li></ul>



<h2>Demo</h2>



<ul class="wp-block-gallery columns-3 is-cropped"><li class="blocks-gallery-item"><figure><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/11313183_10200389875827572_7150279108599626701_o-1024x662.jpg" alt="" data-id="14483" data-link="http://embedded-lab.com/blog/?attachment_id=14483" class="wp-image-14483" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/11313183_10200389875827572_7150279108599626701_o-1024x662.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11313183_10200389875827572_7150279108599626701_o-580x375.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11313183_10200389875827572_7150279108599626701_o-768x496.jpg 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11313183_10200389875827572_7150279108599626701_o.jpg 1369w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></li><li class="blocks-gallery-item"><figure><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/11336848_10200389870307434_1037950550626620014_o-1024x488.jpg" alt="" data-id="14479" data-link="http://embedded-lab.com/blog/?attachment_id=14479" class="wp-image-14479" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/11336848_10200389870307434_1037950550626620014_o-1024x488.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11336848_10200389870307434_1037950550626620014_o-580x276.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11336848_10200389870307434_1037950550626620014_o-768x366.jpg 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11336848_10200389870307434_1037950550626620014_o.jpg 1369w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></li><li class="blocks-gallery-item"><figure><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/10478731_10200389876187581_7731499384904138721_o-1024x668.jpg" alt="" data-id="14480" data-link="http://embedded-lab.com/blog/?attachment_id=14480" class="wp-image-14480" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/10478731_10200389876187581_7731499384904138721_o-1024x668.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/10478731_10200389876187581_7731499384904138721_o-580x378.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/10478731_10200389876187581_7731499384904138721_o-768x501.jpg 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/10478731_10200389876187581_7731499384904138721_o.jpg 1369w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></li><li class="blocks-gallery-item"><figure><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/11266588_10200389873227507_5289857930890268648_o-1024x752.jpg" alt="" data-id="14482" data-link="http://embedded-lab.com/blog/?attachment_id=14482" class="wp-image-14482" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/11266588_10200389873227507_5289857930890268648_o-1024x752.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11266588_10200389873227507_5289857930890268648_o-580x426.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11266588_10200389873227507_5289857930890268648_o-768x564.jpg 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11266588_10200389873227507_5289857930890268648_o.jpg 1369w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></li><li class="blocks-gallery-item"><figure><img src="http://embedded-lab.com/blog/wp-content/uploads/2019/06/11039305_10200389869747420_4541973740726294462_o-1024x859.jpg" alt="" data-id="14481" data-link="http://embedded-lab.com/blog/?attachment_id=14481" class="wp-image-14481" srcset="https://embedded-lab.com/blog/wp-content/uploads/2019/06/11039305_10200389869747420_4541973740726294462_o-1024x859.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11039305_10200389869747420_4541973740726294462_o-580x486.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11039305_10200389869747420_4541973740726294462_o-768x644.jpg 768w, https://embedded-lab.com/blog/wp-content/uploads/2019/06/11039305_10200389869747420_4541973740726294462_o.jpg 1369w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></li></ul>



<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Graphical SPL dB Meter with Seeedstudio Grove Sound Sensor and PIC18F242" width="860" height="484" src="https://www.youtube.com/embed/_grNn9yVFz0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div></figure>



<p>Resources related to this project can be downloaded from <a href="https://github.com/sshahryiar/PIC-Microcontroller-Projects/tree/main/GLCD%20dB%20Meter">here</a>.<br></p>



<p></p>



<p><em>Author: Shawon M. Shahryiar</em></p>



<p><a href="https://www.youtube.com/user/sshahryiar">https://www.youtube.com/user/sshahryiar</a></p>



<p><em><a href="https://www.facebook.com/MicroArena?ref=hl">https://www.facebook.com/MicroArena</a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </em></p>



<p><em>26.05.2015</em></p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/making-a-spl-db-meter/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
							</item>
		<item>
		<title>Exploring STC 8051 Microcontrollers</title>
		<link>https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers/</link>
				<comments>https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers/#comments</comments>
				<pubDate>Fri, 28 Sep 2018 02:05:03 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[STC8051]]></category>
		<category><![CDATA[8-bit Microcontroller]]></category>
		<category><![CDATA[8051]]></category>
		<category><![CDATA[STC]]></category>
		<category><![CDATA[STC Micrcontroller]]></category>

		<guid isPermaLink="false">http://embedded-lab.com/blog/?p=14434</guid>
				<description><![CDATA[8051 microcontrollers are the first-generation microcontrollers that sparked the modern embedded-system era and established the basic concepts for almost all microcontrollers. In the early 1980s, 8051 microcontrollers were first introduced by Intel. Later other manufacturers like Philips (NXP), Atmel (now Microchip), Silicon Labs, Maxim, etc took the 8051 architecture and introduced their variants of 8051s. Today there are hundreds of such companies which still manufactures this old school legendary micro. of them have even added more features like ADCs, communication peripherals like SPI and I2C, etc that were not originally incepted or integrated. There are even some manufacturers who produce]]></description>
								<content:encoded><![CDATA[<p style="text-align: justify">8051 microcontrollers are the first-generation microcontrollers that sparked the modern embedded-system era and established the basic concepts for almost all microcontrollers. In the early 1980s, 8051 microcontrollers were first introduced by Intel. Later other manufacturers like Philips (NXP), Atmel (now Microchip), Silicon Labs, Maxim, etc took the 8051 architecture and introduced their variants of 8051s. Today there are hundreds of such companies which still manufactures this old school legendary micro. of them have even added more features like ADCs, communication peripherals like SPI and I2C, etc that were not originally incepted or integrated. There are even some manufacturers who produce micros under their naming convention/branding while maintaining the basic architecture. Recently I covered an article about Nuvoton N76E003 <a href="http://embedded-lab.com/blog/category/nuvoton/">here</a>. It is based on such ideas. <a href="https://www.stcmicro.com">STC</a> (not to be confused with <em>STMicroelectronics</em>) is a Chinese semiconductor manufacturer that operates in the same way as Nuvoton. STC took the model of 8051 just like other manufacturers and upgraded it to new levels by implementing some vital upgrades, enhancements and additions. It also manufactures standard 8051s which are designed to fit in place of any other 8051s from any manufacturer. At present STC has several different variants of 8051s, ranging from standard 40 pin regular DIP 8051s to tiny 8-pin variants. Some are shown below.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC8051s.png"><img class="alignnone size-medium wp-image-14435" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC8051s-580x221.png" alt="STC8051s" width="580" height="221" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC8051s-580x221.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC8051s.png 783w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify"><span id="more-14434"></span></p>
<h1 style="margin-top: 0cm">STC 8051s vs Other 8051s</h1>
<p style="text-align: justify">STC 8051s, as stated, offers additional hardware peripherals when compared to standard 8051s. There are some STC microcontrollers like STC89C52RC that are same as the standard ones while some others like STC8A8K64S4A12 are more robust with many advanced features. Some key differences between standard 8051s and STC micros are discussed below:</p>
<ul>
 	<li style="text-align: justify"><em><span style="color: #339966" data-darkreader-inline-color=""><strong>Packages / Sizes</strong></span></em><br>
STC offers microcontrollers in various DIP and SMD IC packages. Thus, instead of using a 40-pin DIP package microcontroller to solve a problem that can be solved with an 8-pin SMD low cost microcontroller, we can avoid using a big microcontroller and thereby save valuable PCB space. Most STC 8051s are, by the way, 100% pin-compatible with other 8051s. This feature makes STC micros easy and viable replacements for devices that use standard 8051s.</li>
</ul>
<ul style="text-align: justify">
<li><span style="color: #339966" data-darkreader-inline-color=""><em><strong>Speed / Operating Frequency</strong></em></span><br>
STC microcontrollers are relatively faster than common 8051s as they can operate at higher clock frequencies. For example, AT89S52 has a maximum operating frequency of 33MHz while STC89C52RC can be clocked with an 80MHz source.</li>
</ul>
<ul style="text-align: justify">
<li><strong><em><span style="color: #339966" data-darkreader-inline-color="">Additional Hardware Peripherals</span></em></strong><br>
Some STC microcontrollers have in-built ADC, EEPROM, watchdog timer, external interrupt pins and other peripherals. Some are even equipped with higher storage capacities. These are not available in typical 8051s.</li>
</ul>
<ul style="text-align: justify">
<li><span style="color: #339966" data-darkreader-inline-color=""><em><strong>Operating Voltage</strong></em></span><br>
Most 8051 micros need 4.0 – 5.5V DC supply voltage. Some can operate with 3.3V supplies too. Same goes for STC micros. However, there are some STC micros that are designed to operate at yet lower voltage levels. STC offers low power MCUs that operate between 2.0 – 3.6V and general-purpose micros that can operate between 3.6 – 5.5V. The operating voltage ranges and low power consumption figures of STC micros make them well-suited for battery and solar-powered devices.</li>
</ul>
<ul style="text-align: justify">
<li><span style="color: #339966" data-darkreader-inline-color=""><em><strong>Programming Interface</strong></em></span><br>
Most 8051s require a parallel port programmer while some require serial port programmer or separate dedicated programmer hardware. STC micros on the other hand can be programmer with a serial port programmer and so there is no need to buy a dedicated programmer. A simple USB-TTL serial converter can be used to load codes into STC micros.</li>
</ul>
<ul style="text-align: justify">
<li><span style="color: #339966" data-darkreader-inline-color=""><strong><em>Other Minor Differences</em></strong></span><br>
Other areas of differences include added/reduced functionalities/features. In some STC micros, there additional options for GPIOs, timers, etc while in some other devices these extras are not observed. For example, in STC89C52RC, there is 13-bit timer mode for timers 0 and 1 but this feature is absent in STC15L204EA. Likewise in STC15L204EA, there are many ways for setting up GPIOs which are not present in STC89C52RC.</li>
</ul>
<h1>Documentations and Websites</h1>
<p style="text-align: justify">STC microcontrollers are popular in China and Chinese-speaking countries. Owing to this fact, most of the documentation and even the websites are in Chinese. It is hard to get English documentations. Fortunately, we will not be needing anything else other than device datasheets which are luckily available both in Chinese and English.</p>
<p style="text-align: justify">Unlike other manufacturers who maintain one website dedicated to their products and themselves, STC maintains several websites. Most are in Chinese. This creates lot of confusion about STC. Some common STC websites are listed below:</p>
<p style="text-align: justify"><a href="http://www.stcmicro.com">http://www.stcmicro.com</a></p>
<p style="text-align: justify"><a href="http://www.stcmcu.com">http://www.stcmcu.com</a></p>
<p style="text-align: justify"><a href="http://www.stcisp.com/">http://www.stcisp.com</a></p>
<h1 style="margin-top: 0cm">Hardware Tools</h1>
<p style="text-align: justify">From AliExpress, DX, Alibaba and other similar websites/stores, you can buy any STC development board of your choice. Alternatively, you can buy common STC chips and use them with your existing development board or setup a bread-board arrangement.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/stc.jpg"><img class="alignnone size-medium wp-image-14436" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/stc-580x408.jpg" alt="stc" width="580" height="408" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/stc-580x408.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/stc.jpg 1024w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">One such board is shown above. These boards have lot of hardware devices like external 24 series EEPROM, I2C ADC-DAC, communication and display interfaces, etc already embedded and ready for go. Such boards are, thus easy to use and need less wiring. However, boards as such are relatively expensive and big than the one shown below:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/nrf.jpg"><img class="alignnone size-full wp-image-14437" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/nrf.jpg" alt="nrf" width="507" height="361"></a></p>
<p style="text-align: justify">This board is designed to bridge a serial interface between a host micro and a nRF24L01 2.4GHz wireless communication module. However, that doesn’t restrict us from using the STC15F(L)204EA micro embedded in it. If you just want to give STC micros a shot with very little investment then this sort of board is all that you can ever expect.</p>
<p style="text-align: justify">In my tutorials, I’ll be using both kinds of boards but the main focus will be towards STC15L204EA or similar slightly non-standard 8051s since they are not like playing with typical 8051s.</p>
<p style="text-align: justify">We will also need an USB-serial converter for uploading code.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/USB-Serial-Converter.png"><img class="alignnone size-medium wp-image-14438" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/USB-Serial-Converter-580x209.png" alt="USB-Serial Converter" width="580" height="209" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/USB-Serial-Converter-580x209.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/USB-Serial-Converter.png 734w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Apart from these, some regularly used hardware items like LCDs, sensors, wires, etc will be needed. These can easily be found in any starter kit and most are available in any hobbyist’s collection.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/new_starter_kit_waspmote_big.jpg"><img class="alignnone size-medium wp-image-14439" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/new_starter_kit_waspmote_big-580x438.jpg" alt="new_starter_kit_waspmote_big" width="580" height="438" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/new_starter_kit_waspmote_big-580x438.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/new_starter_kit_waspmote_big.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h1 style="margin-top: 0cm">Software Tools</h1>
<p style="text-align: justify">Only two software tools will be needed. The first is Keil C51 compiler and second STC ISP tool.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP.png"><img class="alignnone size-medium wp-image-14440" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-580x310.png" alt="STC-ISP" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-1024x548.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP.png 1364w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">STC ISP tool can be downloaded from <a href="https://www.stcmicro.com/rjxz.html">here</a>. This is one helluva tool that has many useful features. It a programmer interface, a code generator, serial port monitor, code bank and many other stuffs. It sure does make coding STC micros lot easier than you can possibly imagine.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil.png"><img class="alignnone size-full wp-image-14441" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil.png" alt="Keil" width="445" height="227"></a></p>
<p style="text-align: justify">Keil C51 C compiler will be needed to code STC micros. At present, Keil is the only C compiler that can be used reliably to code STC micros. STC documentations speak of Keil mostly. If you want to use some other compiler like IAR Embedded Workbench, MikroC for 8051, etc other than Keil, your have to add the SFR definitions of your target STC micros and do other stuffs to familiarize it with the STC micro target. Alternatively, you can use models of other similar 8051 model. For example, STC89C52RC is similar to AT89S52. You can use codes for such interchangeably. However, this method won’t work in cases where we have more hardware peripheral than an ordinary 8051 micro. STC15L204EA, for instance, can’t be used like ordinary 8051 or like STC89/90 series micros.</p>
<h1 style="margin-top: 0cm">Programming STC Microcontrollers</h1>
<p style="text-align: justify">By default, STC microcontroller database is absent in Keil. It is imperative that this database is added to Keil when using it for STC micros for the very first time. Though this database is not complete in the sense that not chips are enlisted in it, it is still a must or else we will have to use unconventional coding methods by using models of similar microcontrollers of different manufacturers. Personally, I hate unconventional tactics because why use such methods when we can add the database easily. We only have to add this database once.</p>
<p style="text-align: justify">First run the STC-ISP tool.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Icon.png"><img class="alignnone size-full wp-image-14442" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Icon.png" alt="STC-ISP Icon" width="98" height="98" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Icon.png 98w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Icon-90x90.png 90w" sizes="(max-width: 98px) 100vw, 98px" /></a></p>
<p style="text-align: justify">After clicking the STC-ISP tool icon, the application starts and the following window appears:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Garbage.png"><img class="alignnone size-full wp-image-14443" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Garbage.png" alt="Garbage" width="431" height="407"></a></p>
<p style="text-align: justify">Don’t worry. It is not an error or garbage text window. It appears so if you don’t have Chinese font database installed in your PC and so just click OK to continue. Recent versions of STC-ISP don’t have this issue.</p>
<p style="text-align: justify">Once the application starts, navigate to <strong><em>Keil ICE Settings</em></strong> tab and locate the highlighted button as shown below:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-ICE.png"><img class="alignnone size-medium wp-image-14444" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-ICE-580x309.png" alt="Keil-ICE" width="580" height="309" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-ICE-580x309.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-ICE-1024x545.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-ICE.png 1364w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Now just navigate to Keil installation folder and hit OK as shown below:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Folder.png"><img class="alignnone size-medium wp-image-14445" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Folder-580x326.png" alt="Keil Folder" width="580" height="326" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Folder-580x326.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Folder-1024x576.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Folder.png 1366w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Selecting wrong folder will end up with an error and the database won’t be installed.</p>
<p style="text-align: justify">If the database addition is a success, you’ll get the following message:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Add-Successful.png"><img class="alignnone size-medium wp-image-14446" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Add-Successful-580x340.png" alt="Add Successful" width="580" height="340" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Add-Successful-580x340.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Add-Successful.png 798w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Now run Keil C51 compiler.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Icon.png"><img class="alignnone size-full wp-image-14447" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Icon.png" alt="Keil Icon" width="99" height="99" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Icon.png 99w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Icon-90x90.png 90w" sizes="(max-width: 99px) 100vw, 99px" /></a></p>
<p style="text-align: justify">Go to <strong><em>Project &gt;&gt; New </em></strong><strong><em>µVision Project… </em></strong>as shown below:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-1.png"><img class="alignnone size-medium wp-image-14448" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-1-580x309.png" alt="Keil New Project 1" width="580" height="309" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-1-580x309.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-1-1024x546.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-1.png 1366w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Give your project a folder and a name as shown below:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-2.png"><img class="alignnone size-medium wp-image-14449" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-2-580x310.png" alt="Keil New Project 2" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-2-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-2-1024x547.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-New-Project-2.png 1366w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p>Select STC Database and appropriate chip or similar part number.
</p><p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Chip-Selection.png"><img class="alignnone size-medium wp-image-14450" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Chip-Selection-580x310.png" alt="Keil Chip Selection" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Chip-Selection-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Chip-Selection-1024x547.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Chip-Selection.png 1366w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Please note that your target chip may not be in the list. For example, the L-series chips are not enlisted in the database and so they are absent in the list. STC15L204, for example, is not shown in the list. You can use STC15F204EA instead of it as they are similar stuffs. The only difference is their power consumptions. You have to use such tricks when your target chip is not listed. Make sure that the model you selected matches with the target chip or else things may not work properly.</p>
<p>After chip selection, add the startup assembler file to your project.
</p><p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Startup-File.png"><img class="alignnone size-full wp-image-14451" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Startup-File.png" alt="Keil Startup File" width="416" height="153"></a></p>
<p style="text-align: justify">By default, Keil doesn’t add/create any file and so you’ll see that the project folder has no main source file. We’ll have to create one main source file and add additional files if needed.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Main-File.png"><img class="alignnone size-medium wp-image-14452" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Main-File-580x310.png" alt="Keil Main File" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Main-File-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Main-File-1024x547.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Main-File.png 1366w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Still we are not ready to start coding. This is because we have not yet added SFR definition header file and other custom optional files.</p>
<p>Again, we need to take the help of STC-ISP tool.</p>
<p>In STC-ISP tool, locate the <strong><em>Header File</em></strong> tab and select appropriate MCU series.
</p><p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Header-File.png"><img class="alignnone size-medium wp-image-14453" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Header-File-580x310.png" alt="Header File" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Header-File-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Header-File-1024x548.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Header-File.png 1364w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Save or copy the file to your desired location.</p>
<p style="text-align: justify">In Keil, go to target options by right click the folder icon and set target options as shown in the following screenshots:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings.png"><img class="alignnone size-medium wp-image-14454" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-580x310.png" alt="Keil Target Settings" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-1024x547.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings.png 1364w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-1.png"><img class="alignnone size-medium wp-image-14455" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-1-580x437.png" alt="Keil Target Settings 1" width="580" height="437" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-1-580x437.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-1.png 631w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p>From this window select clock frequency and memory model.
</p><p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-2.png"><img class="alignnone size-medium wp-image-14456" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-2-580x435.png" alt="Keil Target Settings 2" width="580" height="435" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-2-580x435.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-2.png 630w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Select <strong><em>Create HEX File</em></strong> from this window as this file will be uploaded in the target chip.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-3.png"><img class="alignnone size-medium wp-image-14457" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-3-580x252.png" alt="Keil Target Settings 3" width="580" height="252" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-3-580x252.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-3-1024x444.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-3.png 1279w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">This section above is highly important because here we have to show the compiler the locations of the header or include files. Check the step numbering carefully.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-4.png"><img class="alignnone size-medium wp-image-14458" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-4-580x437.png" alt="Keil Target Settings 4" width="580" height="437" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-4-580x437.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Keil-Target-Settings-4.png 629w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p>Lastly disable<em> <strong>Warning Number 16</strong></em>. Now, we are good to code.
</p><p style="text-align: justify">I made a small Youtube video on all the above discussed processes. If you didn’t understand some part or if you are confused at some point, you can watch the video <a href="https://youtu.be/nHCjFw2TS4M">here</a>.</p>
<p><iframe title="How to use Keil C51 Compiler to Code STC 8051 Microcontrollers" width="860" height="484" src="https://www.youtube.com/embed/nHCjFw2TS4M?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</p><p style="text-align: justify">Now let us discuss about uploading codes to STC micros. The most advantageous part is the fact that we don’t need to invest on a dedicated programmer as with other microcontrollers as a simple USB-serial converter will do the job. However, on first go things may look confusing.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Steps.png"><img class="alignnone size-medium wp-image-14459" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Steps-580x310.png" alt="STC-ISP Steps" width="580" height="310" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Steps-580x310.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Steps-1024x547.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/STC-ISP-Steps.png 1362w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Shown above is the STC-ISP tool’s screenshot with numbers. We have to follow them one-by-one and in incremental order. 1 denotes that we must select the right COM port and part number. You can use <strong><em>Windows Device Manager</em></strong> to find out which COM port is being used for uploading code. Step 2 is to select the target HEX code file. Optionally in step 3, we can set some additional internal MCU parameters. When everything has been set properly, we can hit the <strong><em>Download Program</em></strong> button shown in step 4. If the target microcontroller or board is already powered then the code won’t be uploaded. This is the confusing part because it should have been the other way.</p>
<p style="text-align: justify">Notice the red arrow in the schematic below. The code is not uploaded by holding and releasing the reset button for some time or by pulling high or low some special pin or by some other means. We need to create a handshake between the PC and the target MCU and this is done when the MCU is powered off and then powered on, i.e. when the micro is powered up.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/ISP-Circuit.png"><img class="alignnone size-full wp-image-14460" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/ISP-Circuit.png" alt="ISP Circuit" width="565" height="571" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/ISP-Circuit.png 565w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/ISP-Circuit-90x90.png 90w" sizes="(max-width: 565px) 100vw, 565px" /></a></p>
<p style="text-align: justify">This is why the red arrow highlights the power switch in the schematic. Though the schematic shows a MAX232-based converter, we can use a USB-serial converter instead.</p>
<p style="text-align: justify">All of these steps are demoed in <a href="https://youtu.be/PcvktG9sc9Q">this video</a>. Note that no external USB-serial converter/cable can be seen in the video as it is embedded in the board. The following schematic and photo will make this fact clearer. This is why most STC development boards come with such arrangement and without any programmer.</p>
<p><iframe title="How to Load a Hex File in a STC Microcontroller" width="860" height="484" src="https://www.youtube.com/embed/PcvktG9sc9Q?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</p><p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Cut-Away-Schematic.png"><img class="alignnone size-medium wp-image-14462" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/Cut-Away-Schematic-580x309.png" alt="Cut Away Schematic" width="580" height="309" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/Cut-Away-Schematic-580x309.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/Cut-Away-Schematic.png 841w" sizes="(max-width: 580px) 100vw, 580px" /></a> <a href="http://embedded-lab.com/blog/wp-content/uploads/2018/09/board.jpg"><img class="alignnone size-medium wp-image-14461" src="http://embedded-lab.com/blog/wp-content/uploads/2018/09/board-580x341.jpg" alt="board" width="580" height="341" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/09/board-580x341.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/board-1024x603.jpg 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/09/board.jpg 1369w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>


<p>The continuation of this post can be found <a href="https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers-coding/">here</a>.</p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/exploring-stc-8051-microcontrollers/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
							</item>
		<item>
		<title>Getting Started with Nuvoton 8-bit Microcontrollers – Coding Part 3</title>
		<link>https://embedded-lab.com/blog/getting-started-nuvoton-8-bit-microcontrollers-coding-part-3/</link>
				<comments>https://embedded-lab.com/blog/getting-started-nuvoton-8-bit-microcontrollers-coding-part-3/#comments</comments>
				<pubDate>Mon, 06 Aug 2018 16:01:34 +0000</pubDate>
		<dc:creator><![CDATA[Shawon Shahryiar]]></dc:creator>
				<category><![CDATA[Nuvoton]]></category>
		<category><![CDATA[8-bit Microcontroller]]></category>
		<category><![CDATA[8051]]></category>
		<category><![CDATA[Communication]]></category>
		<category><![CDATA[IAR]]></category>
		<category><![CDATA[Keil]]></category>
		<category><![CDATA[N76E003]]></category>

		<guid isPermaLink="false">http://embedded-lab.com/blog/?p=14383</guid>
				<description><![CDATA[This post is a continuation of the previous post on Nuvoton N76E003 microcontroller here. Communication Peripheral Overview N76E003 packs basic serial communication peripherals for I2C, SPI and UART. These interfaces enable us to interface external EEPROM and flash memories, real-time clocks (RTC), sensors, etc. N76E003 has two hardware UARTs, one SPI and one I2C peripheral. The UART interfaces can be further expanded to implement RS-485 and RS-422 communication protocols. With ordinary GPIOs and optionally with hardware timers we can implement software-based UART, SPI and I2C too. However, software methods are slow and resource-hungry. Software-based approach is, on the other hand, needed]]></description>
								<content:encoded><![CDATA[<p>This post is a continuation of the previous post on Nuvoton N76E003 microcontroller <a href="http://embedded-lab.com/blog/getting-started-nuvoton-8-bit-microcontrollers-coding-part-2/" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/s-l16001.jpg"><img class="alignnone size-medium wp-image-14384 aligncenter" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/s-l16001-580x397.jpg" alt="s-l1600" width="580" height="397" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/s-l16001-580x397.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/s-l16001.jpg 639w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><span id="more-14383"></span></p>
<h1><span lang="EN-GB">Communication Peripheral Overview </span></h1>
<p style="text-align: justify">N76E003 packs basic serial communication peripherals for I2C, SPI and UART. These interfaces enable us to interface external EEPROM and flash memories, real-time clocks (RTC), sensors, etc.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/Comm-types.png"><img class="alignnone size-medium wp-image-14385" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/Comm-types-580x189.png" alt="Comm types" width="580" height="189" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/Comm-types-580x189.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/Comm-types.png 818w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">N76E003 has two hardware UARTs, one SPI and one I2C peripheral. The UART interfaces can be further expanded to implement RS-485 and RS-422 communication protocols. With ordinary GPIOs and optionally with hardware timers we can implement software-based UART, SPI and I2C too. However, software methods are slow and resource-hungry. Software-based approach is, on the other hand, needed when we have to interface devices that don’t use any of these communication topologies. For example, the one-wire protocol used by DHT series relative humidity and temperature sensors needs to be implemented by using an ordinary GPIO pin. Same goes for typical text and graphical LCDs.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/N76E003-Comms.png"><img class="alignnone size-medium wp-image-14386" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/N76E003-Comms-580x189.png" alt="N76E003 Comms" width="580" height="189" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/N76E003-Comms-580x189.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/N76E003-Comms.png 818w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Note that there is a conflict between UART1 and alternative I2C pins. There are also similar conflicts with other hardware peripherals like PWMs, ADCs, etc since N76E003 packs lots of stuff in such a small form-factor. Every single GPIO pin is precious. Try to keep things with default GPIO pins in order to reduce conflicts with other hardware peripherals, coding and to maximize effective use of GPIOs. Likewise bear in mind that timers have also such conflicts as they are used to implement both hardware-based delays and the UART peripherals. You have to know for sure what you are doing, what do you want and with which stuffs you wish to accomplish your task.</p>
<p style="text-align: justify"><!--more--></p>
<h1 style="margin-top: 0in"><span lang="EN-GB">Serial Communication &#8211; UART</span></h1>
<p style="text-align: justify">To date serial communication (UART) is perhaps the simplest and widely used form of communication in use. UART block is only block available in most microcontrollers that can be easily interfaced with a computer or a phone. Most communication modules like Bluetooth, Wi-Fi, GSM modems, GPS modules, etc are interfaced using UART. It has incredible range and is also the backbone of other communication methods like RS-485, RS-422, etc.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022.jpg"><img class="alignnone size-full wp-image-14387" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022.jpg" alt="HMC1022" width="358" height="329" /></a></p>
<p>To learn more about UART visit the following link:</p>
<p><a href="https://learn.mikroe.com/uart-serial-communication">https://learn.mikroe.com/uart-serial-communication</a></p>
<h2 style="margin-top: 0in"><span lang="EN-GB">Code</span></h2>
<h3><strong>HMC1022.h</strong></h3>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define Get_Angular_Measurement                      0x31</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define Start_Calibration                            0xC0 </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define End_Calibration                              0xC1                     </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define Set_Magnetic_Declination_High_Byte           0x03  </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define Set_Magnetic_Declination_Low_Byte            0x04</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define no_of_data_bytes_returned                    0x08</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">#define calibration_LED                              P15</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">void read_heading(void);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">void calibrate_compass(void); </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">void factory_reset(void);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">void set_declination_angle(unsigned long angle);</span></pre>
<h3><strong>HMC1022.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "HMC1022.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char done = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char data_bytes[no_of_data_bytes_returned] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};</span></pre>
<pre></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void read_heading(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{                        </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned char s = 0; </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned long CRC = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     Send_Data_To_UART1(Get_Angular_Measurement); </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     for(s = 0; s &lt; no_of_data_bytes_returned; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        data_bytes[s] = Receive_Data_From_UART1();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        if(s &lt; (no_of_data_bytes_returned - 1))  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            CRC += data_bytes[s];</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }                                                      </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     CRC = (CRC &amp; 0xFF);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     if(CRC == data_bytes[7])</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {                                    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       done = 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void calibrate_compass(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> unsigned char s = 0x00;    </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(Start_Calibration);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> for(s = 0; s &lt; 60; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     calibration_LED = 1;       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_ms(100);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     calibration_LED = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_ms(900);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> } </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> for(s = 0; s &lt; 60; s++)   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     calibration_LED = 1;   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_ms(400);            </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     calibration_LED = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_ms(600);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> }             </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(End_Calibration);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void factory_reset(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(0xA0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(0xAA);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(0xA5); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(0xC5);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}     </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void set_declination_angle(unsigned long angle)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> unsigned long hb = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> unsigned char lb = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> lb = (angle &amp; 0x00FF);   </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> hb = (angle &amp; 0xFF00);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> hb &gt;&gt;= 8; </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(Set_Magnetic_Declination_High_Byte);    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(hb);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(Set_Magnetic_Declination_Low_Byte);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> Send_Data_To_UART1(lb);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>main.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "LCD_2_Wire.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "HMC1022.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">const unsigned char symbol[8] =</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   0x00, 0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">extern unsigned char done;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">extern unsigned char data_bytes[no_of_data_bytes_returned];</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_symbol(void);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  setup();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    read_heading();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(done)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_goto(6, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_putchar(data_bytes[2]);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_goto(7, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_putchar(data_bytes[3]);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_goto(8, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_putchar(data_bytes[4]);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_goto(9, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_putchar('.');</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_goto(10, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       LCD_putchar(data_bytes[6]);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       done = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     P15 = ~P15;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_ms(200);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  };</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  P15_PushPull_Mode;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_clear_home();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  lcd_symbol();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto(3, 0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_putstr("Heading  N");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto(11, 0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_send(0, DAT);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  InitialUART1_Timer3(9600);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_symbol(void) </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char s = 0; </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_send(0x40, CMD);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  for(s = 0; s &lt; 8; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   LCD_send(symbol[s], DAT);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_send(0x80, CMD);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2><span lang="EN-GB">Schematic</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-Schematic.png"><img class="alignnone size-medium wp-image-14388" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-Schematic-580x257.png" alt="UART Schematic" width="580" height="257" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-Schematic-580x257.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-Schematic.png 843w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h2><span lang="EN-GB">Explanation</span></h2>
<p style="text-align: justify">The following are the commands that HMC1022 acknowledges when sent via UART:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022-Commands.png"><img class="alignnone size-full wp-image-14389" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022-Commands.png" alt="HMC1022 Commands" width="571" height="202" /></a></p>
<p style="text-align: justify">HMC1022 gives heading data when it is requested. The highlighted command is that command.</p>
<p style="text-align: justify">Once requested it sends out a string of characters that carry heading information. The followings are the response package and its details:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022-Response.png"><img class="alignnone size-medium wp-image-14390" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022-Response-580x237.png" alt="HMC1022 Response" width="580" height="237" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022-Response-580x237.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/HMC1022-Response.png 860w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">From the above info, it is clear that HMC1022 will return 8 bytes when requested for heading. Out of these we need bytes 2, 3,4 and 6. The rest can be ignored for simplicity.</p>
<p style="text-align: justify">Data from HM1022 is received by the following function:</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void read_heading(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{                        </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned char s = 0; </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned long CRC = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     Send_Data_To_UART1(Get_Angular_Measurement); </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     for(s = 0; s &lt; no_of_data_bytes_returned; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        data_bytes[s] = Receive_Data_From_UART1();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        if(s &lt; (no_of_data_bytes_returned - 1))  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            CRC += data_bytes[s];</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }                                                      </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     CRC = (CRC &amp; 0xFF);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     if(CRC == data_bytes[7])</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {                                    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       done = 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<p>Note that the function <strong><em>Send_Data_To_UART1</em></strong> and <strong><em>Receive_Data_From_UART1</em></strong> are BSP functions. Likewise, <strong><em>InitialUART1_Timer3(9600)</em></strong> function is also a BSP function that initiates UART1 with Timer 3. As with ADC, BSP functions for UART are enough for basic setup. Try to use Timer 3 as it remains mostly free. If you need more control over the UART, you can manually configure the registers.</p>
<p>In the main, the received bytes containing heading info are displayed.</p>
<h2><span lang="EN-GB">Demo</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/UART.jpg"><img class="alignnone size-medium wp-image-14391" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-580x466.jpg" alt="UART" width="580" height="466" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-580x466.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/UART.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/Y0jehv58ugE?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><!--more--></p>
<h1 style="margin-top: 0in"><span lang="EN-GB">UART Interrupt</span></h1>
<p style="text-align: justify">UART, as we saw in the last example, can be used in polling mode but it is wise to use it in interrupt mode. This feature becomes especially important and therefore, a must-have requirement when it come to that fact that the host micro may not always know when to receive data. Unlike SPI/I2C, UART doesn’t always follow known data transactions. Take the example of a GSM modem. We and so does our tiny host N76E003 micro don’t know for sure when a message would arrive. Thus, when an interrupt due to reception is triggered, it is known to mark the beginning of data reception process. The host micro can relax idle until data is received fully.</p>
<p style="text-align: justify">Here, we will see how to use UART interrupt to read a LV-Max EZ0 SONAR module.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/LV-Max-Ez0.jpg"><img class="alignnone size-full wp-image-14392" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/LV-Max-Ez0.jpg" alt="LV-Max Ez0" width="435" height="435" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/LV-Max-Ez0.jpg 435w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/LV-Max-Ez0-150x150.jpg 150w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/LV-Max-Ez0-90x90.jpg 90w" sizes="(max-width: 435px) 100vw, 435px" /></a></p>
<h2 style="margin-top: 0in"><span lang="EN-GB">Code</span></h2>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "LCD_2_Wire.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char received = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char count = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char buffer[5] = {0x00, 0x00, 0x00, 0x00, 0x00};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void UART0_ISR(void)    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">interrupt 4 </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(RI == 1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {                                                               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        buffer[count] = SBUF;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        count++;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        if(count &gt;= 4)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            clr_ES;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            received = 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        clr_RI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    P15 = ~P15;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char i = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    setup();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        Send_Data_To_UART0('S');</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        delay_ms(40);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        set_ES;     </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        if(received)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            for(i = 1; i &lt; 4; i++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              LCD_goto((12 + i), 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              LCD_putchar(buffer[i]);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            count = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            received  = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            set_ES;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        delay_ms(40);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    P15_PushPull_Mode;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_clear_home();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(1, 0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr("UART Interrupt");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(0, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr("Range/Inch:");</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    InitialUART0_Timer3(9600);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_EA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2><span lang="EN-GB">Schematic</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-INT-Schematic.png"><img class="alignnone size-medium wp-image-14393" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-INT-Schematic-580x257.png" alt="UART INT Schematic" width="580" height="257" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-INT-Schematic-580x257.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/UART-INT-Schematic.png 843w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h6><em>*Note the LV-Max EZ0 SONAR sensor is not directly connected with the N76E003 as shown in the schematic but rather it is connected via a 74HC04 hex inverter. Two of these inverters are used – one for the TX side and the other for the RX side.</em></h6>
<h2><span lang="EN-GB">Explanation</span></h2>
<p style="text-align: justify">This time UART0 is used and is setup using BSP built-in function. The only exception is the interrupt part. The global interrupt is enabled but not the UART interrupt.</p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">InitialUART0_Timer3(9600);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">set_EA;</span></pre>
<p style="text-align: justify">The UART interrupt is only enabled after commanding the SONAR sensor:</p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">Send_Data_To_UART0('S');</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">delay_ms(40);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">set_ES;  </span></pre>
<p style="text-align: justify">This is done to avoid unnecessary reads.</p>
<p style="text-align: justify">The sensor is read inside the interrupt routine. The sensor outputs data as <strong><em>Rxxx&lt;CR&gt;</em></strong>. So, there are 5 bytes to read. The <strong><em>“R” </em></strong>in the readout works as a preamble or sync byte. The <strong><em>“xxx”</em></strong> part contains range info in inches. Finally, <strong><em>&lt;CR&gt;</em></strong> is a carriage return character. Therefore, every time a character is received an interrupt is triggered and the character is saved in an array. When all 5 bytes have been received, the display is updated. On exiting the interrupt, the interrupt flag is cleared. P15 is also toggled to visually indicate that an UART interrupt has been triggered.</p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">void UART0_ISR(void)    </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">interrupt 4 </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  if(RI == 1)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  {                                                               </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">     buffer[count] = SBUF;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">     count++;</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">     if(count &gt;= 4)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">       clr_ES;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">       received = 1;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">     clr_RI;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  P15 = ~P15;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2><span lang="EN-GB">Demo</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/Lv-Max-Ez0.jpg"><img class="alignnone size-medium wp-image-14394" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/Lv-Max-Ez0-580x373.jpg" alt="Lv-Max Ez0" width="580" height="373" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/Lv-Max-Ez0-580x373.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/Lv-Max-Ez0.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/SCsPt88HFVk?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><!--more--></p>
<h1 style="margin-top: 0in"><span lang="EN-GB">Inter-Integrated Circuit (I2C) – Interfacing DS1307 I2C RTC</span></h1>
<p style="text-align: justify">Developed by Philips nearly three decades ago, I2C communication (<strong><em>Inter-Integrated Circuit</em></strong>) is widely used in a number of devices and is comparatively easier than SPI. For I2C communication only two wires – <em>serial data (SDA)</em> and <em>serial clock (SCK)</em> are needed and these two wires form a bus in which we can connect up to 127 devices.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C.png"><img class="alignnone size-full wp-image-14398" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C.png" alt="I2C" width="489" height="192" /></a></p>
<p style="text-align: justify">Everything you need to know about I2C can be found in these pages:</p>
<ul style="text-align: justify">
<li><a href="https://learn.mikroe.com/i2c-everything-need-know">https://learn.mikroe.com/i2c-everything-need-know</a></li>
<li><a href="https://learn.sparkfun.com/tutorials/i2c">https://learn.sparkfun.com/tutorials/i2c</a></li>
<li><a href="http://www.ti.com/lsds/ti/interface/i2c-overview.page">http://www.ti.com/lsds/ti/interface/i2c-overview.page</a></li>
<li><a href="http://www.robot-electronics.co.uk/i2c-tutorial">http://www.robot-electronics.co.uk/i2c-tutorial</a></li>
<li><a href="https://www.i2c-bus.org/i2c-bus">https://www.i2c-bus.org/i2c-bus</a></li>
<li><a href="http://i2c.info">http://i2c.info</a></li>
</ul>
<p style="text-align: justify">Apart from these N76E003’s datasheet explains I2C communication in high detail.</p>
<h2 style="margin-top: 0in"><span lang="EN-GB">Code</span></h2>
<h3><strong>I2C.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define regular_I2C_pins              0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define alternate_I2C_pins            1</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define regular_I2C_GPIOs()           do{P13_OpenDrain_Mode; P14_OpenDrain_Mode; clr_I2CPX;}while(0)</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define alternative_I2C_GPIOs()       do{P02_OpenDrain_Mode; P16_OpenDrain_Mode; set_I2CPX;}while(0)</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define I2C_GPIO_Init(mode)           do{if(mode != 0){alternative_I2C_GPIOs();}else{regular_I2C_GPIOs();}}while(0)</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define I2C_CLOCK                     0x27 //Fclk = Fsys / (4*(prescalar + 1))</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define I2C_ACK                       0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define I2C_NACK                      1</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define timeout_count                 1000</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_start(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_stop(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char I2C_read(unsigned char ack_mode);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_write(unsigned char value);</span></pre>
<h3><strong>I2C.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "I2C.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_init(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_GPIO_Init(regular_I2C_pins);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2CLK = I2C_CLOCK;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_I2CEN;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_start(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    signed int t = timeout_count;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_STA;                               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    clr_SI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while((SI == 0) &amp;&amp; (t &gt; 0))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       t--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_stop(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    signed int t = timeout_count;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    clr_SI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_STO;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while((STO == 1) &amp;&amp; (t &gt; 0))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        t--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char I2C_read(unsigned char ack_mode)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    signed int t = timeout_count;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char value = 0x00;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_AA;                            </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    clr_SI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while((SI == 0) &amp;&amp; (t &gt; 0))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        t--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };      </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    value = I2DAT;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(ack_mode == I2C_NACK)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        t = timeout_count;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        clr_AA;  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        clr_SI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        while((SI == 0) &amp;&amp; (t &gt; 0))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            t--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        };          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_write(unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    signed int t = timeout_count;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2DAT = value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    clr_STA;          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    clr_SI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while((SI == 0) &amp;&amp; (t &gt; 0))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        t--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }; </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>DS1307.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define I2C_W                            0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define I2C_R                            1</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define sec_reg                          0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define min_reg                          0x01</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define hr_reg                           0x02</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define day_reg                          0x03</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define date_reg                         0x04</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define month_reg                        0x05</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define year_reg                         0x06</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define control_reg                      0x07</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS1307_addr                      0xD0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS1307_WR                        (DS1307_addr + I2C_W)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS1307_RD                        (DS1307_addr + I2C_R)</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DS1307_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char DS1307_read(unsigned char address);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DS1307_write(unsigned char address, unsigned char value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char bcd_to_decimal(unsigned char value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char decimal_to_bcd(unsigned char value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void get_time(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void set_time(void);</span></pre>
<h3><strong>DS1307.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "DS1307.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "I2C.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">struct</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char s;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char m;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char h;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char dy;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char dt;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char mt;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char yr;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}time;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DS1307_init(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  DS1307_write(control_reg, 0x00);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char DS1307_read(unsigned char address)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char value = 0x00;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_start();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_write(DS1307_WR);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_write(address);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_start();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_write(DS1307_RD);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    value = I2C_read(I2C_NACK);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_stop();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DS1307_write(unsigned char address, unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_start();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_write(DS1307_WR);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_write(address);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_write(value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    I2C_stop();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char bcd_to_decimal(unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return ((value &amp; 0x0F) + (((value &amp; 0xF0) &gt;&gt; 0x04) * 0x0A));</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char decimal_to_bcd(unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return (((value / 0x0A) &lt;&lt; 0x04) &amp; 0xF0) | ((value % 0x0A) &amp; 0x0F);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void get_time(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.s = DS1307_read(sec_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.s = bcd_to_decimal(time.s);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.m = DS1307_read(min_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.m = bcd_to_decimal(time.m);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.h = DS1307_read(hr_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.h = bcd_to_decimal(time.h);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.dy = DS1307_read(day_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.dy = bcd_to_decimal(time.dy);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.dt = DS1307_read(date_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.dt = bcd_to_decimal(time.dt);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.mt = DS1307_read(month_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.mt = bcd_to_decimal(time.mt);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.yr = DS1307_read(year_reg);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.yr = bcd_to_decimal(time.yr);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void set_time(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.s = decimal_to_bcd(time.s);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(sec_reg, time.s);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.m = decimal_to_bcd(time.m);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(min_reg, time.m);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.h = decimal_to_bcd(time.h);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(hr_reg, time.h);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.dy = decimal_to_bcd(time.dy);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(day_reg, time.dy);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.dt = decimal_to_bcd(time.dt);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(date_reg, time.dt);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.mt = decimal_to_bcd(time.mt);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(month_reg, time.mt);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.yr = decimal_to_bcd(time.yr);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_write(year_reg, time.yr);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>main.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "LCD_3_Wire.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "I2C.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "DS1307.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">extern struct</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char s;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char m;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char h;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char dy;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char dt;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char mt;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char yr;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}time;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void show_value(unsigned char x_pos, unsigned char y_pos, unsigned char value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void display_time(void);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.s = 30;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.m = 58;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    time.h = 23;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    P15_PushPull_Mode;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_clear_home();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(0, 0);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr("N76E003 I2C RTCC");</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS1307_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_time();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        get_time();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        display_time();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void show_value(unsigned char x_pos, unsigned char y_pos, unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char chr = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    chr = ((value / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putchar(chr);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    chr = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto((x_pos + 1), y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putchar(chr);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void display_time(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    P15 ^= 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(6, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putchar(' ');</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(9, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putchar(' ');</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    delay_ms(400);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    show_value(4, 1, time.h);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    show_value(7, 1, time.m);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    show_value(10, 1, time.s);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(6, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putchar(':');</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(9, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putchar(':');</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    delay_ms(400);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2><span lang="EN-GB">Schematic</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_Schematic.png"><img class="alignnone size-medium wp-image-14396" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_Schematic-580x257.png" alt="I2C_Schematic" width="580" height="257" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_Schematic-580x257.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_Schematic.png 843w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h6><em>*Note that the pin naming of the chip in the schematic above is wrong. P13 and P14 are both SDA pins according to this naming when actually P13 is SCL and P14 is SDA pin.  </em></h6>
<h2><span lang="EN-GB">Explanation</span></h2>
<p style="text-align: justify">I have coded two files for I2C easy and quick I2C implementation. These are I2C header and source file. These files describe I2C hardware functionality as well as provide higher level functions under the hood of which I2C hardware is manipulated. I have only coded these files for master mode only since barely we would ever need N76E003 slaves. I also didn’t implement interrupt-based I2C functionalities as this, in my experience, is also not needed in most of the cases.</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_start(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_stop(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char I2C_read(unsigned char ack_mode);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_write(unsigned char value);</span></pre>
<p style="text-align: justify">Using hardware I2C requires us to manipulate the following registers apart from clock and GPIO settings.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C-Registers.png"><img class="alignnone size-medium wp-image-14397" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C-Registers-580x99.png" alt="I2C Registers" width="580" height="99" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C-Registers-580x99.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C-Registers-1024x174.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C-Registers.png 1118w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">I2C GPIOs must be set as open-drain GPIOs as per I2C standard. I2C clock must be set according to the devices connected in the bus. Typically, I2C clock speed ranges from 20 – 400kHz. This clock speed is dependent on system clock speed Fsys. Therefore, before setting I2C clock speed you have to set/know Fsys. I2C clock is decided by the value of <strong><em>I2CLK</em></strong> register. It is basically a prescalar value in master mode.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C1.png"><img class="alignnone size-full wp-image-14399" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C1.png" alt="I2C" width="226" height="53" /></a></p>
<p style="text-align: justify">So, if Fsys = 16MHz and I<em>2CLK = 39 (0x27)</em>, the I2C bus clock rate is 100kHz.</p>
<p style="text-align: justify">Note that only in master I2C clock can be setup. In slave mode, the slave(s) synchronizes automatically with bus clock.</p>
<p style="text-align: justify"><strong><em>I2CON</em></strong> register is they key register for using I2C. It contains all the flags and condition-makers.</p>
<p style="text-align: justify">For instance, consider the I2C start condition. In order to make a start condition, we have to set the <strong><em>STA</em></strong> bit and clear I2C interrupt flag, <strong><em>SI</em></strong>. Since I used polling mode, <strong><em>SI</em></strong> is polled until it is cleared. This ensures that a start condition has been successfully made. I have also added a software-based timeout feature should there be an issue with the I2C bus. In N76E003, there is a hardware-based approach for timeout too. Note that I didn’t care about the I2C status register states as again this is rarely needed. If you want more grip on the I2C you can follow the BSP examples.</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void I2C_start(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    signed int t = timeout_count;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    set_STA;                               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    clr_SI;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while((SI == 0) &amp;&amp; (t &gt; 0))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       t--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<p style="text-align: justify">Finally, the last register that we will need is the I2C data register (<strong><em>I2DAT</em></strong>). It is through it we send and receive data from I2C bus.</p>
<p style="text-align: justify">The demo I have shown here is that of a DS1307 I2C-based real time clock. Perhaps this is the simplest device for learning about and understanding I2C.</p>
<h2><span lang="EN-GB">Demo</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_pic.jpg"><img class="alignnone size-medium wp-image-14400" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_pic-580x338.jpg" alt="I2C_pic" width="580" height="338" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_pic-580x338.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/I2C_pic.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/tsjbRC59m2I?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><!--more--></p>
<h1 style="margin-top: 0in"><span lang="EN-GB">Serial Peripheral Interface (SPI) – Interfacing MAX7219 and MAX6675 </span></h1>
<p style="text-align: justify">SPI just like I2C is another highly popular form of onboard serial communication. Compared to I2C it is fast and robust. However, it requires more GPIO pins than other communication forms. These make it ideal communication interface for TFT displays, OLED displays, flash memories, DACs, etc.</p>
<p style="text-align: justify">SPI is best realized as a shift register that shifts data in and out with clock pulses. In a SPI bus, there is always one master device which generates clock and selects slave(s). Master sends commands to slave(s). Slave(s) responds to commands sent by the master. The number of slaves in a SPI bus is virtually unlimited. Except the chip selection pin, all SPI devices in a bus can share the same clock and data pins.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Block-Diagram.png"><img class="alignnone size-medium wp-image-14401" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Block-Diagram-580x543.png" alt="SPI Block Diagram" width="580" height="543" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Block-Diagram-580x543.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Block-Diagram.png 599w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">In general, if you wish to know more about SPI bus here are some cool links:</p>
<ul>
<li style="list-style-type: none">
<ul>
<li style="text-align: justify"><a href="https://learn.mikroe.com/spi-bus">https://learn.mikroe.com/spi-bus</a></li>
</ul>
</li>
</ul>
<ul>
<li style="list-style-type: none">
<ul>
<li style="text-align: justify"><a href="https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi">https://learn.sparkfun.com/tutorials/serial-peripheral-interface-spi</a></li>
</ul>
</li>
</ul>
<ul>
<li style="list-style-type: none">
<ul>
<li style="text-align: justify"><a href="http://ww1.microchip.com/downloads/en/devicedoc/spi.pdf">http://ww1.microchip.com/downloads/en/devicedoc/spi.pdf</a></li>
</ul>
</li>
</ul>
<ul>
<li style="list-style-type: none">
<ul>
<li style="text-align: justify"><a href="http://tronixstuff.com/2011/05/13/tutorial-arduino-and-the-spi-bus">http://tronixstuff.com/2011/05/13/tutorial-arduino-and-the-spi-bus</a></li>
</ul>
</li>
</ul>
<ul>
<li style="list-style-type: none">
<ul>
<li style="text-align: justify"><a href="https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi">https://embeddedmicro.com/tutorials/mojo/serial-peripheral-interface-spi</a></li>
</ul>
</li>
</ul>
<ul>
<li style="text-align: justify"><a href="http://www.circuitbasics.com/basics-of-the-spi-communication-protocol">http://www.circuitbasics.com/basics-of-the-spi-communication-protocol</a></li>
</ul>
<h2 style="margin-top: 0in"><span lang="EN-GB">Code</span></h2>
<h3><strong>MAX72xx.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define MAX72xx_SPI_GPIO_init()                             do{P00_PushPull_Mode; P10_PushPull_Mode; P11_PushPull_Mode;}while(0)</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define MAX72xx_CS_OUT_HIGH()                               set_P11</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define MAX72xx_CS_OUT_LOW()                                clr_P11</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define NOP                                                 0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG0                                                0x01</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG1                                                0x02</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG2                                                0x03</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG3                                                0x04</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG4                                                0x05</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG5                                                0x06</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG6                                                0x07</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DIG7                                                0x08</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define decode_mode_reg                                     0x09</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define intensity_reg                                       0x0A</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define scan_limit_reg                                      0x0B</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define shutdown_reg                                        0x0C</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define display_test_reg                                    0x0F</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define shutdown_cmd                                        0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define run_cmd                                             0x01</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define no_test_cmd                                         0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define test_cmd                                            0x01</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_only                                        0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_1                                        0x01</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_2                                        0x02</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_3                                        0x03</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_4                                        0x04</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_5                                        0x05</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_6                                        0x06</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define digit_0_to_7                                        0x07</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define No_decode_for_all                                   0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define Code_B_decode_digit_0                               0x01</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define Code_B_decode_digit_0_to_3                         0x0F    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define Code_B_decode_for_all                               0xFF</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX72xx_SPI_HW_Init(unsigned char clk_value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX72xx_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX72xx_write(unsigned char address, unsigned char value);</span></pre>
<h3><strong>MAX72xx.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003_IAR.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "MAX72xx.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX72xx_SPI_HW_Init(unsigned char clk_value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  switch(clk_value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    case 1:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    case 2:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    case 3:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    default:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }   </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_DISMODF;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_MSTR;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  clr_CPOL;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  clr_CPHA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_SPIEN;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX72xx_init(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_SPI_GPIO_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_SPI_HW_Init(0);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_write(shutdown_reg, run_cmd);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_write(decode_mode_reg, Code_B_decode_digit_0_to_3);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_write(scan_limit_reg, digit_0_to_3);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_write(intensity_reg, 0x19);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX72xx_write(unsigned char address, unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_CS_OUT_LOW(); </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  SPDR = address;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  while(!(SPSR &amp; SET_BIT7)); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  clr_SPIF;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  SPDR = value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  while(!(SPSR &amp; SET_BIT7)); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  clr_SPIF;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_CS_OUT_HIGH();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>MAX6675.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define MAX6675_SPI_GPIO_init()     do{P01_Input_Mode; P10_PushPull_Mode; P12_PushPull_Mode;}while(0)</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define MAX6675_CS_OUT_HIGH()       set_P12</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define MAX6675_CS_OUT_LOW()        clr_P12</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define T_min                       0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define T_max                       1024</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define count_max                   4096</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define no_of_pulses                16</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define deg_C                       0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define deg_F                       1</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define tmp_K                       2</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define open_contact                0x04</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define close_contact               0x00</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define scalar_deg_C                0.25</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define scalar_deg_F_1              1.8</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define scalar_deg_F_2              32.0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define scalar_tmp_K                273.0</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define no_of_samples               16</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX6675_SPI_HW_Init(unsigned char clk_value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX6675_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char MAX6675_get_ADC(unsigned int *ADC_data);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">float MAX6675_get_T(unsigned int ADC_value, unsigned char T_unit);</span></pre>
<h3><strong>MAX6675.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003_IAR.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "MAX6675.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX6675_SPI_HW_Init(unsigned char clk_value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  switch(clk_value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    case 1:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    case 2:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    case 3:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    default:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_SPR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }   </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_DISMODF;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_MSTR;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  clr_CPOL;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_CPHA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_SPIEN;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void MAX6675_init(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    MAX6675_SPI_GPIO_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    MAX6675_SPI_HW_Init(0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char MAX6675_get_ADC(unsigned int *ADC_data)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char lb = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char hb = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char samples = no_of_samples;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned int temp_data = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned long avg_value = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while(samples &gt; 0)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         MAX6675_CS_OUT_LOW();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         SPDR = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         while(!(SPSR &amp; SET_BIT7)); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         hb = SPDR;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         clr_SPIF; </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         SPDR = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         while(!(SPSR &amp; SET_BIT7));         </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         lb = SPDR;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         clr_SPIF;   </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         MAX6675_CS_OUT_HIGH();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         temp_data = hb;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         temp_data &lt;&lt;= 8;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         temp_data |= lb;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         temp_data &amp;= 0x7FFF;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         avg_value += (unsigned long)temp_data;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         samples--;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         Timer0_Delay1ms(10);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    temp_data = (avg_value &gt;&gt; 4);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if((temp_data &amp; 0x04) == close_contact)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        *ADC_data = (temp_data &gt;&gt; 3);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        return close_contact;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        *ADC_data = (count_max + 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        return open_contact;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">float MAX6675_get_T(unsigned int ADC_value, unsigned char T_unit)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    float tmp = 0.0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    tmp = (((float)ADC_value) * scalar_deg_C);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    switch(T_unit)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case deg_F:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">             tmp *= scalar_deg_F_1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">             tmp += scalar_deg_F_2;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">             break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case tmp_K:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            tmp += scalar_tmp_K;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        default:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return tmp;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>main.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003_IAR.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "MAX72xx.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "MAX6675.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned int ti = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned int t = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  P15_PushPull_Mode;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX6675_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  MAX72xx_init(); </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      P15 = 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_CPOL;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      set_CPHA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      MAX6675_get_ADC(&amp;ti);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      t = ((unsigned int)MAX6675_get_T(ti, tmp_K));</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      delay_ms(100);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      P15 = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_CPOL;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      clr_CPHA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      MAX72xx_write(DIG3, ((t / 1000) % 10));</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      MAX72xx_write(DIG2, ((t / 100) % 10));</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      MAX72xx_write(DIG1, ((t / 10) % 10));</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      MAX72xx_write(DIG0, (t % 10));</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      delay_ms(100);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  };</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2><span lang="EN-GB">Schematic</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Schematic.png"><img class="alignnone size-medium wp-image-14403" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Schematic-580x243.png" alt="SPI Schematic" width="580" height="243" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Schematic-580x243.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Schematic.png 890w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h2><span lang="EN-GB">Explanation</span></h2>
<p style="text-align: justify">With SPI we have to deal with two things – first, the initialization and second, the data transfer process. Configuring SPI needs a few things to be set up. These are:</p>
<ul style="text-align: justify">
<li>SPI communication bus speed or simply clock speed</li>
<li>Clock polarity</li>
<li>Clock phase</li>
<li>Orientation of data, i.e. MSB first or LSB first</li>
<li>Master/slave status</li>
<li>Optionally hardware slave selection pin use</li>
</ul>
<p style="text-align: justify">Most of these can be done by manipulating the following registers:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Registers.png"><img class="alignnone size-medium wp-image-14402" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Registers-580x161.png" alt="SPI Registers" width="580" height="161" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Registers-580x161.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Registers.png 769w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify"><strong><em>SPCR</em></strong> configures the hardware SPI peripheral of N76E003 while <strong><em>SPDR</em></strong> is used for transferring data.</p>
<p style="text-align: justify">To aid in all these I have coded the following functions. Though I didn’t use these code snippets in the actual demo code for demonstration purposes, these will most certainly work and reduce coding effort.</p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">void SPI_init(unsigned char clk_speed, unsigned char mode)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  set_SPI_clock_rate(clk_speed);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  set_SPI_mode(mode);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  set_DISMODF;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  set_MSTR;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  set_SPIEN;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">}



</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char SPI_transfer(unsigned char write_value)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  signed int t = timeout_count;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  register unsigned char read_value = 0x00;</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  SPDR = write_value;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  while((!(SPSR &amp; SET_BIT7)) &amp;&amp; (t &gt; 0))</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">    t--;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  };        </span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  read_value = SPDR;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  clr_SPIF;   </span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  return read_value;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<p style="text-align: justify"><strong><em>SPI_init </em></strong>function sets up the SPI peripheral using two information – the bus clock speed and SPI data transfer mode. It initializes the SPI hardware as a SPI master device and without hardware salve selection pin. This configuration is mostly used in common interfacings. Only mode and clock speed are the variables. In the demo, it is visible that MAX7219 and MAX6675 work with different SPI modes. I also didn’t use the hardware slave selection because there are two devices and one slave pin. Certainly, both external devices are not driven at the same time although both share the same bus lines.</p>
<p style="text-align: justify"><strong><em>SPI_transfer</em></strong> reads and writes on the SPI bus. Here the master writes to the slave first, waits for successful transmission and reads from the slave later. It is best realized by the following figure:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Loop.png"><img class="alignnone size-medium wp-image-14405" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Loop-580x221.png" alt="SPI-Loop" width="580" height="221" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Loop-580x221.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-Loop.png 673w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">To demo SPI, MAX6675 and MAX7219 were used because one lacked read feature while the other lacked write feature. In the demo, MAX6675 is read to measure the temperature sensed by the K-type thermocouple attached with it and display the measured temperature in Kelvin on MAX7219-based seven segment display arrays.</p>
<h2><span lang="EN-GB">Demo</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI.jpg"><img class="alignnone size-medium wp-image-14406" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-580x442.jpg" alt="SPI" width="580" height="442" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI-580x442.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/SPI.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/0E-nOCFYh54?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><!--more--></p>
<h1 style="margin-top: 0in"><span lang="EN-GB">One Wire (OW) Communication – Interfacing DHT11</span></h1>
<p style="text-align: justify">One protocol is not a standard protocol like I2C or SPI. It is just a mere method of communicating with a device that uses just one wire. There are a few devices that uses such principle for communication. DHT series sensors, DS18B20s, digital serial number chips, etc. are a few to mention. As I stated before, since one wire communication doesn’t belong to a dedicated format of communication, there is no dedicated hardware for it. With just a bidirectional GPIO pin we can implement one wire communication. Optionally we can also use a timer for measuring response pulse widths since the method of sending ones and zeroes over one wire requires the measurement of pulse durations. This way of encoding ones and zeros as a function of pulse width is called time-slotting.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DHT11-Timing-Diagram.jpg"><img class="alignnone size-full wp-image-14408" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DHT11-Timing-Diagram.jpg" alt="DHT11 Timing Diagram" width="569" height="185" /></a></p>
<p style="text-align: justify">Shown above is the timing diagram for DHT11’s time slots. Check the length of pulse high time for one and zero. This is the technique applied in time-slotting mechanism. We have to time pulse lengths in order to identify the logic states.</p>
<h2 style="margin-top: 0in"><span lang="EN-GB">Code</span></h2>
<h3><strong>DHT11.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define HIGH                    1</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define LOW                     0</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DHT11_pin_init()        P05_Quasi_Mode      </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DHT11_pin_HIGH()        set_P05</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DHT11_pin_LOW()         clr_P05</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DHT11_pin_IN()          P05             </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DHT11_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char get_byte(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char get_data(void);</span></pre>
<h3><strong>DHT11.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "DHT11.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">extern unsigned char values[5];</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DHT11_init(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   DHT11_pin_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   delay_ms(1000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char get_byte(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char s = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char value = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   for(s = 0; s &lt; 8; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      value &lt;&lt;= 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      while(DHT11_pin_IN() == LOW);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      delay_us(30);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      if(DHT11_pin_IN() == HIGH)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          value |= 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      while(DHT11_pin_IN() == HIGH);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   return value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char get_data(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   short chk = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char s = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char check_sum = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   DHT11_pin_HIGH();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   DHT11_pin_LOW();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   delay_ms(18);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   DHT11_pin_HIGH();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   delay_us(26);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   chk = DHT11_pin_IN();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   if(chk)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      return 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   delay_us(80);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   chk = DHT11_pin_IN();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   if(!chk)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      return 2;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   delay_us(80);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   for(s = 0; s &lt;= 4; s += 1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       values[s] = get_byte();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   DHT11_pin_HIGH();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   for(s = 0; s &lt; 4; s += 1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       check_sum += values[s];</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   if(check_sum != values[4])</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      return 3;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      return 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>main.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "LCD_2_Wire.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "DHT11.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char values[5];</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">const unsigned char symbol[8] =</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   0x00, 0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_symbol(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char state = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  setup();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    state = get_data();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    switch(state)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            case 1:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            case 2:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_clear_home();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_putstr("No Sensor Found!");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            case 3:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_clear_home();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_putstr("Checksum Error!");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            default:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_goto(0, 0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_putstr("R.H/ %:       ");</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 lcd_print(14, 0, values[0]);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_goto(0, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_putstr("Tmp/");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_goto(4, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_send(0, DAT);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_goto(5, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 LCD_putstr("C:");</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 if((values[2] &amp; 0x80) == 1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                     LCD_goto(13, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                     LCD_putstr("-");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                     LCD_goto(13, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                     LCD_putstr(" ");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 lcd_print(14, 1, values[2]);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                 break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    delay_ms(1000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  };</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  DHT11_init();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_init(); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_clear_home();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  lcd_symbol();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_symbol(void) </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char s = 0; </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_send(0x40, CMD);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  for(s = 0; s &lt; 8; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   LCD_send(symbol[s], DAT);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_send(0x80, CMD);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> unsigned char chr = 0x00;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> chr = ((value / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> LCD_putchar(chr);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> chr = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> LCD_goto((x_pos + 1), y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color=""> LCD_putchar(chr);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2><span lang="EN-GB">Schematic</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DH11-Schematic.png"><img class="alignnone size-medium wp-image-14407" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DH11-Schematic-580x257.png" alt="DH11 Schematic" width="580" height="257" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/DH11-Schematic-580x257.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/DH11-Schematic.png 843w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h2><span lang="EN-GB">Explanation</span></h2>
<p style="text-align: justify">As stated earlier, OW basically needs two things – first, the control of a single GPIO pin and second, the measurement of time. I would like to highlight the most important part of the whole code here:</p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char get_byte(void)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char s = 0;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">   unsigned char value = 0;</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">   for(s = 0; s &lt; 8; s++)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      value &lt;&lt;= 1;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      while(DHT11_pin_IN() == LOW);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      delay_us(30);</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      if(DHT11_pin_IN() == HIGH)</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      {</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">          value |= 1;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      }</span></pre>
<pre style="text-align: justify"></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">      while(DHT11_pin_IN() == HIGH);</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">   return value;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<p style="text-align: justify">From DHT11’s timing diagram, we know that a zero is define by a pulse of 26 &#8211; 28μs and a logic one is defined by a pulse of 70μs. It is here in the <strong><em>get_byte</em></strong> function we check the pulse coming from DHT11. The DHT11’s pin is polled as an input and after 30μs if the result of this polling is high then it is considered as a logic one or else it is considered otherwise. Once triggered, DHT11 will provide a 5-byte output. All of the bits in these 5 bytes are checked this way. Though it is not the best method to do so, it is easy and simple.</p>
<h2><span lang="EN-GB">Demo</span></h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DHT11.jpg"><img class="alignnone size-medium wp-image-14409" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DHT11-580x279.jpg" alt="DHT11" width="580" height="279" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/DHT11-580x279.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/DHT11.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/1Zetmad3fLU?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><!--more--></p>
<h1 style="margin-top: 0in"><span lang="EN-GB">One Wire (OW) Communication – Interfacing DS18B20</span></h1>
<p style="text-align: justify">One wire communication, as stated previously, doesn’t have a defined protocol. Except for the time-slotting mechanism part, there is nothing in common across the devices using this form of communication. We have seen how to interface a DHT11 relative humidity and temperature sensor previously. In this segment, we will see how to interface a DS18B20 one-wire digital temperature sensor with N76E003. DS18B20 follows and uses a completely different set of rules for communication.</p>
<h2 style="margin-top: 0in"><span lang="EN-GB">Code</span></h2>
<h3><strong>one_wire.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS18B20_GPIO_init()             P06_OpenDrain_Mode</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS18B20_IN()                    P06</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS18B20_OUT_LOW()               clr_P06</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define DS18B20_OUT_HIGH()              set_P06</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define TRUE                            1</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define FALSE                           0</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char onewire_reset(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void onewire_write_bit(unsigned char bit_value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char onewire_read_bit(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void onewire_write(unsigned char value);   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char onewire_read(void);</span></pre>
<h3><strong>one_wire.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "one_wire.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char onewire_reset(void) </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{                                        </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned char res = FALSE;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     DS18B20_GPIO_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     DS18B20_OUT_LOW();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_us(480);       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     DS18B20_OUT_HIGH();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_us(60);       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     res = DS18B20_IN();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     delay_us(480);      </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     return res;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void onewire_write_bit(unsigned char bit_value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS18B20_OUT_LOW();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(bit_value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        delay_us(104);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        DS18B20_OUT_HIGH();  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }             </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char onewire_read_bit(void)       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS18B20_OUT_LOW(); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS18B20_OUT_HIGH(); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  delay_us(15);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return(DS18B20_IN());   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void onewire_write(unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{                   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned char s = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     while(s &lt; 8)   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {                             </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          if((value &amp; (1 &lt;&lt; s)))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              DS18B20_OUT_LOW();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">                nop;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              DS18B20_OUT_HIGH(); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              delay_us(60);  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          }      </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            DS18B20_OUT_LOW();           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              delay_us(60);          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              DS18B20_OUT_HIGH();  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              nop;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          s++;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}                                     </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char onewire_read(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned char s = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     unsigned char value = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     while(s &lt; 8)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          DS18B20_OUT_LOW();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          nop;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          DS18B20_OUT_HIGH(); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          if(DS18B20_IN()) </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          {                                     </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">              value |=  (1 &lt;&lt; s);                         </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          }       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          delay_us(60);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">          s++;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     return value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>DS18B20.h</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "one_wire.h" </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define convert_T                       0x44</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define read_scratchpad                 0xBE           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define write_scratchpad                0x4E</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define copy_scratchpad                 0x48  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define recall_E2                       0xB8</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define read_power_supply               0xB4   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define skip_ROM                        0xCC</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define resolution                      12</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DS18B20_init(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">float DS18B20_get_temperature(void); </span></pre>
<h3><strong>DS18B20.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "DS18B20.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void DS18B20_init(void)                            </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{                                      </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_reset();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    delay_ms(100);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}             </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">float DS18B20_get_temperature(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{                                              </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char msb = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char lsb = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    register float temp = 0.0; </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_reset();    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_write(skip_ROM);       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_write(convert_T);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    switch(resolution)  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {                                                 </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 12:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {                                           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            delay_ms(750);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 11:                                    </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {             </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            delay_ms(375);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 10:                            </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {                                </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            delay_ms(188);  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }                                       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 9:                                  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {                                               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            delay_ms(94);                </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;                           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }                       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }                 </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_reset();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_write(skip_ROM);                </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    onewire_write(read_scratchpad);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    lsb = onewire_read();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    msb = onewire_read();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    temp = msb;                          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    temp *= 256.0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    temp += lsb;</span></pre>
<pre></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    switch(resolution)  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {                                 </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 12:           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {                                               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            temp *= 0.0625;                </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;                           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 11:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            temp *= 0.125;      </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }               </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 10:</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {           </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            temp *= 0.25;       </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        } </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        case 9:                                </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {                                </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            temp *= 0.5;        </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            break;     </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }                         </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }  </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    delay_ms(40);       </span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    return (temp);      </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h3><strong>main.c</strong></h3>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "DS18B20.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "LCD_3_Wire.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">const unsigned char symbol[8] =</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   0x00, 0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_symbol(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_C(unsigned char x_pos, unsigned char y_pos, signed int value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_I(unsigned char x_pos, unsigned char y_pos, signed long value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_D(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char points);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_F(unsigned char x_pos, unsigned char y_pos, float value, unsigned char points);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    float t = 0.0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    DS18B20_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    lcd_symbol();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(0, 0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr("N76E003 DS18B20");</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(0, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr("T/ C");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(2, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_send(0, DAT);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       t = DS18B20_get_temperature();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       print_F(9, 1, t, 3);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       delay_ms(100);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    };</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_symbol(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    unsigned char s = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   LCD_send(0x40, CMD);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   for(s = 0; s &lt; 8; s++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        LCD_send(symbol[s], DAT);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">   LCD_send(0x80, CMD);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_C(unsigned char x_pos, unsigned char y_pos, signed int value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     char ch[5] = {0x20, 0x20, 0x20, 0x20, '\0'};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     if(value &lt; 0x00)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[0] = 0x2D;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        value = -value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[0] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     if((value &gt; 99) &amp;&amp; (value &lt;= 999))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[1] = ((value / 100) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[2] = (((value % 100) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[3] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     else if((value &gt; 9) &amp;&amp; (value &lt;= 99))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[1] = (((value % 100) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[2] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[3] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     else if((value &gt;= 0) &amp;&amp; (value &lt;= 9))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[1] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[2] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">         ch[3] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     LCD_putstr(ch);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_I(unsigned char x_pos, unsigned char y_pos, signed long value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    char ch[7] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, '\0'};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(value &lt; 0)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[0] = 0x2D;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        value = -value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[0] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(value &gt; 9999)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[1] = ((value / 10000) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[2] = (((value % 10000)/ 1000) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[3] = (((value % 1000) / 100) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[4] = (((value % 100) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[5] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((value &gt; 999) &amp;&amp; (value &lt;= 9999))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[1] = (((value % 10000)/ 1000) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[2] = (((value % 1000) / 100) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[3] = (((value % 100) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[4] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[5] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((value &gt; 99) &amp;&amp; (value &lt;= 999))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[1] = (((value % 1000) / 100) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[2] = (((value % 100) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[3] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[4] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[5] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((value &gt; 9) &amp;&amp; (value &lt;= 99))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[1] = (((value % 100) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[2] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[3] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[4] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[5] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[1] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[2] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[3] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[4] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[5] = 0x20;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr(ch);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_D(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char points)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    char ch[5] = {0x2E, 0x20, 0x20, '\0'};</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    ch[1] = ((value / 100) + 0x30);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(points &gt; 1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        ch[2] = (((value / 10) % 10) + 0x30);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        if(points &gt; 1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">            ch[3] = ((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    LCD_putstr(ch);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void print_F(unsigned char x_pos, unsigned char y_pos, float value, unsigned char points)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    signed long tmp = 0x0000;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    tmp = value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    print_I(x_pos, y_pos, tmp);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    tmp = ((value - tmp) * 1000);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(tmp &lt; 0)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       tmp = -tmp;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if(value &lt; 0)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        value = -value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        LCD_putchar(0x2D);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        LCD_putchar(0x20);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if((value &gt;= 10000) &amp;&amp; (value &lt; 100000))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        print_D((x_pos + 6), y_pos, tmp, points);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((value &gt;= 1000) &amp;&amp; (value &lt; 10000))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        print_D((x_pos + 5), y_pos, tmp, points);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((value &gt;= 100) &amp;&amp; (value &lt; 1000))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        print_D((x_pos + 4), y_pos, tmp, points);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((value &gt;= 10) &amp;&amp; (value &lt; 100))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        print_D((x_pos + 3), y_pos, tmp, points);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if(value &lt; 10)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">        print_D((x_pos + 2), y_pos, tmp, points);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2>Schematic</h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DS18B20-Schematic.png"><img class="alignnone size-medium wp-image-14412" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/DS18B20-Schematic-580x257.png" alt="DS18B20 Schematic" width="580" height="257" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/DS18B20-Schematic-580x257.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/DS18B20-Schematic.png 843w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h2>Explanation</h2>
<p style="text-align: justify">One wire communication is detailed in these application notes from Maxim:</p>
<p style="text-align: justify"><a href="https://www.maximintegrated.com/en/app-notes/index.mvp/id/126">https://www.maximintegrated.com/en/app-notes/index.mvp/id/126</a></p>
<p style="text-align: justify"><a href="https://www.maximintegrated.com/en/app-notes/index.mvp/id/162">https://www.maximintegrated.com/en/app-notes/index.mvp/id/162</a></p>
<p style="text-align: justify">These notes are all that are needed for implementing the one wire communication interface for DS18B20. Please go through these notes. The codes are self-explanatory and are implemented from the code examples in these app notes.</p>
<h2><span style="color: #0000ff" data-darkreader-inline-color=""><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/ds18b20.png"><img class="alignnone size-medium wp-image-14432 aligncenter" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/ds18b20-580x534.png" alt="ds18b20" width="580" height="534" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/ds18b20-580x534.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/ds18b20-1024x942.png 1024w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/ds18b20.png 1149w" sizes="(max-width: 580px) 100vw, 580px" /></a></span></h2>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/uOq7etfuqvg?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe><br />
<!--more--></p>
<h1 style="margin-top: 0cm">Decoding NEC IR Remote Protocol</h1>
<p style="text-align: justify">IR remote controllers are used in a number of devices for remotely controlling them. Examples of these devices include TV, stereo, smart switches, projectors, etc. IR communication as such is unidirectional and in a way one wire communication. Ideally there is one transmitter and one receiver only.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Remote.jpg"><img class="alignnone size-full wp-image-14415" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Remote.jpg" alt="IR Remote" width="540" height="540" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Remote.jpg 540w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Remote-150x150.jpg 150w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Remote-90x90.jpg 90w" sizes="(max-width: 540px) 100vw, 540px" /></a></p>
<p style="text-align: justify">Data to be sent from a remote transmitter is sent by modulating it with a carrier wave (usually between 36kHz to 40kHz). Modulation ensure safety from data corruption and long-distance transmission. An IR receiver at the receiving end receives and demodulates the sent out modulated data and outputs a stream of pulses. These pulses which vary in pulse widths/timing/position/phase carry the data information that was originally sent by the remote transmitter. How the pulses should behave is governed closely by a protocol or defined set of rules. In most micros, there is no dedicated hardware for decoding IR remote protocols. A micro that needs to decode IR remote data also doesn’t know when it will be receiving an IR data stream. Thus, a combination of external interrupt and timer is needed for decoding IR data.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC.png"><img class="alignnone size-full wp-image-14416" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC.png" alt="NEC" width="340" height="200" /></a></p>
<p style="text-align: justify">In this segment, we will see how we can use an external interrupt and a timer to easily decode a NEC IR remote. This same method can be applied to any IR remote controller. At this stage, I recommend that you do a study of NEC IR protocol from <a href="https://www.sbprojects.net/knowledge/ir/nec.php">here</a>. SB-Project’s website is an excellent page for info as such.</p>
<h2 style="margin-top: 0cm">Code</h2>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "N76E003.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "SFR_Macro.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Function_define.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Common.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "Delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "soft_delay.h"</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#include "LCD_2_Wire.h"</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define sync_high          22000</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define sync_low           14000</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define one_high            3600</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define one_low             2400</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define zero_high           1800</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define zero_low            1200</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">bit received;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char bits = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned int frames[33];</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void set_Timer_0(unsigned int value);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned int get_Timer_0(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void erase_frames(void);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char decode(unsigned char start_pos, unsigned char end_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void decode_NEC(unsigned char *addr, unsigned char *cmd);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value);</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void EXTI0_ISR(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">interrupt 0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  frames[bits] = get_Timer_0();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  bits++;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_TR0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  if(bits &gt;= 33)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     received = 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     clr_EA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     clr_TR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_Timer_0(0x0000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  P15 = ~P15;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void main(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char address = 0x00;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char command = 0x00;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  setup();</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  while(1)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {   </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     if(received)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       decode_NEC(&amp;address, &amp;command);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       lcd_print(13, 0, address); </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       lcd_print(13, 1, command);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       delay_ms(100);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       erase_frames();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">       set_EA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  };</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void setup(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{ </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  erase_frames();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  P15_PushPull_Mode;  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  TIMER0_MODE1_ENABLE;          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_Timer_0(0x0000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_IT0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_EX0;  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_EA;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_init();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_clear_home();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto(0, 0);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_putstr("Address:");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto(0, 1);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_putstr("Command:");</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void set_Timer_0(unsigned int value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  TH0 = ((value &amp;&amp; 0xFF00) &gt;&gt; 8);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  TL0 = (value &amp; 0x00FF);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned int get_Timer_0(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned int value = 0x0000;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  value = TH0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  value &lt;&lt;= 8;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  value |= TL0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  return value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void erase_frames(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  for(bits = 0; bits &lt; 33; bits++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    frames[bits] = 0x0000;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_Timer_0(0x0000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  received = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  bits = 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char decode(unsigned char start_pos, unsigned char end_pos)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char value = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  for(bits = start_pos; bits &lt;= end_pos; bits++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    value &lt;&lt;= 1;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if((frames[bits] &gt;= one_low) &amp;&amp; (frames[bits] &lt;= one_high))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      value |= 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((frames[bits] &gt;= zero_low) &amp;&amp; (frames[bits] &lt;= zero_high))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      value |= 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((frames[bits] &gt;= sync_low) &amp;&amp; (frames[bits] &lt;= sync_high))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      return 0xFF;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  return value;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void decode_NEC(unsigned char *addr, unsigned char *cmd)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  *addr = decode(2, 9);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  *cmd = decode(18, 25);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{ </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto(x_pos, y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_putchar((value / 100) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto((x_pos + 1), y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_putchar(((value % 10) / 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_goto((x_pos + 2), y_pos);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  LCD_putchar((value % 10) + 0x30);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<h2>Schematic</h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Schematic.png"><img class="alignnone size-medium wp-image-14417" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Schematic-580x257.png" alt="IR Schematic" width="580" height="257" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Schematic-580x257.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-Schematic.png 843w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<h2>Explanation</h2>
<p style="text-align: justify">A NEC transmission sends out 33 pulses. The first one is a sync bit and the rest 32 contain address and command info. These 32 address and command bits can be divided into 4 groups – address, command, inverted address and inverted command. The first 16 bits contain address and inverted address while the rest contain command and inverted command. The inverted signals can be used against the non-inverted ones for checking signal integrity.</p>
<p style="text-align: justify">We already know that IR data is received as a steam of pulses. Pulses represent sync bit or other info, ones and zeros. In case of NEC IR protocol, the pulses have variable lengths. Sync bit represented by a pulse of 9ms high and 4.5ms low – total pulse time is 13.5ms. Check the timing diagram below. Please note that in this timing diagram the blue pulses are from the transmitter’s output and the yellow ones are those received by the receiver. Clearly the pulses are inverted.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-Sync.png"><img class="alignnone size-full wp-image-14418" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-Sync.png" alt="NEC Sync" width="375" height="240" /></a></p>
<p style="text-align: justify">Logic one is represented by a pulse of 560µs high time and 2.25ms of low time – total pulse time is 2.81ms. Likewise, logic zero is represented by a pulse of 560µs high time and 1.12ms of low time – total pulse time is 1.68ms.</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-High-Low.png"><img class="alignnone size-medium wp-image-14419" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-High-Low-580x246.png" alt="NEC High Low" width="580" height="246" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-High-Low-580x246.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-High-Low.png 730w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">These timings can vary slightly about 15 &#8211; 25% due to a number of factors like medium, temperature, etc. Therefore, we can assume the following timings:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/IR.png"><img class="alignnone size-medium wp-image-14420" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-580x108.png" alt="IR" width="580" height="108" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR-580x108.png 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/IR.png 820w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p style="text-align: justify">Now as per timing info and timing diagram we have to detect falling edges and time how long it takes to detect another falling edge. In this way, we can time the received pulses and use the pulse time info to decode a received signal.</p>
<p style="text-align: justify">In the demo, I used external interrupt channel EXTI0 and Timer 0. The system clock frequency is set to 16MHz with HIRC. Timer 0 is set in Mode 1 and its counter is rest to 0 count. EXTI0 is set to detect falling edges. Note that the timer is set but not started.</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">TIMER0_MODE1_ENABLE;          </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">set_Timer_0(0x0000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">set_IT0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">set_EX0;  </span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">set_EA;</span></pre>
<p>Also note that each tick of Timer 0 here is about:</p>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC1.png"><img class="alignnone size-full wp-image-14421" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC1.png" alt="NEC" width="519" height="78" /></a></p>
<p style="text-align: justify">Based on this tick info, we can deduce the maximum and minimum pulse durations as like:</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define sync_high          22000 // 22000 × 0.75ms = 16.5ms</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define sync_low           14000 // 14000 × 0.75ms = 10.5ms</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define one_high            3600 // 3600 × 0.75ms = 2.7ms</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define one_low             2400 // 2400 × 0.75ms = 1.8ms</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define zero_high           1800 // 1800 × 0.75ms = 1.35ms</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">#define zero_low            1200 // 1200 × 0.75ms = 0.9ms</span></pre>
<p style="text-align: justify">Now when an IR transmission is received, an interrupt will be triggered. Therefore, in the ISR, we immediately capture the timer’s tick count and reset it. When all 33 pulses have been received this way, we temporarily halt all interrupts by disabling the global interrupt and stop the timer in order to decode the received signal. P15 is also toggled to demonstrate reception.</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">void EXTI0_ISR(void)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">interrupt 0</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  frames[bits] = get_Timer_0();</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  bits++;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_TR0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  if(bits &gt;= 33)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     received = 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     clr_EA;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">     clr_TR0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  set_Timer_0(0x0000);</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  P15 = ~P15;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<p style="text-align: justify">Now the signal is decoded in the <strong><em>decode</em></strong> function. This function scans a fixed length of time frames for sync, ones and zeros and return the value obtained by scanning the time info of the pulses. In this way, a received signal is decoded.</p>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">unsigned char decode(unsigned char start_pos, unsigned char end_pos)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">{</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  unsigned char value = 0;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  for(bits = start_pos; bits &lt;= end_pos; bits++)</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    value &lt;&lt;= 1;</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    if((frames[bits] &gt;= one_low) &amp;&amp; (frames[bits] &lt;= one_high))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      value |= 1;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((frames[bits] &gt;= zero_low) &amp;&amp; (frames[bits] &lt;= zero_high))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      value |= 0;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    else if((frames[bits] &gt;= sync_low) &amp;&amp; (frames[bits] &lt;= sync_high))</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    {</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">      return 0xFF;</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">    }</span></pre>
<pre><span style="color: #0000ff" data-darkreader-inline-color="">  }</span></pre>
<pre></pre>
<p> </p>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">  return value;</span></pre>
<pre style="text-align: justify"><span style="color: #0000ff" data-darkreader-inline-color="">}</span></pre>
<p style="text-align: justify">In the main loop, the decode info are displayed on a text LCD.</p>
<h2>Demo</h2>
<p style="text-align: center"><a href="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC.jpg"><img class="alignnone size-medium wp-image-14422" src="http://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-580x552.jpg" alt="NEC" width="580" height="552" srcset="https://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC-580x552.jpg 580w, https://embedded-lab.com/blog/wp-content/uploads/2018/08/NEC.jpg 590w" sizes="(max-width: 580px) 100vw, 580px" /></a></p>
<p><iframe width="860" height="484" src="https://www.youtube.com/embed/9xFYY9zVkFQ?feature=oembed" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe></p>
<p><!--more--></p>
<h1 style="margin-top: 0cm">Epilogue</h1>
<p style="text-align: justify">After going through all these topics and exploring the N76E003 to the finest details, I have to say that just like flagship killer cell phones, this is a flagship killer 8-bit microcontroller. In terms of price vs feature ratio, it is a winner. I’m truly impressed by its performance and hardware features. It offers something like an 8051 but with more advanced modern features. Old-school 8051 users will surely love to play with it.</p>
<p style="text-align: justify">Every day we talk about software piracy and hacking but little effort is done to prevent them. Students, hobbyists and low-profile business houses can’t afford to use the expensive Keil/IAR compiler. They often go for pirated versions of these software and this is a very wrong path to follow. Like I said in my first post on N76E003, Nuvoton has rooms for making its devices more popular by investing on a compiler of its own or at least start doing something with free Eclipse-IDE.</p>
<p>All files and code examples can be downloaded from <a href="https://github.com/sshahryiar/Nuvoton-N76E003-Tutorial" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p><a href="https://www.youtube.com/watch?v=xZ5gkk6WQpw&amp;list=PL-EErZRpDPIXmXL_Oo9v1j2PD8scq3VkW" target="_blank" rel="noopener noreferrer">Youtube playlist.</a></p>
<p style="text-align: justify">Happy coding.</p>
<p><em>Author: Shawon M. Shahryiar</em></p>
<p><em><a href="https://www.youtube.com/user/sshahryiar">https://www.youtube.com/user/sshahryiar</a></em></p>
<p><em><a href="https://www.facebook.com/groups/microarena/">https://www.facebook.com/groups/microarena</a></em></p>
<p><em><a href="https://www.facebook.com/MicroArena?ref=hl">https://www.facebook.com/MicroArena</a></em><em>                                                                          </em></p>
<p><em>06.08.2018</em></p>
]]></content:encoded>
							<wfw:commentRss>https://embedded-lab.com/blog/getting-started-nuvoton-8-bit-microcontrollers-coding-part-3/feed/</wfw:commentRss>
		<slash:comments>62</slash:comments>
							</item>
	</channel>
</rss>
