<?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/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>lpc1343 - OCFreaks!</title>
	<atom:link href="https://www.ocfreaks.com/tag/lpc1343/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.ocfreaks.com/tag/lpc1343/</link>
	<description>Overclocking , Gaming , Technology , Robotics &#38; DIY!</description>
	<lastBuildDate>Mon, 04 Dec 2017 19:18:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.4</generator>
<site xmlns="com-wordpress:feed-additions:1">42777727</site>	<item>
		<title>LPC1343 ADC Programming Tutorial</title>
		<link>https://www.ocfreaks.com/lpc1343-adc-programming-tutorial/</link>
					<comments>https://www.ocfreaks.com/lpc1343-adc-programming-tutorial/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Umang Gajera]]></dc:creator>
		<pubDate>Sat, 18 Nov 2017 12:37:41 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[lpc1343]]></category>
		<guid isPermaLink="false">http://www.ocfreaks.com/?p=3009</guid>

					<description><![CDATA[<p>This time we will go through ARM Cortex-M3 LPC1343 ADC programming tutorial. We will see how to convert an Analog signal to its Digital version. We will also see LPC134x basic ADC Interfacing Example along with an interrupt based example.</p>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-adc-programming-tutorial/">LPC1343 ADC Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="introleft">This time we will go through ARM Cortex-M3 LPC1343 ADC programming tutorial. We will see how to convert an Analog signal to its Digital version. We will also see LPC134x basic ADC Interfacing Example along with an interrupt based example.</p>
<div class="toc_container">
<span class="toc_title">Table of Contents</span></p>
<div class="toc">
<ol class="toc_list">
<li class="toc_text"><a href="#ADC_Block"><span>LPC134x ADC Block</span></a></li>
<li class="toc_text"><a href="#ADC_Regs"><span>ADC Registers in LPC1343</span></a></li>
<li class="toc_text"><a href="#ADC_Modes"><span>ADC Modes &#038; Programming</span></a></li>
<li class="toc_text"><a href="#Example_1"><span>Interfacing Potentiometer Example</span></a></li>
<li class="toc_text"><a href="#Example_2"><span>LPC1343 ADC Interrupt Example</span></a></li>
</ol>
</div>
</div>
<h2 class="shead" id="ADC_Block">LPC134x ADC Block</h2>
<p>Analog to Digital Conversion is used when want to interface an external analog signal or when interfacing analog sensors, like for example a temperature sensor. The ADC block in ARM Cortex-M3 LPC1343 Microcontroller is based on <a href="http://en.wikipedia.org/wiki/Successive_approximation_ADC">Successive Approximation(SAR)</a> conversion method. LPC1343 ADC Module uses 10-bit SAR having a conversion time of >= 2.44us i.e. around 409Khz max convertion rate. The Measurement range is from 0V to V<sub>DD</sub>, or commonly from 0V to ~3.3V (3.6V max). Maximum of 8 multiplexed inputs can be used for ADC.</p>
<div class="special sp_blue noteinfo">Note that LPC134x devices do not have any dedicated Analog voltage supply (V<sub>DDA</sub> &#038; V<sub>SSA</sub>) pins nor does it have any dedicated Voltage reference input pin (V<sub>REF</sub>). It uses V<sub>DD</sub> &#038; V<sub>SS</sub> as Analog Voltage supply inputs and V<sub>DD</sub> as Reference Voltage for ADC module.</div>
<h4>Pins relating to ADC Module:</h4>
<p><center></p>
<table>
<tr>
<th><strong>Pin</strong></th>
<th><strong>Description</strong></th>
</tr>
<tr>
<td><strong>AD0 to AD7</strong> (PIO0_11, PIO1_0/1/2/3/4/10/11) </td>
<td>Analog input pins. <br /><strong>Note from Datasheet:</strong> &#8220;IWhile the pins are 5 V tolerant in digital mode, the maximum input voltage must not exceed V<sub>DD</sub> when the pins are configured as analog inputs.&#8221; </td>
</tr>
<tr>
<td><strong>V<sub>DD</sub></strong> (V<sub>REF</sub>)</td>
<td> V<sub>DD</sub> itself is used as reference voltage pins for ADC block.</td>
</tr>
<tr>
<td><strong>V<sub>DD</sub>, V<sub>SS</sub></strong></td>
<td>V<sub>DD</sub> is Analog Power pin and V<sub>SS</sub> is Ground pin used to power the ADC module. </td>
</tr>
</table>
<p></center></p>
<h2 class="shead" id="ADC_Regs">LPC134x ADC Registers</h2>
<p>Lets see registers which are used for ADC programming.</p>
<div class="highlight">
<strong>1) <span class="doc_ref">ADCR</span> &#8211; A/D Control Register : </strong>This is the main control register for ADC Block.</p>
<ol>
<li><strong>Bits[7:0] &#8211; SEL:</strong> Bit &#8216;x'(in this group) is used to select pin ADx.</li>
<li><strong>Bits[15:8] &#8211; CLKDIV: </strong>ADC Peripheral clock i.e. PCLK(same as PCLK for lpc134x) is divided by CLKDIV+1 to get the ADC clock. Note that ADC clock speed must be <= 4.5Mhz! As per user manual user must program the smallest value in this field which yields a clock speed of around 4.5 MHz or a bit less.</li>
<li><strong>Bit[16] &#8211; BURST:</strong> Set to 1 for doing repeated conversions, else 0 for software controlled conversions. Note: START bits must be set to 000 when BURST=1 or conversions will not start.  Refer user manual for detailed info.</li>
<li><strong>Bits[19 to 17] &#8211; CLKS :</strong> These bits are used to select the number of clocks used for conversion in burst mode along with number of bits of accuracy of the result in RESULT bits of ADDR.<br />
<center></p>
<table>
<tr>
<td><strong>Value</strong></td>
<td><strong>clocks / bits</strong></td>
</tr>
<tr>
<td>0x0</td>
<td>11 clocks / 10 bits </td>
</tr>
<tr>
<td>0x1</td>
<td>10 clock / 9 bits</td>
</tr>
<tr>
<td>0x2</td>
<td>9 clock / 8 bits</td>
</tr>
<tr>
<td>0x3</td>
<td>8 clock / 7 bits</td>
</tr>
<tr>
<td>0x4</td>
<td>7 clock / 6 bits</td>
</tr>
<tr>
<td>0x5</td>
<td>6 clock / 5 bits</td>
</tr>
<tr>
<td>0x6</td>
<td>5 clock / 4 bits</td>
</tr>
<tr>
<td>0x7</td>
<td>4 clock / 3 bits</td>
</tr>
</table>
<p></center></li>
<li><strong>Bits[26:24] &#8211; START: </strong>These bits are used to control the start of ADC conversion when BURST (bit 16) is set to 0. 0x0 = No start , 0x1 = Start the conversion now, and rest(0x2 to 0x7) of the values are used to start conversion when edge selected by bit 27(given below) occurs on a corresponding pin &#8211; refer LPC13xx User Manual for more.
<li><strong>Bit[27] &#8211; EDGE: </strong>Set this bit to 1 to start the conversion on falling edge of the selected CAP/MAT signal and set this bit to 0 to start the conversion on rising edge of the selected signal. (Note: This bit is of used only in the case when the START contains a value between 0x3 to 0x7 as mentioned above.)</li>
<li>Other bits are reserved.</li>
</ol>
<p><strong>2) <span class="doc_ref">ADGDR</span> &#8211; A/D Global Data Register :</strong> Contains the ADC’s flags and the result of the most recent A/D conversion.	</p>
<ol>
<li><strong>Bits[15:6] &#8211; V_VREF (RESULT):</strong> When DONE bit = 1, these bits give a binary fraction which represents the voltage on the pin ADx, divided by voltage in V<sub>DD</sub>. Value of 0x0 indicates that voltage on the given pin was less than, equal to or close to V<sub>SS</sub>(i.e. GND). And a value of 0x3FF means that the input voltage was close to, equal to or greater than the V<sub>DD</sub>.</li>
<li><strong>Bits[26:24] &#8211; CHN: </strong>Represents the channel from which V_VREF bits were converted. 0x0 = channel 0, 0x1= channel 1 and so on.</li>
<li><strong>Bit[30] &#8211; OVERRUN:</strong> In burst mode this bit is 1 in case of an Overrun i.e. the result of previous conversion being lost(overwritten).</li>
<li><strong>Bit[31] &#8211; DONE:</strong> When ADC conversion completes this bit is 1. When this register(ADGDR) is read and ADCR is written, this bit gets cleared i.e. set to 0. If ADCR is written while a conversion is in progress then this bit is set and a new conversion is started.</li>
<li>Other bits are reserved.</li>
</ol>
<p><strong>4) <span class="doc_ref">ADDR0 to ADDR7</span> &#8211; A/D Data registers :</strong> This register contains the result of the most recent conversion completed on the corresponding channel [0 to 7]. Its structure is same as ADGDR except Bits[26:24] are not used/reserved.</p>
<p><strong>5) <span class="doc_ref">ADSTAT</span> &#8211; A/D Status register :</strong> This register contains DONE and OVERRUN flags for all of the A/D channels along with A/D interrupt flag.</p>
<ol>
<li><strong>Bits[7:0] &#8211; DONE[7 to 0]:</strong> Here xth bit mirrors DONEx status flag from the result register for A/D channel x.</li>
<li><strong>Bits[15:8] &#8211; OVERRUN[7 to 0]:</strong> Even here the xth bit mirrors OVERRUNx status flag from the result register for A/D channel x </li>
<li><strong>Bit 16 &#8211; ADINT:</strong> This bit represents the A/D interrupt flag. It is 1 when any of the individual A/D channel DONE flags is asserted and enabled to contribute to the A/D interrupt via the ADINTEN(given below) register.</li>
<li>Other bits are reserved.</li>
</ol>
<p><strong>6) <span class="doc_ref">ADINTEN</span> &#8211; A/D Interrupt Enable Register :</strong> Using this register interrupts can be enabled or disabled for any ADC channels.</p>
<ol>
<li><strong>Bits[0 to 7] &#8211; ADINTEN[7:0]:</strong> If xth bit is set to 1 then an interrupt will be generated on completion of A/D conversion on channel x. Similarly if this bit is set to 0 then an interrupt wont be generated.</li>
<li><strong>Bit 8 &#8211; ADGINTEN:</strong> When set to 1, the global DONE flag in AADR will be used to generate an interrupt. When 0, only individual channels enabled by ADINTEN[7:0] will generate interrupts</li>
</ol>
</div>
<h2 class="shead" id="ADC_Modes">ADC Modes, Setup and Programming</h2>
<h4>ADC modes in LPC1343: </h4>
<ol>
<li><strong>Software controlled mode :</strong> In Software mode only one conversion will be done at a time. To perform another conversion you will need to restart the process. In software mode, only 1 bit in the SEL field of ADCR can be 1 i.e. only 1 Channel(i.e. Pin) can be selected for conversion at a time. Hence conversions can be done only any channel but one at a time.</li>
<li><strong>Hardware or Burst mode :</strong> In Hardware or Burst mode, conversions are performed continuously on the selected channels in round-robin fashion. Since the conversions cannot be controlled by software, Overrun may occur in this mode. Overrun is the case when a previous conversion result is replaced by new conversion result without previous result being read i.e. the conversion is lost. Usually an interrupt is used in Burst mode to get the latest conversion results. This interrupt is triggered when conversion in one of the selected channel ends.</li>
</ol>
<h4>1A. Setting up and configuring ADC Module for software controlled mode</h4>
<p>First, lets define some values which will help us in setting up ADCR register to configure &#038; Initialize ADC block.</p>
<pre><code class="language-cpp">
#define ADC_CLK_EN (1<<13) //Enable ADC clock

#define SEL_AD0    (1<<0) //Select Channel AD0

#define CLKDIV     15 // ADC clock-divider (ADC_CLOCK=PCLK/CLKDIV+1), yields 4.5Mhz ADC clock  
 
#define ADC_PWRUP  (~(1<<4)) //setting it to 0 will power it up 
 
#define START_CNV  (1<<24) //001 for starting the conversion immediately
 
#define ADC_DONE   (1U<<31) //define it as unsigned value or compiler will throw #61-D warning

#define ADCR_SETUP_SCM (CLKDIV<<8)
//SCM = Software Controlled Mode
</code></pre>
<p>Now we assign ADCR_SETUP to ADCR along with channel selection information to select channels as required. Finally we assign(by ORing) START_NOW to ADCR to start the conversion process as shown:</p>
<pre><code class="language-cpp">
LPC_SYSCON->PDRUNCFG &= ADC_PWRUP; //Power-up ADC Block
LPC_SYSCON->SYSAHBCLKCTRL |= ADC_CLK_EN; //Enable ADC clock
LPC_ADC->CR = ADCR_SETUP_SCM | SEL_AD0; //Setup ADC Block
LPC_ADC->CR |= START_CNV; //Start Conversion immediately
</code></pre>
<p>Note that before setting ADC using ADCR the ADC block must be powered-up using PDRUNCFG register and ADC Clock must be enabled using SYSAHBCLKCTRL register.</p>
<h4>1B. Fetching the conversion result in software controlled mode :</h4>
<p>In software controlled mode we continuously monitor bit 31 in the corresponding channel data register ADDR. If bit 31 changes to 1 from 0, it means that current conversion has been completed and the result is ready. For example, if we are using channel 0 of AD0 then we monitor for changes in bit 31 as follows :</p>
<pre><code class="language-cpp">
while((LPC_ADC->DR0 & ADC_DONE) == 0); //this loop will end when bit 31 of AD0DR6 changes to 1.
</code></pre>
<p>After this we extract the result which is stored in ADDR bits 4 to 15. Here we right shift ADDR by 6 places and force all other unrelated bits to 0 by using a 10-bit mask value of 0x3FF. 0x3FF is a mask containing 1's in bit locations 0 to 9 and rest 0's. In our case with ADDR0 being used, it can be done as follows :</p>
<pre><code class="language-cpp">
result = (LPC_ADC->DR0>>6) & 0x3FF;
</code></pre>
<h4>2A. Setting up and configuring ADC Module for Burst mode </h4>
<p>Configuring ADC Module is similar to what was done in software controlled mode except here we use the CLKS bits and don't use the START bits in ADCR. ADC_DONE is also not applicable since we are using an ISR which gets triggered when a conversion completes on any of the enabled channels. Additionally, we define the following constants:</p>
<pre><code class="language-cpp"> 
#define BURST_ON  (1<<16) // 1 for on and 0 for off

