Saturday, September 29, 2012

Button (PIC16F690)

Action After event

Today we are going create a simple program that will enable a led after an event (button). So, we are going to need:
1. A Micro controller (i usually use PIC16F690)
2. Resistor, led, push button
3. Power 5 Vdc

For this program I created the flowchart below in order to help you understand the “flow” of the program. (it is recommended for every program a flow chart to be created)



Flow chart
So the first subroutine is the initialization. At this point we are going to configure the I/Os of our microncontroller. (more on this article: "Hello World" with micro controllers ). Then the main routine is just waiting the user to press the button. When this happen we wait a few microseconds (debounce time) and check if the button is still pressed, if its still pressed then someone (human) press it, so we have to respond by enabling the led light.
First lets take a look on the schematic:


Circuit of today's project

This is a very simple schematic, at the PORTC<0> we connected the led with a small resistor, and at the PORTA<0> we connected the push button with a pull up resistor. So when the user pushes the button the Vdd wil be applied to the microncontreller PORTA<0>, as a logic "1".

Below you can see the code i created based on the flow chart above.



  1. ........
  2. ;***** VARIABLE DEFINITIONS (examples)
  3. #define COUNTER_us 0x20
  4. #define COUNTER_ms 0x21
  5. #define COUNTER_100ms 0x22
  6. .........
  7. .........
  8. start

  9. ; remaining code goes here
  10. call Initialization
  11. main_routine
  12. btfss PORTA, 0 ;if PORTA<0> == 0 ask again
  13. goto main_routine
  14. call Delay100ms ;if PORTA<0> == 1 execute this
  15. btfss PORTA, 0 ;if PORTA<0> == 0 ask again
  16. goto main_routine
  17. enable_led
  18. bsf PORTC, 0 ;if PORTA<0> == 1 execute this
  19. goto enable_led

  20. Initialization
  21. bsf STATUS, RP0
  22. bcf STATUS, RP1 ;bank 1

  23. movlw 0xff
  24. movwf TRISA ;PORTA is input
  25. clrf TRISB ;PORTB is output
  26. clrf TRISC ;PORTC is output
  27. bcf STATUS, RP0
  28. bsf STATUS, RP1 ;bank 2
  29. clrf ANSEL
  30. clrf ANSELH ;set all I/Os as digitals

  31. bcf STATUS, RP1 ;bank0

  32. clrf PORTC
  33. clrf PORTB
  34. return
  35. goto start ; loop forever

  36. ; initialize eeprom locations
  37. ;subroutines
  38. Delay100us
  39. movlw d'31'
  40. movwf COUNTER_us
  41. delay100us
  42. decfsz COUNTER_us, 1
  43. goto delay100us
  44. nop
  45. nop
  46. return
  47. Delay1ms
  48. movlw d'9'
  49. movwf COUNTER_ms
  50. delay1ms
  51. nop
  52. nop
  53. nop
  54. nop
  55. nop
  56. nop
  57. nop
  58. call Delay100us
  59. decfsz COUNTER_ms, 1
  60. goto delay1ms
  61. nop
  62. nop
  63. nop
  64. nop
  65. nop
  66. return
  67. Delay1.5ms
  68. call Delay1ms
  69. call Delay100us
  70. call Delay100us
  71. call Delay100us
  72. call Delay100us
  73. movlw d'31'
  74. movwf COUNTER_us
  75. decfsz COUNTER_us, 1
  76. goto $-1
  77. nop
  78. nop
  79. return
  80. Delay100ms
  81. movlw d'98'
  82. movwf COUNTER_100ms
  83. delay100ms
  84. call Delay1ms
  85. decfsz COUNTER_100ms, 1
  86. goto delay100ms
  87. ;+ 700us
  88. movlw d'16'
  89. movwf COUNTER_100ms
  90. call Delay100us
  91. nop
  92. nop
  93. nop
  94. decfsz COUNTER_100ms, 1
  95. goto $-5
  96. nop
  97. nop
  98. nop
  99. nop
  100. return
  101. .......

