Monday, October 18, 2021

Programming PIC16F877A Using XC8

 

Introduction

PIC16F877A was a popular 8-bit microcontroller for university students and hobbyists. It still useful for novice programmers learning to program microcontroller.

Programming PIC16F877A Using XC8

This device has digital I/O, analog input, Timer, PWM output, Communication, and other features.

Programming PIC16F877A Using XC8
PIC16F87XA devices Table


I select PIC16F877A-I/P in DIP package that ease of prototyping.

Programming PIC16F877A Using XC8
PIC16F877A 40-Pin DIP Package Pin Diagram

 
Programming PIC16F877A Using XC8
PIC16F877A 40 pins DIP

Architecture

It’s designed using Harvard architecture, separating between program and data memory. CPU fetches both data and program memory concurrently. Its pipe-lining technique make instruction execution archive at one CPU cycle, but it excepts some instructions that require more than one cycle.

Memory

Its program counter is 13-bit wide. Instruction length is 14-bit (called one word). It can address program memory of 8K x 14 program space. Reset vector locate at address 0000h. It has only one interrupt vector which locate at address 0004h.

Programming PIC16F877A Using XC8
PIC16F877A memory map and stack

Stack used for calling and returning sub routine. It’s 8 levels, allowing up to 8 nested sub routine calling. Nested calling more than this value, making program unpredictable.

Coding PIC16F877A

Assembly language is core programming for microcontroller. It’s preferred for most of university program. It’s essential for programmer to understand overall operation of microcontroller before allowing to program in Assembly language.

Assembly language is free offered by device’s manufacturer. Programming made from this language composes of a lot of lines. It consumes a very long time to complete a program using this language. Updating and modifying program is very hard.

However microcontroller program written in Assembly language is very effective in program memory. Program execution is very fast.

Modern embedded C compilers for PIC microcontroller is very popular now. Even small 8-bit microcontroller implemented using C regardless of its program memory space – for example PIC microcontroller with 1KB of program memory. I see only a few of C compilers in market,

  • MikroC
  • CCS PICC
  • XC8

XC8 integrated in MPLABX IDE from Microchip Technology. It has a free version without limitation.

Getting Started With C Using XC8

Toggling digital I/O is a good getting-started section for most of microcontroller new learner. It allow us to test its normal operation.

Hardware

PIC16F877A supplies at +5V DC with its clocking input of 20MHz, from external crystal oscillator. Port C connects to 8 LED outputs via a resistor network.

Programming PIC16F877A Using XC8
Schematic Diagram

In Proteus, power supply pins are hidden but they internally wired by this simulator program.

C Programmer

This getting started program made of a little lines of code. Device configuration section seem very long due XC8 compiler directives. Port C toggles its output with a delay of one second.

  1. /*
  2.  * Blinking PORTC of PIC16F877A
  3.  * using XC8 in MPLABX IDE
  4.  */
  5. #include <xc.h>
  6.  
  7. // CONFIG
  8. #pragma config FOSC = HS
  9. // Oscillator Selection bits (HS oscillator)
  10. #pragma config WDTE = OFF
  11. // Watchdog Timer Enable bit (WDT disabled)
  12. #pragma config PWRTE = OFF
  13. // Power-up Timer Enable bit (PWRT disabled)
  14. #pragma config BOREN = ON
  15. // Brown-out Reset Enable bit (BOR enabled)
  16. #pragma config LVP = OFF
  17. // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit
  18. //(RB3 is digital I/O, HV on MCLR must be used for programming)
  19. #pragma config CPD = OFF
  20. // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
  21. #pragma config WRT = OFF
  22. // Flash Program Memory Write Enable bits (Write protection off;
  23. //all program memory may be written to by EECON control)
  24. #pragma config CP = OFF
  25. // Flash Program Memory Code Protection bit (Code protection off)
  26.  
  27. /*Clocking Parameter for Delay Function*/
  28. #define _XTAL_FREQ 20000000
  29.  
  30. void main(void){
  31. /*Clear Port C*/
  32. PORTC=0x00;
  33. /*Set Port C To Output*/
  34. TRISC=0x00;
  35. while(1){
  36. PORTC=0x00;
  37. __delay_ms(1000);
  38. PORTC=0xFF;
  39. __delay_ms(1000);
  40. }
  41. }

 This program consumes about 1% of memory resource.

Programming PIC16F877A Using XC8
Statistic in MPLABX IDE dashboard

Click here to download this example package.



Friday, October 15, 2021

AT89C52 Character LCD and Keypad Interfacing Using C

We have seen about 4x4 matrix keypad and character LCD interfacing with AT89C52 in previous post. Now let put these two external devices to work together with this controller.

AT89C52 Character LCD and Keypad Interfacing Using C

In this programming example, I use a 4x4 matrix keypad and a HD44780-based character LCD, controlled by AT89C52. The two lines character LCD shows the received the controller received from keypad.

This keypad has 16 value ranging from 1 to 9, and from A to F in ASCII format.