#define ADCR_SETUP_BURST ((CLKDIV<<8) | BURST_ON)
</code></pre>
<p>We configure and setup the ADC module in a similar manner(as shown above) as follows :</p>
<pre><code class="language-cpp">
LPC_SYSCON->PDRUNCFG &= ADC_PWRUP; //Power-up ADC Block
LPC_SYSCON->SYSAHBCLKCTRL |= ADC_CLK_EN; //Enable ADC clock
LPC_ADC->CR =  ADCR_SETUP_BURST | SEL_AD0; //Setup ADC Block
</code></pre>
<p>Note that in this case we can select multiple channels for conversion when setting up AD0CR. START bits are not applicable here since the conversions starts as soon we setup AD0CR register.</p>
<h4>2B. Fetching the conversion result in Burst mode :</h4>
<p>In Burst mode we use an ISR which triggers at the completion of a conversion in any one of the channel. Now, we just need to find the Channel for which the conversion was done. For this we fetch the channel number from ADGDR which also stores the conversion result. Bits [26:24] in ADGDR contain the channel number. Hence, we shift it 24 places and use a 3-bit mask value of 0x7 as shown below:</p>
<pre><code class="language-cpp">
unsigned long AD_GDR_Read = LPC_ADC->GDR;
int channel = (AD_GDR_Read>>24) & 0x7; //Extract Channel Number
</code></pre>
<p>After knowing the Channel number, we have 2 options to fetch the conversion result from. Either we can fetch it from ADGDR or from ADDRx of the corresponding channel. Lets use ADGDR for extracting the conversion result as follows:</p>
<pre><code class="language-cpp">
int currentResult = (AD_GDR_Read>>6) & 0x3FF; //Extract Conversion Result
</code></pre>
<div class="highlight">
<h4>Selecting AD Alternate function using IOCON (LPC_IOCON)</h4>
<p>To select AD0 function for pin <span class="doc_ref">PIO0_11</span> we just need to set FUNC bits[2:0] to 0x2 and set the ADMODE bit[7] to 0. In latest(current) versions of CMSIS library the member <span class="code_ref">R_PIOO_11</span> of <span class="code_ref">LPC_IOCON</span> is used as <span class="code_var">LPC_IOCON->R_PIO0_11 = 0x2;</span> but in older versions of CMSIS (used by CoIDE[as of now]) <span class="code_ref">R_PIO0_11</span> was defined as <span class="code_ref">JTAG_TDI_PIO0_11</span>. Hence in this case you will have to use <span class="code_var">LPC_IOCON->JTAG_TDI_PIO0_11 = 0x2;</span>. Newer versions of CMSIS included in LPCXpresso and MCUXpresso support both of them but KEIL doen't support <span class="code_ref">LPC_IOCON->JTAG_TDI_PIO0_11</span>. So just keep this in mind while programming in KEIL or CoIDE.</div>
<h2 class="shead" id="ADC_Examples">ARM Cortex-M3 LPC1343 ADC Example</h2>
<p>Note that in this case no input protection nor filtering was required. But, when Interfacing external analog signals it is recommended to use some form of input protection.</p>
<h4 id="Example_1">Interfacing Potentiometer using ADC on LPC134x</h4>
<p>This example performs Analog to Digital conversion in Software Controlled Mode. Here we use PIO0_11(P0.11) as analog input for measuring the voltage. PIO0_11 corresponds to Channel 0 of ADC i.e. AD0. For testing I had used a 10K potentiometer for ADC Interfacing and connected the middle leg of POT to PIO0_11 of my LPC1343 development board. You can also use a 5K potentiometer for this ADC Example. PIO0_11 is marked as AD0 on LPCXpresso board. Schematic for this example is as shown below:</p>
<p><img fetchpriority="high" decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/lpc1343-tutorial/lpc134x_adc_schematic.png" width="375" height="355" alt="Schematic for ADC interfacing on LPC134x" /></p>
<p><strong>Source Code :</strong></p>
<pre><code class="language-cpp">
/*(C) Umang Gajera - www.ocfreaks.com
LPC1343 ADC Interfacing Example 1 Source Code for MCUXpresso
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
License : GPL.*/

#include &lt;lpc17xx.h&gt;
#include &lt;stdio.h&gt;
#include "ocf_LPC134x_lib.h" //contains code for UART, Timer & to retarget printf().

#define VREF       3.3 //Reference Voltage at VREFP pin, given VREFN = 0V(GND)
#define ADC_CLK_EN (1<<13) //Enable ADC clock
#define SEL_AD0    (1<<0) //Select Channel AD0
#define CLKDIV     15 // ADC clock-divider (ADC_CLOCK=PCLK/CLKDIV+1), yields 4.5Mhz ADC clock
#define ADC_PWRUP  (~(1<<4)) //setting it to 0 will power it up
#define START_CNV  (1<<24) //001 for starting the conversion immediately
#define ADC_DONE   (1U<<31) //define it as unsigned value or compiler will throw warning
#define ADCR_SETUP_SCM (CLKDIV<<8)

int main(void)
{
	//SystemInit(); //Gets called by Startup code, sets CCLK=100Mhz, PCLK=25Mhz
	initUART(); //Initialize UART for printf()
	initTimer0(); //For delayMS()

	LPC_SYSCON->PDRUNCFG &= ADC_PWRUP; //Power-up ADC Block
	LPC_SYSCON->SYSAHBCLKCTRL |= ADC_CLK_EN; //Enable ADC clock
	LPC_ADC->CR =  ADCR_SETUP_SCM | SEL_AD0; //Setup ADC Block

	/* Now select AD0 function and set ADMODE=0 for PIO0_11(P0.11) */
	LPC_IOCON->R_PIO0_11 = 0x2; //Use this for KEIL and LPCXpresso/MCUXpresso - check tutorial for more
	//LPC_IOCON->JTAG_TDI_PIO0_11 = 0x2; //Older version of CMSIS uses this. Uncomment this for CoIDE.

	unsigned int result = 0;
	float voltage = 0;

	printf("OCFreaks.com LPC134x ADC Tutorial Example 1.\nSoftware Controlled ADC Mode on AD0 Channel.\n");
	while(1)
	{
		LPC_ADC->CR |= START_CNV; //Start new Conversion
		while((LPC_ADC->DR0 & ADC_DONE) == 0); //Wait until conversion is finished
		
		result = (LPC_ADC->DR0>>6) & 0x3FF; //10 bit Mask to extract result
		voltage = ((float)result * VREF) / 1024;
		
		printf("AD0 = %dmV\n" , (int)(voltage*1000)); //Print millivolts
		delayMS(500); //Slowing down Updates to 2 Updates per second
	}

	//return 0; //This won't execute
}
</code></pre>
<div class="special sp_blue noteinfo"><span class="code_var">ocf_lpc134x_lib.c</span> header used in project also contains code for <strong>retargeting printf()</strong> over UART for LPCXpresso/MCUXpresso. The project for CoIDE contains separate printf.c to retarget printf() using UART.</div>
<div class="highlight">
<p><strong>MCUXpresso Project for Example given above is on GitHub @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/ADC/Example_1" target="_blank">LPC134x ADC Interfacing Example 1</a> [Successfully tested on MCUXpresso v10.0.2], <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/ADC" target="_blank">Download Project Workspace Zip</a></p>
<p><strong>CoIDE Project on GitHub</strong> @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/ADC/Example_1" target="_blank">LPC134x ADC Interfacing Example 1</a> [Successfully tested on CooCox CoIDE v1.7.8], <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/ADC/Example_1" target="_blank">Download Project Zip</a>
</div>
<h4 id="Example_2">LPC1343 ADC Interrupt Example</h2>
<p>Now, lets cover an example using Hardware controlled mode or Burst mode using ADC Interrupt. In this mode we will have to use ADC interrupt since the ADC block will scan the selected channels and generated interrupt when a conversion gets finished on a particular channel. It scans the channels in round-robin fashion.</p>
<p>In this example too, we will use PIO0_11(P0.11) for measuring the voltage. The connections are same as given in example 1. The ADC ISR <span class="code_var">ADC_IRQHandler()</span> gets called everytime conversion is finished on selected channel. </p>
<p><strong>Source Code:</strong></p>
<pre><code class="language-cpp">
/*(C) Umang Gajera - www.ocfreaks.com
LPC1343 ADC Interrupt Example Source Code for MCUXpresso
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
License : GPL.*/

#include &lt;lpc17xx.h&gt;
#include &lt;stdio.h&gt;
#include "ocf_LPC134x_lib.h" //contains code for UART, Timer & to retarget printf().

#define VREF       3.3 //Reference Voltage at VREFP pin, given VREFN = 0V(GND)
#define ADC_CLK_EN (1<<13) //Enable ADC clock
#define SEL_AD0    (1<<0) //Select Channel AD0
#define CLKDIV     15 // ADC clock-divider (ADC_CLOCK=PCLK/CLKDIV+1), yields 4.5Mhz ADC clock
#define ADC_PWRUP  (~(1<<4)) //setting it to 0 will power it up
#define START_CNV  (1<<24) //001 for starting the conversion immediately
#define ADC_DONE   (1U<<31) //define it as unsigned value or compiler will throw warning
#define ADC_BURST  (1<<16) //Enable burst(hardware) mode
#define ADCR_SETUP_BURST ((CLKDIV<<8) | ADC_BURST)

int AD0Result = 0;

int main(void)
{
	//SystemInit(); //Gets called by Startup code, sets CCLK=100Mhz, PCLK=25Mhz
	initUART(); //Initialize UART for printf()
	initTimer0(); //For delayMS()

	LPC_SYSCON->PDRUNCFG &= ADC_PWRUP; //Power-up ADC Block
	LPC_SYSCON->SYSAHBCLKCTRL |= ADC_CLK_EN; //Enable ADC clock
	LPC_ADC->CR =  ADCR_SETUP_BURST | SEL_AD0; //Setup ADC Block

	/* Now select AD0 function and set ADMODE=0 for PIO0_11(P0.11) */
	LPC_IOCON->R_PIO0_11 = 0x2; //Use this for KEIL and LPCXpresso/MCUXpresso - check tutorial for more
	//LPC_IOCON->JTAG_TDI_PIO0_11 = 0x2; //Older version of CMSIS uses this. Uncomment this for CoIDE.

	LPC_ADC->INTEN = SEL_AD0; //Enable AD0 Interrupt, set ADGINTEN to 0
	NVIC_EnableIRQ(ADC_IRQn); //Enable ADC IRQ
	float voltage = 0;

	printf("OCFreaks.com LPC134x ADC Interrupt Tutorial Example.\n");
	printf("BURST/Hardware-Controlled ADC Mode on AD0 Channel.\n");
	while(1)
	{
		voltage = ((float)AD0Result * VREF) / 1024;
		printf("AD0 = %dmV\n" , (int)(voltage*1000)); //Print millivolts
		delayMS(500); //Slowing down Updates to 2 Updates per second
	}
	//return 0; //This won't execute
}