Let me explain the code. The first part you can see (lines 3-5) is a definition of three variables which are going to be used by the delay subroutines (more on the delays you can find here http://electronsvsholes.blogspot.com/2012/09/delay.html ).
Then, as we used to, we have to use the initialization subroutine in order to set digital/analog and inputs/outputs.
The main program starts at line 12, where a loop will run forever until the input becomes high, when this happen we move to line 15 where we call a debounce delay (you could use less than 100ms) and after that small delay we check if the input is still high, if not that means that was a "false alarm" so we go back to line 12 and wait again, but if the input is still high we move to line 18-19 where the command bsf makes the output high and ...voilĂ !!! The led is ON!!!

Enabling led

You can find all the files of that article here.






Measure time in MPLAB

Measure Time


In today's article i am going to show you how to take advantage of an excellent feature of mplab IDE. As the title suggests, we are going to measure time of some instructions, by following those simple steps:

1. Probably the most important part is to set the frequency of your pic. To do that go to : Debugger>Settings  and change the Processor frequency (i am going to use 4 MHz)

2. Next, select that: Debugger>Select Tool> 5 MPLAB sim. When you select that, a new button bar will appear(see the picture below)


    These new controls can be used to simulate your code.The first button "Run", will run the code without any stop. The second button "Pause" will pause the run, the third one "Animate", does the same job as the run but you can see a green arrow moving which indicated the PC (program counter). The forth button "Step into", will move the PC one step every time you click on it. The fifth button "Step Over" it can pass "over" a subroutine, the sixth is the "Step out" button and it can move out of a subroutine. The yellow button is the "Reset" and as the name suggests resets the PC and finally is the red button named "Breakpoints", which is a "flag" that says to the simulator please stop here.

3. In order to measure time we need another tool, the "StopWatch" tool, where it can be found here: Debugger>Stopwatch

4. To count the the instructions of a part of code you must move your PC (using the buttons from the second step) to the begging of that part and then click on the "Zero" button of the stop watch, and continue to move the PC. As the PC moves you can see on the Stop watch in the first column how many instructions, and time has pass by.

That's easy isn't it? :)

Thursday, September 27, 2012

Delay (PIC16F690)

How to kill your micro controller's time.


Today we are going to create subroutines that do nothing more than killing the time of micro controller. These subroutines will be used almost to any serious application we are going to make. In order to create precise delay functions we have to know the frequency of the micro controller crystal, and how many cycles ( A 'cycle' is the smallest amount of time it takes for your micro controller to do anything) will take for every command to be executed.
I think an example will clear it all out. Let assumed that our micro controller clock is set to 4 MHz, and we would like to make a delay of 100 uS.

  1.  ;***** VARIABLE DEFINITIONS (examples) 
  2. #define COUNTER_us 0x20
  3. .... 
  4. ;somewhere in the program
  5. call Delay100us
  6. ......
  7. ......
  8. Delay100us
  9. movlw d'31'
  10. movwf COUNTER_us
  11. delay100us
  12. decfsz COUNTER_us, 1
  13. goto delay100us
  14. nop
  15. nop
  16. return
Lets start by the variable definition, this is not necessary, but is very helpful. So we are defining a variable with name COUNTER_us which is at the 0x20 cell of memory and its going to be used as a temporary register which is going to help us to count the time. When the programmer uses the call command it means from that moment the delay should be start counting, so the total instructions are given below:

Instructions = 2(call) + 1 (movlw) + 1 (movwf) + 30x[1+2](decfsz and goto) + 2(decfsz the last time) + 2 (2 nop) + 2 (return) => Instructions = 100

You have to remember that every instruction cycle = 4 Tosc (Tosc = 1/frequency of the pic). So lets do the maths:
Tosc=1/Fosc = 1/4MHz = 0.25uS
100 instruction cycles = 4x0.25us =>uS = 100/(4x0.25) => Time = 100uS

And now you can create more delay subroutines, based on that logic. For example if you want a delay of 1ms you can use this delay 10 times, and so on.

Please keep in mind that post because we are going to use delay functions to a lot articles.