AT89C52 Character LCD and Keypad Interfacing Using C
Circuit diagram
Source code is written in C, using Keil uVision IDE.

  1. /*
  2. AT89C52 8051 Interface to Character LCD
  3. and Matrix Keypad Programming in C using Keil
  4. */
  5.  
  6. #include <REG52.h>
  7.  
  8. #define DPORT P2
  9. #define KEY_PORT P1
  10.  
  11. /*Keypad rows setting*/
  12. sbit row0=P1^4;
  13. sbit row1=P1^5;
  14. sbit row2=P1^6;
  15. sbit row3=P1^7;
  16.  
  17. /*
  18. RS bit 0
  19. RW to GND
  20. EN bit 1
  21. */
  22.  
  23. void lcdInit();
  24. void lcdCmd(unsigned char cmd);
  25. void lcdDat(unsigned char dat);
  26. void lcdStr(unsigned char *str);
  27. void lcdXY(unsigned char x, unsigned char y);
  28. void _delay_us(unsigned int t);
  29. void _delay_ms(unsigned int T);
  30. void lcdClear();
  31.  
  32. /**********KeyPad*************/
  33. unsigned char getKey();
  34.  
  35. unsigned char keypad[4][4]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
  36. unsigned char output[4]={0xFE,0xFD,0xFB,0xF7};
  37. unsigned row,col,key_value;
  38. bit found=0;
  39.  
  40. unsigned char temp;
  41.  
  42. int main(void)
  43. {
  44. unsigned char keyVal,pressCnt=0;
  45. unsigned char keyStr[16];
  46. unsigned int i=0;
  47. unsigned char keyChar[16]={'7','8','9','F','4','5','6','E','1','2','3','D','A','0','B','C'};
  48. lcdInit();
  49. KEY_PORT=0xF0;
  50. lcdXY(1,1);
  51. P3=0x00;
  52. lcdStr("Enter Key Value:");
  53. lcdXY(1,2);
  54. while(1)
  55. {
  56. keyVal=getKey();
  57. if(found==1){
  58. lcdDat(keyChar[keyVal]);
  59. found=0;
  60. pressCnt++;
  61. for(i=0;i<32800;i++);
  62. }
  63. if(pressCnt>16){
  64. pressCnt=0;
  65. for(i=0;i<50000;i++);
  66. lcdClear();
  67. lcdXY(1,1);
  68. lcdStr("Enter Key Value:");
  69. lcdXY(1,2);
  70. }
  71. }
  72.  
  73. }
  74.  
  75.  
  76. void lcdCmd(unsigned char cmd){
  77. temp=0x02;
  78. DPORT=temp|(cmd&0xF0);
  79. _delay_us(10);
  80. temp=0x00;
  81. DPORT=temp|(cmd&0xF0);
  82. _delay_us(100);
  83.  
  84. temp=0x02;
  85. DPORT=temp|(cmd<<4);
  86. _delay_us(10);
  87. temp=0x00;
  88. DPORT=temp|(cmd<<4);
  89. }
  90.  
  91. void lcdDat(unsigned char dat){
  92. temp=0x03;
  93. DPORT=temp|(dat&0xF0);
  94. _delay_us(10);
  95. temp=0x01;
  96. DPORT=temp|(dat&0xF0);
  97. _delay_us(100);
  98.  
  99. temp=0x03;
  100. DPORT=temp|(dat<<4);
  101. _delay_us(10);
  102. temp=0x01;
  103. DPORT=temp|(dat<<4);
  104. }
  105.  
  106. void lcdInit(){
  107.  
  108. DPORT=0x00;
  109. _delay_ms(2);
  110. lcdCmd(0x33);
  111. _delay_us(100);
  112. lcdCmd(0x32);
  113. _delay_us(100);
  114. /*2-Lines Mode 4-Bit*/
  115. lcdCmd(0x28);
  116. _delay_us(100);
  117. /*Display On Cursor Blink*/
  118. lcdCmd(0x0F);
  119. _delay_us(100);
  120. /*Clear Screen*/
  121. lcdCmd(0x01);
  122. _delay_ms(2);
  123. /*Cursor Increment*/
  124. lcdCmd(0x06);
  125. _delay_us(100);
  126. }
  127.  
  128. void lcdStr(unsigned char *str){
  129. unsigned char i=0;
  130. while(str[i]!=0){
  131. lcdDat(str[i]);
  132. i++;
  133. }
  134. }
  135.  
  136. void lcdXY(unsigned char x, unsigned char y){
  137. /*20x4 LCD Address */
  138. //unsigned char tbe[]={0x80,0xC0,0x94,0xD4};
  139. /*16x2 LCD Address*/
  140. unsigned char tbe[]={0x80,0xC0};
  141. lcdCmd(tbe[y-1]+x-1);
  142. _delay_us(100);
  143. }
  144.  
  145. void _delay_us(unsigned int a){
  146. unsigned int i,j;
  147. for(i=0;i<5;i++)
  148. for(j=0;j<a;j++);
  149. }
  150.  
  151. void _delay_ms(unsigned int b){
  152. unsigned int i;
  153. for(i=0;i<b;i++) _delay_us(1000);
  154. }
  155.  
  156. void lcdClear(){
  157. lcdCmd(0x01);
  158. _delay_us(10);
  159. }
  160.  
  161. /*4x4 Matrix KeyPad Routine*/
  162. unsigned char getKey(){
  163.  
  164. static unsigned char i=0;
  165.  
  166. for (i=0;i<4;i++){
  167. KEY_PORT=output[i];
  168. if((KEY_PORT&0xF0)!=0xF0)
  169. { col=i;
  170. found=1;
  171. break;
  172. }
  173. }
  174.  
  175. if(row0==0) row=0;
  176. else if (row1==0) row=1;
  177. else if (row2==0) row=2;
  178. else if (row3==0) row=3;
  179.  
  180. if(found==1)
  181. return key_value=keypad[row][col];
  182. found=0;
  183. }
  184.  

Click here to download source file.


Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)