void ADC_IRQHandler(void)
{
	unsigned long ADC_GDR_Read = LPC_ADC->GDR;
	int channel = (ADC_GDR_Read>>24) & 0x7; //Extract Channel Number
	int currentResult = (ADC_GDR_Read>>6) & 0x3FF; //Extract Conversion Result

	if(channel == 0)
	{
		AD0Result = LPC_ADC->DR0; //Dummy read to Clear Done bit
		AD0Result = currentResult;
	}
}
</code></pre>
<div class="highlight">
<p><strong>MCUXpresso Project for Example given above is on GitHub @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/ADC/Example_2" target="_blank">LPC134x ADC Interrupt Example</a> [Successfully tested on MCUXpresso v10.0.2], <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/ADC" target="_blank">Download Project Workspace Zip</a></p>
<p><strong>CoIDE Project on GitHub</strong> @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/ADC/Example_2" target="_blank">LPC134x ADC Interrupt Example</a> [Successfully tested on CooCox CoIDE v1.7.8], <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/ADC/Example_2" target="_blank">Download Project Zip</a>
</div>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-adc-programming-tutorial/">LPC1343 ADC Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.ocfreaks.com/lpc1343-adc-programming-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3009</post-id>	</item>
		<item>
		<title>LPC1343 UART Programming Tutorial</title>
		<link>https://www.ocfreaks.com/lpc1343-uart-programming-tutorial/</link>
					<comments>https://www.ocfreaks.com/lpc1343-uart-programming-tutorial/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Umang Gajera]]></dc:creator>
		<pubDate>Wed, 15 Nov 2017 12:31:02 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[lpc1343]]></category>
		<guid isPermaLink="false">http://www.ocfreaks.com/?p=2993</guid>

					<description><![CDATA[<p>In this tutorial, I will be discussing basic UART (SERIAL) programming tutorial for ARM Cortex-M0 LPC1343 microcontroller.  We will also go through two LPC1343 UART examples.</p>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-uart-programming-tutorial/">LPC1343 UART Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="introleft">In this tutorial, I will be discussing basic UART(SERIAL) programming tutorial for ARM Cortex-M0 LPC1343. If you are new to UART, you can go through the basic UART tutorial which I&#8217;ve posted @ <a href="https://www.ocfreaks.com/uart-tutorial-basics/">Basic Uart Tutorial</a>. This tutorial is also applicable to MCUs of same family (LPC13xx)</p>
<div class="toc_container">
<span class="toc_title">Table of Contents</span></p>
<div class="toc">
<ol class="toc_list">
<li class="toc_text"><a href="#UART_Block"><span>ARM Cortex-M LPC1343 UART Block</span></a></li>
<li class="toc_text"><a href="#UART_Registers"><span>LPC1343 UART Registers</span></a></li>
<li class="toc_text"><a href="#Baud_Calc"><span>UART Baud Rate Calculation</span></a></li>
<li class="toc_text"><a href="#Config_Init"><span>How to Configure UART in LPC134x</span></a></li>
<li class="toc_text"><a href="#UART_Connections"><span>Connections between MCU and PC</span></a></li>
<li class="toc_text"><a href="#UART_Examples"><span>LPC1343 UART Examples</span></a></li>
<ol class="toc_list">
<li class="toc_text"><a href="#Example_1"><span>Hello World using UART Example</span></a></li>
<li class="toc_text"><a href="#Example_2"><span>Echo data in Terminal</span></a></li>
</ol>
</ol>
</div>
</div>
<h2 class="shead" id="UART_Block">ARM Cortex-M0 LPC1343 UART Block</h2>
<p>ARM Cortex-M0 LPC134x micro-controllers have only 1 UART block. UART block takes it input clock as CCLK since for LPC134x PCLK=CCLK.<strong> By default, after reset the input clock for UART is disabled. Hence to use it, we need to enable its input clock. For LPC1311/13/42/43 part numbers the TxD and RxD pins must configured using IOCON register before enabling the UART clock.</strong> This <strong>sequence</strong> is not mandatory for LPC1311/01 and LPC1313/01. Since we will be using LPC1343 MCU, we will have to use the clock enable sequence for UART examples given in the Examples section. Please check the user-manual to verify if the sequence is applicable for your LPC13xx device. Pin mapping for TXD and RXD pins is as given below:</p>
<table class="ocf-table">
<tr>
<th>Pins:</th>
<th>RXD</th>
<th>TXD</th>
</tr>
<tr>
<td>UART0/UART</td>
<td>PIO1_6</td>
<td>PIO1_7</td>
</tr>
<tr>
<td>IOCON</td>
<td>LPC_IOCON->PIO1_6</td>
<td>LPC_IOCON->PIO1_7</td>
</tr>
</table>
<p  style="margin-bottom:0px;">The UART block internally has a 16-byte FIFO (First In First Out) structure to hold data. Each byte in this FIFO represents a character which was sent or received <strong>in order</strong>. It also contains two registers each, for data access and assembly as given below:</p>
<ul>
<li><strong>Tx has THR(Transmit Holding Register) and TSR(Transmit Shift Register)</strong> &#8211; When we write Data to be sent into THR it is then transferred to TSR which assembles the data to be transmitted via Tx Pin.</li>
<li><strong>Similarly Rx has RSR(Receive Shift Register) and RBR(Receive Buffer Register)</strong> &#8211; When a valid data is Received at Rx Pin it is first assembled in RSR and then passed in to Rx FIFO which can be then accessed via RBR.</li>
</ul>
<div class="special sp_red noteinfo"> UART Pins on LPC134x are 5V tolerant. But I would recommend using 3.3v for UART communication. Hence, if you have RS232 to serial TTL module make sure it has MAX3232 =OR= if you are using FTDI&#8217;s FT232R based USB to serial TTL module make sure it is configured for 3.3v I/O.</div>
<h2 class="shead" id="UART_Registers">LPC1343 UART Registers</h2>
<p>Before we can do any UART/Serial communication, first we need to configure and initialize the UART block in LPC134x microcontroller. But before doing that, lets go through some of the important registers used in LPC134x UART programming:</p>
<div class="highlight">
<h4><strong>Data Related Registers </strong></h4>
<p><strong>1) RBR &#8211; Receiver Buffer Register:</strong> Bits[7:0] contains the top most BYTE in the Rx FIFO i.e the oldest received data in FIFO. Before reading from RBR, the DLAB(Divisor Latch Access) bit in U0LCR register must be 0. As mentioned in user manual &#8220;The right approach for fetching the valid pair of received byte and its status bits is first to read the content of the U0LSR register, and then to read a byte from the RBR&#8221;.</p>
<p><strong>2) THR &#8211; Transmit Holding Register:</strong> Bits[7:0] contains the top most BYTE in Tx FIFO and in this case its the newest(latest) transmitted data. DLAB must be 0 to access THR for write operation.</p>
<h4><strong> Baud Rate Setup related registers </strong></h4>
<p><strong>1) DLL and DLM &#8211; Divisor Latch registers:</strong> Both of them hold 8-bit values. These registers together form a 16-bit divisor value which is used in baud-rate generation. DLM holds the upper 8-bits(DLMSB) and DLL holds the lower 8-bits(DLLSB) and the formation is &#8220;<strong>[DLM:DLL]</strong>&#8220;. Since these form a divisor value and division by zero is invalid, the starting value for DLL is 0x01 (and not 0x00). <strong>Please keep this in mind while doing baud-rate calculations. In order to access and use these registers properly, DLAB must be first set to 1</strong>. </p>
<p><strong>2) FDR &#8211; Fractional Divider Register :</strong> It is used to define the prescale value for baud-rate generation. This register actually holds to different 4-bit values (a divisor and a multiplier) for prescaling which are:</p>
<ol>
<li><strong>Bit [3 to 0] &#8211; DIVADDVAL:</strong> This is the divisor value. If this value if 0 then fractional baud rate generator wont have any effect on Uart Baud rate.</li>
<li><strong>Bit [7 to 4] &#8211; MULVAL:</strong> This is the multiplier value. Even if fractional baud rate generator is not used the value in this register must be >= 1.</li>
<li>Other Bits reserved.</li>
</ol>
<p>Remark from User-manual:&#8221; <strong>If the fractional divider is active (DIVADDVAL > 0) and DLM = 0, the value of the DLL register must be 3 or greater!</strong>&#8221;</p>
<h4><strong>Control and Status Registers</strong></h4>
<p><strong>1) UxFCR &#8211; FIFO Control Register: </strong>Used to control Rx/Tx FIFO operations.</p>
<ol>
<li><strong>Bit 0 &#8211; FIFO Enable:</strong> 1 to Enable both Rx and Tx FIFOs and 0 to disable.</li>
<li><strong>Bit 1 &#8211; Rx FIFO Reset:</strong> Writing a 1 will clear and reset Rx FIFO.</li>
<li><strong>Bit 2 &#8211; Tx FIFO Reset:</strong> Writing a 1 will clear and reset Tx FIFO.</li>
<li><strong>Bits [7 to 6]</strong> &#8211; Rx Trigger Level:</strong> Used to determine that how many Rx FIFO characters must be written before an interrupt is activated. Refer User Manual for information.</li>
<li>Others bits are reserved.</li>
</ol>
<p><strong>2) LCR &#8211; Line Control Register :</strong> Used to configure the UART block (i.e the data format used in transmission).</p>
<ol>
<li><strong>Bit [1 to 0] &#8211; Word Length Select:</strong> Used to select the length of an individual data chunk. [00] for 5 bit character length. Similarly [01] , [10] , [11] for 6 , 7 , 8 bit character lengths respectively.</li>
<li><strong>Bit 2 &#8211; Stop bit select:</strong>  0 for using 1 stop bit and 1 for using 2 stop bits.</li>
<li><strong>Bit 3 &#8211; Parity Enable:</strong> 0 to disabled Parity generation &#038; checking and 1 to enable it.</li>
<li><strong>Bit [5 to 4] &#8211; Parity Select:</strong> [00] to Odd-parity , [01] for Even-parity , [10] for forced &#8220;1&#8221;(Mark) parity  and [11] for forced &#8220;0&#8221;(Space) parity.</li>
<li><strong>Bit 6 &#8211; Break Control:</strong> 0 to disable break transmission and 1 to enable it. TxD pin will be forced to logic 0 when this bit is 1!</li>
<li><strong>Bit 7 &#8211; Divisor Latch Access bit:</strong> 0 to disable access to divisor latches and 1 to enable access.</li>
</ol>
<p><strong>3) LSR &#8211; Line Status Register:</strong> used to read the status of Rx and Tx blocks.</p>
<ol>
<li><strong>Bit 0 &#8211; Receiver Data Ready(RDR):</strong> 0 = RBR is empty(i.e Rx FIFO is empty) and 1 means RBR contains valid data.</li>
<li><strong>Bit 1 &#8211; Overrun Error(OE):</strong> 0 = Overrun hasn&#8217;t occurred and 1 = Overrun has occurred. (<strong>Note:</strong> <em>Reading LSR clears this bit</em>)</li>
<li><strong>Bit 2 &#8211; Parity Error(PE):</strong> 0 = no parity error, 1 = parity error. (Note: Reading LSR clears this bit)</li>
<li><strong>Bit 3 &#8211; Framing Error(FE):</strong> 0 = no framing error, 1 = framing error detected. (<strong>Note:</strong> Reading LSR clears this bit)</li>
<li><strong>Bit 4 &#8211; Break Interrupt:</strong> 0 = no Break Interrupt occurs and 1 = Break Interrupt has occurred. (<strong>Note:</strong> Reading LSR clears this bit)</li>
<li><strong>Bit 5 &#8211; Transmit Holding Register Empty(THRE):</strong> 0 = THR contains valid data and 1 means its empty.</li>
<li><strong>Bit 6 &#8211; Transmitter Empty (TEMT):</strong> 0 = THR and/or RSR contains valid data, 1 = both THR and UxRSR are empty.</li>
<li><strong>Bit 7 &#8211; Error in RX FIFO(RXFE) :</strong> 0 = RBR has no Rx Errors or Rx FIFO is disabled(i.e 0th bit in FCR is 0), 1 = RBR has at-least one error. (<strong>Note:</strong> This bit is cleared only if LSR is read and there are no other subsequent errors in Rx FIFO, else this bit will stay 1)</li>
</ol>
<p><strong>4) TER &#8211; Transmit Enable Register : </strong>This register is used to enable UART transmission. When bit-7 (i.e TXEN) is set to 1 Tx block will be enabled and will keep on transmitting data as soon as its ready. If bit-7 is set to 0 then Tx will stop transmission. Other bits are reserved.</p>
<h4><strong> Interrupt Related Registers</strong></h4>
<p><strong>1) IER &#8211; Interrupt Enable Register:</strong> Set a bit to 0 to disable and 1 to enable the corresponding interrupt. Other bits are reserved.</p>
<ol>
<li><strong>Bit 0</strong> &#8211; RBR Interrupt Enable </li>
<li><strong>Bit 1 </strong>&#8211; THRE Interrupt Enable</li>
<li><strong>Bit 2</strong> &#8211; RX Line Status Interrupt Enable</li>
<li><strong>Bit 8</strong> &#8211; ATEOInt (End of Auto Baud Interrupt) Enable</li>
<li><strong>Bit 9</strong> &#8211; ATBOInt (Auto Baud Time-Out Interrupt) Enable </li>
</ol>
<p><strong>2) IIR &#8211; Interrupt Identification Register:</strong> This register is used to get the status code which give the priority along with sourcing of a pending interrupt. Refer User Manual(Rev 5) Pg. 187 Section 12.6.5 for more information.
</div>
<h2 class="shead" id="Baud_Calc">LPC134x UART Baud Rate Calculations</h2>
<div class="special sp_blue notestar">
<h4>The main formula for calculating baud rate is given as: </h4>
<div class="equation" style="font-size:14px;">Baud</sub> =</p>
<div class="fraction"><span class="fup">UART_PCLK in Hertz</span><span class="bar">/</span><span class="fdn">16 x (256xDLM + DLL) x (1 + DIVADDVAL/MULVAL)</span></div>
</div>
<p>Where DIVADDVAL &#038; MULVAL are part of &#8220;Fractional Rate Divider&#8221; or &#8220;Baud-Prescaler&#8221; which is used in Baud-Rate generation. This &#8220;Fractional Divider&#8221; is only active when DIVADDVAL > 0. This formula is pretty common for LPC ARM micro-controllers.</p>
<p><strong>which can be further simplified to :</strong></p>
<div class="equation" style="font-size:14px;">Baud</sub> =</p>
<div class="fraction"><span class="fup">MULVAL</span><span class="bar">/</span><span class="fdn">MULVAL + DIVADDVAL</span></div>
<p>X</p>
<div class="fraction"><span class="fup">UART_PCLK in Hertz</span><span class="bar">/</span><span class="fdn">16 x (256xDLM + DLL)</span></div>
</div>
<p><strong></p>
<p style="margin-bottom:0px">with following conditions strictly applied:</p>
<ul>
<li>0 < MULVAL <= 15 </li>
<li>0 <= DIVADDVAL <= 14 {if DIVADDVAL > 0 &#038; DLM = 0 then, DLL must be >= 3} </li>
<li>DIVADDVAL < MULVAL </li>
</ul>
<p></strong></p>
<p>Where UART_PCLK is the UART Peripheral Clock (derived from CCLK using UARTCLKDIV register) value in Hz, DLM and DLL are the divisor registers which we saw earlier and finally DIVADDVAL and MULVAL are part of the Fractional baudrate generator register.</p>
<p>As it can been seen this formula has 2 prominent parts which are: A <strong>Base value</strong> and a <strong>Fraction Part(Prescaler) </strong> i.e:</p>
<div class="equation">BaudRate = [ Fraction Part (Prescaler) ] x [ Base ]</div>
<p>This Fraction Part i.e. the Fractional Divider or the &#8220;Baud Rate Prescaler&#8221; can be used to scale down or keep the base value as it is (when disabled). Hence, its very useful for fine-tuning and getting the baudrate as accurate as possible.  </p>
</div>
<div class="special sp_red notestar"> <strong>Note</strong>: In real world there are very less chances that you will get the actual baudrate same as the desired baudrate. In most cases the actual baudrate will drift a little above or below the desired baud and also, as the desired baudrate increases this drift or error will also increase &#8211; this is because of the equation itself and the limitations on MULVAL , DIVADDVAL! For e.g. if the desired baud rate is 115200 and depending on the variables you may get a baud rate like 114100, 115690, 116100 .. and so on. But in most cases it will work as required if the error is not significant. A small amount of error in actual baudrate is generally tolerable in most systems which must be <strong><1.1% (relative error)</strong>.</div>
<p><strong>Now we know the formula, how do we actually start ?</strong></p>
<h4>1) The Dirty and Simplest Method: </h4>
<p>The quickest and also the dirtiest(accuracy wise) method without using any algorithm or fine-tuning is to set DLM=0 and disable the Fractional Divider(i.e DIVADDVAL=0). In this case MULVAL=1 and DIVADDVAL=0 which makes the Fraction Part(FP) = 1. Now we are left with only 1 unknown in the equation which is DLL and hence we simplify the equation and solve for UxDLL.</p>
<div class="equation">DLL</sub> =</p>
<div class="fraction"><span class="fup">UART_PCLK in Hertz</span><span class="bar">/</span><span class="fdn">16 x Desired-BaudRate</span></div>
</div>
<p>In my opinion, if possible, you must stay away from above method as it works only for particular bauds &#038; specific PCLK value and moreover computed DLL might get out of range i.e. > 255 in which case you have to start increasing DLM and recompute a new value for DLL. This method works for 115200 desired baud when UART_PCLK = 72Mhz, 48Mhz and 24Mhz.</p>
<h4>2) A better Method/Algorithm (Recommended): </h4>
<p>In these method we again start with DLM=0 , DIVADDVAL=0(i.e. Fractional divider disabled) and MULVAL=1 and get an initial value for DLM. If you are lucky you will get a very close baudrate to the desired one. If not then we perform some fine-tuning using DLM, MULVAL and DIVADDVAL and get a new value for DLM. The Algorithm which I have given below is a basic one suitable for beginners. A more invloved Iterative Algorithm is given on Page 202(Rev 5) under section 12.6.15.1 of the user manual.</p>
<p>When using 72Mhz clock we get DLL = 39.06 with the 1st method, hence we can use DLL = 39 since DLL must be an integer to get Actual Baud = 115384.6(~115384) with an relative error of 0.16% only. Similary when UART_PCLK = 48Mhz we can use DLL = 26 for Baud mentioned above. In both cases we were lucky to get a DLL very close to an integer, but not when we use a clock of 12.5Mhz or change the desired baud to something like 9600. </p>
<div class="highlight">
<h4>Example: UART_PCLK = CCLK = 72 Mhz and Required Baud Rate is 9600.</h4>
<p>Lets start with<strong> DLM = 0 , DIVADDVAL = 0 and MULVAL = 1<br />
We have UART_PCLK = CCLK = 72Mhz = 72 x 10<sup>6</sup> Hz</strong></p>
<p>So the equation now gets simplified and we can find DLL.</p>
<p>We get <strong>DLL = 468.75</strong>, which is out of range since DLL must be < 255 as it uses only 8-bits. To bring DLL in range lets use a non-zero DLM value in which case our equation becomes,



