Pic tutorial :: Examples for subsystems

Examples for subsystems

 

Introduction

Every microcontroller comprises a number of subsystems allowing for flexibility and wide range of applications. These include internal EEPROM memory, AD converters, serial or other form of communication, timers, interrupts, etc. Two most commonly utilized elements are interrupts and timers. One of these or several in combination can create a basis for useful and practical programs.

Writing to and reading from EEPROM

Program "eeprom.asm" uses EEPROM memory for storing certain microcontroller parameters. Transfer of data between RAM and EEPROM has two steps - calling macros eewrite and eeread. Macro eewrite writes certain variable to a given address, while eeread reads the given address of EEPROM and stores the value to a variable.

Macro eewrite writes the address to EEADR register and the variable to EEDATA register. It then calls the subprogram which executes the standard procedure for initialization of writing data (setting WREN bit in EECON1 register and writing control bytes 0x55 and 0xAA to EECON2).

/*  SOURCE : WWW.ROMUX.COM
    AUTHOR : romux team     */ 
    
    
EEWRITE  MACRO ADDR,PROM
MOVLW  ADDR                    ;Pass   che parameters   to  subprogram E2write    
MOVWF   EEADR
MOVF  PROM,W
MOVWF  EEDATA
CALL  E2WRITE                ;Call E2write  which initializes writing  data 
PAUSEMS   .10                ;10ms  delay
ENDM

E2WRITE
BCF  IHTC0N,GIE                ;disable  all  interrupts
BSF  STATUS,RPO                ;select bank  1
BSF EEC0N1,WREN             ;set UREN bit  in EEC0N1
MOVLW  0X55                 ;write  0x55   to  EEC0N2
MOVWF  EEC0N2 
MOVLW 0XAA                     ;write  Oxaa  to  EEC0N2,   as
MOVWF  EEC0N2                 ;writing  confirmation
BSF EEC0N1,WR                 ;set bit WR  to  initialize  writing
BCF  STATUS,RPO 
RETURN

EEREAD MACRO ADDR,PROM        ;Pass  the parameters   to  subprogram E2read
MOVLW ADDR 
MOVWF EEADR 
CALL  E2READ                  ;Call E2write  which  initializes   reading data
MOVWF PROM 
ENDM

E2READ
BSF  STATUS,RPO
BSF EEC0N1,RD 
BCF  STATUS,RPO 
MOVF    EEDATA,W 
RETURN      
      

For data to be actually stored in EEPROM, 10ms delay is necessary. This is achieved by using macro pausems. In case that this pause is unacceptable for any reason, problem can be solved by using an interrupt for signaling that data is written to EEPROM.

 

eewrite macro addr, var
   
addr Destination address. With PIC16F84, there are 68 bytes
  of EEPROM for a total address range of 0x00 - 0x44.
var Name of the variable to be stored to EPROM
   
eeread macro addr, var
   
addr Destination address. With PIC16F84, there are 68 bytes
  of EEPROM for a total address range of 0x00 - 0x44.
var Name of the variable into which data read from EPROM will be stored.

 

Example: Variable volume, which is set via buttons RA0 and RA1, will be stored to the address 0 of EEPROM. After reboot, when the program is started, it first loads the last known value of variable volume from EEPROM.

/*  SOURCE : WWW.ROMUX.COM
    AUTHOR : romux team     */ 
    
    
            PROCESSOR   16F84
            #INCLUDE  "P16F84.INC"
__COHFIG   _CP_0FF   &  _WDT_0FF  &   _PWRTE_0N   &  _XT_0SC

CBLOCK     0X0C         ;   RAM starting  address
HICNT
LOCNT
LOOPCNT 
VOLUME 
ENDC 

ORG    0X00
GOTO    MAIN
ORG    0X04
GOTO    MAIN

INCLUDE  "ROMUX_LIB.INC"
INCLUDE  "BUTTON.INC "
INCLUDE  "EEPROM.INC"

MAIN                                ;main program

            BANKSEL  TRISB
             CLRF  TRISB
            BANKSEL   P0RTB

            EEREAD 0X00,VOLUME        ;Read  the  previous  value   of volume movwf   P0RTB
LOOP
            BUTTON PORTA,0,0,INCREASE 
            BUTTON PORTA,1,0,DECREASE
            GOTO   LOOP

INCREASE

            INCF VOLUME,F            ;Increase volume by 1 
            MOVF VOLUME,W            ;display  on port B
            MOVWF P0RTB
            EEWRITE 0X00,VOLUME        ;write  to   eeprom,   address   0x00
            GOTO   LOOP



DECREASE
            DECF  VOLUME,F            ;Decrease volume by 1
            MOVF  VOLUME,  W         ;display  on port B
            MOVWF   P0RTB
            EEWRITE   0X00,VOLUME    ;Write  to   eeprom,   address   0x00

            GOTO   LOOP



            ORG 0X2100               ; Star ting value of EEPROM address zero
            DE   .5                 ;after  the microcontroller   is programmed  is   0x05
            END
      
      

 

