Tampilkan postingan dengan label Proteus tutorial. Tampilkan semua postingan
Tampilkan postingan dengan label Proteus tutorial. Tampilkan semua postingan

Kamis, 18 Oktober 2012

Communication System Development using PIC16F84A Microcontroller using Proteus 8 and MpLAB

In this communication system project using Proteus 8 software a simple communication system is shown using two PIC16F84A microcontrollers which acts as a transmitter and receiver. Assembly code for the two microcontroller is provided and shown how these microcontroller communicate.

The basic communication is via a simple protocol which allows the two micro-controllers to communicate. The switches at the transmitter MC are used as input and converted to message and sent to the receiving microcontroller serially. The received message is then shown to light up the output leds at the receiver. In other words the state of the switches forms the message to be sent and the LED glow at the receiver forms the message received.

The Schematic for this communication system is shown below-

PIC16F84A microcontroller communication System using Protues 8

The components used are-
  • 9C04021A4700FLHF3(470 ohm resistor)
  • 9C08052A1002FKHFT(10k ohm resistor)
  • Button
  • Crystal
  • DIPSW_8
  • LED-BIBY
  • LED-BIBG
  • LED-BLUE
  • PIC16F84A(micro-controller)
 The schematic is shown above. Once the schematic is drawn, hex file are required for the micro-controller for the simulation. The two micro-controller should be loaded with hex code. The hex code are generated using the MpLAB IDE. Two MpLAB project are required to generate two hex code- one for transmitter microcontroller and one for receiver microcontroller.

To generate the hex code open the MpLAB and create a new project by clicking on the Project>Project Wizard.

hex code generation step using MpLAB
A new window will pop-up, click next. Then in the next window select PIC16F84A, then click next. In the language toolsuite option, select Microchip MPASM Toolsuite as shown-

hex code generation step using MpLAB
In the next window step 3, select a folder where you want to save the project and the name of the project.

Then the step 4 allows you to add files to the project. Add the following files-
  • C:\Program Files\Microchip\MPASM Suite\LKR\16f84a_g.lkr
  • C:\Program Files\Microchip\MPASM Suite\p16f84a.inc
  • C:\Program Files\Microchip\MPASM Suite\Template\Object\16F84ATEMO.ASM
The first file is a linker file, the second is the include file and the third is a assembly template. Once these are added, click next and then finish to finish up the project wizard.

For the transmitter microcontroller, open the 16F84ATEMO.asm template just created by double clicking on it and copy-paste the below assembly code for the transmitter.
hex code generation step using MpLAB
hex code generation step using MpLAB

Transmitter Microcontroller Source Code:
;=========================
; setup and configuration
;=========================
    processor 16f84A
    include      <p16f84A.inc>
    __config  _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
;============================================================
;                        M A C R O S
;============================================================
; Macros to select the register banks
Bank0    MACRO            ; Select RAM bank 0
        bcf        STATUS,RP0
        ENDM

Bank1    MACRO            ; Select RAM bank 1
        bsf        STATUS,RP0
        ENDM
;=====================================================
;          constant definitions for pin wiring
;=====================================================
#define readySW  2  ;|
#define readyLED 3    ;| -- from wiring diagram
#define serialLN 0    ;|
;=====================================================
;            PIC register and flag equates
;=====================================================
c        equ        0        ; Carry flag
tmrOVF    equ        2        ; Timer overflow bit
;
;======================================================
;              variables in PIC RAM
;=====================================================
    cblock    0x0c    ; Start of block
    bitCount        ; Counter for 8 bits
    rcvReg            ; Data to send
    temp
    endc
;=========================================================
;                           program
;=========================================================
    org    0      ; start at address
    goto    main
; Space for interrupt handlers
    org    0x04

main:
    Bank1
; Port A bits 0 and 2 are input. All others are output
    movlw    b'00000101' ; port A setup
    movwf    TRISA
; Port B is all output
    movlw    b'00000000' ; port B setup
    MOVWF    TRISB
    Bank0
; Turn off all port B LEDs
    clrf    PORTB
; And receiver register
    clrf    rcvReg
; Prepare to set prescaler
    clrf    TMR0
    clrwdt
; Setup OPTION register for full timer speed
    movlw    b'11011000'
;   1  1  0  1  1  0  0  0 <= OPTION bits
;   |  |  |  |  |  |__|__|_____ PS2-PS0 (prescaler bits)
;   |  |  |  |  |               Values for Timer0
;   |  |  |  |  |              *000 = 1:2   001 = 1:4
;   |  |  |  |  |               010 = 1:8   011 = 1:16
;   |  |  |  |  |               100 = 1:32  101 = 1:64
;   |  |  |  |  |               110 = 1:128 111 = 1:256
;   |  |  |  |  |______________ PSA (prescaler assign)
;   |  |  |  |                 *1 = to WDT
;   |  |  |  |                  0 = to Timer0
;   |  |  |  |_________________ TOSE (Timer0 edge select)
;   |  |  |                     0 = increment on low-to-high
;   |  |  |                    *1 = increment in high-to-low
;   |  |  |____________________ TOCS (TMR0 clock source)
;   |  |                       *0 = internal clock
;   |  |                        1 = RA4/TOCKI bit source
;   |  |_______________________ INTEDG (Edge select)
;   |                           0 = falling edge
;   |                          *1 = raising edge
;   |__________________________ RBPU pullups
;                               0 = enabled
;                              *1 = dissabled
    option
; Dissable interrupts
    bcf        INTCON,5   ; Timer0 overflow dissabled
    bcf        INTCON,7   ; Global interupts dissabled
;=========================
;  wait for READY switch
;     to be pressed
;=========================
ready2rcv:
    btfsc    PORTA,readySW    ; Test switch
    goto    ready2rcv        ; loop