<div class="equation" style="font-size:14px;">256xDLM + DLL</sub> =</p>
<div class="fraction"><span class="fup">UART_PCLK in Hertz</span><span class="bar">/</span><span class="fdn">16 x Desired-BaudRate</span></div>
</div>
<p style="margin-bottom:15px">Now using DLM=1, we get DLL = 212.75 i.e. = 213 when rounded. With <strong>DLL = 213 &#038; DLM = 1</strong> our actual baud rate will be <strong>= 9594.8</strong> with a error of 5.2(magnitude) which gives a relative error of <strong>0.05%</strong>. Hence, we can use these settings since error is within specification. But if this error would have been larger we would have used the Fraction Part as follows:</p>
<ul>
<li>Choose DLL(&#038; DLM if requried) which gives a positive error (i.e. Actual Baud-rate > Desired Baud-Rate, given DLL is >= 3 if DLM = 0) so we can scale it down using Fractional Divider.</li>
<li>Calculate Required Fraction Part(FP) value given by:<br />
	<strong>FP<sub>required</sub> = [Desired Baud / Actual Baud Rate]</strong></li>
<li>Choose MULVAL and DIVADDVAL so that the Fraction Part is as close to <strong>FP<sub>required</sub></strong></li>
<li>Most of the time this will give the actual baud-rate close to required with <1.1% relative error. If not try with different DLL (&#038; or DLM) and repeat.</li>
</ul>
</div>
<div class="special sp_cyan notestar"><strong>To sum it up, we saw the following usable settings:</p>
<p>115200 Baud @ 72Mhz UART_PLCK &#8211; Use: DLL=39, DLM=0, MULVAL=1, DIVADDVALL=0<br />
115200 Baud @ 48Mhz UART_PLCK &#8211; Use: DLL=26, DLM=0, MULVAL=1, DIVADDVALL=0<br />
9600 Baud   @ 72Mhz UART_PLCK &#8211; Use: DLL=213, DLM=1, MULVAL=1, DIVADDVALL=0<br />
</strong></div>
<div class="special sp_blue noteinfo"><strong>Note:</strong> Some of the standard Baud rates that can be used are: 2400, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, etc..  </div>
<h2 class="shead" id="Config_Init">How to Configure UART in LPC134x</h2>
<p>Once you know how UART/Serial communication works, configuring and initializing UART is pretty straight forward. In Source Code Examples for this tutorial we will use the following configuration:</p>
<ul>
<li>BaudRate = 115200 (with UART_PCLK=CCLK=72Mhz)</li>
<li>Data Length = 8 bits</li>
<li>No Parity Bit</li>
<li>and 1 Stop Bit</li>
</ul>
<p><strong>Note: Please make it sure that configuration is same on both the communicating ends.</strong></p>
<p>As seen in example above: in order to get ~115200 bauds at 72Mhz UART_PCLK we must use the following settings for baud generation :</p>
<div class="highlight">
<strong>U0DLL = 39 ; U0DLM = 0 ; MULVAL = 1 ; DIVADDVAL = 0</strong>
</div>
<p>Now, lets write a function &#8220;<strong>InitUART()</strong>&#8221; which we can use initialize and configure UART0:</p>
<pre><code class="language-cpp">
#define MULVAL      1
#define DIVADDVAL   0
#define Ux_FIFO_EN  (1<<0)
#define Rx_FIFO_RST (1<<1)
#define Tx_FIFO_RST (1<<2)
#define DLAB_BIT    (1<<7)
#define LINE_FEED   0x0A //LF, For Linux, MAC and Windows Terminals
#define CARRIAGE_RETURN 0x0D //CR, For Windows Terminals (CR+LF).

void initUART(void)
{
	/*Assuming CCLK=72Mhz!*/

	//UART CLOCK Enable Sequence Step 1 - Select TXD,RXD functions
	LPC_IOCON->PIO1_6 = 0x1; //Select RXD for PIO1_6
	LPC_IOCON->PIO1_7 = 0x1; //Select RXD for PIO2_6

	//UART CLOCK Enable Sequence Step 2 - Set Divider & Enable Clock
	LPC_SYSCON->UARTCLKDIV = 1; //Set Divider by 1, so UART_PCLK=CCLK
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);//Enable UART clock

	LPC_UART->LCR = 3 | DLAB_BIT ; /* 8 bits, no Parity, 1 Stop bit & DLAB set to 1  */
	LPC_UART->DLL = 39; /*As per our calculations*/
	LPC_UART->DLM = 0;

	//LPC_UART0->IER |= ..; //Edit this if want you to use UART interrupts
	LPC_UART->FCR |= Ux_FIFO_EN | Rx_FIFO_RST | Tx_FIFO_RST;
	LPC_UART->FDR = (MULVAL<<4) | DIVADDVAL; /* MULVAL=15(bits - 7:4) , DIVADDVAL=2(bits - 3:0)  */
	LPC_UART->LCR &= ~(DLAB_BIT);
	//Now since we have applied DLL and DLM we now lock or freeze those values by disabling DLAB i.e DLAB=0
	//Baud= ~115200. Now we can perform UART communication!
}
</code></pre>
<p>Once this is done you are now ready to transfer data using RBR and THR registers.</p>
<h2 class="shead" id="UART_Connections">Connections between MCU and PC or Laptop</h2>
<p>Here we can have 2 possible scenarios.</p>
<ol style="margin-bottom:0px;">
<li>Your PC/Laptop(older ones) already has a serial port. In this case you will need a RS232 to TTL converter.</li>
<li>Your PC/Laptop doesn&#8217;t have a serial port and you are using USB to Serial converter(FTDI ones, etc..).</li>
</ol>
<div class="highlight">If you are using a separate converter then in both cases the TTL side of the converter have to use a minimum of 3 pins for basic UART communication which are: TxD, RxD and GND. Connect your MCU RxD to TxD of converter and MCU TxD to RxD of converter. Finally connect GND on both sides. Make sure you module supports 3.3v voltage-levels.</div>
<p>Please refer to the connection diagrams &#038; terminal software configuration(and COM ports) as given in <a href="https://www.ocfreaks.com/uart-tutorial-basics/">Basic Uart Tutorial</a>.</p>
<p>Here is a configuration screenshot for  terminal software PuTTYtel which we will be using for examples :<br />
<img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/common/puttytel_serial_config.png" alt="PuTTYtel UART,Serial Config" width="452px" height="343px" /></p>
<p><strong>Note</strong>: You can get PuTTYtel from <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html">Here</a>. Direct download link: <a href="http://the.earth.li/~sgtatham/putty/latest/x86/puttytel.exe">Here</a>. You can also use other similar terminal software as well.</p>
<h2 class="shead" id="UART_Examples">LPC1343 UART Examples with Source Code</h2>
<p>Now its time to actually use UART in real life! Lets do some communication between your LPC134x MCU and PC/Laptop. The code is based on CMSIS which is the Base library for ARM Cortex Micrcontrollers.</p>
<h4 id="Example_1">Example 1: Hello World using UART Example</h4>
<p>This demo will print &#8220;Hello from LPC1343!&#8221; on a new line in Serial Terminal repeatedly. The code given below uses Carriage-Return + Line-Feed (i.e. CR+LF) as New-Line(Enter or &#8220;\n&#8221;) character. If you are using Terminal on Linux or MacOS for interfacing LPC134x then only use Line-Feed(LF) character for New-Line. The function <span class="code_var">uartWrite()</span> is used to transmit data one BYTE at a time. The output of this example is shown below:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/lpc1343-tutorial/lpc134x_uart_example1.png" width="533px" height="290px" alt="LPC1343 UART Example 1 output" /></p>
<p><strong>Source Code:</strong></p>
<pre><code class="language-cpp">
/*(C) Umang Gajera - www.ocfreaks.com
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
LPC1343 UART Example 1 Source Code.
License: GPL.*/

#include &lt;lpc13xx.h&gt;

#define THRE        (1<<5) //Transmit Holding Register Empty
#define MULVAL      1
#define DIVADDVAL   0
#define Ux_FIFO_EN  (1<<0)
#define Rx_FIFO_RST (1<<1)
#define Tx_FIFO_RST (1<<2)
#define DLAB_BIT    (1<<7)
#define LINE_FEED   0x0A //LF, For Linux, MAC and Windows Terminals
#define CARRIAGE_RETURN 0x0D //CR, For Windows Terminals (CR+LF).

void initUART(void);
void uartWrite(char data);

int main(void)
{
	//SystemInit(); //This already gets called by CMSIS Startup Code, sets CCLK=72Mhz
	char msg[] = { 'H','e','l','l','o',' ','f','r','o','m',' ','L','P','C','1','3','4','3','\0' };
	int count=0;

	initUART();

	while(1)
	{
		while( msg[count]!='\0' )
		{
			uartWrite(msg[count]);
			count++;
		}
		//Send NEW Line Character(s) i.e. "\n"
		uartWrite(CARRIAGE_RETURN); //Comment this for Linux or MacOS
		uartWrite(LINE_FEED); //Windows uses CR+LF for newline.
		count=0; // reset counter
	}
	//return 0; //This won't execute normally
}

void uartWrite(char txData)
{
	while(!(LPC_UART->LSR & THRE)); //wait until THR is empty
	//now we can write to Tx FIFO
	LPC_UART->THR = txData;
}

void initUART(void)
{
	/*Assuming CCLK=UART_PCLK=72Mhz!*/

	//UART CLOCK Enable Sequence Step 1 - Select TXD,RXD functions
	LPC_IOCON->PIO1_6 = 0x1; //Select RXD for PIO1_6
	LPC_IOCON->PIO1_7 = 0x1; //Select RXD for PIO2_6

	//UART CLOCK Enable Sequence Step 2 - Set Divider & Enable Clock
	LPC_SYSCON->UARTCLKDIV = 1; //Set Divider by 1, so UART_PCLK=CCLK
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);//Enable UART clock

	LPC_UART->LCR = 3 | DLAB_BIT ; /* 8 bits, no Parity, 1 Stop bit & DLAB set to 1  */
	LPC_UART->DLL = 39;
	LPC_UART->DLM = 0;

	LPC_UART->FCR |= Ux_FIFO_EN | Rx_FIFO_RST | Tx_FIFO_RST;
	LPC_UART->FDR = (MULVAL<<4) | DIVADDVAL; /* MULVAL=15(bits - 7:4) , DIVADDVAL=2(bits - 3:0)  */
	LPC_UART->LCR &= ~(DLAB_BIT);
	//Now since we have applied DLL and DLM we now lock or freeze those valuse by diabling DLAB i.e DLAB=0
	//Baud= ~115200. Now we can perform UART communication!
}
</code></pre>
<div class="highlight"><strong>CoIDE Project for Example #1 on GitHub @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/UART/Example_1/" target="_blank">LPC1343 UART Example 1</a> [Successfully tested on CoIDE v1.7.8]. <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/UART/Example_1/" target="_blank">Download Project Zip</a>. You can also download <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/UART/" target="_blank">MCUXpresso Workspace (Zipped) for both examples</a> on GitHub.</div>
<h4 id="Example_2">Example 2: Echo data in Terminal</h4>
<p>In this example you will see the characters that you type on your keyboard i.e. we echo back the characters(data) received by MCU. Serial Terminals only displays the character that it receives via serial Port. When you type a character it is directly sent to the other side via serial port. Hence, in order for us to see the character which we typed, we need to send back the same character. This is what the program below does. Whenever MCU receives a character from the RXD pin, it will send the same character back to PC via the TXD Pin and it gets displayed in Terminal. Here I&#8217;ve defined additional function <span class="code_var">uartRead()</span> which is used to read the recieved data one BYTE at a time.</p>
<p>LPC134x UART Example 2 output:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/lpc1343-tutorial/lpc134x_uart_example2.png" width="533px" height="242px" alt="LPC1343 UART Example 1 output" /></p>
<p><strong>Source code: </strong></p>
<pre><code class="language-cpp">
/*(C) Umang Gajera - www.ocfreaks.com
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
LPC1343 UART Example 2 Source Code.
License : GPL.*/

