MCU Examples.com
PIC Microcontroller Project Examples, free source codes and resources collection.
;Program Macros and Functions ;Program Macros ;UART Initialization Macro ;=============================================================================; The macro is used to initializes Universal Asynchronous Receiver Transmitter ; module with a Baud rate of 9600bps and the crystal used is a 20MHz crystal. ;============================================================================= Initialise_UART macro ; initialize for 9600bps with 20Mhz crystal ; Setting PORTC 7th pin as input to receive serial data from the weighing ; scale and PORTC 6th pin as output to send serial data to the computer for ; testing the system. banksel TRISC bsf TRISC,7 ;I/p to MCU bcf TRISC,6 ;O/p from MCU ; Decimal value 129 (from the PIC16F877A datasheet) is written to SPBRG ; register since the desired baud rate is 9600bps and the crystal used is ; 20MHz. banksel SPBRG movlw .129 ; literal value .129 is moved to Working Register movwf SPBRG ; decimal value of 129 in Working Register is moved to SPBRG ; Since the desired baud rate is high 9600bps and the transmission mode is ; asynchronous the second bit 'BRGH' in TXSTA register needs to be set and ; fourth bit 'SYNC' needs to be cleared. banksel TXSTA ; Bank containing TXSTA register is selected bsf TXSTA,BRGH ; BRGH bit is set since transmission mode is high ; speed asynchronous transmission bcf TXSTA,SYNC ; the SYNC bit is cleared since the transmission mode ; is asynchronous ; In order to receive or send data the RC7 and RC6 pins need to be configured ; as serial port pins and according to the system the data needs to be ; received continuously. banksel RCSTA ; Bank containing RCSTA is selected bsf RCSTA,SPEN ; 7th bit of RCSTA register 'SPEN' is set to configure ; RC7 and RC6 pins as serial port pins (serial port ; enabled) bcf RCSTA,CREN ; Continuous reception of data is disabled nop bsf RCSTA,CREN ; Continuous reception of data is enabled by setting ; the 'CREN' bit banksel RCREG movf RCREG,W ; Making sure that there are no framing errors ; initially, by moving the value in RCREG to Working ; Register banksel PIE1 ; Bank containing PIE1 register is selected bsf PIE1,RCIE ; Since a data byte reception is identified by an ; interrupt RCIE is set to enable USART receive ; interrupt banksel PORTB ; Bank containing PORTB is selected before ending the ; macro endm ;________________________________________Delay Macro ;============================================================================= ; A delay macro designed to be used in a program where a 20MHz oscillator is ; used. In this macro the value given in par1 is taken and it is decreased 1 ; by 1 until zero and each time the value is decreased by 1 the program is ; delayed almost by 1ms before another literal 1 is reduced from the current ; value. By this method it is possible to get the delay time defined by the ; par1 value in milliseconds. ;============================================================================= pausems macro par1 ; par1 is the delay time required ; Labels only for the macro are defined local Dec_Loop local Delay_Loop_1 local Delay_Loop_2 local Decrease local Delay_1ms local exit movlw HIGH par1 ; High part of the parameter 'par1' is saved to ; the Working Register movwf HIprt ; Value in the Working Register is moved to the ; HIprt variable movlw LOW par1 ; Low part of the parameter 'par1' is saved to ; the Working Register movwf LOprt ; Value in the Working Register is moved to the ; LOprt variable Dec_Loop movf LOprt, F btfsc STATUS, Z ; Value in LOprt is checked for zero goto Decrease ; If the value is zero program jumps to Decrease call Delay_1ms ; If the value is not zero a 1ms delay is given decf LOprt, F ; After the delay the value in LOprt is decremented by ; 1 and the result is saved in LOprt variable goto Dec_Loop ; Program goes to Dec_Loop Decrease movf HIprt, f btfsc STATUS, Z ; Value in HIprt is checked for zero goto exit ; If the value is zero it means that the value ; in both HIprt and LOprt is zero so the value ; is decreased up to zero so the program exits ; from the macro by jumping to exit. call Delay_1ms ; If the value in HIprt is not zero again 1ms ; delay is given decf HIprt, f ; Value in HIprt is decreased by 1 decf LOprt, f ; Value in LOprt is decreased by 1 goto Dec_Loop ; The Program jumps to Dec_Loop ; This is the function written inside the macro to give a delay of ; approximately 1ms. 1 instruction takes 0.2 microseconds to execute when a ; 20MHz oscillator is used. Delay time required is 1ms therefore number of ; instructions required to get 1ms delay is 1ms/0.2us = 5000 so two loops were ; made to execute 5000 instructions where each loop executes almost 2500 ; instructions when each exits from their respective loops. Delay_1ms movlw .250 ; Literal 250 is moved to the Working Register. movwf LOOPcnt1 ; Value in Working Register is moved to LOOPcnt1 ; variable. movlw .250 ; Literal 250 is moved to the Working Register. movwf LOOPcnt2 ; Value in Working Register is moved to LOOPcnt2 ; variable. ; Value in LOOPcnt1 is decreased by one each time as the program goes one loop ; in Delay_Loop_1 thereby executing almost 2500 instructions when the program ; exits from the Delay_Loop_1 Delay_Loop_1 clrwdt ; Watch Dog Timer is cleared since the program ; continues in the loop for a long time. The ; instruction takes one instruction cycle ; 5 nop command are given to get the loop to have 10 instruction cycles per ; loop. Each nop command takes one instruction cycle to execute. nop nop nop nop nop clrwdt ; Watch Dog Timer is cleared and the instruction takes ; one instruction cycle decfsz LOOPcnt1, f ; Value in LOOPcnt1 is decremented by 1 and the result ; is stored in LOOPcnt1. For decrementing the value in ; LOOPcnt1 by 1 it takes one instruction cycle and for ; skipping is zero it takes another one instruction ; cycle. goto Delay_Loop_1 ; If the result after decreasing LOOPcnt1 by 1 is not ; zero the program jumps to Delay_Loop_1 to continue ; the loop. ; Once the value in LOOPcnt1 is zero program comes to Delay_Loop_2 where the ; value in LOOPcnt2 is decreased by one each time as the program loops thereby ; executing almost another 2500 instructions when the program exits from the ; Delay_Loop_2 and hence 5000 instructions executed when exiting from the ; function. Delay_Loop_2 clrwdt nop nop nop nop nop clrwdt decfsz LOOPcnt2, f goto Delay_Loop_2 return exit endm ; End of the pausems macro. ;________________________________________
;Program Functions ;Function to Multiply a Value by 10 ;============================================================================= ; This is a function developed to multiply the value in mul_x variable by 10 ; and save the result in mul_z ;============================================================================= multiply_by_10 ; xy x<2 banksel mul_z ; Bank containing mul_z is selected clrf mul_z ; mul_z variable is cleared movlw .10 ; Literal value 10 is taken to the Working Register ; since the multiplying factor is 10 movwf mul_y ; Value in working register is moved to mul_y variable movf mul_x,W ; value in mul_x, the value that needs to be multiplied ; by 10, is taken to the Working Register ; This loop keeps on adding the value in the Working Register to the value in ; mul_z until the value in mul_y , which is 10, is decremented by one upto ; zero. ; This process is equivalent to multiplying the value in the Working Register ; by 10.Program exits from the loop once the value in mul_y is zero. add_10_times addwf mul_z,F ; Value in working register is added with value in ; mul_z decfsz mul_y,F ; Each time the value in Working Register is added ; with value in mul_z the value in mul_y is ; decremented by one goto add_10_times ; If the value in mul_y is not zero the program goes ; back to add_10_times movf mul_z,W ; Once the value in mul_y is zero the value in mul_z ; is taken to the Working Register before the program ; returns from the function return ;________________________________________ ;Function to Multiply a Value by 100 ;________________________________________ ;============================================================================= ; This is a function developed to multiply the value in mul_x variable by 100 ; and save the result in mul_z ;============================================================================= multiply_by_100 ; xy x<2 banksel mul_z ; Bank containing mul_z is selected clrf mul_z ; mul_z variable is cleared movlw .100 ; Literal value 100 is taken to the Working Register ; since the multiplying factor is 100 movwf mul_y ; Value in working register is moved to mul_y variable movf mul_x,W ; value in mul_x, the value that needs to be ; multiplied by 100, is taken to the Working Register ; This loop keeps on adding the value in the Working Register to the value in ; mul_z until the value in mul_y , which is 100, is decremented by one up to ; zero. This process is equivalent to multiplying the value in the Working ; Register by 100.Program exits from the loop once the value in mul_y is zero. add_100_times addwf mul_z,F ; Value in working register is added with value in mul_z decfsz mul_y,F ; Each time the value in Working Register is added ; with value in mul_z the value in mul_y is ; decremented by one goto add_100_times ; If the value in mul_y is not zero the program goes ; back to add_100_times movf mul_z,W ; Once the value in mul_y is zero the value in mul_z ; is taken to the Working Register before the program ; returns from the function return ;________________________________________ ;Function to Identify the Starting Point Of Data Packet from the 40 Data Bytes Saved ;________________________________________ ;;=============================================================================; When the program comes here there are data bytes saved from register 0x40 to ; 0x68 by indirect addressing. The starting point of a complete data packet ; from the weighing scale is identified by this function and the starting ; ASCII character is assumed to be 'B'. ;============================================================================= String_start ; Initially starting address value, where the 40 data bytes are saved, is ; moved to the FSR register. movlw 0x40 movwf FSR check_string_start movf INDF,W ; Value in INDF Register is taken to Working Register ; (simillar to taking the value from the FSR Register) ;***************************************************************************** xorlw 'B' ; Exclusive OR operation between the value in Working ; Register and literal ASCII character B btfsc STATUS,Z ; Similarity between the value in Working Register and ; literal ASCII character B is checked by checking the ; Z bit of the STATUS register goto process_weight_val ; If Z is set it means that the two values are ; equal therefore the program jumps to the label ; process_weight_val which is found in the main ; program ;***************************************************************************** incf FSR,F ; If the two values did not match the Z bit is clear ; and the value in FSR register is incremented by one movf FSR,W ; Then the value in FSR Register taken to the Working ; Register xorlw 0x68 ; Exclusive OR operation between the value in the ; Working Register and the literal 0x68 where 0x68 is ; the address value of the final byte of the 40 byte ; string is saved. btfss STATUS,Z ; Equality of the value in the Working Register and ; the literal 0x68 is checked by checking the status ; of the Z bit in the STATUS Register goto check_string_start ; Z clear means that the values did not match ; therefore the program jumps to ; check_string_start label in the function goto start ; Z set means that the two values had matched ; therefore the program jumps to start label in ; the main program return ;________________________________________ ;Function to Transmit a Value from the PIC to the Computer ;________________________________________ ;============================================================================= ; This function is used to transmit a data byte through the serial port RC6 ; but before calling this function the value that is to be transmitted needs ; to be in the Working Register ;============================================================================= UART_Print_Char banksel TXREG ; Bank containing TXREG is selected movwf TXREG ; The data that is to be transmitted is moved to the ; TXREG register ;***************************************************************************** banksel TXSTA bsf TXSTA,TXEN ; To transmit data transmission is enabled banksel PIR1 ; Bank containing PIR1 is selected ;***************************************************************************** ; The data in the TXREG register is not directly transmitted instead it is ; moved to the TSR register after the stop bit of the previous data loaded to ; TSR register is sent when this occur the TXIF flag bit in PIR1 register is ; set so by checking the TXIF flag bit it is possible to check whether the ; data transmission is complete. chk_again btfss PIR1,TXIF ; checking TXIF flag bit goto chk_again ; if TXIF is not set the program goes to ; chk_again to check TXIF flag bit, if TXIF flag ; bit is set the program exits from the macro ; since the desired data byte is sent. RETURN