; Turn ON the ready-to-receive LED
    bsf        PORTA,readyLED
;===========================
;        receiving
;===========================
    call    rcvData        ; Call serial input procedure
;===========================
;       data received
;===========================
; Turn ready to receive LED off
    bcf        PORTA,readyLED
; Display received data
    movf    rcvReg,w    ; Byte received to w
    movwf    PORTB        ; display in port B
;===========================
;      wait forever
;===========================
endloop:
    goto    endloop
;============================================================
;               procedure to receive serial data
;============================================================
; ON ENTRY:
;         local variable dataReg is used to store 8-bit value
;         received through port (labeled serialLN)
; OPERATION:
;      1. The timer at register TMR0 is set to run at
;         maximum clock speed, that is, 256 clock beats.
;         The timer overflow flag in the INTCON register
;         is set when the timer cycles from 0xff to 0x00.
;      2. When the START signal is received, the code
;         waits for 128 timer beats so as to read data in
;         the middle of the send period.
;      3. Each bit (start, data, and stop bits) is read
;         at intervals of 256 timer beats.
;      4. The procedure tests the timer ofverflow flag
;         (tmrOVF) to determine when the timer cycle has
;         ended, that is when 256 clock beats have passed.

;------------------------------------------------------------
rcvData:
    clrf    TMR0    ; Reset timer
    movlw    0x08    ; Initialize bit counter
    movwf    bitCount
;=========================
;   wait for START bit
;=========================
startWait:
    btfsc    PORTA,0        ; Is port A0 low?
    goto    startWait    ; No. Wait for mark
;=========================
;  offset 128 clock beats
;=========================
; At this point the receiver has found the falling
; edge of the start bit. It must now wait 128 timer
; beats to synchronize in the middle of the sender's
; data rate, as follows:
;             |<========= falling edge of START bit
;             |
;             |-----|<====== 128 clock beats offset
;   ----------.     |     .---------
;             |           |  <== SIGNAL
;              -----------
;             |<-- 256 -->|
;
    movlw    0x80        ; 128 clock beats offset
    movwf    TMR0        ; to TMR0 counter
    bcf        INTCON,tmrOVF    ; Clear overflow flag
offsetWait:
    btfss    INTCON,tmrOVF   ; timer overflow?
    goto    offsetWait        ; wait until
    btfsc    PORTA,0            ; Test start bit for error
    goto    offsetWait        ; Recycle if a false start
;==========================
;      receive data
;==========================
    clrf    TMR0        ; Restart timer
    bcf        INTCON,tmrOVF    ; Clear overflow flag
; Wait for 256 timer cycles for first/next data bit
bitWait:
    btfss    INTCON,tmrOVF  ; Timer cycle end?
    goto    bitWait            ; Keep waiting
; Timer has counter 256 beats
    bcf        INTCON,tmrOVF    ; Reset overflow flag
    movf    PORTA,w            ; Read port A into w
    movwf    temp            ; Store value read
    rrf        temp,f            ; Rotate bit 0 into carry flag
    rlf        rcvReg,f           ; Rotate carry into rcvReg bit 0
    decfsz    bitCount,f        ; 8 bits received
    goto    bitWait            ; Next bit
; Wait for one time cycle at end of reception
markWait:
    btfss    INTCON,tmrOVF    ; timer overflow flag
    goto    markWait        ; keep waiting
;========================
;   end of reception
;========================
    return

;=========================================================
;                       end of program
;=========================================================
    end

Once copied click on Build All option to start compiling the assembly code. Once this is complete, it should show Build Succeeded as shown below-

hex code generation step using MpLAB

This create a transmit.hex (transmit is the project name here) in the MpLAB project folder. See below-

hex code generation step using MpLAB

Copy the transmit.hex file into your microcontroller proteus project folder. See example below-

hex code generation step using MpLAB


Now to burn the transmit.hex file to the transmitter microcontroller, go to the schematic and double click on the transmitter microcontroller to bring up its properties window. Then click on the folder icon and browse for the transmit.hex file and click ok to exit the window.

buring hex file in proteus 8

Now the transmitter microcontroller is ready for simulation.

Repeat the same steps for the receiver microcontroller by starting by creating a new MpLAB project, adding the same files, copying and pasting the receiver assembly code provided below, compiling and creating a receive.hex file and lastly uploading the hex file to the receiver microcontroller.

Receiver Microcontroller Source Code:

;=========================
; setup and configuration
;=========================
    processor 16f84A
    include      <p16f84A.inc>
    __config  _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
;============================================================
;                        M A C R O S
;============================================================
; Macros to select the register banks
Bank0    MACRO            ; Select RAM bank 0
        bcf        STATUS,RP0
        ENDM

Bank1    MACRO            ; Select RAM bank 1
        bsf        STATUS,RP0
        ENDM
;=====================================================
;          constant definitions for pin wiring
;=====================================================
#define readySW  2  ;|
#define readyLED 3    ;| -- from wiring diagram
#define serialLN 0    ;|
;=====================================================
;            PIC register and flag equates
;=====================================================
c        equ        0        ; Carry flag
tmrOVF    equ        2        ; Timer overflow bit
;
;======================================================
;              variables in PIC RAM
;=====================================================
    cblock    0x0c    ; Start of block
    bitCount        ; Counter for 8 bits
    rcvReg            ; Data to send
    temp
    endc
;=========================================================
;                           program
;=========================================================
    org    0      ; start at address
    goto    main
; Space for interrupt handlers
    org    0x04

main:
    Bank1
; Port A bits 0 and 2 are input. All others are output
    movlw    b'00000101' ; port A setup
    movwf    TRISA
; Port B is all output
    movlw    b'00000000' ; port B setup
    MOVWF    TRISB
    Bank0
