Advertisement
Guest User

sdfsdfsdf

a guest
Oct 10th, 2018
166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "P16F1829.inc"
  2.    
  3.     __CONFIG _CONFIG1, (_FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF);
  4.     __CONFIG _CONFIG2, (_WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF);
  5.  
  6.     #define INTERRUPT_FLAGS h'0021' ;BANK 0 General Purpose Registers
  7.     #define TMR0_COUNT      h'0022'
  8.    
  9.     errorlevel -302
  10.                    
  11.     org 0x0              
  12.     goto START
  13.    
  14.     org 0x4             ;Interrupt vector, when an interrupt accors this will be executed. It will goto the ISR label.
  15.     goto ISR
  16.    
  17.    
  18.    
  19. START:
  20.     banksel     OSCCON      ;Select OSCCON register bank (Memory bank 1, address 099h, Datasheet page: 26)
  21.     movlw       b'01011000'     ;Set clock speed to 1MHz (Datasheet page: 70)
  22.     movwf       OSCCON      ;Move the data in WREG to the OSCCON register
  23.    
  24.    
  25.     banksel     OPTION_REG      ;Select OPTION_REG register bank (Memory bank 1, address 095h, Datasheet page: 26)
  26.     bcf         OPTION_REG, TMR0CS  ;0, use internal instruction cycle clock(Fosc / 4)
  27.     bcf         OPTION_REG, PSA ;0, assign prescalar to TMR0
  28.     bsf         OPTION_REG, PS0 ;1
  29.     bsf         OPTION_REG, PS1 ;1
  30.     bsf         OPTION_REG, PS2 ;1 psd<2:0> = 111 = prescalar 1:256
  31.                     ;OPTION_REG: Datasheet page: 185
  32.    
  33.                     ;Fosc = 1MHz, Fcy = 1MHz / 4 = 250Khz.
  34.                     ;TMR0 will be incremented after 256 cycles because of the prescalar, so 250Khz should be devided by 256:
  35.                     ;250Khz / 256 = 976.5625, So the timer will be increment by 976.5625.
  36.                     ;TMR0 can't count >255 so every 255 increments an interrupt occurs and TMR0 is set back to 0;
  37.                     ;976.5625 / 255 = 3.8296568627, this is how many interrupts happen each second.
  38.                     ;1 / 3.8296568627 = 0.2612, this means it takes 261.12 milisecond for each interrupt.
  39.                     ;
  40.                     ;The LED should blink every second, we can conclude that if there would be 4 interrupts arround 1 second would have passed (1.04448 to be precise).
  41.                     ;To get close to 1 second preciser, the prescalar should be decreased, this causes more interrupt which will be more precise.
  42.                     ;The disadvantage of using a lower prescalar is that more interrupts will occur, this means your main code will be interuppted more.
  43.    
  44.  
  45.                     ;LED(DS4) is connected to RC3, by default all the C port pins are set to intput (Datasheet page: 32). RC3 should be set to output.
  46.     banksel     TRISC       ;Select TRISC register bank (Memory bank: 1, address: 08Eh, Datasheet page: 26)
  47.     bcf         TRISC, RC3      ;0, set RC3 to as output (Datasheet page: 136), 0 = output, 1 = input.
  48.    
  49.     banksel     LATC        ;Select LATC register bank (Memory bank 2, address 10Eh, Datasheet page: 26)
  50.     bcf         LATC, RC3       ;0, clear RC3 in the LATC register (Datasheet page: 136)
  51.        
  52.    
  53.     banksel     INTERRUPT_FLAGS
  54.     clrf        INTERRUPT_FLAGS ;Clear INTERRUPT_FLAGS, this is a shadow register for the Flag bits in the INTCON register.
  55.     clrf        TMR0_COUNT      ;Clear TMR0_COUNT, this register is increment when an overflow occurs for TMR0.
  56.    
  57.    
  58.     bsf         INTCON, TMR0IE  ;1, Enables the Timer0 overflow interrupt
  59.     bcf         INTCON, TMR0IF  ;0, Clear Timer0 Overflow Interrupt Flag bit
  60.     bsf         INTCON, GIE     ;1, Enables all active interrupts
  61.                     ;INTCON: Datasheet page: 90
  62.    
  63.     goto MAIN
  64.    
  65.    
  66.  
  67. ISR_TMR0_OVERFLOW:    
  68.     banksel     INTERRUPT_FLAGS
  69.     bsf         INTERRUPT_FLAGS, TMR0IF ;1, Set the TMR0IF bit in the shadow register INTERRUPT_FLAGS
  70.    
  71.     bcf         INTCON, TMR0IF      ;0, Clear TMR0IF
  72.     return
  73.    
  74.    
  75. ISR:  
  76.     btfsc       INTCON, TMR0IF      ;Check if the TMR0IF overflow flag is set, this bit is set when an overflow happends in Timer0
  77.     call        ISR_TMR0_OVERFLOW      
  78.    
  79.     retfie
  80.    
  81.  
  82. LED_TURNON:
  83.     banksel     LATC            ;Select LATC register bank (Memory bank 2, address 10Eh, Datasheet page: 26)
  84.     bsf         LATC, RC3           ;1, Set RC3 bit in the LATC register to 1
  85.     return
  86.    
  87.    
  88. LED_TURNOFF:
  89.     banksel     LATC            ;Select LATC register bank (Memory bank 2, address 10Eh, Datasheet page: 26)
  90.     bcf         LATC, RC3           ;0, Clear RC3 bit in the LATC register to 1
  91.     return
  92.    
  93.    
  94. LED_TOGGLE:
  95.     banksel     LATC            ;Select LATC register bank (Memory bank 2, address 10Eh, Datasheet page: 26)       
  96.     movf        LATC, W         ;Move the LATC register to WREG
  97.    
  98.     btfsc       WREG, RC3           ;Check if RC3 bit is set in WREG (WREG contains a copy of the LATC register)
  99.     call        LED_TURNOFF
  100.                         ;The reason why we make a copy of LATC to WREG and use WREG to check the RC3 bit, is because if we would use the
  101.                         ;LATC register directly, after the LED is turned off the RC3 bit is set to 0. When the code goes to
  102.                         ;the next operation (btfsss WREG, RC3) to check if the RC3 bit is 0, it is 0 because we turned it off in the previous line,
  103.                         ;the result is that btfss won't skip the next operation and turns on the LED.
  104.                         ;Conclusion: if we don't make a copy of LATC to WREG and use LATC directly the LED would always be on.
  105.    
  106.     btfss       WREG, RC3           ;Check if RC3 bit is clear in WREG (WREG contains a copy of the LATC register)
  107.     call        LED_TURNON         
  108.    
  109.     banksel     TMR0_COUNT          ;LED is now toggled and we can CLEAR the TMR0_COUNT. The code will now wait another 4 Timer0 overflow interrupts
  110.     clrf        TMR0_COUNT          ;before toggling the LEDs again.
  111.    
  112.     return
  113.  
  114.    
  115. TMR0_OVERFLOW:
  116.     banksel     TMR0_COUNT     
  117.     incf        TMR0_COUNT          ;Increment TMR_COUNT.
  118.    
  119.     movf        TMR0_COUNT, W       ;Move TMR0_COUNT in WREG
  120.     xorlw       b'00000100'         ;Do a XOR operation on WREG and the LITERAL: '00000100'(4), If WREG is equal to the LITERAL then the Z bit in the STATUS register is set to 1.
  121.     btfsc       STATUS, Z           ;Check if Z = 1.
  122.     call        LED_TOGGLE
  123.    
  124.     banksel     INTERRUPT_FLAGS
  125.     bcf         INTERRUPT_FLAGS, TMR0IF ;Clear the first bit.
  126.     return
  127.    
  128.    
  129. MAIN:
  130.     btfsc       INTERRUPT_FLAGS, TMR0IF ;If the TMR0IF bit is set in the INTERRUPT_FLAGS regiser, TMR0_OVERFLOW will be called. The TMR0IF bit is set when Timer0 overflows and gives an interrupt.
  131.     call        TMR0_OVERFLOW
  132.    
  133.     goto        MAIN            ;Infinite loop MAIN.
  134.     end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement