Register ADCON1, TRISA, and TRISE must be initialized to select the refrence voltage and the input channel desired, as described by figure 10.2 and 10.3. then ADCON0 is initialized with the step listed in figure 10.6. the first step is select the ADC clock source from among the four choices. The choice show in the figure 10.6a provide the highest rate consistent with the constrain that the ADC clock period must be 1.6µs or greater. The RC choice (made by setting
36 ADCON0[7:6] to 11) is designed for use with PIC being clocked by a relatively slow clock. It lets the ADC run at a nominal 250kHz rate.
37 If just one analog input is to be used, it can be selected once and for all by combining the channel selection of figuer10.6b with the ADC clock period selection of figure 10.6a. if several analog channels are to be used, it is important to remember to wait for the sample time discussed in conjunction with figure 10.5. that is, select the channel, wait out the required sample time , and the initiate the conversion by setting the GO_DONE bit of ADCON0. When GO_DONE =0 again, the result from ADRES(H’1E’), the ADC result register
38 If one or more channel channels are to be periodically sampled, the timer1/CCP2 combination can be used to initiate each conversion. The register involved as shown in the figure 10.7
40
UART( Universal Asynchronous Receiver & Transmitter):
UART stands for Universal Asynchronous Receiver / Transmitter, is a module include in the following parts: PIC16C63, PIC16C65A, PIC16C73A, and PIC16C74A,
It is a serial communication interface which uses two lines for sending (TX) and
receiving (RX) data. As its name indicates it is an
asynchronous communication interface, which means it doesn’t need to send clock along with it as in synchronous communications. UART is the communication standard of our old computer’s RS-232 serial port. Most of the Microchip’s PIC Microcontrollers have built in USART Module. USART stands for Universal Synchronous Asynchronous Receiver Transmitter. It can be configured in the following Modes:
UART – Asynchronous (Full Duplex)
USRT Master – Synchronous (Half Duplex) USRT Slave – Synchronous (Half Duplex)
TXSTA – Transmit Status and Control Register:
Bit 7 CSRC : Clock Source Select Bit, this bit has no application in the Asynchronous mode operation of USART module. It is used to select master or slave mode in Synchronous mode operation.
Bit 6 TX9 : When this bit is set it enables the 9 bit transmission otherwise 8 bit transmission is used. 9th bit in the 9 bit transmission mode is commonly used as parity bit.
Bit 5 TXEN : Setting this bit enables the transmission. In the synchronous mode operation CREN and SREN bits of RCSTA register overrides this bit.
41 Bit 4 SYNC : This is the USART Mode select bit. Setting this bit selects
Synchronous mode while clearing this bit selects Asynchronous mode. Bit 3 Unimplemented : This bit is unimplemented and will read as 0. Bit 2 BRGH : This is the High Baud Rate Select bit for Asynchronous
mode operation and is unused in Synchronous mode. Setting this bit selects High Speed and clearing this bit selects Low Speed baud rates. You will can see the baud rate calculation later in this article.
Bit 1 TRMT : This is the Transmit Shift Register (TSR) status bit. This can be used to check whether the data written to transmit register is transmitted or not. When the TRS is empty this bit is set and when the TSR is full this bit will be 0.
Bit 0 TX9D : This is the 9th bit of data in the 9 bit transmission mode. This is commonly used as parity bit.
RCSTA – Receive Status and Control Register :
Bit 7 SPEN : Serial Port Enable bit. Setting this bit enables serial port and configures RC7, RC6 as serial port pins.
Bit 6 RX9 : Setting this bit enables 9 bit reception otherwise it will be in 8 bit reception mode.
Bit 5 SREN : Single Receive Enable bit. This bit has no effect on Asynchronous mode and Synchronous Slave mode. Setting this bit will enables Single Receive. This bit will cleared after the reception is complete.
Bit 4 CREN : Continuous Receive Enable bit. Setting this bit will enable Continuous Receive. In the Synchronous Mode CREN overrides SREN. Bit 3 ADDEN : Address Detect Enable bit. This bit is applicable only in
Asynchronous 9 bit mode. Setting this bit enables Address Detect.
Bit 2 FERR : Framing Error bit. 1 at this bit stands for Framing Error while 0 stands for No Framing Error.
42 Bit 1 OERR : Overrun Error bit. A high at this bit indicates that Overrun
error has occured.
Bit 0 RX9D : This is the 9th bit of Received Data and is commonly used as Parity Bit.
USART Baud Rate Generator (BRG)
Baud Rate Generator provides the required clock for the data transmission and reception. USART module has a dedicated 8 bit baud rate generator which
supports both Synchronous and Asynchronous modes. The 8-
bit SPBRG register controls the time period of this free running timer. In Asynchronous mode BRGH, 2nd bit of TXSTA register also controls the generated baud rate but in Synchronous mode it is ignored. Baud Rate can be calculated from the following equations, where FOSCis the clock frequency of the microcontroller.
Waveform and BAUD-Rate Accuracy:
When a serial data is transmitted asynchronously, the data stream is generated with the transmitter’s clock. The receiver must synchronize the incoming data stream to the receiver’s clock.
43 An example of the transmission of 4 bytes is show in the figure 11.1. each 8 bit is framed by a START bit and STOP bit. For transmission at 9,600Bd, each of these bits lasts for a bit time(BT) of 1/9,600 second. Before the first frame is transmitted, the line from the transmitter’s TX output to the recivers’S RX input idles high. The receiver monitors its RX input, waiting for the line to drop low because of the transmission of the (low) START bit. The receiver synchronizes on this high to low transition. Then the receiver reads the 8 bit of serial data by sampling the RX input at 1.5BT,2.5BT, 3.5BT, 4.5BT, 6.5BT, 7.5BT, AND 8.5BT as show in the figure 1101. It checks that the framing of The byte has been interpreted correctly by reading the high STOP bit at 9.5BT. if the RX line is actually low at this time , for whatever the reason, the receiver sets a flag to indicate a framing error. Regardless of whether or not a framing error occurs, the receiver then begins again, resynchronizing upon the next high to low transition of the RX line. Because of this resynchronization, the receiver can generate its own baud-rate clock that only approximate the transmitter’s baud-rate clock and yet the reciver can recover the serial data perfectly.
44 The PIC’s baud-rate clock operates at either of two ranges, called high speedbaud rate and low speed baud rate. Using the low speed baud rate, the reciver looks for STOP to START transition by sampling its RX input every 1/16th of one of its bit times, as show in the figure 11.2, then it counts six more of these sample times to point where it reads a cluster of three closely spaced samples of RX and votes among them to ensure that it is seeing the low START bit. There after, it reads successive clusters of three samples spaced 16 sample time apart.in effect, the reciver is reading its input every 16 periods of its sample clock.
BAUD-RATE Selection:
A desired baud rate can be approximated by the UART’s baud rate generator. If the crystal clock rate were selected to be carefully chosen multiple pf the desired baud rate, then the baud rate generator would produce the desired baud rate exactly. The clock rates used by microchip to characterized the three speed grades of their parts
45 These speed grades do not provide exact multiples of the popular 9,600Bd and 19,200Bd rate commonly used by personal computer serial port. However, the flexibility of the baud rate generator circuitry permits close approximation to both 9,600 Bd and 19,200Bd with any of the standard clock rates. The baud rate is derived from the crystal rate using an 8 bit presentable divider and a fixed diver of either 16 or 64, as show in the figure 11.4b. the results are tabulated in the figure 11.4a. even in the worst case , the percent error of the approximate baud rate is only one-third of the percent error that cannot be tolerated by the UART.
Nominal
Baud Rate BRGH SPBRG %error BRGH SPBRG %error BRGH SPBRG %error OSC =4MHz OSC = 10MHz OSC = 20MHz
9,600 baud 1 25 +0.16% 1 64 +0.16% 1 129 +0.16%
19,200 baud 1 12 +0.16% 1 32 -1.4% 1 64 +0.16%
Figure: 114.a Register contents and accuracy of approximated baud rate
For BRGH = 1(high speed baud rate)
For BRGH =0 (low speed baud rate)
Figure: 114.b Relation between OSC,BRGH, SPBRG, and Bayd Rate
UART Data Handling Circuitry:
The transmitted data circuit show in the figure 11.5a. to transmit a byte of data serially from TX pin, the byte written to TXREG register. Assuming there is not already data in TSR (transmit shift register), the content of TXREG will be automatically transferred to the TSR, making TXREG available for a second byte even as the first byte is being shifted out of the TX pin, framed by START and STOP bits
47 The receiver data circuit is similar, with received data shifted into RSR(receiver shift register) when it is in place, the STOP bit is checked and an error flag is set if the STOP bit does not equal one. In any case, the receiver byte is automatically transferred into a 2 byte FIFO. If the FIFO was initially empty, the receiver byte will fall through to the RCREG (receiver register) virtually immediately, where it is ready to be read by the CPU. If the CPU is slow in reading the RCREG, a second byte can be received at the RX pin. When it is in place in the RSR, it will follow the first byte into the 2 byte FIFO. At that point, the FIFO is full. If the third byte enters the RX pin and is shifted all the way across the RSR before at least one of the two bytes in the FIFO has been read, then the new byte will be lost. An overflow error flag will be set, alerting the receiver software of the loss of a byte of data
At 9600Bd, it takes 10/9600 second, or just a little longer than a millisecond, to receive each byte. If the receiver bytes are handled under interrupt control, each byte should be easily handled in a timely fashion, well before an overrun error can even occur. No oher interrupt handler should be permitted to lock out.
UART Initialization:
The register involved with UART is show in the figure 11.6. the data direction bit associated with the RC6/TX pin and the RC7/RX pin must both be set up as inputs, with ones in bits 6 and 7 of the TRISC register, the setting of these two bits disable the general I/O port output circuitry associated with these two pins( the handling of these bits of TRISC stands in contrast to the clearing of bits 3 and 5 of TRISC in support of the serial peripheral interface output pins) The UART’s baud rate and its transmit and receive funcations are initialized by writes to SPBRG, TXSTA, and RCSTA, as show in figures 11.4 and 11.6 at 9600 Bd, each transfer takes about a millisecond, so sending or receiving a string of characters is best carried out under interrupt control. The flag and interrupt enable bits of the PIR1,PIE1 and INTCOON register control the timing of CPU interactions with the UART.
UART Use:
A major application for the PIC’s UART is to provide a two-wire(plus ground) serial interface to a personal computer. The circuit of figure 11.7 uses mortorola chip to translate between the ov to a =5V logic level signal swings on the PIC’s RX and TX pins and ±10V signal swings that support the RS-232
48 interface requirement. Both the PIC and the PC should be setup for the same baud rate and for one start bit, 8data bits, one stop bit, and no parity bit
50 Given this setup, the PIC will respond to PCIF interrupts by reading each byte from the RCREG register sent by the PC. The RCIF flag will clear itself when the byte read from RCREG leaves the receive circuit’s FIFO empty.
The PIC sends out a string of bytes by writing them, one by one under interrupt control, to TXREG , the TXIF flag takes care of itself, clearing automatically when TXREG is written to, and setting again as the data written TXREG are automatically transferred to the transmit shift register, at the completion of sending the string of bytes to the PC, the TXIE bit in the PIE1 register is cleared to disable further ”transmit” interrupts until another string needs to be sent to the PC
51 Another application of the PIC UART is to couple two PIC’s together. In this way some of the work that would be done by one PIC is off loaded to a second PIC, figure 11.8 show s this connection of two PIC’s, using the maximum possible baud rate to obtain fast coupling between the two PICs with in 40 internal clock cycles, what is written into one PIC’s TXREG register appears in the other PIC’s RCREG register.
Carrying out transfers at this fast rate calls for some precautions is need if overrun error are to avoided, given PICs that are try to carry out the task in additional to monitoring the UART’s RCREG register. A given PIC can only receive 2 bytes into its FIFO without reading them immediately. Any further bytes received will be discard until the earlier bytes are read out of the FIFO, making room for new bytes
52
Keypad:
A keypad is a matrix of push-buttons aligned in rows and columns to provide user input, a 3x4 keypad is basically formed like the following schematic:
it consists of 3 columns and 4 rows, hence the name, whenever the user taps one button, the column and the row corresponding to that button are shorted, for example, if a user chooses to tap the "5" button, col2 and row2 are shorted, if a users picks "0" button, col2 and row4 are shorted, and so on. the method used to read such input is called Scanning, you connect the rows and the columns to the microcontroller, you set the columns as outputs, rows as inputs (or vice versa) and you start feeding a pattern of inputs to the columns while checking the readings of the rows.
For example, if you tied all rows through pull-up resistors to Vcc, all row inputs are typically 1s (1111), now if you start feeding columns with the following pattern, 011, 101, 110, you can check which row conducts the 0 signal to the controller, thus, you'll detect the shorted row and column.
example: if a user presses button "6", when I feed the columns by 011, the rows output would be 1111, when I feed it by 101, the rows output would be also 1111, but when I feed it by 110, button "6" will conduct the 0 signal, thus my rows output would be 1011, Knowing that I used col3 to conduct the 0 signal, and I got the 0 signal at row2, I'll know the pressed button is "6".
53 PIC-C provides a common library for reading keypads named kbd.c, all you have to do is to include the kbd.c library in your code, and use the function kbd_getc() to scan the keypad.
kbd.c library uses either port D or port B to interface the keypad, you'll find the schematic for the interface further below, but if you need to use other ports to interface your keypad, you'll have to use a user defined library, you can find those on ccsinfo.com forum, or you can write your own library (which is pretty simple).
Note: the kbd_getc(); function returns the ASCII code of the pressed button (returns a character).
The Alphanumeric LCD:
An alphanumeric LCD is a type of LCDs that only displays English letters, numbers and some ASCII characters, those LCDs contains a controller unit that processes the input and forms the displayed character on the LCD, most alphanumeric LCDs have a parallel interface, some other LCDs have a serial interface to minimize the construction complicity.
Alphanumeric LCDs comes in different sizes, the size describes the number of characters an LCD can display, common sizes are 16x2, 20x2, 16x4, 20x4 ..etc. a 16x2 has 2 rows and can display 16 characters on each row.
Parallel LCD Pinout:
Parallel LCDs typically have 16 pins as following: - Power Supply Pins:
Vss : Ground reference (0V) Vcc : +5V supply voltage
Vee : Contrast pin, typically connected to GND via a resistor (0Ω - 5kΩ), change the value to change the contrast.
- Control Bus Pins:
RS : Register Select, used to set the LCD either to command mode or to data mode.
R/W : Read/Write select, used either to read characters from LCD or to write new characters.
E : Active low Enable signal. - Data Bus Pins:
54 D0-D7 : used to pass 8Bit character data, you have the choice either to use only 4Bit bus (D4-D7) or to use the whole data bus.
- Backlight Voltage Pins: A : Anode (+5V)
K : Cathode (0V)
used to turn ON/OFF the backlight LED of your LCD.
Using PIC-C to Write to LCD:
To write to an LCD you need a software library, you can either go with the original lcd.c library that comes with your compiler's software bundle (which I don't recommend), or you can use flex_lcd.c libraries written by PCM programmer, here:
The flex_lcd.c library gives you the opportunity to select PIC pins to be connected to the LCD by changing the definers at the top of the library.
After including the flex_lcd.c library in your code, you should initialize the LCD at the beginning of your main code using the function lcd_init();
Then you can use the function lcd_putc("Your String"); to display your strings.
The Schematic:
Click on the schematic to zoom in,
I've selected the LCD pinouts in flex_lcd as following: #define LCD_DB4 PIN_B4
#define LCD_DB5 PIN_B5 #define LCD_DB6 PIN_B6
55 #define LCD_DB7 PIN_B7
#define LCD_E PIN_B3 #define LCD_RS PIN_B1 #define LCD_RW PIN_B2 and commented out
// #define USE_LCD_RW 1
The PIC-C Code:
/*
PIC16F877A interface to 3x4 Keypad and 16x2 LCD Badr Ghatasheh [email protected] */ #include <16f877a.h> #fuses XT,NOLVP,NOWDT,NOPROTECT #use delay(clock=4000000) #include "flex_lcd.c" #include <kbd.c> void main() {
char k=0; // Character k to store keypad input delay_ms(1);
/* Peripherals Configurations */
lcd_init(); // Turn LCD ON, along with other initialization commands
kbd_init(); // Initialize Keypad
lcd_gotoxy(1,1); // point LCD cursor to col1 row1 lcd_putc("Hello World !!"); // print on LCD
lcd_gotoxy(1,2); // point LCD cursor to col1 row2 while(1) // infinite loop
{
k = kbd_getc(); // read keypad input (if exists) if(k!=0) // if key captured
{
lcd_putc(k); // print captured key to lcd k=0; // reset k for another loop round delay_ms(250); // delay between key presses
56 }
delay_ms(1); // delay_between read trials