; Turn off all port B LEDs
    clrf    PORTB
; And receiver register
    clrf    rcvReg
; Prepare to set prescaler
    clrf    TMR0
    clrwdt
; Setup OPTION register for full timer speed
    movlw    b'11011000'
;   1  1  0  1  1  0  0  0 <= OPTION bits
;   |  |  |  |  |  |__|__|_____ PS2-PS0 (prescaler bits)
;   |  |  |  |  |               Values for Timer0
;   |  |  |  |  |              *000 = 1:2   001 = 1:4
;   |  |  |  |  |               010 = 1:8   011 = 1:16
;   |  |  |  |  |               100 = 1:32  101 = 1:64
;   |  |  |  |  |               110 = 1:128 111 = 1:256
;   |  |  |  |  |______________ PSA (prescaler assign)
;   |  |  |  |                 *1 = to WDT
;   |  |  |  |                  0 = to Timer0
;   |  |  |  |_________________ TOSE (Timer0 edge select)
;   |  |  |                     0 = increment on low-to-high
;   |  |  |                    *1 = increment in high-to-low
;   |  |  |____________________ TOCS (TMR0 clock source)
;   |  |                       *0 = internal clock
;   |  |                        1 = RA4/TOCKI bit source
;   |  |_______________________ INTEDG (Edge select)
;   |                           0 = falling edge
;   |                          *1 = raising edge
;   |__________________________ RBPU pullups
;                               0 = enabled
;                              *1 = dissabled
    option
; Dissable interrupts
    bcf        INTCON,5   ; Timer0 overflow dissabled
    bcf        INTCON,7   ; Global interupts dissabled
;=========================
;  wait for READY switch
;     to be pressed
;=========================
ready2rcv:
    btfsc    PORTA,readySW    ; Test switch
    goto    ready2rcv        ; loop
; Turn ON the ready-to-receive LED
    bsf        PORTA,readyLED
;===========================
;        receiving
;===========================
    call    rcvData        ; Call serial input procedure
;===========================
;       data received
;===========================
; Turn ready to receive LED off
    bcf        PORTA,readyLED
; Display received data
    movf    rcvReg,w    ; Byte received to w
    movwf    PORTB        ; display in port B
;===========================
;      wait forever
;===========================
endloop:
    goto    endloop
;============================================================
;               procedure to receive serial data
;============================================================
; ON ENTRY:
;         local variable dataReg is used to store 8-bit value
;         received through port (labeled serialLN)
; OPERATION:
;      1. The timer at register TMR0 is set to run at
;         maximum clock speed, that is, 256 clock beats.
;         The timer overflow flag in the INTCON register
;         is set when the timer cycles from 0xff to 0x00.
;      2. When the START signal is received, the code
;         waits for 128 timer beats so as to read data in
;         the middle of the send period.
;      3. Each bit (start, data, and stop bits) is read
;         at intervals of 256 timer beats.
;      4. The procedure tests the timer ofverflow flag
;         (tmrOVF) to determine when the timer cycle has
;         ended, that is when 256 clock beats have passed.

;------------------------------------------------------------
rcvData:
    clrf    TMR0    ; Reset timer
    movlw    0x08    ; Initialize bit counter
    movwf    bitCount
;=========================
;   wait for START bit
;=========================
startWait:
    btfsc    PORTA,0        ; Is port A0 low?
    goto    startWait    ; No. Wait for mark
;=========================
;  offset 128 clock beats
;=========================
; At this point the receiver has found the falling
; edge of the start bit. It must now wait 128 timer
; beats to synchronize in the middle of the sender's
; data rate, as follows:
;             |<========= falling edge of START bit
;             |
;             |-----|<====== 128 clock beats offset
;   ----------.     |     .---------
;             |           |  <== SIGNAL
;              -----------
;             |<-- 256 -->|
;
    movlw    0x80        ; 128 clock beats offset
    movwf    TMR0        ; to TMR0 counter
    bcf        INTCON,tmrOVF    ; Clear overflow flag
offsetWait:
    btfss    INTCON,tmrOVF   ; timer overflow?
    goto    offsetWait        ; wait until
    btfsc    PORTA,0            ; Test start bit for error
    goto    offsetWait        ; Recycle if a false start
;==========================
;      receive data
;==========================
    clrf    TMR0        ; Restart timer
    bcf        INTCON,tmrOVF    ; Clear overflow flag
; Wait for 256 timer cycles for first/next data bit
bitWait:
    btfss    INTCON,tmrOVF  ; Timer cycle end?
    goto    bitWait            ; Keep waiting
; Timer has counter 256 beats
    bcf        INTCON,tmrOVF    ; Reset overflow flag
    movf    PORTA,w            ; Read port A into w
    movwf    temp            ; Store value read
    rrf        temp,f            ; Rotate bit 0 into carry flag
    rlf        rcvReg,f           ; Rotate carry into rcvReg bit 0
    decfsz    bitCount,f        ; 8 bits received
    goto    bitWait            ; Next bit
; Wait for one time cycle at end of reception
markWait:
    btfss    INTCON,tmrOVF    ; timer overflow flag
    goto    markWait        ; keep waiting
;========================
;   end of reception
;========================
    return