#include &lt;lpc13xx.h&gt;

#define RDR         (1<<0) //Receiver Data Ready
#define THRE        (1<<5) //Transmit Holding Register Empty
#define MULVAL      1
#define DIVADDVAL   0
#define Ux_FIFO_EN  (1<<0)
#define Rx_FIFO_RST (1<<1)
#define Tx_FIFO_RST (1<<2)
#define DLAB_BIT    (1<<7)
#define LINE_FEED   0x0A //LF, For Linux, MAC and Windows Terminals
#define CARRIAGE_RETURN 0x0D //CR, For Windows Terminals (CR+LF).
#define ENTER       CARRIAGE_RETURN //Ascii value/code for Enter is 0x0D i.e. CR

void initUART(void);
void uartWrite(char data);
char uartRead(void);

int main(void)
{
	initUART();
	char data = 0;

	while(1)
	{
		data = uartRead(); //Read Data from Rx
		if(data == ENTER || data == LINE_FEED) //Check if user pressed Enter key
		{
			//Send NEW Line Character(s) i.e. "\n"
			uartWrite(CARRIAGE_RETURN); //Comment this for Linux or MacOS
			uartWrite(LINE_FEED); //Windows uses CR+LF for newline.
		}
		else
		{
			uartWrite(data); //Tx Read Data back
		}
	}
	//return 0; //Normally this won't execute
}

char uartRead(void)
{
	while(!(LPC_UART->LSR & RDR)); //wait until data arrives in Rx FIFO
	return LPC_UART->RBR;
}

void uartWrite(char txData)
{
	while(!(LPC_UART->LSR & THRE)); //wait until THR is empty
	//now we can write to Tx FIFO
	LPC_UART->THR = txData;
}

void initUART(void)
{
	/*Assuming CCLK=UART_PCLK=72Mhz!*/

	//UART CLOCK Enable Sequence Step 1 - Select TXD,RXD functions
	LPC_IOCON->PIO1_6 = 0x1; //Select RXD for PIO1_6
	LPC_IOCON->PIO1_7 = 0x1; //Select RXD for PIO2_6

	//UART CLOCK Enable Sequence Step 2 - Set Divider & Enable Clock
	LPC_SYSCON->UARTCLKDIV = 1; //Set Divider by 1, so UART_PCLK=CCLK
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12);//Enable UART clock

	LPC_UART->LCR = 3 | DLAB_BIT ; /* 8 bits, no Parity, 1 Stop bit & DLAB set to 1  */
	LPC_UART->DLL = 39;
	LPC_UART->DLM = 0;

	LPC_UART->FCR |= Ux_FIFO_EN | Rx_FIFO_RST | Tx_FIFO_RST;
	LPC_UART->FDR = (MULVAL<<4) | DIVADDVAL; /* MULVAL=15(bits - 7:4) , DIVADDVAL=2(bits - 3:0)  */
	LPC_UART->LCR &= ~(DLAB_BIT);
	//Now since we have applied DLL and DLM we now lock or freeze those values by disabling DLAB i.e DLAB=0
	//Baud= ~115200. Now we can perform UART communication!
}
</code></pre>
<div class="highlight"><strong>CoIDE Project for Example #2 on GitHub @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/UART/Example_2/" target="_blank">LPC1343 UART Example 2</a> [Successfully tested on CoIDE v1.7.8]. <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/UART/Example_2/" target="_blank">Download Project Zip</a>. You can also download <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/UART/" target="_blank">MCUXpresso Workspace (Zipped) for both examples</a> on GitHub.</div>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-uart-programming-tutorial/">LPC1343 UART Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.ocfreaks.com/lpc1343-uart-programming-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2993</post-id>	</item>
		<item>
		<title>Function to calculate Prescaler value for LPC1114 &#038; LPC1343</title>
		<link>https://www.ocfreaks.com/function-calculate-prescaler-value-lpc1114-lpc1343/</link>
					<comments>https://www.ocfreaks.com/function-calculate-prescaler-value-lpc1114-lpc1343/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Umang Gajera]]></dc:creator>
		<pubDate>Mon, 06 Nov 2017 14:11:24 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[lpc1114]]></category>
		<category><![CDATA[lpc1343]]></category>
		<guid isPermaLink="false">http://www.ocfreaks.com/?p=2975</guid>

					<description><![CDATA[<p>Since ARM Cortex based LPC111x and LPC134x MCUs use CCLK as PCLK for Timer blocks its relatively easy to write a function which can compute required prescale value for a given resolution in micro-seconds or milli-seconds. In this tutorial we will define a function to calculate prescaler value for LPC1114 &#038; LPC1343</p>
<p>The post <a href="https://www.ocfreaks.com/function-calculate-prescaler-value-lpc1114-lpc1343/">Function to calculate Prescaler value for LPC1114 &#038; LPC1343</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In previous tutorials I had explained prescale calulations for <a href="https://www.ocfreaks.com/lpc1343-timer-programming-tutorial/#Prescaler_Calc">LPC1343</a> and <a href="https://www.ocfreaks.com/lpc1114-timer-programming-tutorial/#Prescaler_Calc">LPC1114</a>. Since ARM Cortex based LPC111x and LPC134x MCUs use CCLK as PCLK for Timer blocks its relatively easy to write a function which can compute required prescaler value for a given resolution in micro-seconds or milli-seconds. Given below, are two functions to find the prescale value &#8211; one that takes argument as Desired Timer Resolution in Milli-seconds viz. <span class="code_var">calcPrescaleMS(..)</span>, and one that takes the argument in Mirco-Seconds viz. <span class="code_var">calcPrescaleUS(..)</span>. The argument cannot be less than 1 since it is the minimum resolution required to find prescale, and we will limit it to a max value of 1000. Both functions will return 0 if argument is invalid. <span class="code_var">SystemCoreUpdate()</span> is a &#8216;system function&#8217;, defined in startup code, which updates <span class="code_var">SystemCoreClock</span> variable to current System AHB Clock(CCLK) frequency in Hz.</p>
<p>C++ Source Code for function definition:</p>
<pre><code class="language-cpp">
/*Find a prescale given Timer Resolution in Milli-Secs (ms) at CCLK*/
unsigned int calcPrescaleMS(unsigned short resMS) //Argument in ms
{
	if( resMS<1 || resMS>1000 ) return 0; //Accept between 1 and 1000ms only
	SystemCoreClockUpdate();
	float prescale = SystemCoreClock * ((float)resMS/1000);
	return ((unsigned int)prescale - 1);
}

/*Find a prescale given Timer Resolution in Micro-Secs (us) at CCLK*/
unsigned int calcPrescaleUS(unsigned short resUS) //Argument in us
{
	if( resUS<1 || resUS>1000 ) return 0; //Accept between 1 and 1000us only
	SystemCoreClockUpdate();
	float prescale = SystemCoreClock * ((float)resUS/1000000);
	return ((unsigned int)prescale - 1);
}
</code></pre>
<h4>Example Usage</h4>
<pre><code class="language-cpp">
//Get prescaler value for 1ms Resolution/Delay per TC increment
LPC_TMR32B0->PR = calcPrescaleMS(1);

//Find prescaler value for 10ms Resolution/Delay per TC increment
LPC_TMR32B0->PR = calcPrescaleMS(10);

//Use prescaler value for 1us Resolution/Delay per TC increment
LPC_TMR32B0->PR = calcPrescaleUS(1);

//Get prescaler value for 100us Resolution/Delay per TC increment
LPC_TMR32B0->PR = calcPrescaleUS(100);
</code></pre>
<p>The post <a href="https://www.ocfreaks.com/function-calculate-prescaler-value-lpc1114-lpc1343/">Function to calculate Prescaler value for LPC1114 &#038; LPC1343</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.ocfreaks.com/function-calculate-prescaler-value-lpc1114-lpc1343/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2975</post-id>	</item>
		<item>
		<title>LPC1343 Timer Programming Tutorial</title>
		<link>https://www.ocfreaks.com/lpc1343-timer-programming-tutorial/</link>
					<comments>https://www.ocfreaks.com/lpc1343-timer-programming-tutorial/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Umang Gajera]]></dc:creator>
		<pubDate>Sat, 28 Oct 2017 16:16:05 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[lpc1343]]></category>
		<guid isPermaLink="false">http://www.ocfreaks.com/?p=2970</guid>

					<description><![CDATA[<p>In this discussion we will go through ARM Cortex-M3 LPC1343 Timer Programming Tutorial. LPC1343 has two 16-bit Timers and two 32-bit Timers. Both of them are similar in operation except for the bit-size. We will be using 32-bit timers in this tutorial and is also applicable to similar MCUs like LPC1347.</p>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-timer-programming-tutorial/">LPC1343 Timer Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p class="introleft"><img decoding="async" style="margin-top:20px;"class="aligncenter" src="https://www.ocfreaks.com/imgs/lpc1343-tutorial/lpc134x_tmr_title.png" width="335px" height="140px" /></p>
<div class="toc_container">
<span class="toc_title">Table of Contents</span></p>
<div class="toc">
<ol class="toc_list">
<li class="toc_text"><a href="#Timer_Module"><span>Timer Module in LPC134x</span></a></li>
<li class="toc_text"><a href="#Timer_Registers"><span>LPC134x Timer Registers</span></a></li>
<li class="toc_text"><a href="#Configure_Timer"><span>Configuring Timers in LPC1343</span></a></li>
<ol class="toc_list">
<li class="toc_text"><a href="#Prescaler_Calc"><span>LPC134x Timer Prescaler Calculation</span></a></li>
</ol>
<li class="toc_text"><a href="#Examples"><span>LPC1343 Timer Examples</span></a></li>
<ol class="toc_list">
<li class="toc_text"><a href="#Example_1"><span>Blinky Example</span></a></li>
<li class="toc_text"><a href="#Example_2"><span>Match Output Example</span></a></li>
</ol>
</ol>
</div>
</div>
<p>In this discussion we will go through ARM Cortex-M3 LPC1343 Timer Tutorial. Previously we saw a blinky example using GPIO and hardcoded delays, now its time to improvise and use precise delay using timers. LPC1343 has two 16-bit Timers and two 32-bit Timers. Both of them are similar in operation except for the bit-size. We will be using 32-bit timers in this tutorial and is also applicable to similar MCUs like LPC1347.</p>
<h2 class="shead" id="Timer_Module">Timer Module in LPC134x</h2>
<p>Each Timer module in ARM Cortex-M3 LPC134x microcontroller has its own <strong>Timer Counter(TC)</strong> and <strong>Prescale Register(PR)</strong> associated with it. When a Timer is Reset and Enabled, the TC is set to 0 and incremented by 1 every <strong>&#8216;PR+1&#8217;</strong> clock cycles &#8211; where PR is the value stored in Prescale Register. When it reaches its maximum value it gets reset to 0 and hence restarts counting. Prescale Register is used to define the <strong>resolution</strong> of the timer. If <strong>PR is 0</strong> then TC is incremented every <strong>1 clock cycle of the peripheral clock</strong>. If <strong>PR=1</strong> then TC is incremented every <strong>2 clock cycles of peripheral clock and so on</strong>. By setting an appropriate value in PR we can make timer increment or count: every peripheral clock cycle or 1 microsecond or 1 millisecond or 1 second and so on.</p>
<h4>Match Register</h4>
<p>A Match Register is a Register which contains a specific value set by the user. When the Timer starts &#8211; every time after TC is incremented the value in TC is compared with match register. If it matches then it can Reset the Timer or can generate an interrupt as defined by the user. We are only concerned with match registers in this tutorial.</p>
<p><strong>Match Registers can be used to:</strong></p>
<ul>
<li>Stop Timer on Match(i.e when the value in count register is same as than in Match register) and trigger an optional interrupt.</li>
<li>Reset Timer on Match and trigger an optional interrupt.</li>
<li>To count continuously and trigger an interrupt on match.</li>
</ul>
<h4>External Match Output</h4>
<p>When a corresponding Match register(MRx) equals the Timer Counter(TC) the match output can be controlled using External Match Register(EMR) to: either toggle, go HIGH, go LOW or do nothing. This Match output is diverted to a physical pin on the MCU by selecting CT32Bx_MATn alternate function for the pin which supports it.</p>
<h4>Capture Register</h4>
<p>As the name suggests it is used to Capture Input signal. When a transition event occurs on a Capture pin , it can be used to copy the value of TC into any of the 4 Capture Register or to genreate an Interrupt. Hence these can be also used to demodulated PWM signals. We are not going to use them in this tutorial since we are only concerned with using Timer block as a &#8216;Timer&#8217;. We&#8217;ll see them in a later tutorial.</p>
<p>LPC1343 which is found on LPCXpresso Board has <strong>four Match Outputs</strong> and <strong>one Capture Input</strong>.</p>
<div class="special sp_blue noteinfo"><strong>Naming Conventions used in this Tutorial</strong>: <strong>CT32Bx</strong> and <strong>TMR32Bx</strong> both are same and refer to 32-Bit Timer &#8216;<strong>x</strong>&#8216;. E.g. CT32B0 and TMR32B0 refer to 32-bit Timer 0. <strong>CT32Bx_MATn</strong> refers to Match output &#8216;<strong>n</strong>&#8216; for 32bit Timer &#8216;<strong>x</strong>&#8216;. These are the naming conventions used in the Datasheet and User Manual of LPC13xx.</div>
<h2 class="shead" id="Timer_Registers">LPC134x Timer Registers</h2>
<p>We will be using CMSIS based <span class="code_var">lpc13xx.h</span> (ARM Cortex M3) header file for programming. In CMSIS, all the Registers used to program and use 32-bit timers are defined as members of structure(pointer) <span class="code_var">LPC_TMR32Bx</span> where x is the 32-bit Timer module 0 or 1. So for Timer0 we will use <span class="code_var">LPC_TMR32B0</span> and so on. Registers can be accessed by de-referencing the pointer using &#8220;->&#8221; operator. For, example we can access TCR of Timer0 block as <span class="code_var">LPC_TMR32B0->TCR</span>. Similary for 16-bit Timer block, the structure is defined as  <span class="code_var">LPC_TMR16Bx</span> where x is the 16-bit Timer module 0 or 1.</p>
<div class="highlight">
<strong>Now lets see some of the main 32-bit timer registers used in LPC1343 Timer Programming.</strong></p>
<p><strong>1) <span class="doc_ref">PR (LPC_TMR32Bx->PR)</span>: Prescale Register</strong> &#8211; Stores Prescale Value.</p>
<p><strong>2) <span class="doc_ref">PC (LPC_TMR32Bx->PC)</span>: Prescale Counter Register</strong> &#8211; This register increments on every PCLK(CCLK). This register controls the resolution of the timer. When PC reaches the value in PR , PC is reset back to 0 and Timer Counter is incremented by 1. Hence if PR=0 then Timer Counter Increments on every 1 PCLK. E.g. If PR=9 then Timer Counter Increments on every 10th cycle of PCLK. Hence by selecting an appropriate prescale value we can control the resolution of the timer. </p>
<p><strong>3) <span class="doc_ref">TC (LPC_TMR32Bx->TC)</span>: Timer Counter Register</strong> &#8211; This stores current Timer Counter Value. Timer Counter increments when PC reaches its maximum value as specified by PR. If timer is not reset explicitly(directly) or by using an interrupt then it will act as a free running counter which resets back to zero when it reaches its maximum value which is 0xFFFFFFFF.</p>
<p><strong>4) <span class="doc_ref">TCR (LPC_TMR32Bx->TCR)</span>: Timer Control Register</strong> &#8211; This register is used to enable , disable and reset TC. When bit0 is 1 timer is enabled and when 0 it is disabled. When bit1 is set to 1 TC and PC are set to zero together in sync on the next positive edge of PCLK. Rest of the bits of TCR are reserved.</p>
<p><strong>5) <span class="doc_ref">CTCR  (LPC_TMR32Bx->CTCR)</span>: Count Control register</strong> &#8211; It is used to select Timer/Counter Mode. When the value of the CTCR is set to 0x0 Timer Mode is selected.</p>
<p><strong>6) <span class="doc_ref">MCR (LPC_TMR32Bx->MCR)</span>: Match Control register</strong> &#8211; This register is used to control what operations can be done when the value in MR matches the value in TC. Bits 0,1,2 are for MR0 , Bits 3,4,5 for MR1 and so on.. The bit Mapping is as given below:</p>
<p><strong>For MR0:</strong></p>
<ul>
<li>Bit 0 : Interrupt on MR0 i.e. trigger an interrupt when MR0 matches TC. Interrupts are enabled when set to 1 and disabled when set to 0.</li>
<li>Bit 1 : Reset on MR0. When set to 1 , TC will be reset when it matched MR0. Disabled when set to 0.</li>
<li>Bit 2 : Stop on MR0. When set to 1 , TC &#038; PC will stop when MR0 matches TC.</li>
</ul>
<p>Similarly bits 3-5 , 6-8 , 9-11 are for MR1 , MR2 , MR3 respectively.</p>
<p><strong>7) <span class="doc_ref">IR (LPC_TMR32Bx->IR)</span>: Interrupt Register</strong> &#8211; It contains the interrupt flags for 4 match and 2 capture interrupts. Bit0 to bit3 are for MR0 to MR3 interrupts respectively. And similarly the next 2 for CR0 &#038; CR1 interrupts. when an interrupt is raised the corresponding bit in IR will be set to 1 and 0 otherwise. Writing a 1 to the corresponding bit location will reset the interrupt &#8211; which is used to acknowledge the completion of the corresponding ISR execution.</p>
<p><strong>8) <span class="doc_ref">EMR  (LPC_TMR32Bx->EMR)</span>: External Match Register</strong> &#8211; It provides both status and control of External Match Output Pins. First four bits are for EM0 to EM3. Next 8 bits are for EMC0 to EMC3 in pairs of 2.</p>
<ul>
<li>Bit 0 &#8211; EM0: External Match 0. When a match occurs between TC and MR0, depending on bits[5:4] i.e. EMC0 of this register, this bit can either toggle, go LOW, go HIGH, or do nothing. This bit is driven to MATx.0 where x=Timer number. </li>
<li>Similarly for Bits 1 (EM1), 2 (EM2) &#038; 3 (EM3).</li>
<li>Bits[5:4] &#8211; EMC0: External Match 0. The values in these bits select the functionality of EM0 as follows:
<ul style="margin-top:0px;">
<li>0x0 &#8211; Do nothing</li>
<li>0x1 &#8211; Clear the corresponding External Match output to 0 (MATx.m pin is LOW).</li>
<li>0x2 &#8211; Set the corresponding External Match output to 1 (MATx.m pin is HIGH).</li>
<li>0x3 &#8211; Toggle the corresponding External Match output.</li>
</ul>
</li>
<li>Similarly for Bits[7:6] &#8211; EMC1, Bits[9,8] &#8211; EMC2, Bits[11:10] &#8211; EMC3.</li>
</ul>
</div>
<h2 class="shead" id="Configure_Timer">Setting up &#038; configuring Timers in LPC1343</h2>
<p>To use timers we need to first configure them. We need to set appropriate values in <span class="doc_ref">CTCR</span>, <span class="doc_ref">IR</span>, <span class="doc_ref">PR</span> registers and reset <span class="doc_ref">PC</span>, <span class="doc_ref">TC</span> registers. Finally we assign <span class="doc_ref">TCR = 0x01</span> which enables the timer. </p>
<div class="highlight">I would recommend to use the following sequence for Setting up 32-bit Timers:</p>
<ol>
<li>Enable Clock Input for the Timer Block using <span class="code_var">LPC_SYSCON->SYSAHBCLKCTRL</span> register</li>
<li>Set appropriate value in <span class="code_var">LPC_TMR32Bx->CTCR</span></li>
<li>Define the Prescale value in <span class="code_var">LPC_TMR32Bx->PR</span></li>
<li>Set Value(s) in Match Register(s) if required</li>
<li>Set appropriate value in <span class="code_var">LPC_TMR32Bx->MCR</span> if using Match registers / Interrupts</li>
<li>Reset Timer using <span class="code_var">LPC_TMR32Bx->TCR</span> &#8211; Which resets PR and TC</li>
<li>Set <span class="code_var">LPC_TMR32Bx->TCR</span> to <span class="code_var">0x01</span> to Enable the Timer when required</li>
<li>Reset <span class="code_var">LPC_TMR32Bx->TCR</span> to <span class="code_var">0x00</span> to Disable the Timer when required</li>
</ol>
</div>
<p><strong>Selecting Match Outputs:</strong> Match outputs for Timer0(CT32B0) and Timer1(CT32B1) is available as an alternate function on pins given below. Match output function must be selected using <a href="https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/" target="_blank">IOCON registers</a> for the following pins:</p>
<ul style="margin-bottom:10px;">
<li>Timer0 MAT 0 (CT32B0_MAT0) &#8211; PIO1_6</li>
<li>Timer0 MAT 1 (CT32B0_MAT1) &#8211; PIO1_7</li>
<li>Timer0 MAT 2 (CT32B0_MAT2) &#8211; PIO0_1</li>
<li>Timer0 MAT 3 (CT32B0_MAT3) &#8211; PIO0_11 (R_PIO0_11)</li>
<li>Timer1 MAT 0 (CT32B1_MAT0) &#8211; PIO1_1 (R_PIO1_1)</li>
<li>Timer1 MAT 1 (CT32B1_MAT1) &#8211; PIO1_2 (R_PIO1_1)</li>
<li>Timer1 MAT 2 (CT32B1_MAT2) &#8211; PIO1_3 (SWDIO_PIO1_3)</li>
<li>Timer1 MAT 3 (CT32B1_MAT3) &#8211; PIO1_4</li>
</ul>
<p>The name inside brackets above represent actual member(IOCON register) names of <span class="code_var">LPC_IOCON</span> structure, if brackets are present. You can go through my previous <a href="https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/" target="_blank">tutorial on IOCON register</a> regarding its usage.</p>
<p><strong>Enabling System AHB Clock for Timer:</strong> The input clock for timers is from System AHB clock or simply the System Clock. The System Clock can be derived from the Main Clock using System AHB Clock Divider Register <span class="doc_ref">SYSAHBLKDIV</span>. System Clock for Peripherals like Timers needs to be enabled, before using them, by setting appropriate bits (1=enable, 0=disable) in System AHB Clock Control Register <span class="doc_ref">SYSAHBCLKCTRL</span> as given below:</p>
<ul>
<li>Bit 7 For 16-Bit Timer0 (CT16B0)</li>
<li>Bit 8 For 16-Bit Timer1 (CT16B1)</li>
<li>Bit 9 For 32-Bit Timer0 (CT32B0)</li>
<li>Bit 10 For 32-Bit Timer1 (CT32B1)</li>
</ul>
<div class="special sp_red noteinfo">Note: In LPC1343, the Timer module doesn&#8217;t have a dedicated input Clock Divider. The System Clock (CCLK) is directly given to Timer module. Hence for Timer module, <strong>PCLK=CCLK</strong>. Other Peripherals like UART and SPI have their own dividers for clock inputs which is derived directly from Main Clock (MCLK). The default System Clock configured by Startup Code is 72Mhz.</div>
<div class="special sp_blue notestar" id="Prescaler_Calc">
<h4>LPC1343 Timer Prescaler Calculations:</h4>
<p>The delay or time required for 1 clock cycle when PCLK/CCLK(System Clock) = &#8216;X&#8217; Mhz is given by:</p>
<div class="equation">T<sub>PCLK</sub> =</p>
<div class="fraction"><span class="fup">1</span><span class="bar">/</span><span class="fdn">PCLK<sub>Hz</sub></span></div>
<p>=</p>
<div class="fraction"><span class="fup">1</span><span class="bar">/</span><span class="fdn">X * 10<sup>6</sup></span></div>
<p>Seconds</p></div>
<p>It is also the maximum resolution Timer block can provide at a given PCLK(CCLK) frequency of X Mhz. The general formula for Timer resolution at X Mhz PCLK(CCLK) and a given value for prescale (PR) is as given below:</p>
<div class="equation">T<sub>RES</sub> =</p>
<div class="fraction"><span class="fup">PR+1</span><span class="bar">/</span><span class="fdn">PCLK<sub>Hz</sub></sup></span></div>
<p> =</p>
<div class="fraction"><span class="fup">PR+1</span><span class="bar">/</span><span class="fdn">X * 10<sup>6</sup></span></div>
<p>Seconds</p></div>
<p>Hence, we get the <strong>Formula for Prescaler (PR) for required Timer resolution (T<sub>RES</sub> in Secs)</strong> at given <strong>PCLK(in Hz)</strong> frequency as:</p>
<div class="equation">PR = (PCLK<sub>Hz</sub> * T<sub>RES</sub>) &#8211; 1</div>
<div class="equation">PR = ((X * 10<sup>6</sup>) * T<sub>RES</sub>) &#8211; 1</div>
<p>Note that here, the resolution is also the time delay required to increment TC by 1.</p>
<p>Hence, Prescaler value for 1 micro-second resolution/ 1us time delay at 72 Mhz PCLK(CCLK) is,</p>
<div class="equation">PR<sub>1us</sub> = (72Mhz * 1uS) -1 = (72*10<sup>6</sup> * 10<sup>-6</sup>) -1 = 71</div>
<p>Prescale for 1 mS (milli-second) resolution at 72Mhz PCLK(CCLK) is,</p>
<div class="equation">PR<sub>1ms</sub> = (72Mhz * 1ms) -1 = (72*10<sup>6</sup> * 10<sup>-3</sup>) -1 = 71999</div>
</div>
<h2 class="shead" id="Examples">LPC1343 Timer Examples with sample code</h2>
<h4 id="Example_1"> Example 1) &#8211; LPC134x Blinky Example using Timer &#038; GPIO</h4>
<p>Now lets write a C/C++ blinky program which flashes an LED every half a second. Since 0.5 second = 500 millisecond we will invoke timer delay function &#8216;delayMS&#8217; as <span class="code_var">delayMS(500)</span>. An LED is connected to Pin PIO0_7 which is present on LPCXpresso 1343 board. </p>
<pre><code class="language-cpp">
/*(C) Umang Gajera - www.ocfreaks.com 2011-17.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
LPC1343 Basic Timer example.*/