Processing interrupt caused by changes on pins RB4-RB7

Program "intportb.asm" illustrates how interrupt can be employed for indicating changes on pins RB4-RB7. Upon pushing any of the buttons, program enters the interrupt routine and determines which pin caused an interrupt. This program could be utilized in systems with battery power supply, where power consumption plays an important role. It is useful to set microcontroller to low consumption mode with a sleep instruction. Microcontroller is practically on stand-by, saving energy until the occurrence of interrupt.

Example of processing interrupt caused by changes on pins RB4-RB7

/*  SOURCE : WWW.ROMUX.COM
    AUTHOR : romux team     */ 
    
    
            PROCESSOR   16f84                    
            #include  "P16F84.inc"            
__CONFIG _CP_0FF & _WDT_0FF  &  _PWRTE_0N  &  _XT_0SC        

            ORG 0X00 
            GOTO MAIN 
            ORG 0X04 
            GOTO  ISR                    
MAIN                        
            BANKSEL  TRISB                    
            MOVLW 0XF0                     ;Higher   four  LED  diodes  are   on
            MOVWF  TRISB 
            BANKSEL   P0RTB 
            MOVLW OXFF 
            MOVWF   P0RTB
                            
            BSF  INTC0N,RBIE            ;interrupt upon pin change   enabled        
            BSF   INTC0N,GIE            ;all  interrupts  are  enabled        

LOOP                                    ;Main loop        
            GOTO  LOOP
ISP                        
            BCF  INTC0N,RBIF            ;Clears   the  flag that  indicates RB  interrupt 
                                        ;took place  thus  enabling detection of 
                                        ;new interrupts  in main program        
            BTFSS  P0RTB,7                 ;determining  which  button caused the  interrupt
            GOTO  LEDO 
            BTFSS  P0RTB,6 
            GOTO  LEDL 
            BTFSS  P0RTB,5 
            GOTO  LED2 
            BTFSS  P0RTB,4 
            GOTO  LED3 
            RETFIE
                
LEDO                        
            BCF  P0RTB,0             ;Switch  off  diode  LD0
            RETFIE            
LEDL                        
            BCF  P0RTB,1             ;Switch  off  diode  LD1
            RETFIE            
LED2                        
            BCF  P0RTB,2             ;Switch  off  diode  LD2
            RETFIE            
LED3                        
            BCF  P0RTB,3             ;Switch  off  diode  LD3
            RETFIE 
            END      
      

 

Processing interrupt caused by change on pin RB0

Example "intrb0.asm" demonstrates use of interrupt RB0/INT. Upon falling edge of the impulse coming to RB0/INT pin, program jumps to subprogram for processing interrupt. This routine then performs a certain operation, in our case it blinks the LED diode on PORTB, 7.

Example of processing interrupt caused by changes on pin RB0

/*  SOURCE : WWW.ROMUX.COM
    AUTHOR : romux team     */ 
    
    
    PROCESSOR   16f84            
    #include  "P16F84.inc"            
    __CONFIG _CP_0FF  &   _WDT_0FF  &  _PWRTE_0N  &  _XT_0SC            

            ORG 0X00            
            GOTO MAIN            
            ORG 0X04            
            GOTO  ISR            
MAIN                
            BANKSEL TRISB            
            MOVLW B'00000001'                 ;RB0  is   input,   the  rest are   output            
            MOVWF  TRISB            
            BANKSEL  OPTI0N_REG            
            BCF  OPTI0N_REG,INTEDG          ;interrupt  occurs  at faling edge            
            BSF   OPTI0N_REG,N0T_RBPU       ;intemal pull-up  resistors  are  off            
            BANKSEL  P0RTB            
            CLRF  PORTB            
            BSF   P0RTB,7                                   ;0nly LED  diode  P0RTB,7  is   on            
            BSF   INTC0N,INTE                          ;interrupt RB0  enabled            
            BSF  INTC0N,GIE                            ;all  interrupts  enabled            
LOOP                
            GOTO  LOOP                                       ;Main loop            
ISR                
            BCF  INTC0N,INTF                   ;Clears  the  flag that indicates  RB  interrupt            
                                            ;took place  thus  enabling detection of            
                                            ;new interrupts  in main program            
            BTFSS  PORTO,7                   ;Is  LED7  on?            
            GOTO  LABI            
            BCF  PORTO, 7                   ;If  true  switch off  LED7            
            RETFIE            
LABI                
            BSF   P0RTB,7                   ;If  false  switch on LED7            
            RETFIE            
            END      
      

 

Processing interrupt caused by overflow on timer TMR0

Program "inttmr0.asm" illustrates how interrupt TMR0 can be employed for generating specific periods of time. Diodes on port B are switched on and off alternately every second. Interrupt is generated every 5.088ms; in interrupt routine variable cnt is incremented to the cap of 196, thus generating approx. 1 second pause (5.088ms*196 is actually 0.99248s). Pay attention to initialization of  OPTION register which enables this mode of work for timer TMR0.