;=========================================================
;                       end of program
;=========================================================
    end

    Senin, 15 Oktober 2012

    Proteus Microcontroller Tutorial on LCD display

    This tutorial is about the programming of PIC16F84A microcontroller and LCD driven by Hitachi HD44780 LCD controller for real time simulation to display character onto the display.

    The way this whole works is that an assembly program is written and then burned into the PIC microcontroller and the program directs and control the smaller LCD hardware controller HD44780. That is HD44780 is in itself a primitive machine that has its own instruction set, memory, timing and display control circuit. In order to correctly control the LCD display it is necessary to have knowledge about the functions it supports, the initialization it requires such as font size, duty cycle, 8 or 4 pin interface width, diplay on/off, cursor on/off, character shift etc, ports and pins, the size and types of memory and working of the LCD controller.

    The program starts by defining constants and variables required for routines and allocating memory space for text data to be displayed. The ports type(whether inputs or outputs) of the PIC microcontroller are defined. The next step is the initialization of the LCD, that is setting up the font size, the 8 or 4 interface width, display, cursor and shift of character. Then the last step is the generation of text and transfer of text to buffer in PIC microcontroller and then finally the transfer from buffer to the DDRAM of the LCD controller which is then displayed. This transfer and display requires sending commands to the controller.

    The schematic diagram that shows the interfacing between the microcontroller and the LCD controller is shown below-

    Proteus Microcontroller Tutorial on LCD display

    The part that has been used here are-
    •  9C08052A1002FKHFT
    • BUTTON
    • CRYSTAL
    • ERA-3YEB101V
    • LM016L
    • PIC16F84A
     The source code is provided below. To use this source code, simply double click on the microcontroller and select edit firmware option. Then copy paste the below source code. Compile it by clicking on the build icon as shown in figure and you should see compiled successfully(perhaps with minor warning which can just be ignored).

    Proteus Microcontroller Tutorial on LCD display

     To run the simulation, go back to the schematic and click on the Run icon.

    Proteus Microcontroller Tutorial on LCD display
    Source Code:; Processor: 16F84A
    ;
    ; Description:
    ; Program to exercises 8-bit PIC-to-LCD interface.
    ; Code assumes that LCD is driven by Hitachi HD44780
    ; controller and that the display supports two lines
    ; each one with 16 characters. The wiring and base
    ; address of each display line is stored in #define
    ; statements. These statements can be edited to
    ; accomodate a different set-up.
    ; Program uses delay loops for interface timing.
    ; WARNING:
    ; Code assumes 4Mhz clock. Delay routines must be
    ; edited for faster clock

    ; Displays: Minnesota State, Mankato
    ;
    ;===========================
    ;        switches
    ;===========================
    ; Switches used in __config directive:
    ;   _CP_ON          Code protection ON/OFF    
    ; * _CP_OFF     
    ; * _PWRTE_ON     Power-up timer ON/OFF
    ;   _PWRTE_OFF    
    ;   _WDT_ON       Watchdog timer ON/OFF 
    ; * _WDT_OFF      
    ;   _LP_OSC       Low power crystal occilator
    ; * _XT_OSC       External parallel resonator/crystal ocillator 
    ;   _HS_OSC       High speed crystal resonator (8 to 10 MHz)
    ;                 Resonator: Murate Erie CSA8.00MG = 8 MHz  
    ;   _RC_OSC       Resistor/capacitor ocillator (simplest, 20% error)
    ; |
    ; |_____ * indicates setup values

    ;=========================
    ; setup and configuration
    ;=========================
        processor 16f84A
        include      <p16f84A.inc>
        __config  _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

    ;=====================================================
    ;                 constant definitions
    ;  for PIC-to-LCD pin wiring and LCD line addresses
    ;=====================================================
    #define E_line 1       ;|
    #define RS_line 2    ;| -- from wiring diagram
    #define RW_line 3    ;|
    ; LCD line addresses (from LCD data sheet)
    #define LCD_1 0x80    ; First LCD line constant
    #define LCD_2 0xc0    ; Second LCD line constant
    ; Note: The constant that define the LCD display line
    ;       addresses have the high-order bit set in
    ;       order to faciliate the controller command
    ;
    ;=====================================================
    ;              variables in PIC RAM
    ;=====================================================
    ; Reserve 16 bytes for string buffer
        cblock    0x0c
        strData
        endc
    ; Leave 16 bytes and Continue with local variables
        cblock    0x1d        ; Start of block
        count1        ; Counter # 1
        count2        ; Counter # 2
        count3        ; Counter # 3
        pic_ad        ; Storage for start of text area
                    ; (labeled strData) in PIC RAM
        J            ; counter J
        K            ; counter K
        index        ; Index into text table (also used
                    ; for auxiliary storage)
        endc

    ;============================================================
    ;                           program
    ;============================================================
            org        0      ; start at address
            goto    main
    ; Space for interrupt handlers
        org        0x08

    main:
        movlw    b'00000000' ; All lines to output
        tris    PORTA        ; in port A
        tris    PORTB        ; and port B
        movlw    b'00000000' ; All outputs ports low
        movwf    PORTA
        movwf    PORTB
    ; Wait and initialize HD44780
        call    delay_5ms        ; Allow LCD time to initialize itself
        call    initLCD        ; Then do forced initialization
        call    delay_5ms        ; (Wait probably not necessary)
    ; Store base address of text buffer in PIC RAM
        movlw    0x0c        ; Start address of text buffer
        movwf    pic_ad        ; to local variable
    ;======================
    ;   first LCD line
    ;======================
    ; Store 16 blanks in PIC RAM, starting at address stored
    ; in variable pic_ad
        call    blank16
    ; Call procedure to store ASCII characters for message
    ; in text buffer
        movlw    d'3'        ; Offset into buffer
        call    storeMN
    ; Set DDRAM address to start of first line
        call     line1
    ; Call procedure to display 16 characters in LCD
        call    display16
    ;========================
    ;   second LCD line
    ;========================
        call    delay_125mcs    ; Wait for termination
        call    blank16        ; Blank buffer
    ; Call procedure to store ASCII characters for message
    ; in text buffer
        movlw    d'1'        ; Offset into buffer
        call    storeUniv
        call    line2        ; DDRAM address of LCD line 2
        call    display16
    ;=======================
    ;       done!
    ;=======================
    loopHere:
        goto    loopHere  ;done

    ;************************************************************
    ;                  INITIALIZE LCD PROCEDURE
    ;************************************************************
    initLCD
    ; Initialization for Densitron LCD module as follows:
    ;    8-bit interface
    ;   2 display lines of 16 characters each
    ;   cursor on
    ;   left-to-right increment
    ;   cursor shift right
    ;   no display shift
    ;***********************|
    ;     COMMAND MODE      |
    ;***********************|
        bcf        PORTA,E_line    ; E line low
        bcf        PORTA,RS_line    ; RS line low for command
        bcf        PORTA,RW_line   ; Write mode
        call    delay_125mcs        ;delay 125 microseconds
    ;***********************|
    ;     FUNCTION SET      |
    ;***********************|
        movlw    0x38    ; 0 0 1 1 1 0 0 0 (FUNCTION SET)
                        ;     | | | |__ font select:
                        ;     | | |    1 = 5x10 in 1/8 or 1/11 dc
                        ;     | | |    0 = 1/16 dc
                        ;     | | |___ Duty cycle select
                        ;     | |      0 = 1/8 or 1/11
                        ;     | |      1 = 1/16 (multiple lines)
                        ;     | |___ Interface width
                        ;     |      0 = 4 bits
                        ;     |      1 = 8 bits
                        ;     |___ FUNCTION SET COMMAND
        movwf    PORTB    ;0011 1000
        call    pulseE    ;pulseE and delay

    ;***********************|
    ;    DISPLAY OFF        |
    ;***********************|
        movlw    0x08    ; 0 0 0 0 1 0 0 0 (DISPLAY ON/OFF)
                        ;         | | | |___ Blink character at cursor
                        ;         | | |      1 = on, 0 = off
                        ;         | | |___ Curson on/off
                        ;         | |      1 = on, 0 = off
                        ;         | |____ Display on/off
                        ;         |       1 = on, 0 = off
                        ;         |____ COMMAND BIT

        movwf    PORTB
        call    pulseE    ;pulseE and delay

    ;***********************|
    ; DISPLAY AND CURSOR ON |
    ;***********************|
        movlw    0x0e    ; 0 0 0 0 1 1 1 0 (DISPLAY ON/OFF)
                        ;         | | | |___ Blink character at cursor
                        ;         | | |      1 = on, 0 = off
                        ;         | | |___ Curson on/off
                        ;         | |      1 = on, 0 = off
                        ;         | |____ Display on/off
                        ;         |       1 = on, 0 = off
                        ;         |____ COMMAND BIT
        movwf    PORTB
        call    pulseE    ;pulseE and delay

    ;***********************|
    ;    ENTRY MODE SET     |
    ;***********************|
        movlw    0x06    ; 0 0 0 0 0 1 1 0 (ENTRY MODE SET)
                        ;           | | |___ display shift
                        ;           | |      1 = shift
                        ;           | |      0 = no shift
                        ;           | |____ cursor increment mode
                        ;           |       1 = left-to-right
                        ;           |       0 = right-to-left
                        ;           |___ COMMAND BIT
        movwf    PORTB    ;00000110
        call    pulseE

    ;***********************|
    ; CURSOR/DISPLAY SHIFT  |
    ;***********************|
        movlw    0x14    ; 0 0 0 1 0 1 0 0 (CURSOR/DISPLAY SHIFT)
                           ;       | | | |_|___ don't care
                        ;       | |_|__ cursor/display shift
                        ;       |       00 = cursor shift left
                        ;       |       01 = cursor shift right
                        ;       |       10 = cursor and display
                        ;       |            shifted left
                        ;       |       11 = cursor and display
                        ;       |            shifted right
                        ;       |___ COMMAND BIT
        movwf    PORTB    ;0001 1111
        call    pulseE

    ;***********************|
    ;   CLEAR DISPLAY       |
    ;***********************|
        movlw    0x01    ; 0 0 0 0 0 0 0 1 (CLEAR DISPLAY)
                        ;               |___ COMMAND BIT
        movwf    PORTB    ;0000 0001
    ;
        call    pulseE
        call    delay_5ms    ;delay 5 milliseconds after init
        return
    ;************************************************************
    ;               DELAY AND PULSE PROCEDURES
    ;************************************************************
    ;=======================
    ;  Procedure to delay
    ;   42 microseconds
    ;=======================
    delay_125mcs
        movlw    D'42'            ; Repeat 42 machine cycles
        movwf    count1            ; Store value in counter
    repeat
        decfsz    count1,f           ; Decrement counter
        goto    repeat            ; Continue if not 0
        return                    ; End of delay   
    ;------------------------------------------------------------
    ;=======================
    ;  Procedure to delay
    ;   5 milliseconds
    ;=======================
    delay_5ms
        movlw    D'41'            ; Counter = 41
        movwf    count2            ; Store in variable
    delay
        call    delay_125mcs        ; Delay
        decfsz    count2,f        ; 40 times = 5 milliseconds
        goto    delay
        return                ; End of delay
    ;========================
    ;     pulse E line
    ;========================
    pulseE
        bsf        PORTA,E_line    ;pulse E line
        bcf        PORTA,E_line
        call    delay_125mcs        ;delay 125 microseconds
        return

    ;=============================
    ;   long delay sub-routine
    ;     (for debugging)
    ;=============================
    long_delay
            movlw    D'200'    ; w = 200 decimal
            movwf    J        ; J = w
    jloop:    movwf    K        ; K = w
    kloop:    decfsz    K,f        ; K = K-1, skip next if zero
            goto     kloop
            decfsz    J,f        ; J = J-1, skip next if zero
            goto    jloop
            return
    ;=============================
    ;   LCD display procedure
    ;=============================
    ; Sends 16 characters from PIC buffer with address stored
    ; in variable pic_ad to LCD line previously selected
    display16:
    ; Set up for data
        bcf        PORTA,E_line    ; E line low
        bsf        PORTA,RS_line    ; RS line low for control
        call    delay_125mcs        ; Delay
    ; Set up counter for 16 characters
        movlw    D'16'            ; Counter = 16
        movwf    count3   
    ; Get display address from local variable pic_ad
        movf    pic_ad,w        ; First display RAM address to W
        movwf    FSR                ; W to FSR
    getchar:
        movf    INDF,w            ; get character from display RAM
                                ; location pointed to by file select
                                ; register
        movwf    PORTB
        call    pulseE    ;send data to display   
    ; Test for 16 characters displayed
        decfsz    count3,f          ; Decrement counter
        goto    nextchar        ; Skipped if done
        return
    nextchar:
        incf    FSR,f            ; Bump pointer
        goto    getchar
    ;========================
    ;     blank buffer
    ;========================
    ; Procedure to store 16 blank characters in PIC RAM
    ; buffer starting at address stored in the variable
    ; pic_ad
    blank16:
        movlw    D'16'        ; Setup counter
        movwf    count1
        movf    pic_ad,w    ; First PIC RAM address
        movwf    FSR            ; Indexed addressing
        movlw    0x20        ; ASCII space character
    storeit:
        movwf    INDF        ; Store blank character in PIC RAM
                            ; buffer using FSR register
        decfsz    count1,f      ; Done?
        goto    incfsr        ; no
        return                ; yes
    incfsr:
        incf    FSR,f        ; Bump FSR to next buffer space
        goto    storeit

    ;========================
    ; Set address register
    ;    to LCD line 1
    ;========================
    ; ON ENTRY:
    ;         Address of LCD line 1 in constant LCD_1
    line1:
        bcf        PORTA,E_line     ; E line low
        bcf        PORTA,RS_line    ; RS line low, set up for control
        call    delay_125mcs        ; delay 125 microseconds
    ; Set to second display line
        movlw    LCD_1            ; Address and command bit
        movwf    PORTB
        call    pulseE            ; Pulse and delay
    ; Set RS line for data
        bsf        PORTA,RS_line    ; Setup for data
        call    delay_125mcs        ; Delay
        return
    ;========================
    ; Set address register
    ;    to LCD line 2
    ;========================
    ; ON ENTRY:
    ;         Address of LCD line 2 in constant LCD_2
    line2:
        bcf        PORTA,E_line    ; E line low
        bcf        PORTA,RS_line    ; RS line low, setup for control
        call    delay_125mcs        ; delay
    ; Set to second display line
        movlw    LCD_2            ; Address with high-bit set
        movwf    PORTB
        call    pulseE            ; Pulse and delay
    ; Set RS line for data
        bsf        PORTA,RS_line    ; RS = 1 for data
        call    delay_125mcs        ; delay
        return

    ;===============================
    ;  first text string procedure
    ;===============================
    storeMN:
    ; Procedure to store in PIC RAM buffer the message
    ; contained in the code area labeled msg1
    ; ON ENTRY:
    ;         variable pic_ad holds address of text buffer
    ;         in PIC RAM
    ;         w register hold offset into storage area
    ;         msg1 is routine that returns the string characters
    ;         an a zero terminator
    ;         index is local variable that hold offset into
    ;         text table. This variable is also used for
    ;         temporary storage of offset into buffer
    ; ON EXIT:
    ;         Text message stored in buffer
    ;
    ; Store offset into text buffer (passed in the w register)
    ; in temporary variable
        movwf    index        ; Store w in index
    ; Store base address of text buffer in FSR
        movf    pic_ad,w    ; first display RAM address to W
        addwf    index,w        ; Add offset to address
        movwf    FSR            ; W to FSR
    ; Initialize index for text string access
        movlw    0            ; Start at 0
        movwf    index        ; Store index in variable
    ; w still = 0
    get_msg_char:
        call    msg1        ; Get character from table
    ; Test for zero terminator
        andlw    0x0ff
        btfsc    STATUS,Z    ; Test zero flag
        goto    endstr1        ; End of string
    ; ASSERT: valid string character in w
    ;         store character in text buffer (by FSR)
        movwf    INDF        ; store in buffer by FSR
        incf    FSR,f        ; increment buffer pointer
    ; Restore table character counter from variable
        movf    index,w        ; Get value into w
        addlw    1            ; Bump to next character
        movwf    index        ; Store table index in variable
        goto    get_msg_char    ; Continue   
    endstr1:
        return

    ; Routine for returning message stored in program area
    msg1:
        addwf    PCL,f        ; Access table
        retlw    'M'
        retlw    'i'
        retlw    'n'
        retlw    'n'
        retlw    'e'
        retlw    's'
        retlw    'o'
        retlw    't'
        retlw    'a'
        retlw    0

    ;=================================
    ;   second text string procedure
    ;=================================
    storeUniv:
    ; Processing identical to procedure StoreMSU
        movwf    index        ; Store w in index
    ; Store base address of text buffer in FSR
        movf    pic_ad,0    ; first display RAM address to W
        addwf    index,0        ; Add offset to address
        movwf    FSR            ; W to FSR
    ; Initialize index for text string access
        movlw    0            ; Start at 0
        movwf    index        ; Store index in variable
    ; w still = 0
    get_msg_char2:
        call    msg2        ; Get character from table
    ; Test for zero terminator
        andlw    0x0ff
        btfsc    STATUS,Z    ; Test zero flag
        goto    endstr2        ; End of string
    ; ASSERT: valid string character in w
    ;         store character in text buffer (by FSR)
        movwf    INDF        ; Store in buffer by FSR
        incf    FSR,f        ; Increment buffer pointer
    ; Restore table character counter from variable
        movf    index,w        ; Get value into w
        addlw    1            ; Bump to next character
        movwf    index        ; Store table index in variable
        goto    get_msg_char2    ; Continue   
    endstr2:
        return

    ; Routine for returning message stored in program area
    msg2:
        addwf    PCL,f        ; Access table
        retlw    'S'
        retlw    't'
        retlw    'a'
        retlw    't'
        retlw    'e'
        retlw    ','
        retlw    0x20
        retlw    'M'
        retlw    'a'
        retlw    'n'
        retlw    'k'
        retlw    'a'
        retlw    't'
        retlw    'o'
        retlw    0

        end






    Sabtu, 06 Oktober 2012

    PIC16F877A Microcontroller Tutorial using Proteus

    In this post, a 7 segment display controlled by PIC16F877A microcontroller simulation in Proteus 8 will be shown.

    The schematic for using PIC16F877A to produce characters on a 7 segment display is shown below-

    PIC16F877A Microcontroller Tutorial using Proteus


     The parts that are used are-
    • PIC16F877A microcontroller
    • 7SEG-COM-CAT-Blue
    • 9C04021A2200FLHF3(220 ohm resistor)
    • 9C08052A1002JLHFT(10k ohm resistor)
    • BUTTON
    • CRYSTAL
    • DIPSW_4
    • SOUNDER
     The assembly source code is below-

    ;=========================
    ; setup and configuration
    ;=========================
        processor 16f877A
        include      <p16f877A.inc>
        __config  _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _LVP_OFF

    #define Pb_sw  4    ; Port A line 4 to push button switch

    porta    equ    0x05
    portb   equ     0x06
    ;============================
    ;      local variables
    ;============================
        cblock    0x20        ; Start of block
        J                ; counter J
        K                ; counter K
        endc
    ;============================================================
    ;                           program
    ;============================================================
        org    0      ; start at address 0
        goto    main
    ;
    ; Space for interrupt handlers
        org        0x08

    main:
        bsf STATUS,RP0
    ; Port A. Five low-order lines set for for input
        movlw    B'00011111'    ; w = 00011111 binary
        movwf    TRISA        ; port A (lines 0 to 4) to input
    ; Port B. All eight lines for output
        movlw    B'00000000'    ; w := 00000000 binary
        movwf    TRISB        ; port B to output
        movlw    0x6
        movwf    ADCON1
        bcf        STATUS,RP0
    ;===============================
    ; Pushbutton switch processing
    ;===============================
    pbutton:
    ; Push button switch on demo board is wired to port A bit 4
    ; Switch logic is active low
        btfss    PORTA,Pb_sw    ; Test and skip if switch bit set
        goto    buzzit        ; Buz if switch ON,
    ; At this point port A bit 4 is set (switch is off)
        call    buzoff        ; Buzzer off
        goto    readdip        ; Read DIP switches
    buzzit:
        call    buzon        ; Turn on buzzer
        goto    pbutton
    ;============================
    ;   dip switch monitoring
    ;============================
    readdip:
    ; Read port A switches
        movf    PORTA,w        ; Port A bits to w
    ; Since board is wired active low then all switch bits
    ; must be negated.  This is done by XORing with 1-bits
        xorlw    b'11111111'    ; Invert all bits in w
    ; Mask off 4 high-order bits
        andlw    b'00001111'        ; And with mask
    ; At this point the w register contains a 4-bit value
    ; in the range 0 to 0xf. Use this value (in w) to
    ; obtain seven-segment display code
        call    segment
        movwf    PORTB        ; Display switch bits
        goto    pbutton
    ;================================
    ;  routine to returns 7-segment
    ;             codes
    ;================================
    segment:
            addwf    PCL,f    ; PCL is program counter latch
            retlw    0x3f    ; 0 code
            retlw    0x06    ; 1
            retlw    0x5b    ; 2
            retlw    0x4f    ; 3
            retlw    0x66    ; 4
            retlw    0x6d    ; 5
            retlw    0x7d    ; 6
            retlw    0x07    ; 7
            retlw    0x7f    ; 8
            retlw    0x6f    ; 9
            retlw    0x77    ; A
            retlw    0x7c    ; B
            retlw    0x39    ; C
            retlw    0x5b    ; D
            retlw    0x79    ; E
            retlw    0x71    ; F
            retlw    0x7f    ; Just in case all on

    ;============================
    ;   piezo buzzer ON
    ;============================
    ; Routine to turn on piezo buzzer on port B bit 7
    buzon:
            bsf        PORTB,7        ; Tune on bit 7, port B
            return   
    ;
    ;============================
    ;   piezo buzzer OFF
    ;============================
    ; Routine to turn off piezo buzzer on port B bit 7
    buzoff:
            bcf        PORTB,7        ; Bit 7 port b clear
            return
    ;=============================
    ;   long delay sub-routine
    ;    (for code testing)
    ;=============================
    long_delay
            movlw    D'200'    ; w = 200 decimal
            movwf    J        ; J = w
    jloop:    movwf    K        ; K = w
    kloop:    decfsz    K,f        ; K = K-1, skip next if zero
            goto     kloop
            decfsz    J,f        ; J = J-1, skip next if zero
            goto    jloop
            return       

            end   

    -------------------------------------------------------------------------

    It's easy to use this assembly code as the firmware code for the 16F877A micro-controller. Double click on the microcontroller and you can see "Edit Firmware" option. Click on that and copy/paste the above code into the firmware source editor.

    PIC16F877A Microcontroller Tutorial using Proteus




    Then click on the Build Project icon to compile the assembly code into Hex code(firmware). You should see Complied Successfully output message with minor warning.

    PIC16F877A Microcontroller Tutorial using Proteus

    Now go back to schematic and click on RUN to run the simulation. You can change the character to be displayed by turning ON/OFF the 4 Dip switch. And you can hear sound when you click on the push button.

    PIC16F877A Microcontroller Tutorial using Proteus


    If you require proteus, see the proteus software download post. See more microcontroller tutorials.

    Kamis, 04 Oktober 2012

    Proteus Microcontroller Project

    This Proteus simulation shows alphanumeric character on a 7 segment display using a PIC16F84A micro-controller.

    The schematic diagram is shown below-


    The components used in the schematic are-
    • 7SEG-COM-CAT-BLUE(7 segment display)
    • 9C04021A2200FLHF3(200 ohm resistor)
    • 9C08052A1002FKHFT(10k ohm resistor)
    • BUTTON
    • CRYSTAL
    • DIPSW_4(switch 4 ports)
    • SOUNDER
    • PIC16F84A(Microcontroller)
     Connect the parts as shown in the schematic. The crystal is connected across the pin 15 and 16. The MCLR is a active low pin for reset which is connected to the +5V source with a 10k ohm series resistor. The microcontroller PIC16F84A has a two I/O ports- port A and port B. Port A will be configured as an input port and the port B will be the output port. The output signal from port B will be connected to the 7 segment display.

    The microcontroller is programmed in assembly language, compiled into hex code and this hex code is burned into the microcontroller in Proteus. But first the program. The assembly program code is below-


    ;=========================
    ; setup and configuration
    ;=========================
        processor 16f84A
        include      <p16f84A.inc>
        __config  _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

    #define Pb_sw  4    ; Port A line 4 to push button switch

    porta    equ    0x05
    portb   equ     0x06
    ;============================
    ;      local variables
    ;============================
        cblock    0x0c        ; Start of block
        J                ; counter J
        K                ; counter K
        endc
    ;============================================================
    ;                           program
    ;============================================================
        org    0      ; start at address 0
        goto    main
    ;
    ; Space for interrupt handlers
        org        0x08

    main:
    ; Port A. Five low-order lines set for for input
        movlw    B'00011111'    ; w = 00011111 binary
        tris    porta        ; port A (lines 0 to 4) to input
    ; Port B. All eight lines for output
        movlw    B'00000000'    ; w := 00000000 binary
        tris    portb        ; port B to output
    ;===============================
    ; Pushbutton switch processing
    ;===============================
    pbutton:
    ; Push button switch on demo board is wired to port A bit 4
    ; Switch logic is active low
        btfss    porta,Pb_sw    ; Test and skip if switch bit set
        goto    buzzit        ; Buz if switch ON,
    ; At this point port A bit 4 is set (switch is off)
        call    buzoff        ; Buzzer off
        goto    readdip        ; Read DIP switches
    buzzit:
        call    buzon        ; Turn on buzzer
        goto    pbutton
    ;============================
    ;   dip switch monitoring
    ;============================
    readdip:
    ; Read port A switches
        movf    porta,w        ; Port A bits to w
    ; Since board is wired active low then all switch bits
    ; must be negated.  This is done by XORing with 1-bits
        xorlw    b'11111111'    ; Invert all bits in w
    ; Mask off 4 high-order bits
        andlw    b'00001111'        ; And with mask
    ; At this point the w register contains a 4-bit value
    ; in the range 0 to 0xf. Use this value (in w) to
    ; obtain seven-segment display code
        call    segment
        movwf    portb        ; Display switch bits
        goto    pbutton
    ;================================
    ;  routine to returns 7-segment
    ;             codes
    ;================================
    segment:
            addwf    PCL,f    ; PCL is program counter latch
            retlw    0x3f    ; 0 code
            retlw    0x06    ; 1
            retlw    0x5b    ; 2
            retlw    0x4f    ; 3
            retlw    0x66    ; 4
            retlw    0x6d    ; 5
            retlw    0x7d    ; 6
            retlw    0x07    ; 7
            retlw    0x7f    ; 8
            retlw    0x6f    ; 9
            retlw    0x77    ; A
            retlw    0x7c    ; B
            retlw    0x39    ; C
            retlw    0x5b    ; D
            retlw    0x79    ; E
            retlw    0x71    ; F
            retlw    0x7f    ; Just in case all on

    ;============================
    ;   piezo buzzer ON
    ;============================
    ; Routine to turn on piezo buzzer on port B bit 7
    buzon:
            bsf        portb,7        ; Tune on bit 7, port B
            return   
    ;
    ;============================
    ;   piezo buzzer OFF
    ;============================
    ; Routine to turn off piezo buzzer on port B bit 7
    buzoff:
            bcf        portb,7        ; Bit 7 port b clear
            return
    ;=============================
    ;   long delay sub-routine
    ;    (for code testing)
    ;=============================
    long_delay
            movlw    D'200'    ; w = 200 decimal
            movwf    J        ; J = w
    jloop:    movwf    K        ; K = w
    kloop:    decfsz    K,f        ; K = K-1, skip next if zero
            goto     kloop
            decfsz    J,f        ; J = J-1, skip next if zero
            goto    jloop
            return       

            end

    -------------------------------------------------------------------------------------------------------------

    Copy the code and double click on the PIC16F84A microcontroller and then click on edit firmware and paste into the source editor.

    7 segment proteus simulation





    Then click on the build project icon to compile the .asm file into hex source code.

    7 segment proteus simulation
    7 segment proteus simulation



    The VMS output should show "Compiled Successfully" as shown below-

    7 segment proteus simulation
    Now come back to the schematic diagram and run the simulation-

    7 segment proteus simulation




    By toggling ON/OFF the 4 DIP switch button the characters in the 7 segment will change.

    7 segment proteus simulation

    Also by pressing the button we will hear a tone from the SOUND part-

    7 segment proteus simulation