Skip to content
Snippets Groups Projects
C-programming.html 15.5 KiB
Newer Older
Ahmad Fares's avatar
Ahmad Fares committed
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
  <link rel="stylesheet" href="styles.css" type="text/css" />
</head>
<body>
<h1 id="programming-in-c">Programming in C</h1>
<h2 id="introduction">Introduction</h2>
<p>Programming in C was not that hard for me, I have learned C++ and I have a previous experience with Java. I know the loops like for and while, conditional statement like if, variables like int, classes and libraries. I have also programmed an Arduino before, but I have never programmed in C or an micro controller on a lower level.</p>
<p>The problem was not the syntax of C, the problem was to understand the registers and how to use them for a specific function.</p>
<p>The micro controller used is ATTiny44.</p>
<h2 id="input-and-output">Input and Output</h2>
<p>ATTiny44 has 14 pins, 12 of them are for reading inputs and applying outputs. An input or an output can be either digital or analog. Any operation of a computer or a micro controller is simply a 0 or 1 which is 0v or 5v, digital is represented by 0 and 1 whereas the analog is represented as voltage range.</p>
<p>The micro controller should know if a specific pin will be used as an input or an output. If it is an input, the DDR register has to be 0 then it should know if it will write or read a specific pin. If the pin is an input and the operation is to write then the 0 is to deactivate pull up resistor and 1 is to activate pull up resistor, if the operation is to read then 0 is means 0v and 1 means 5v. If the pin is output, DDR registers has to be 1 then if it writes 0 means 0v and 1 means write 5v.</p>
<p>The process programmatically can be seen in the following code which I have used as the starting point in C programming.</p>
<p>Hardware is explained in Electronics documentation</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
<span class="co">This code was created by Ahmad Fares on 4th-Dec-2017.</span>
<span class="co">The code is used to switch on an LED when a Button is pressed.</span>

<span class="co">MIT License</span>
<span class="co">*/</span>
<span class="ot">#define F_CPU 1000000UL </span><span class="co">//Define the speed 1Mhz</span>
<span class="ot">#include &lt;avr/io.h&gt; </span><span class="co">//Include io library</span>
<span class="ot">#include &lt;util/delay.h&gt; </span><span class="co">//include delay library</span>

<span class="dt">int</span> main (<span class="dt">void</span>)
{

 DDRA = <span class="bn">0b00001000</span>; <span class="co">// set PA3 as output in DDRA.</span>
 DDRB = <span class="bn">0b00000000</span>; <span class="co">// set PB2 as input in DDRB.</span>
 PORTB = <span class="bn">0b00000100</span>; <span class="co">// activate pull up resistor.</span>

 <span class="kw">while</span>(<span class="dv">1</span>) {

   <span class="kw">if</span>(PINB == <span class="bn">0b00000000</span>){ <span class="co">//Read PB2</span>

     PORTA = <span class="bn">0b00000000</span>; <span class="co">//Switch on the LED</span>
   }<span class="kw">else</span>{
     PORTA = <span class="bn">0b00001000</span>; <span class="co">//Switch off the LED</span>
   }

}

}</code></pre></div>
<h4 id="another-way-to-define-inputs-and-outputs">Another way to define inputs and outputs</h4>
<p>It seems hard to define inputs and outputs at the way explained above, sometimes I forget a bit, sometimes I need to define only one pin not all of them so another way is to use bitwise method.</p>
<p>(register) |= (1 &lt;&lt; (bit)) means to write 1 (register) &amp;= ~(1 &lt;&lt; (bit)) means to write 0 (register) &amp; (1 &lt;&lt; (bit)) to read statues.</p>
<p>The following code explains this method:</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
<span class="co">This code was created by Ahmad Fares on 4th-Dec-2017.</span>
<span class="co">The code is used to switch on an LED when a Button is pressed using bitewise method</span>