#include &lt;lpc13xx.h&gt;

#define PRESCALE (72000-1) //72000 PCLK clock cycles to increment TC by 1 

void delayMS(unsigned int milliseconds);
void initTimer0(void);

int main(void)
{
	//SystemInit(); //called by Startup Code before main(), hence no need to call again.
	initTimer0(); //Initialize Timer0
	LPC_GPIO0->DIR = (1<<7); //Configure PIO0_7 as output

	while(1)
	{
		LPC_GPIO0->DATA = (1<<7); //Turn LED ON
		delayMS(500); //0.5 Second(s) Delay
		LPC_GPIO0->DATA = ~(1<<7); //Turn OFF LED
		delayMS(500);
	}
	//return 0; //normally this wont execute ever
}

void initTimer0(void)
{
	/*Assuming CCLK (System Clock) = 72Mhz (set by startup code)*/
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9); //Enable 32Bit Timer0 Clock
	LPC_TMR32B0->CTCR = 0x0;
	LPC_TMR32B0->PR = PRESCALE; //Increment LPC_TMR32B0->TC at every 71999+1 clock cycles
	//72000 clock cycles @72Mhz = 1 mS
	LPC_TMR32B0->TCR = 0x02; //Reset Timer
}

void delayMS(unsigned int milliseconds) //Using Timer0
{
	LPC_TMR32B0->TCR = 0x02; //Reset Timer
	LPC_TMR32B0->TCR = 0x01; //Enable timer

	while(LPC_TMR32B0->TC < milliseconds); //wait until timer counter reaches the desired delay

	LPC_TMR32B0->TCR = 0x00; //Disable timer
}