Example of processing interrupt caused by overflow on timer TMR0

/*  SOURCE : WWW.ROMUX.COM
    AUTHOR : romux team     */ 
    
    
            PROCESSOR   16f84 
            #include  "P16F84.inc"
__CONFIG   _CP_0FF  &  _WDT_0FF  &  _PWRTE_0N   &  _XT_0SC

CNT          EQU  0X0C

            ORG    0X00                ;Reset vector
            GOTO    MAIN
            ORG    0X04                ;Interrupt vector
            GOTO    ISR

MAIN
            BANKSEL TRISB
            CLRF    TRISB            ;Port B   is  output
            MOVLW    0xFF
            MOVWF TRISA                ;Port A  is  input

 
            MOVLW B'10000100'          ;Set prescaler  to  TMRO BANKSEL  0PTI0N_REG
            MOVWF OPTI0N_REG           ;ps   =  32 => TMRO   is   incremented  every 32us BANKSEL  P0RTB
            CLRF P0RTB              ;A11   the  diodes  are  off by default
            BSF INTC0N,T0IE         ;Enable  TMRO  interrupt
            MOVLW                     .96;initialize TMRO
                                    ;Overflow  occurs
                                    ;every   (255-96)*32us=5.088ms
            MOVWF TMRO                ;Start  the   counter            

            BSF   INTC0N,GIE         ;Interrupts  are  globally enabled
            CLRF  CNT
LOOP    
            GOTO  LOOP                ;Remain  at  this  line
ISR    
            MOVLW  .96                ;Initialize TMRO   to   ensure  next interrupt
                                    ; in  5ms
            MOVWF TMRO
            BCF  INTCON              ;clear   int.   flag
            INCF   CNT,F
            MOVLW  .196                ;Has  one   second  elapsed?(ls~196*5.088 ms
            SUBWF   CNT,W
            BTFSS   STATUS,Z
            RETFIE
            COMF      P0RTB,F        ;If  true,   complement the  values   of port B
            CLRF   CNT                ;and set  the   initial value  of  variable   cnt
            RETFIE                    ;If  false,   exit  the   interrupt routine
            END                        ;END of program
      
      

 

Processing interrupt caused by overflow on TMR0 connected to external input (TOCKI)

Counter TMR0 increments upon signal change on pin RA4/TOCKI. Prescaler is set to 4, meaning that TMR0 will be incremented on every fourth impulse. Pay attention to initialization of  OPTION register which enables this mode of work for timer TMR0 (this mode is common for devices such as counters).

Example of processing interrupt caused by overflow on timer TMR0 connected to TOCKI

/*  SOURCE : WWW.ROMUX.COM
    AUTHOR : romux team     */ 
    
    
            PROCESSOR  16f84                
            #include  "P16F84.inc"        
__CONFIG _CP_0FF  &    _WDT_0FF & _PWRTE_0N & _XT_0SC        
        
    NUM_REV     EQU   .100            ;        (1-256)        
                
            ORG 0X00
            GOTO MAIN                ;  Reset vector        
            ORG 0X04 
            GOTO ISR                ;   Interrupt vector        

Main        BANKSEL TRISB                
            CLRF TRISB                ;   Port B  is  input        
            MOVLW TRISA                ;   Port A is  output        
            MOVLW B'10100001'        ;  External  impulses  on T0CKI   increment 
                                    ;  TMRO        
            MOVWF OPTI0N_REG        ;  ps  =   4 TMRO  increments  every  4 impulses        
            BANKSEL P0RTB            ;   i.e.   1  revolution  =  4  impulses        
            CLRF PORTB                ;  All  diodes   are   off  by  default        
            BSF INTC0N,T0IE            ;  Enable  TMRO  interrupt        
            MOVLW .256                ;   Initialize  TMRO  so  that  overflow        
            SUBLW NUM_REV            ;   occurs   every 100  revolutions, 
                                    ;   i.e.   TMRO  is  set to  156 ;   256-156=100)        
            MOVWF TMRO                ;   Start the  counter        
            BSF INTC0N,GIE            ;   Interrupts   are  globally  enabled        
LOOP
            MOVF TMRO,W                ;   Display number  of  remaining revolutions 
                                    ;   on port B        
            SUBLW .256 
            MOVWF  P0RTB            ;   number  of   remaining revolutions=256-TMRO        
            GOTO   LOOP                ;   Remain at  this  line        
ISR                    
            MOVLW .256                ;   Initialize TMRO   so   it can count next 
                                    ;   100  revolutions        
            SUBLW  NUM_REV 
            MOVWF TMRO        
            BCF INTC0N,T0IF         ;   clear   int.   fleg                
            RETFIE                    ;   return to  main program        
            END                        ;   END of  program    
        
      
      

 









Post Your Comments Here :
 


User Login

Username :


Password :