<span class="co">MIT License</span>
<span class="co">*/</span>
<span class="ot">#define F_CPU 1000000UL </span><span class="co">//Define the speed 1Mhz</span>
<span class="ot">#include &lt;avr/io.h&gt; </span><span class="co">//Include io library</span>
<span class="ot">#include &lt;util/delay.h&gt; </span><span class="co">//include delay library</span>

<span class="dt">int</span> main (<span class="dt">void</span>)
{


 DDRA |= (<span class="dv">1</span> &lt;&lt; PA3); <span class="co">// set PA3 as output in DDRA.</span>
 DDRB &amp;= ~(<span class="dv">1</span> &lt;&lt; PB2); <span class="co">// set PB2 as input in DDRB.</span>

 PORTB |= (<span class="dv">1</span> &lt;&lt; PB2); <span class="co">// activate pull up resistor.</span>

 <span class="kw">while</span>(<span class="dv">1</span>) {

   <span class="kw">if</span>(PINB &amp; (<span class="dv">1</span> &lt;&lt; PB2)){ <span class="co">//Read PB2</span>

      PORTA &amp;= ~(<span class="dv">1</span> &lt;&lt; PA3); <span class="co">//Switch on the LED</span>
   }<span class="kw">else</span>{
     PORTA |= (<span class="dv">1</span> &lt;&lt; PA3);; <span class="co">//Switch off the LED</span>
   }

}

}
</code></pre></div>
<h4 id="macron">Macron</h4>
<p>A much simpler way of defining inputs and outputs and writing zeros and ones is macron.</p>
<p>Using macron, I have been able to write a code in human understandable language rather than registers.</p>
<p>The following code explains the macron method</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
<span class="co">This code was created by Ahmad Fares on 4th-Dec-2017.</span>
Ahmad Fares's avatar
Ahmad Fares committed
<span class="co">The code is used to switch on an LED when a Button is pressed using Macron</span>
Ahmad Fares's avatar
Ahmad Fares committed

<span class="co">MIT License</span>
<span class="co">*/</span>
Ahmad Fares's avatar
Ahmad Fares committed
<span class="ot">#define F_CPU 1000000UL </span><span class="co">//Define speed</span>

<span class="co">//Define Macron</span>
Ahmad Fares's avatar
Ahmad Fares committed
<span class="ot">#define setbit(register, bit)   (register) |= (1 &lt;&lt; (bit))</span>
<span class="ot">#define clearbit(register, bit)   (register) &amp;= ~(1 &lt;&lt; (bit))</span>
<span class="ot">#define testbit(register, bit)   (register) &amp; (1 &lt;&lt; (bit))</span>

<span class="ot">#include &lt;avr/io.h&gt;</span>
<span class="ot">#include &lt;util/delay.h&gt;</span>

<span class="dt">int</span> main (<span class="dt">void</span>)
{

 setbit(DDRA, PA3); <span class="co">// set PA3 as output in DDRA.</span>
 clearbit(DDRB, PB2); <span class="co">// set PB2 as input in DDRB.</span>
 setbit(PORTB, PA3); <span class="co">// activate pull up resistor.</span>

 <span class="kw">while</span>(<span class="dv">1</span>) {

Ahmad Fares's avatar
Ahmad Fares committed
   <span class="kw">if</span>(testbit(PINB, PB2)){ <span class="co">//Read button statues</span>
Ahmad Fares's avatar
Ahmad Fares committed
     setbit(PORTA, PA3); <span class="co">//Switch off LED</span>
Ahmad Fares's avatar
Ahmad Fares committed
   }<span class="kw">else</span>{
Ahmad Fares's avatar
Ahmad Fares committed
     clearbit(PORTA, PA3); <span class="co">// Switch on LED</span>
Ahmad Fares's avatar
Ahmad Fares committed
   }

}

}</code></pre></div>
<h2 id="interrupts">Interrupts</h2>
Ahmad Fares's avatar
Ahmad Fares committed
<p>Interrupts are used to force the microcontroller to pause the code and execute a specific block of code inside ISR function.</p>
<p>I have used interrupts to switch on an LED when a button is pressed instead of asking the microcontroller &quot;Is button pressed?&quot; by continuously reading the PB2 statues.</p>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
<span class="co">This program was created by Ahmad Fares on 7th-Dec-2017</span>
<span class="co">The purpose of this program is to use interrupt to detect a button statues</span>
<span class="co">MIT License</span>
<span class="co">*/</span>