</code></pre>
<div class="highlight"><strong>CoIDE Projects for Example #1 on GitHub @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/Timer/Example_1/" target="_blank">LPC1343 Timer Example 1</a> [Successfully tested on CoIDE v1.7.8]. <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/Timer/Example_1/" target="_blank">Download Project Zip</a>. MCUXpresso Workspace for both examples on GitHub @ <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/Timer/" target="_blank">Here</a></div>
<h4 id="Example_2"> Example 2) &#8211; LPC134x example code using Timer &#038; Match Outputs </h4>
<p>In this C/C++ Example we will use Match outputs 0 and 1 of 32-bit Timer 0 i.e. CT32B0_MAT0 and CT32B0_MAT1. CT32B0_MAT0 is pinned to PIO1_6(P1.6) and CT32B0_MAT1 pinned to PIO1_7(P1.7). You can connect LED to any of the Match ouput pin (PIO1_6 or PIO1_7) and see the code in action. Note that, on LPCXpresso 1114 Board PIO1_6 is marked as RXD and PIO1_7 is marked as TXD since these pin have UART alternate functions.</p>
<pre><code class="language-cpp">
/*(C) Umang Gajera - https://www.ocfreaks.com 2011-17.
More Embedded tutorials @ https://www.ocfreaks.com/cat/embedded/
LPC1343 Timer example 2.*/

#include &lt;lpc13xx.h&gt;

#define PRESCALE (72000-1) //72000 PCLK clock cycles to increment TC by 1 

void initTimer0(void);

int main (void)
{
	//SystemInit(); //called by Startup Code before main(), hence no need to call again.

	LPC_IOCON->PIO1_6 |= 0x2; //Select CT32B0_MAT0 function - Marked as TXD on LPCXpresso Board
	LPC_IOCON->PIO1_7 |= 0x2; //Select CT32B0_MAT1 function - Marked as RXD on LPCXpresso Board

	initTimer0(); //Initialize Timer0

	while(1)
	{
		//Idle loop
	}
	//return 0; //normally this won't execute
}

void initTimer0(void)
{
	/*Assuming CCLK (System Clock) = 72Mhz (set by startup code)*/
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9); //Enable 32Bit Timer0 Clock
	LPC_TMR32B0->CTCR = 0x0;
	LPC_TMR32B0->PR = PRESCALE; //Increment LPC_TMR32B0->TC at every 71999+1 clock cycles
	//72000 clock cycles @72Mhz = 1 mS

	LPC_TMR32B0->MR0 = 500; //toggle time in mS
	LPC_TMR32B0->MCR = (1<<1); //Reset on MR0 Match
	LPC_TMR32B0->EMR |= (1<<7) | (1<<6) | (1<<5) | (1<<4); //Toggle Match output for MAT0.0(P2.5), MAT0.1(P2.6)

	LPC_TMR32B0->TCR = 0x02; //Reset Timer
	LPC_TMR32B0->TCR = 0x01; //Enable timer
}
</code></pre>
<div class="highlight"><strong>CoIDE Projects for Example #2 on GitHub @</strong> <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/Timer/Example_2/" target="_blank">LPC1343 Timer Example 2</a> [Successfully tested on CoIDE v1.7.8]. <a href="https://minhaskamal.github.io/DownGit/#/home?url=https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/CoIDE/Timer/Example_2/" target="_blank">Download Project Zip</a>. MCUXpresso Workspace for both examples on GitHub @ <a href="https://github.com/OCFreaks/LPC1343-Tutorial-Examples/tree/master/MCUXpresso/Timer/" target="_blank">Here</a></div>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-timer-programming-tutorial/">LPC1343 Timer Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.ocfreaks.com/lpc1343-timer-programming-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2970</post-id>	</item>
		<item>
		<title>LPC1343 GPIO Programming Tutorial</title>
		<link>https://www.ocfreaks.com/lpc1343-gpio-programming-tutorial/</link>
					<comments>https://www.ocfreaks.com/lpc1343-gpio-programming-tutorial/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Umang Gajera]]></dc:creator>
		<pubDate>Sun, 10 Sep 2017 17:39:32 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[lpc1343]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">http://www.ocfreaks.com/?p=2854</guid>

					<description><![CDATA[<p>In this tutorial we will go through LPC1343 GPIO Programming. This tutorial is also applicable for LPC13x1/x2/x3 as well. LPC1343 is a ARM Cortex-M3 based MCU from NXP(Philips). The Name of Registers, Data structures that we will be using in programming examples in this tutorial are defined in LPC11xx.h header file. Most of the function [&#8230;]</p>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-gpio-programming-tutorial/">LPC1343 GPIO Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>In this tutorial we will go through LPC1343 GPIO Programming. This tutorial is also applicable for LPC13x1/x2/x3 as well. LPC1343 is a <strong>ARM Cortex-M3</strong> based MCU from NXP(Philips). The Name of Registers, Data structures that we will be using in programming examples in this tutorial are defined in <span class="code_var">LPC11xx.h</span> header file. </p>
<p>Most of the function pins on LPC1343 Micro-controllers are grouped into <strong>Ports</strong>. LPC1343 has <strong>4 ports</strong> viz. Port <strong>0 to 3</strong>. <strong>By default, all pins are configured as inputs after reset.</strong></p>
<p>The registers for each port are grouped into a structure with the following naming convention: <span class="code_var">LPC_GPIOx</span> , where <strong>x</strong> is the port number. The GPIO ports are <strong>12-bit wide</strong> i.e. a <strong>maximum 12 pins</strong> can be mapped, but depending you MCU package each port may have a few or many pins which cannot be used i.e. they are &#8216;reserved&#8217;. For this tutorial I will be using <strong>LPC1343</strong> in LQFP48 package as reference. For HVQFN33 package please refer table no. 146 on page 132 of the user-manual (Rev 5) for which pins are available for use.</p>
<p><strong>For LPC1343 (LQFP48):</strong></p>
<ul>
<li>All 12 pins on Ports 0, 1 and 2 are avialable.</li>
<li>On Port 3 only first 4 pins (i.e. PIO3_0 to PIO3_3) are available. Rest of the pins are reserved.</li>
</ul>
<div class="special sp_blue noteinfo">The naming convention(as used in the Datasheet) for Pins on MCU is ‘<strong>PIOx_y</strong>’ where ‘<strong>x</strong>’ is the port number (0, 1, 2 or 3) and ‘<strong>y</strong>’ is simply the pin number in port ‘<strong>x</strong>’. For example : <strong>PIO0_4</strong> refers to Pin number <strong>4</strong> of Port <strong>0</strong> , <strong>PIO1_8</strong> refers to Pin number <strong>8</strong> in Port <strong>1</strong> on some development boards like LCPXpresso it will be marked <strong>Px.y</strong> instead of PIOx_y. Both mean the same.</div>
<h2 class="shead">GPIO Registers in LPC134x</h2>
<p>The GPIO block has many registers. We will only go through some of these registers that are within the scope of this tutorial.</p>
<div class="highlight">
<p><strong>1) <span class="doc_ref">DATA</span> :</strong> This register can be used to Read or Write values directly to the pins. Regardless of the pin direction set or any function begin selected for the particular pins, it gives the current state of the GPIO pin when read. When a pin is configured as GPIO input, then writing to this register won&#8217;t have any affect on the pin. Similarly when a pin is configured for any other digital function, a write will have no effect. Used as <span class="code_var">LPC_GPIOn->DATA</span> in programming.</p>
<p><strong>2) <span class="doc_ref">DIR</span> :</strong> This register is used to control the Direction of Pins. Setting a bit to 0 in this register will configure the corresponding Pin[0 to 11] to be used as an Input while setting it to 1 will configure it as Output. Used as <span class="code_var">LPC_GPIOn->DIR</span> in programming.</p>
</div>
<p><strong>IOCON (I/O Configuration) Registers</strong> &#8211; Each functional pin on LPC1343 has a dedicated IOCON register with which we can control: the function of PIN, enable pull-up or pull-down, Hysteresis to filter out spurious changes in input, and other modes like I2C, ADC and Open-Drain. For using digital GPIO we are only concerned with : Changing Pin function , enabling internal pull-up/down resistors and hysteresis. In CMSIS, all the IOCON registers are grouped under <span class="code_var">LPC_IOCON</span> structure. While programming these can be accessed as <span class="code_var">LPC_IOCON->[register-name]</span>. Where <span class="code_var">[register-name]</span> is the name of the IOCON register for a specific PIN as given in datasheet/manual.</p>
<p>The general bit description for IOCON register is as shown in the diagram below:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/common/lpc1114_lpc1343_iocon.png" height="215px" width="423px" /></p>
<p>First 2 bits [2:0] are used for selecting PIN function: 0x0 &#8211; 1st function, 0x1 &#8211; 2nd function, 0x2 &#8211; 3rd function, 0x3 &#8211; 4th function. Refer datasheet for which functions are available for the given PIN.</p>
<p>Next 2 bits [3:4] are used to select on-chip pull resistors: 0x0 &#8211; Both pull-up/down resistors disabled, 0x1 &#8211; Pull-down resistor enabled, 0x2 &#8211; Pull-up resistor enabled, 0x3 &#8211; Repeater mode.</p>
<p>5th Bit [5] is for Hysteresis. Setting it to 0 will disable Hysteresis and 1 will enable it.</p>
<p>I have discussed IOCON register in detail for LPC1343 in my previous tutorial : <a hre="https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/" target="_blank">LPC11xx and LPC13xx LPC_IOCON Register Tutorial</a></p>
<p>Most of the PINS of LPC134x MCU are <strong>Multiplexed</strong> i.e. these pins can be configured to provide up to 4 different <strong>functions</strong>. Not all pins on LPC134x are configured as GPIO by default after reset! For these pins you will need to explicitly re-assign the function to GPIO using IOCON register for the respective pins. Other pins can be directly used as GPIO, since their default function is GPIO (configured as inputs with pull-ups enabled) after reset.</p>
<h2 class="shead">LPC1343 GPIO Programming &#038; Example Code in C/C++</h2>
<p><span class="code_var">LPC13xx.h</span> header is based on <span class="doc_ref">CMSIS</span>(Cortex Microcontroller System Interface Standard) developed by ARM. The <strong>register definitions</strong> for Cortex-M3 LPC134x MCUs are organized into groups depending on their functionality using &#8220;<strong>C Structure</strong>&#8221; definitions. From C/C++ programming point of view, this makes interfacing peripherals simple. For example all registers for Port 0 are grouped into structure defined as <span class="code_var">LPC_GPIO0</span>.</p>
<p><span class="code_var">LPC_GPIOx</span> is defined as a pointer to a structure, which contains GPIO registers for Port x, in <span class="code_var">LPC13xx.h</span> header. Hence to use any register, for e.g. DATA, we must use the arrow &#8220;->&#8221; operator to de-reference members of structure (since the structure itself is a pointer) to access the register as follows : <span class="code_var">LPC_GPIO0->DATA</span> = value. For creating projects you can either use KEIL uV5, LPCXpresso or MCUXpresso, but make sure you include CMSIS library. If you are using LPCXpresso LPC1114 board you can check out <a href="https://www.ocfreaks.com/tutorial-using-mcuxpresso-create-cortex-m-project-cmsis/" target="_blank">this tutorial</a>.</p>
<p><strong>Prerequisite :</strong> Before we start programming LPC134x you need to have basic understanding of Binary and Hexadecimal system and Bitwise operations in C/C++, here are two tutorials which can go through (or if you are already acquainted with these you can skip these and continue below) : </p>
<ul>
<li><a href="https://www.ocfreaks.com/hexadecimal-and-binary-number-system-basics-for-embedded-programming/">Hexadecimal and Binary Number System basics for Embedded Programming</a></li>
<li><a href="https://www.ocfreaks.com/tutorial-embedded-programming-basics-in-c-bitwise-operations/">Tutorial : Embedded programming basics in C – bitwise operations</a></li>
</ul>
<p>Now lets see how we can assign values to registers. We can use Hexadecimal notation &#038; decimal notation for assigning values. If your compiler supports other notations like binary notation use can use that too. Lets say, we want to set <strong>PIN 6</strong> of <strong>Port 1 as output</strong>. It can be done in following ways:</p>
<pre><code class="language-cpp">
CASE 1. LPC_GPIO1->DIR = (1<<6); //(binary using left shift - direct assign: other pins set to 0)

CASE 2. LPC_GPIO1->DIR |= 0x0000040; //or 0x40; (hexadecimal - OR and assign: other pins not affected)

CASE 3. LPC_GPIO1->DIR |= (1<<6); //(binary using left shift - OR and assign: other pins not affected)
</code></pre>
<ul>
<li>In many scenarios, Case 1 must be avoided since we are directly assigning a value to the register. So while we are making PIO1_6 ‘1’ others are forced to be assigned a ‘0’ which can be avoided by <strong>ORing</strong> and then assigning Value.</li>
<li>Case 2 can be used when you want to change bits in bulk and</li>
<li>Case 3 when some or single bit needs to be changed.</li>
</ul>
<p>First thing to note here is that preceding Zeros in Hexadecimal Notation can be ignored because they have no meaning since we are working with unsigned values here which are assigned to Registers. For eg. <span class="code_var">0x7F</span> and <span class="code_var">0x07F</span> and <span class="code_var">0x007F</span> all mean the same.</p>
<div class="special sp_red noteinfo">Note that bit on extreme left is <strong>Bit 31</strong> which is the <strong>MSB</strong> and the bit on extreme right is <strong>Bit 0</strong> which is <strong>LSB</strong> which is the Big Endian Format. Hence, bit 0 is the 1st bit from right , bit 1 is the 2nd bit from right and so on. BIT and PIN Numbers are <strong>Zero</strong>(0) indexed which is quite evident since Bit ‘<strong>x</strong>’ refers to <strong>(x-1)<sup>th<sup></strong> location in the corresponding register.</div>
<h4>example codes:</h4>
<p><strong>Ex. 1)</strong></p>
<p>Consider that we want to configure Pin 8 of Port 0 i.e PIO0_8(P0.8) as Output and want to drive it HIGH. This can be done as :</p>
<pre><code class="language-cpp">
LPC_GPIO0->DIR |= (1<<8); //Config PIO0_8 as Ouput
LPC_GPIO0->DATA |= (1<<8); //Drive PIO0_8 HIGH
</code></pre>
<p><strong>Ex. 2)</strong></p>
<p>Driving Pin 5 HIGH of Port 1 i.e PIO1_5(P1.5) and then LOW can be does as follows:</p>
<pre><code class="language-cpp">
LPC_GPIO1->DIR |= (1<<5); //Set PIO1_5 as Output
LPC_GPIO1->DATA |= (1<<5); //PIO1_5 driven HIGH
LPC_GPIO1->DATA &= ~(1<<5); //PIO1_5 driven LOW
</code></pre>
<p><strong>Ex. 3)</strong></p>
<p>Configuring PIO0_6(P0.6) and PIO0_2(P0.2) as Output and Setting them High:</p>
<pre><code class="language-cpp">
LPC_GPIO0->DIR |= (1<<6) | (1<<2); //Config PIO0_6 and PIO0_2 as Output
LPC_GPIO0->DATA |= (1<<6) | (1<<2); //Drive Output High for PIO0_6 and PIO0_2
</code></pre>
<p><strong>Ex. 4)</strong></p>
<p>Configuring Pins 0 to 7 of Port 2 (PIO2_0 to PIO2_7) as Output and Setting them High:</p>
<pre><code class="language-cpp">
LPC_GPIO2->DIR |= 0xFF; //Set PIO2_0 to PIO2_7 as Output
LPC_GPIO2->DATA |= 0xFF; //Drive PIO2_0 to PIO2_7 HIGH
</code></pre>
<p><strong>Ex. 5)</strong></p>
<p>In this example code, we will configure Pin 10 of Port 2 as Input with Pull-Down & Hysteresis enabled :</p>
<pre><code class="language-cpp">
LPC_GPIO2->DIR &= ~(1<<10); //Config PIO1_5 as input (It will be anyways input after reset)
LPC_IOCON->PIO2_10 = (1<<3) | (1<<5); 
//Enable on-chip Pull-down resistor [4,3]=01, Enable HYS [5]=1
</code></pre>
<p>When using switches as inputs, you can use an RC filter with Hysteresis enabled to debounce the input. Bouncing is the spurious changes in input which occurs until the contacts of the switch have stabilized. This can be filtered out using deboucning techniques, either in Software or Hardware. </p>
<p>Now lets play with some real world examples.</p>
<div class="special sp_red notewarning">The below examples are given, assuming <strong>72Mhz CCLK</strong> which is configured & initialized by system startup code generated by Keil UV5/UV4, MCUXpresso, LPCXpresso, CoIDE, etc.</div>
<p><strong>Ex. 6)</strong></p>
<p>LPC13xx Blinky Example Code - Here we drive pin 7 of port 0 (PIO0_7) repeatedly high to low. PIO0_7(P0.7) of LPC13xx devices have High current capability so you can directly drive an LED with it. Connect LED between PIO0_7 and GND. Here we will introduce some "hard-coded" delay between making all pins HIGH and LOW (and vice-versa) so it can be noticed. </p>
<pre><code class="language-cpp">
#include &lt;lpc13xx.h&gt;

