🔌
PIC16F877A
📌
This page will help me with the final exam when solving the hardware question, specifically in writing
the text file and starting to code.
Brain Storming “ for text file and coding steps “
Ports and Pins
We have 5 ports with 33 I/O pins.
PORT A
1. Consists of 6 pins.
2. Defult set is Analog ( when reset / power on )
PORT B
1. Consists of 8 pins.
2. pins (RB0 , RB4-RB7) can generate an interrupt.
PORT C
1. Consists of 8 pins.
2. PORT C gives access to timers and serial ports.
PORT D
1. Consists of 8 pins.
2. Port D can be used as a slave port
PORT E
1. Consists of 3 pins.
2. Defult set is Analog ( when reset / power on )
3. Provide the control pins to make Port D used as a slave port.
Port Function
PIC16F877A
1
this picture to know the exact bits used for your chosen << operation
mode
>>
Indirect access with arrays
need to use a SFR called FSR and INDF is used to get the content of the address
pointed by FSR.
Indirect addressing is very convenient for manipulating data arrays located in GPR
registers.
In this case, it is necessary to initialize FSR register with a
starting address of the array, and the rest of the data can be
accessed by incrementing the FSR register.
Memory Organization
In PIC16F877A, there are 3 memories : Program memory, Data memory and EEPROM memory
Program memory:
PIC16F877A
is divided to 4 banks, each bank contains SFRs, GFRs
2
The most
important registers
have addresses in all the four banks
Bank 0 is the defult bank
Ex: 0Bh address is reserved for INTCON register (bank 0)
Bank 1 contains (TRISA, TRISB, TRISC, TRISD and TRISE) : used to define ( input or
output for the ports ).
Reset Vector
= 0000h (the program will go here on reset)
= 0004h (the program will go here on interrupt)
Interrupt Vector
SFRs “Special Function Registers”
1. STATUS register
2. OPTION_REG register
3. INTCON register
4. How to declare Timer 0 using INTCON, STATUS ?
MOVLW
MOVWF
MOVLW
MOVWF
b'11011000'
OPTION_REG
b'10100000'
INTCON
;
; TMR0 initialisation code
; Int clock, no prescale
; /* Enable the GIF "bit7",
Enable TMR0 interrupt
and TMR0 overflow bit "5" */
Instruction set
Interrupt sources and their bits.
PIC16F877A
3
FOR PWM
https://www.instructables.com/Generating-50Hz-PWM-Using-PIC16F877A/
https://exploreembedded.com/wiki/PIC16F877A_PWM
chromeextension://efaidnbmnnnibpcajpcglclefindmkaj/http://www.mwftr.com/book/PIC_CharlesKim_13.pdf
https://circuitdigest.com/microcontroller-projects/pic-microcontroller-pic16f877a-pwm-tutorial
https://forum.allaboutcircuits.com/threads/generating-a-sound-with-pic-assembly.90874/
http://www.mastincrosbie.com/mark/electronics/pic/fastflash.html
https://www.microchip.com/forums/m161528.aspx
https://www.microchip.com/forums/m164978.aspx
https://pic-microcontroller.com/create-musical-tone-using-pic-code/
http://microcontrollerprojects00.blogspot.com/2012/06/generate-sound-and-melody-using-pic.html
https://maker.pro/forums/threads/understanding-pwm-with-pic-assembly.269449/
https://openlabpro.com/guide/pwm-in-pic16f877a/
Exercise for writing the .txt file in the final “Explain the steps for KeyPad Project”
1. To implement a keypad, 7 pins from PIC16F877A are needed: 3 pins for columns and 4 pins for
rows. PortD pins will be used, specifically (RD0-RD2) for columns and (RD4-RD7) for rows.
2. Rows will be used as output, columns will be used as inputs.
3. The 7 segment will be connected to PORTC, (RC1 -RC7) and they gonna be assign using TRISC
as an output.
4. The idea here is to read the selected button using a combination of output and input bits (rows,
columns). If the pair contents are both (0,0), then that means this is the selected button.
5. I will assume that all the rows and columns are initially high ( inputs), and the keystroke can be
detected by setting each row to low (output) and check each column for a zero. when match print
the number.
6. This works assuming number 2 is pressed, so that means the first row should be zero (RD4 = 0)
and the second column must be 0 (RD1). This leads to a voltage difference and the current will
PIC16F877A
4
flow to RD4.
7. To achieve this result, a variable called "key" will be declared. This key will count the number of
tested keys when each key on the keypad is checked. So when a button is detected, the scan of
the keypad is terminated with the current key number in the counter.
8. So the main loop in this project will contain the scanning subroutine and displaying subroutine.
9. the Scanning subroutine will have the following behavior:
a. Clear the key counter ( After each time we read the button we have to clear it, to start detecing
again)
b. Set the carry Flag using STATUS register. ( will be used to restart the count of rows after we
reach the last row )
c. Set the fist row to 0
d. and created a lable called newrow that GOTO row lable
10. Row lable will be used to check each colunm for the specified row, Pins RD0, RD1, RD2 will be
tested if they are zero, if any match return from scanning and print the number, also here before
testing the pin the keys varaiable should be incremented by 1.
11. in ROW lable if non of the columns are presed, then go to the next row, and this can be done
using the Rotate left instruction ( RLF) and after that goto the scanning to check again the three
colums.
12. The behavior of the scanning subroutain was desciribed as above, when there is a match the
displaying subroutine wil excute.
13. The display subroutine has a defined lookup table that has the vlaues of the keypad ( 0,1,2 …. *,
#)
14. this lookup table return a literal with the help of the key variable to choose the right value.
15. the chosen varaible will be displayed in portC where the 7 segment is connected.
16. the program keeps excuting in an infinte loop since we are not using an intturput.
Exercise for writing the .txt file in the final “Explain the steps for VINTEST Project”
1. To implement an ADC test circuit, the LCD will be connected to port D, and a 4-bit mode will be
implemented to reduce the number of bits used.
2. To do an AD converstion, the first step is to configure analog pins/ voltage reference and digital
input output using ADCON1
3. Here the value of 00000011 was set to ADCON1 meaning that pins RA0, RA1, RA2 and RA5 are
Analog inputs, RE 0-1 are digital and RA3 is voltage refference, aslo it means the A/D Result
Format will be left justified.
4. Then the next step will be selecting A/D input channel using ADCON0, here the selected channal
is 000 → RA0
PIC16F877A
5
5. Then select A/D conversion clock and enabling the A/D module using the ADCON0 → the value of
ADCON0 is 01000001, that means: FOSC/8, and ADC mode is enabled.
6. After the configuration, a subroutine called getADC will be called in the main to start the A/D
converstion and then the saved data will be convered to decimal and didplayed in the lcd using
two functions ( subroutine) condec, putLCD.
7. The getADC will have the behavior as this:
a. set the A/D conversion status bit to one ( to start the ADC)
b. wait till finish convering then store in W register the value using register ADRESH and return.
8. The condec will have the behavior as this:
a. this function (subroutine) get the result of ADC and save it in a register called ADbin to
convert it to decimal using 3 registers ( hunds, tens, ones )
b. The main idea is, find the number of hundreds, tens and ones by subtracting 100, and
incrementing huns register, and subtracting 10 and increment the tens, and the rest is the
ones. This could be done by using the carray flag.
c. lets take a senario: assume the ADC result is 241 and it’s saved in ADbin, to convert it, fitst
find the number of huns by:
i. inialize the 3 registers to zeros
ii. set the carry flag to 1
iii. add 100 to the W register
iv. subtract the W from ADbin
v. add one to the huns
vi. check if the carray flag is 0
vii. If it’s zero, then there is an additional loop count, so decrement the number of huns and
add 100 to ADbin to restore the corret value. ( the carry will flip when the outpus is in
negative )
viii. the steps from (i - vii) will be reapated to find the tens, put insted of adding 100, we add 10
here
ix. after counting the huns and the tens, the reminder put it in the ones register.
d. After finding the huns, tens and the ones, conver the output to ascii code by adding the 0x30
offset to huns, tens, and ones.
e. the ascii step is because the LCD display only ascii code
f. then display the output to the LCD using LCD function that are degined in "LCDIS.INC".
9. this is the behavior of the program, the used SFR are TRISD, ADCON1, ADCON0, & PORTD.
Exercise for writing the .txt file in the final “Explain the steps for LED1H Project”
the idea from this project is to create a two push buttons, one to light up the leds as 1, 2, 3, and the
other is a reset button ( shut down all the leds)
1. To implement a LED circuit, the two buttons will be connected to portB, the step button will be
conncted with the RB1, and the shutdown buttin will be connected to RB2.
PIC16F877A
6
2. an 8 leds will be connected to port D (from RD0 -RD7)
3. PORTB will decleared as an input using TRISB, and portD will decleared as an output using
TRISD.
a. In this example timer0 is used as a hardware interrput, so registers INCON and OPT_REG will
be used.
b. bit 7 in INCON will be set to 1, to enable the global intrreupts, and bit 5, to enable TIMR0
inturrput.
c. in this example the timer0 will have no prescaling and the Prescaler is assigned to the WDT,
so bits(0-2) will be zero and bit 4 will be 1.
d. the logic here to use timer0 intterput to read the button and print the output in the LEDS.
e. a loop will be created to check if the reset button is clicked or not, if it’s clicked, clean portD, if
it’s not ( the value on the pin is 1) so check step button , if pressed then reset the time , check
for time out, if yes (bit 2 in INTCON is 1 ):
i. check step button and wait until relased, then increment output at portB
ii. if done repeate the main loop always.
iii. reset the TMR0 interrupt flag to 0 to be able to read more interrrupts.
if the time is not out yet ( bit 2 in INTCON is 0 ), wait ( means get stuck with the loop )
f. the behavior will repate itselfs.
PIC16F877A
7