<span class="ot">#define F_CPU 1000000UL </span><span class="co">//Define speed</span>

<span class="co">//Define Macron</span>
<span class="ot">#define setbit(register, bit)   (register) |= (1 &lt;&lt; (bit))</span>
<span class="ot">#define clearbit(register, bit)   (register) &amp;= ~(1 &lt;&lt; (bit))</span>
<span class="ot">#define testbit(register, bit)   (register) &amp; (1 &lt;&lt; (bit))</span>

Ahmad Fares's avatar
Ahmad Fares committed
<span class="ot">#include &lt;avr/interrupt.h&gt; </span><span class="co">//include interrupt library</span>
<span class="ot">#include &lt;avr/io.h&gt; </span><span class="co">//include io library</span>
Ahmad Fares's avatar
Ahmad Fares committed
<span class="co">// interrupt function, PCINT1_vect is the vector for interrupt request</span>
Ahmad Fares's avatar
Ahmad Fares committed
 ISR(PCINT1_vect)
{
 <span class="kw">if</span> ( PINB &amp; (<span class="dv">1</span>&lt;&lt;PB2) ) <span class="co">// test PINA7 if true then</span>
  setbit(PORTA,PA3); <span class="co">//turn off LED</span>
 <span class="kw">else</span>
  clearbit(PORTA,PA3); <span class="co">//Turn on LED</span>
}