void delay(void);

int main(void)
{
	LPC_GPIO0->DIR = (1<<7); //Config PIO0_7 as Output
	
	while(1)
	{
		LPC_GPIO0->DATA = (1<<7); //Drive output HIGH to turn LED ON
		// Better way would be LPC_GPIO0->DATA |= (1<<7);
		
		delay();
		LPC_GPIO0->DATA = 0x0; //Drive output LOW to turn LED OFF
		// Better way would be LPC_GPIO0->DATA &= ~(1<<7);
		
		delay();
	}
	return 0; //normally this wont execute
}	

void delay(void) //Hard-coded delay function
{
	int count,i=0;
	for(count=0; count < 4500000; count++) //You can edit this as per your needs
	{
		i++; //something needs to be here else compiler will remove the for loop!
	}
}
</code></pre>
<p><strong>Ex. 7)</strong></p>
<p>In this example we will configure PIO1_5 (P1.5) as Input and monitor it for a logic LOW on the pin. Here we will use a tactile switch whose one end is connected to PIO1_5 and other to GND (+3.3V). PIO0_7(P0.7) is configured as output and connected to an LED. Initially LED will be off but when the switch is pressed it will turn the LED. Once the LED is turned ON it will stay ON until the MCU is reset externally. The setup is shown in the figure below:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/common/lpc_gpio_eg.png" height="175px" width="492px" /></p>
<pre><code class="language-cpp">
#include &lt;lpc13xx.h&gt;

int main(void)
{
	LPC_GPIO1->DIR &= ~((1<<5)) ; //config PIO1_5 as Input
	LPC_GPIO0->DIR |= (1<<7); //config PIO0_7 as Output

	LPC_GPIO0->DATA &= ~(1<<7); //drive PIO0_7 LOW initially

	while(1)
	{
		if( LPC_GPIO1->DATA & (1<<5) ) //Evaluates to True if PIO1_5 is HIGH
		{
			LPC_GPIO0->DATA |= (1<<7); //drive PIO0_7 High to turn LED ON
			//Now PIO0_7 will be held high unless the MCU is reset
		}
	}
	return 0; //this won't execute normally
}

</code></pre>
<p><strong>Ex. 8)</strong></p>
<p>Now lets extend example 7 so that when the button is pressed, the LED will glow and when released or not pressed the LED won't glow. Note that in both Example 7 and 8: Since internal pulls are enabled by default when switch is not pressed, internal pull-up resistor will force the input to be HIGH.</p>
<pre><code class="language-cpp">
#include &lt;lpc13xx.h&gt;

void tinyDelay(void);

int main(void)
{
	LPC_GPIO1->DIR &= ~((1<<5)); 
	LPC_GPIO0->DIR |= (1<<7);
	
	LPC_GPIO0->DATA &= ~(1<<7); //Turn off LED initially
	
	while(1)
	{
		if( !(LPC_GPIO1->DATA & (1<<5)) )
		{
			LPC_GPIO0->DATA |= (1<<7); //Input LOW, LED = ON
		}
		else
		{
			LPC_GPIO0->DATA &= ~(1<<7); //Input HIGH, LED = OFF
		}
	}
	return 0; //normally this won't execute
}
</code></pre>
<div class="special sp_red notewarning" style="margin-top:20px;">
<strong>Imp. Note:</strong> As mentioned in Datasheet, many of the Pins on LPC134x are <strong>5V tolerant</strong> in digital mode. However, I would recommend that whenever possible, use a level-translator(5V<->3.3V) or buffer when interfacing external 5V signal as digital input. If you need any help regarding level translation just let me know in the you comment below.</div>
<p>The post <a href="https://www.ocfreaks.com/lpc1343-gpio-programming-tutorial/">LPC1343 GPIO Programming Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.ocfreaks.com/lpc1343-gpio-programming-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2854</post-id>	</item>
		<item>
		<title>LPC1114 and LPC1343 LPC_IOCON Register Tutorial</title>
		<link>https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/</link>
					<comments>https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Umang Gajera]]></dc:creator>
		<pubDate>Mon, 04 Sep 2017 17:14:26 +0000</pubDate>
				<category><![CDATA[Embedded]]></category>
		<category><![CDATA[lpc1114]]></category>
		<category><![CDATA[lpc1343]]></category>
		<guid isPermaLink="false">http://www.ocfreaks.com/?p=2835</guid>

					<description><![CDATA[<p>Many ARM Cortex-M series of MCUs from NXP from the LPC1000 family viz. LPC11xx, LPC13xx, etc. have I/O configuration registers for Port Pins called IOCON. In this tutorial we will discuss about the structure of these register and how to use them when programming in C/C++. The structure of IOCON might vary depending on the [&#8230;]</p>
<p>The post <a href="https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/">LPC1114 and LPC1343 LPC_IOCON Register Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Many ARM Cortex-M series of MCUs from NXP from the LPC1000 family viz. LPC11xx, LPC13xx, etc. have I/O configuration registers for Port Pins called <span class="doc_ref">IOCON</span>. In this tutorial we will discuss about the structure of these register and how to use them when programming in C/C++. The structure of IOCON might vary depending on the specific micro-controller. </p>
<p>Each pin on MCUs like LPC1114, LPC1115, LPC1343, LPC1347, etc.. have a dedicated IOCON register with which we can control: </p>
<ul>
<li>the Function (for e.g. GPIO or any other Function like TXD,I2C,etc..)</li>
<li>the Input Mode i.e. pull-up, pull-down, repeater mode or none </li>
<li>Hysteresis which gives schmitt trigger action to filter out spurious changes on inputs</li>
<li>I2C bus modes for I2C bus pins</li>
<li>selection of analog input mode for ADC pins</li>
<li>selection of open-drain mode for output, if available</li>
</ul>
<p>You can check the User-Manual or Datasheet of your LPC Cortex-M Micro-controller to check which of the above are available. </p>
<div class="special sp_blue notestar">The naming convention of these IOCON registers is <strong>&lt;default_function&gt;_PIOx_y or PIOx_y</strong>. Where x is port number, y is pin number and &#8220;default_function&#8221; is the function that is selected by default after reset, for example: RESET_PIO0_0 , SWCLK_PIO0_10 , PIO0_7 , etc. Those which don&#8217;t have &lt;default_function&gt; prefix, will be GPIOs by default after reset.</div>
<p>General Bit Description of IOCON registers for LPC1114 and LPC1343 is as given below:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/common/lpc1114_lpc1343_iocon.png" height="215px" width="423px" alt="ioconfig for lpc1114 and lpc1343" /></p>
<p>For pins hosting ADC function the IOCON structure is as follows:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/lpc1114_lpc1343_iocon/lpc_iocon_adc.png" height="189px" width="441px" alt="lpc_iocon for ADC pins" /></p>
<p>For pins hosting I2C function IOCON bit Mapping is as given below:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/lpc1114_lpc1343_iocon/lpc_iocon_i2c.png" height="166px" width="423px" alt="lpc_iocon for I2C pins" /></p>
<table class="ocf-table">
<thead>
<td>Bits</td>
<td>Symbol</td>
<td>Significance of values</td>
</thead>
<tr>
<td>[2:0]</td>
<td><strong>FUNC</strong></td>
<td>
Used to select pin Function.<br />
0x0 &#8211; First function, 0x1 &#8211; Second function<br />
0x2 &#8211; Third function, 0x3 &#8211; fourth function
</td>
</tr>
<tr>
<td>[4:3]</td>
<td><strong>MODE</strong></td>
<td>
For selecting pin Mode. Not applicable for pins having I2C functionality.<br />
0x0 &#8211; Both pull-up/pull-down resistors disabled<br />
0x1 &#8211; Pull-down resistor enabled<br />
0x2 &#8211; Pull-up resistor enabled<br />
0x3 &#8211; Repeater mode
</td>
</tr>
<tr>
<td>[5]</td>
<td><strong>HYS</strong></td>
<td>
0 &#8211; Disable Hysteresis, 1 &#8211; Enable Hysteresis
</td>
</tr>
<tr>
<td>[9:6],<br />[9:8],<br />[7]</td>
<td>N/A,<br /><strong>I2CMODE</strong>,<br /><strong>ADMODE</strong></td>
<td>
For most registers bits 6 to 9 are reserved.<br />
For I2C pins bits [9:8] respresents I2C mode and bits [7:3] are reserved.<br />
For ADC pins bit 7 represents ADMODE while bits 6,8,9 are reserved.<br />
Refer Datasheet for info about how to use them.
</td>
</tr>
<tr>
<td>[10]</td>
<td><strong>OD</strong></td>
<td>
For selecting pseudo open-drain mode.<br />
0 &#8211; Standard GPIO Mode, 1 &#8211; Open-drain Mode
</td>
</tr>
<tr>
<td>[31:11]</td>
<td>N/A</td>
<td>
Reserved
</td>
</tr>
</table>
<p><strong>Note:</strong> pseudo open-drain mode is Not available for LPC1343/42/13/12 devices.</p>
<h4>IOCON register for other LPC13x7 devices</h4>
<p>For devices like LPC1347 ICOCON register given additional control like:</p>
<ul>
<li>Logic Inversion of input pins, if available</li>
<li>Input Glitch filter, on pins which support it, if available</li>
</ul>
<p>The general register map for similar devices is as given below:</p>
<p><img decoding="async" class="aligncenter" src="https://www.ocfreaks.com/imgs/embedded/common/lpc1347_iocon.png" alt="lpc_iocon for lpc1347" height="206px" width="416px" /></p>
<p>The different in structure is that:</p>
<ul>
<li>Bit 6 now represents <strong>INV</strong> which is used to invert the Input(HIGH is read LOW and vice-versa) by setting this bit to 1. If the bit is 0 inputs are not inverted.</li>
<li>For a few pins Bit 8 represents <strong>FILTR</strong> which is used to enabled/disable glitch filter. 0 means glitch filter is enabled and 1 means its disabled.</li>
</ul>
<h2 class="shead">Using IOCON registers in programming</h2>
<p>In the device header files based on CMSIS viz. <span class="code_var">lpc11xx.h</span> and <span class="code_var">lpc13xx.h</span> all the IOCON registers are grouped under <span class="code_var">LPC_IOCON</span> structure. While programming in C/C++ , these can be accessed as: <span class="code_var">LPC_IOCON->[register-name]</span>. Where <span class="code_var">[register-name]</span> is the name of the IOCON register for a specific PIN as given in datasheet/manual.</p>
<p>For example, to access IOCON for PIO0_1(P0.1) in your code you must use <span class="code_var">LPC_IOCON->PIO0_1</span> = value.</p>
<p>Eg.:</p>
<pre><code class="language-cpp">
/*LPC11xx*/
LPC_IOCON->RESET_PIO0_0
LPC_IOCON->PIO0_8
LPC_IOCON->R_PIO0_11
...

/*LPC13xx*/
LPC_IOCON->PIO0_1
LPC_IOCON->SWDIOCLK_PIO0_10
LPC_IOCON->R_PIO1_10
...
</code></pre>
<p>The post <a href="https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/">LPC1114 and LPC1343 LPC_IOCON Register Tutorial</a> appeared first on <a href="https://www.ocfreaks.com">OCFreaks!</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.ocfreaks.com/lpc1114-lpc1343-lpc_iocon-register-tutorial/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2835</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Page Caching using Disk: Enhanced 

Served from: www.ocfreaks.com @ 2026-03-05 23:35:23 by W3 Total Cache
-->