More about delay functions you can find here:
http://pcbheaven.com/picpages/Instruction_Cycle_Duration_and_Programmable_Delays/
http://www.piclist.com/techref/piclist/codegen/delay.htm (i tried this and is very good)
http://waihung.net/microchip-delay-calculator/ ( i didn't tried it)


Thursday, September 20, 2012

"Hello World" with micro controllers (PIC16F690)

"There shall be light..."

(For this article I used information from the microchip website)
In today's article we are going to learn how to say "Hello world" in the language of micro-controllers, in other words how to give light to a led. We are going to need:
  1. Micro-controller (I use PIC16F690)
  2. LED
  3. Resistor (about 250 ohms is fine)
  4. And off course power, 5Vdc
First of all take a look on the schematic of the circuit (I used PROTEUS software, more here):
Led circuit
Open MPLAB and create a new project. When you create the new project, you can start by writing your first program, for the most of the programs we are going to follow these steps:
  1. Initialization of the ports (set I/Os, analogs and digitals)
  2. Main function (main program, call subroutines)
  3. Back to the Main Function.

Initialization

  1. Initialization
  2. bsf STATUS, RP0
  3. bcf STATUS, RP1 ;bank 1
  4. movlw 0xff
  5. movwf TRISA ;PORTA is input
  6. clrf TRISB ;PORTB is output
  7. clrf TRISC ;PORTC is output
  8. bcf STATUS, RP0
  9. bsf STATUS, RP1 ;bank 2
  10. clrf ANSEL
  11. clrf ANSELH ;set all I/Os as digitals
  12. bcf STATUS, RP1 ;bank0
  13. clrf PORTC
  14. clrf PORTB
  15. return

 Before I try to explain the code above, I think you have to know more about the data memory organization of the PIC16F690.(Below its a part of the pdf file  located at the microchip website)
"...The data memory is partitioned into four banks which contain the General  Purpose Registers (GPR) and the Special Function Registers (SFR). The Special Function Registers are located in the first 32 locations of each bank. Register locations 20h-7Fh in Bank 0 and A0h-EFh (A0-BF, PIC16F687 only) in Bank 1 are General Purpose Registers, implemented as static RAM. Register locations F0h-FFh in Bank 1, 170h-17Fh in Bank 2 and 1F0h-1FFh in Bank 3 point to addresses 70h-7Fh in Bank 0. Other General Purpose Resisters (GPR) are also available in Bank 1 and Bank 2, depending on the device. All other RAM is unimplemented and returns ‘0’ when read. RP<1:0> (STATUS<6:5>) are the bank select bits: 
RP1 RP0
0 0 → Bank 0 is selected
0 1 → Bank 1 is selected
1 0 → Bank 2 is selected
1 1 → Bank 3 is selected 



 So if we want to use any register first we have to select the bank that the register is in to, and this can be done by modifying the bits RP0, RP1 of the STATUS register. As you can see at the lines 2 and 3 we select the Bank one, because we need to use the register TRISA which is inside bank 1.
The register TRISA:

This register (TRISA) is responsible for controlling the "direction" of PORTA. For example if I set the bit TRISA<0> (when I say set the bit it means make the bit equal to logically "1") the corresponding bit of the PORTA which is the RA0 will be configured as input and if I unset that bit of TRISA, the corresponding bit of PORTA will be configured as output.
Now we know what TRISA is lets go back to the initial code:

movlw 00xF  --> move inside W (the accumulator) 0xFF (hexademixal format)
movwf TRISA --> move W into TRISA

After these two commands the contents of TRISA will be: xx11 1111. So the corresponding pins of the PORTA will be set as inputs.

We keep on with lines 6 and 7:
clrf TRISB --> clrf (clear register ) TRISB <--0x00
clrf TRISC -->TRISB <--0x00

By clearing these two registers, TRISB and TRISC we are setting the corresponding ports, PORTB and PORTC as outputs.

At this point it is a good idea to make an overview of what we saw until now. First we set the entire PORTA as input by setting all the bits of the register TRISA, next we set the ports B and C as outputs by unssetting all the bits of the registers TRISB and TRISC. This is the first part of the initialization.

