Monday, October 16, 2023

PIC16F84A Software UART Programming Example Using XC8

Overview

For a small embedded controller, UART(Universal Asynchronous Receiver-Transmitter) is a communication module inside the controller that send and receive serial data to or from its peripheral device. Its data format and speed are configurable.

 

PIC16F84A Software UART Progamming Example Using XC8
A Conventional UART Module

This communication module is commonly come with many popular micro-controller such as, AT89S52, ATMega32, or PIC16F877A, etc.







PIC16F84A Software UART Progamming Example Using XC8
A Simple Connection Between Two Devices
Each devices have their own supply voltage and clock generator. The connection requires only Tx/Rx pair and a common ground (GND). In some case it requires only a Tx either an Rx and a common ground signal.

Connecting device may use one of there three communication modes:

  1. simplex
  2. full duplex
  3. haft duplex

A UART frame consists of 5 elements:

  • Idle (logic high)
  • Start bit (logic low)
  • Data bits
  • Parity bit
  • Stop bit (logic high)

In most common settings of 8 data bits, on parity and 1 stop bit (aka 8N1).

PIC16F84A Software UART Progamming Example Using XC8
UART Signal

Signal could be transmitter or receiver signal. BCLK is a clock source inside each devices.

Baud or bits per second (bit/s) is the number of bits that processed per unit of time. Each data bits duration could be calculated a:

Ts = 1 / fs

 Where,

  • Ts : symbol duration
  • fs  : Baud or pits per second

For example, we select a 9600 baud. Hence, 

Ts = 1 / 9600 = 0.000104 second = 104 microseconds.

So each data bits (1's or 0's) must be around 104 microseconds.

For any controller that come with UART module, the programmer can set its baud by hardware setting and calculation.

However some controller doesn't have UART module inside (e.g PIC16F84A). So we can emulate UART by bit banging GPIO pins in software (Assembly or C language).

PIC16F84A UART Bit Banging 

Bit banging of serial communication could be done easily using software routine in most of programming languages. It requires additional program space. The programmer can select any microcontroller digital I/O pin to transmit or receiving data bits. Data processing takes a little period to send and receive serial data. However data errors may occur in some situation.

Some C compiler such as MikroC, CCS PICC have a software driver for bit banging. But we write our own function to process this task.

In this example, I select a 9600 baud, no parity and one stop bit (8N1). Start bit triggers from a high to low transition. Logic low signal should be delayed for around 100 microseconds. Each data bits should be sampled at the middle of data bits duration. The program samples receiving data bits around 60 microseconds. 

PIC16F84A Software UART Progamming Example Using XC8
Sample Data Bits For A 9600 Baud
The sample time begin after the middle of each data bits.

The program listens to serial data start of transmission. Whenever the high to low transition start the serial data reception will process.

PIC16F84A Software UART Progamming Example Using XC8
Received ASCII Data Showed On Port B
Whenever serial data received the controller will echo it to serial terminal. Serial terminal settings is 8N1(8-bit No Parity One Stop Bit). Serial data is in ASCII format. This ASCII character will show on Port B. Whenever a 0 ASCII character received it will toggle RA2. A 1 ASCII character will toggle RA3.

  1.  
  2. /*
  3.  for 9600 baud rate
  4.  * 1/9600 = 104uS per bit
  5.  * we can use 102.5uS per bit
  6.  */
  7.  
  8. #include <xc.h>
  9.  
  10. // PIC16F84A Configuration Bit Settings
  11.  
  12. // CONFIG
  13. #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
  14. #pragma config WDTE = OFF // Watchdog Timer (WDT disabled)
  15. #pragma config PWRTE = OFF // Power-up Timer Enable bit (Power-up Timer is disabled)
  16. #pragma config CP = OFF // Code Protection bit (Code protection disabled)
  17.  
  18. #define _XTAL_FREQ 4000000
  19. #define TX RA0
  20. #define RX RA1
  21.  
  22. void sendChar(char data){
  23. TX=0;
  24. __delay_us(100);
  25. for(int i=0;i<8;i++){
  26. TX=data&(1<<0);
  27. data>>=1;
  28. __delay_us(75);
  29. }
  30. TX=1;
  31. __delay_us(100);
  32. }
  33.  
  34. char myChar=0,temp=0;
  35. void receiveChar(void){
  36. if(RX==0){
  37. __delay_us(100);
  38.  
  39. for(char i=0;i<8;i++){
  40. __delay_us(60);
  41. if(RX==1) myChar|=(1<<i);
  42. else myChar&=~(1<<i);
  43. }
  44. __delay_us(50);
  45. }
  46. }
  47. void sendText(char *text){
  48. while(*text) sendChar(*text++);
  49. }
  50.  
  51. void softUARTInit(void){
  52. PORTA=0x00;
  53. TRISA=0x02;
  54. PORTB=0;
  55. TRISB=0;
  56. TX=1;
  57. }
  58.  
  59. void main(){
  60.  
  61. softUARTInit();
  62. sendText("HELLO WORLD!\r\n");
  63. while(1){
  64. receiveChar();
  65. if(myChar!=0){
  66. PORTB=myChar;
  67. sendChar(myChar);
  68. //sendText("\r\n");
  69. if(myChar=='0') { RA2^=1; sendText(" Toggle RA2.\r\n");}
  70. if(myChar=='1') { RA3^=1; sendText(" Toggle RA3.\r\n");}
  71. myChar=0;
  72. }
  73. }
  74. }
  75.  