<span class="dt">int</span> main (<span class="dt">void</span>){
  sei(); <span class="co">// activate interrupts globally</span>
  setbit(DDRA, PA3); <span class="co">// set PA3 as output in DDRA.</span>
  clearbit(DDRB, PB2); <span class="co">// set PB2 as input in DDRB.</span>
  setbit(PORTB, PB2); <span class="co">// activate pull up resistor.</span>
  setbit(GIMSK,PCIE1); <span class="co">//Enable pin change interrupt PORTB</span>
  setbit(PCMSK1, PCINT10); <span class="co">//Enabl pin change interrupt in pin PB2</span>
  setbit(PINA,PA3);

<span class="kw">while</span>(<span class="dv">1</span>){
<span class="co">//Doing nothing until the interrupt occurs</span>
}
}
</code></pre></div>
Ahmad Fares's avatar
Ahmad Fares committed
<h2 id="timers">Timers</h2>
Ahmad Fares's avatar
Ahmad Fares committed
<p>Timers are registers inside the microcontroller, but run independently and can be used to run a specific code after a certain time. In my case, the ATTiny44 has three 8-bit counter registers: <strong>TCNT0</strong>, <strong>TCNT1L</strong> and <strong>TCNT1H</strong>.</p>
<p>Those registers don't actually count time, they count cycles and from these cycles we can count time. There are two operation modes: normal and CTC (clear time on compare match). In the normal mode a specific block of code is executed after the register overflows whereas in the CTC mode which is the most commonly used, a block of code is executed after a certain number of cycles or seconds.</p>
<h4 id="how-to-count-1-second">How to count 1 second</h4>
<p>ATTiny44 runs at 1Mhz, which means 1 cycle every 1 micro seconds, if a normal mode is chosen so the specific task will be executed every 0.065536 seconds which is very fast, In my case I wanted to toggle the LED state every second so I have chose CTC mode and counted the 1 second as follows:</p>
<p>When the register TCNT overflows at normal mode, the number is 65536 which is 2^16 (16 bit since TCNT is two 8-bit register) so a prescalar is used to slow it down. The prescalars available are 1, 8, 64, 256, 1024.</p>
<p>First is choose the first prescalar which gives a time higher than the required 1 second.</p>
<table>
<thead>
<tr class="header">
Ahmad Fares's avatar
Ahmad Fares committed
<th align="left"><strong>1</strong></th>
<th align="left"><strong>0.065536</strong></th>
Ahmad Fares's avatar
Ahmad Fares committed
</tr>
</thead>
<tbody>
<tr class="odd">
Ahmad Fares's avatar
Ahmad Fares committed
<td align="left"><strong>8</strong></td>
Ahmad Fares's avatar
Ahmad Fares committed
<td align="left"><strong>0.524288</strong></td>
</tr>
<tr class="even">
Ahmad Fares's avatar
Ahmad Fares committed
<td align="left"><strong>64</strong></td>
<td align="left"><strong>4.194304</strong></td>
Ahmad Fares's avatar
Ahmad Fares committed
</tr>
</tbody>
</table>
<p>64 prescalar gives 4.194304 seconds, using the rule of third, I have calculated the number corresponds to 1 second as follows</p>
<p>4.194304 --&gt; 65536 1 ---------&gt; X</p>
<p>X = 65536/4.194304 = 15625 exact.</p>
<h4 id="example">Example</h4>
<div class="sourceCode"><pre class="sourceCode c"><code class="sourceCode c"><span class="co">/*</span>
<span class="co">This code was created by Ahmad Fares on 10-Dec-2017</span>
<span class="co">Timer with timer/counter 1 hardware to toggle LED state every 1 seconds</span>
<span class="co">MIT License</span>
<span class="co">*/</span>
<span class="ot">#define setbit(register, bit)   (register) |= (1 &lt;&lt; (bit))</span>
<span class="ot">#define clearbit(register, bit)   (register) &amp;= ~(1 &lt;&lt; (bit))</span>
<span class="ot">#define testbit(register, bit)   (register) &amp; (1 &lt;&lt; (bit))</span>
<span class="ot">#define togglebit(register,bit)  (register) ^= (1&lt;&lt;bit)</span>
<span class="ot">#define F_CPU 1000000UL</span>
<span class="ot">#include &lt;avr/io.h&gt;</span>
<span class="ot">#include &lt;util/delay.h&gt;</span>
<span class="ot">#include &lt;avr/interrupt.h&gt;</span>

ISR(TIM1_COMPA_vect){
  togglebit(PORTA,PA3);

}

<span class="dt">int</span> main (<span class="dt">void</span>) {

  DDRA |= (<span class="dv">1</span> &lt;&lt; PA3); <span class="co">// set LED pin as output</span>
  OCR1A = <span class="dv">15625</span>; <span class="co">// at 1/64 prescalar this is exactly 1 second.</span>
  setbit(TCCR1B, WGM12);
  sei();
  setbit(TIMSK1,OCIE1A); <span class="co">// enable CTC interrupt when TCNT1 = OCR1A</span>
  setbit(TCCR1B,CS11);
  setbit(TCCR1B,CS10); <span class="co">//These 2 registers set prescalar to 1/64 and start the counter.</span>
<span class="co">//  setbit(PORTA,PA3);</span>

<span class="kw">while</span>(<span class="dv">1</span>) {

}
  }</code></pre></div>
Ahmad Fares's avatar
Ahmad Fares committed
<h2 id="adc">ADC</h2>
<h2 id="sample-code.">Sample Code.</h2>
Ahmad Fares's avatar
Ahmad Fares committed
<p><strong>In sample code put also problems see notebook</strong></p>
<p><strong>Write more about registers in interrupt and other</strong></p>
<p><strong>Push LED, Interrupt, delay, withoutPullUp</strong></p>
Ahmad Fares's avatar
Ahmad Fares committed
<p><strong>Add video of each code</strong></p>
</body>
</html>