The second part is by setting the type of the I/Os, analog or digital. To do that we have to modify the contents of ANSEL and ANSELH registers.
ANSEL:

ANSELH:

 At the lines 8 and 9 we select the bank 2 where the registers ANSEL and ANSELH can be found. And then (lines 10 and 11) we clear (clrf) the contents of those registers in order to make all the pins (ANS0-ANS11) digital I/Os. The next 3 lines is a rule of mine always return to bank 0, and always clear the output ports before leaving the initialization.

Main function (main program, call subroutines)

The main function isn't nothing more than this:

  1. start
  2. ; remaining code goes here
  3. call Initialization
  4. loop
  5. bsf PORTC, 0
  6. goto  loop
Let me explain.
Line 1: is nothing more than a label, when we want to jump to a different part of our code we have to redirect the PC (program counter) to the address of the memory cell that stores the first command of  that part of code, so you can remember all the address (in a hex format) or you can put labels (like we do) and let the assembler do all the work.
Line 2: is comments, everything in the same line after the ; are overlooked by the assembler.
Line 3: Using the command call we redirect the PC to the subroutine with name Initialization. Don't forget to end every subroutine with the return command.
Line 4: Another label.
Line 5: Finally the magic code that will give light to led, the command bsf, it can be translated into "set bit <0> of register PORTC".
Line 6: With the command goto we redirect the PC to the specific memory location depending of the label after the command. The reason we do that is to keep the PC from not leaving that part of code.(that's the third part Back to the Main Function.)

When you are ready you can build your project by clicking on the build all button.
If everything is ok a hex file (among others) will be created. That file (my_project_name.hex) we are going to use with the simulation software (proteus). So open PROTEUS, design the circuit and:

  1. Double click on microcontroller symbol.
  2. Click the browse button next to "Program File" text box.
  3. Browse for the hex file, when you find it select it and click ok.
  4. When you are ready, click on the "Run" button and the simulation will start.
If everything is ok you should see something like that:

That's all for today!!! 

(you can find all the files under this link.)



Saturday, September 15, 2012

Create new Project MPLAB

New Project

Today I am going to show you how to create a new project using the MPLAB IDE.
For you to create a new project you have to follow these simple steps:

  1. Under Project menu select Project Wizard.
  2. A new window will appear, press button Next.
  3. Now you have to select from a list your PIC (you can find on the PIC IC, the exactly name of it), when you find you PIC, select it and hit Next.
  4. This is Step Two of the Project Wizard.  In the Active Toolsuite list box, select Microchip MPASM Toolsuite. Below you can see three files mpasmwin.exe, mplink.exe, mplib.exe. These files are going to be used from the program in order to translate your code and send it to the pic. Press Next.
  5. Now you are at Step Three, where you can name your project and browse for the folder which is going to be stored into. When your sure about the location, and the name hit Next.
  6. At Step four you are going to select files for your project. First of all you should select a template for your code. For example I am going to use PIC16f690, so I should select this file: C:\Program Files\Microchip\MPASM Suite\Template\Object\16F690TMPO.ASM, and press Add>>, then select the linker file following this path: C:\Program Files\Microchip\MPASM Suite\LKR\16f690_g.lkr and again press Add>>. There is a letter at the left side of the file you have just added. Click on the letter until it becomes C (it means that it will copy these files into the project folder, recommended). When you are ready hit Next again.
  7. Final Step, hit Finish. Congratulations! You have just created your first project.
At the left side of the screen is the Project Window. Inside this window you can find all the files of your project. Inside Source Files is the template you have selected at Step Six. Double click on it and the template will open in a new window where you can write/edit some code. You are going to see something like this:

  1. ;**********************************************************************
  2. ;   This file is a basic code template for object module code         *
  3. ;   generation on the PIC16F690. This file contains the               *
  4. ;   basic code building blocks to build upon.                         *
  5. ;                                                                     *
  6. ;   Refer to the MPASM User's Guide for additional information on     *
  7. ;   features of the assembler and linker (Document DS33014).          *
  8. ;                                                                     *
  9. ;   Refer to the respective PIC data sheet for additional             *
  10. ;   information on the instruction set.                               *
  11. ;                                                                     *
  12. ;**********************************************************************
  13. ;                                                                     *
  14. ;    Filename:      xxx.asm                                           *
  15. ;    Date:                                                            *
  16. ;    File Version:                                                    *
  17. ;                                                                     *
  18. ;    Author:                                                          *
  19. ;    Company:                                                         *
  20. ;                                                                     *
  21. ;                                                                     *
  22. ;**********************************************************************
  23. ;                                                                     *
  24. ;    Files required: P16F690.INC                                      *
  25. ;                                                                     *
  26. ;                                                                     *
  27. ;                                                                     *
  28. ;**********************************************************************
  29. ;                                                                     *
  30. ;    Notes:                                                           *
  31. ;                                                                     *
  32. ;                                                                     *
  33. ;                                                                     *
  34. ;                                                                     *
  35. ;**********************************************************************

  36.     list      p=16F690           ; list directive to define processor
  37.     #include <p16F690.inc>        ; processor specific variable definitions

  38.     errorlevel  -302              ; suppress message 302 from list file

  39.     __CONFIG   _CP_OFF & _CPD_OFF & _BOR_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _FCMEN_OFF & _IESO_OFF 

  40. ; '__CONFIG' directive is used to embed configuration word within .asm file.
  41. ; The lables following the directive are located in the respective .inc file.
  42. ; See data sheet for additional information on configuration word settings.

  43. ;***** VARIABLE DEFINITIONS (examples)

  44. ; example of using Shared Uninitialized Data Section
  45. INT_VAR     UDATA_SHR     
  46. w_temp      RES     1       ; variable used for context saving 
  47. status_temp RES     1       ; variable used for context saving
  48. pclath_temp RES     1       ; variable used for context saving

  49. ;**********************************************************************
  50. RESET_VECTOR    CODE    0x0000       ; processor reset vector
  51.         goto    start                ; go to beginning of program

  52. INT_VECTOR      CODE    0x0004       ; interrupt vector location

  53. INTERRUPT

  54.         movwf   w_temp            ; save off current W register contents
  55.         movf    STATUS,w          ; move status register into W register
  56.         movwf   status_temp       ; save off contents of STATUS register
  57.         movf    PCLATH,w          ; move pclath register into W register
  58.         movwf   pclath_temp       ; save off contents of PCLATH register



  59. ; isr code can go here or be located as a call subroutine elsewhere


  60.         movf    pclath_temp,w     ; retrieve copy of PCLATH register
  61.         movwf   PCLATH            ; restore pre-isr PCLATH register contents
  62.         movf    status_temp,w     ; retrieve copy of STATUS register
  63.         movwf   STATUS            ; restore pre-isr STATUS register contents
  64.         swapf   w_temp,f
  65.         swapf   w_temp,w          ; restore pre-isr W register contents
  66.         retfie                    ; return from interrupt

  67. MAIN_PROG       CODE

  68. start

  69. ; remaining code goes here

  70.         goto    start             ; loop forever

  71. ; initialize eeprom locations

  72. EE      CODE    0x2100
  73.         DE  0x00, 0x01, 0x02, 0x03

  74.         END                       ; directive 'end of program'
There is a lot of coding done for you (that is why we use a template). You can start writing you first program from the line 86 below tag start.
That's all for today. Next time we are going to light up a LED using a PIC.

Friday, September 14, 2012

Electrons vs Holes

Day 1...

For my first article I think I should start by explaining what electrons and holes are at the simplest form,  and the meaning of this blog.

Electrons: Its tiny particles spinning around the core of an atom and they are negatively charged (find out more... )
Holes: It is nothing more than a "place" where an electron could be. That is why the correct name of a hole is not just hole but is electrons holes ( find out more... ). 

The electrical charge of an electron is -e and the electrical charge of a hole is the exactly opposite, +e.


In this blog i will try to make notes for any kind of staff that interest me in order to help me and maybe you in the future.