Click here to download this example.

PIC16F84A UART Bit Banging And Character LCD Example

A character LCD is very easy to control using a small micro-controller. Now I will send ASCII characters over UART terminal to the micro-controller. Those character will show on a 20x4 character LCD. 

PIC16F84A Software UART Progamming Example Using XC8
Program Simulation

This example program consume half of program memory.

  1. /*
  2.  Software UART LCD Example 1
  3.  */
  4. #include <xc.h>
  5. #include "LCD4Bits.h"
  6.  
  7. // PIC16F84A Configuration Bit Settings
  8.  
  9. // CONFIG
  10. #pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
  11. #pragma config WDTE = OFF // Watchdog Timer (WDT disabled)
  12. #pragma config PWRTE = OFF // Power-up Timer Enable bit (Power-up Timer is disabled)
  13. #pragma config CP = OFF // Code Protection bit (Code protection disabled)
  14.  
  15. #define _XTAL_FREQ 4000000
  16. #define TX RA0
  17. #define RX RA1
  18.  
  19. void sendChar(char data){
  20. TX=0;
  21. __delay_us(100);
  22. for(int i=0;i<8;i++){
  23. TX=data&(1<<0);
  24. data>>=1;
  25. __delay_us(75);
  26. }
  27. TX=1;
  28. __delay_us(100);
  29. }
  30.  
  31. char myChar=0,temp=0;
  32. void receiveChar(void){
  33. if(RX==0){
  34. __delay_us(100);
  35. for(char i=0;i<8;i++){
  36. __delay_us(60);
  37. if(RX==1) myChar|=(1<<i);
  38. else myChar&=~(1<<i);
  39. }
  40. __delay_us(100);
  41. }
  42. }
  43. void sendText(char *text){
  44. while(*text) sendChar(*text++);
  45. }
  46.  
  47. void softUARTInit(void){
  48. PORTA=0x00;
  49. TRISA=0x02;
  50. PORTB=0;
  51. TRISB=0;
  52. TX=1;
  53. }
  54.  
  55. void main(){
  56. uint8_t line=1,charNum=1;
  57. softUARTInit();
  58. lcdInit();
  59. sendText("PIC16F84A Software UART And Character LCD\r\n");
  60. lcdString("PIC16F84A 20x4 LCD");
  61. lcdXY(1,2);
  62. lcdString("Software Delay UART");
  63. lcdXY(1,3);
  64. lcdString("Programming Example");
  65. lcdXY(1,4);
  66. lcdString("MPLABX IDE And XC8");
  67. __delay_ms(2000);
  68. lcdClear();
  69.  
  70. while(1){
  71. receiveChar();
  72. if(myChar!=0&&myChar!=0x08){
  73. sendChar(myChar);
  74. if(myChar=='0') { RA2^=1; sendText(" Toggle RA2.\r\n");}
  75. if(myChar=='1') { RA3^=1; sendText(" Toggle RA3.\r\n");}
  76. if(myChar==0x0D) {
  77. line+=1;
  78. lcdXY(1,line);
  79. charNum=1;
  80. }else{
  81. lcdData(myChar);
  82. }
  83. charNum+=1;
  84. if(charNum>20) {charNum=1; line+=1; lcdXY(charNum,line);}
  85. if(line>4){line=1;lcdXY(charNum,line);}
  86. myChar=0;
  87. }
  88. }
  89. }

Click here to download its source file.



No comments:

Post a Comment

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)