Está en la página 1de 7

PIC (Programmable Interface Controllers) microcontrollers are a family of specialized microcontroller chips produced by Microchip Technology.

They are electronic circuits that can be programmed to be timers or to control a production line and many other functions in embedded systems in motor vehicles, robots, office machines, medical devices, mobile radios, vending machines, home appliances. PIC18F8722 microcontroller was chosen for this project because it includes a 10-Bit analog to digital converter with up to 13 analog channels and an enhanced addressable USART module which supports RS-485 and RS-232 communication. Special Microcontroller Features: C Compiler Optimized Architecture 100,000 Erase/Write Cycle Enhanced Flash Program Memory Typical 1,000,000 Erase/Write Cycle Data EEPROM Memory Typical Flash/Data EEPROM Retention: 100 Years Typical Single-Supply 5V In-Circuit Serial Programming (ICSP) via Two Pins In-Circuit Debug (ICD) via Two Pins Wide Operating Voltage Range: 2.0V to 5.5V The application was developed in C language using the mikroC Compiler provided by Mikroelektronica. The initial tests were made on a BigPIC5 development board. The final application was tested using an acquisition system based on PIC18F8722 microcontroller which includes eight signal-conditioning blocks for 8 analogical channels (4-20mA). In order to understand how PIC18F8722 works a lot of test program were developed on BigPIC5 development board. 1. The I/O ports of the microcontroller PIC18F8722 has up to nine ports available. Some pins of the I/O ports are multiplexed with an alternate function from the peripheral features on the device. In general, when a peripheral is enabled, that pin may not be used as a general purpose I/O pin. Each port has three registers for its operation. These registers are: TRIS register (Data Direction register) Port register - to read the levels on I/O pins LAT register to read-modify-write operations on pins. A simple example: how to use PORTC as digital output and toggle the state of its pins at every second: TRISC = 0; // set direction to be output 0=output; 1=input

do { PORTC = 0x00; // set PORTC pins to 0 delay_ms(1000); // 1 second delay PORTC = 0xFF; // set PORTC pins to 1 Delay_ms(1000); // 1 second delay } while(1); // Endless loop The first example shows how we can use the PORTx register to change the status of the PORTC pins. The next example shows that we can also use LATx register to change the status of the output pins: pin0 (output) on PORT C changes his status according to the status of the pin0 (input) on PORTB. unsigned char status_portB,status_portC ; TRISC = 0; // set direction to be output TRISB = 1; // set direction to be output do { status_portB=PORTB;// read portB status status_portB&=0x01;//we are interested only in pin0 so we mask the other bits(logic AND) if(status_portB) status_portC=0x01; // pin0 on port C will be ON else status_portC=0x00; // pin0 on port C will be OFF LATC|= status_portC;//we only change the status on pin0 the other ones remain unchanged (logic OR) } while(1); // Endless loop

2. How to connect other peripheral device on PIC18F8722 I/O ports BigPIC5 development board offers the possibility to connect on its ports a standard character LCD or a graphic LCD(GLCD). Because LCD and GLCD share the same port (port D) they cant be used in the same time. In order to use both LCD and GLCD we must define first the bits they use according to the schematic of the board: // Lcd module connections sbit LCD_RS at LATD2_bit; sbit LCD_EN at LATD3_bit; sbit LCD_D4 at LATD4_bit; sbit LCD_D5 at LATD5_bit; sbit LCD_D6 at LATD6_bit; sbit LCD_D7 at LATD7_bit; // Glcd module connections char GLCD_DataPort at PORTD; sbit GLCD_CS1 at LATJ0_bit; sbit GLCD_CS2 at LATJ1_bit; sbit GLCD_RS at LATJ2_bit;

sbit GLCD_RW at LATJ3_bit sbit GLCD_EN at LATJ4_bit; sbit GLCD_RST at LATJ5_bit; (picture with the BigPic board with LCD or GLCD working) 3. Analog to digital conversion module The Analog-to-Digital (A/D) converter module and 12 channels and allows conversion of an analog input signal to a corresponding 10-bit digital number. The module has five registers: - A/D Result High Register (ADRESH) - A/D Result Low Register (ADRESL) - A/D Control Register 0 (ADCON0) - A/D Control Register 1 (ADCON1) - A/D Control Register 2 (ADCON2) Because each port pin associated with the A/D converter can be configured as an analog input, or as a digital I/O, every time we want to use an analog input we must use ADCON1 register. In this registers the 4 least significant bits specify the number of analog inputs we want to use. In ADCON1 and we must select channel in ADCON0: Example: ADCON1 =0b00001110;//use AN0 ADCON0 = 0x00;//select channel 0 (AN0) To start the conversion we must put ADON bit ( ADCON0 register) to 1 to enable the conversion and to set GO_DONE bit( ADCON0 register) to start the conversion. It is possible to receive the result via an interrupt or we can use a while loop and verify the state of GO_DONE pin until it goes low (meaning the A/D conversion is finished): ADCON0.ADON = 0x01;//Enable A/D module ADCON0.GO_DONE = 1;//Start A/D Conversion while(ADCON0.GO_DONE != 0);//Loop here until A/D conversion completes The ADRESH and ADRESL registers contain the result of the A/D conversion. When the A/D conversion is complete, the result is loaded into the ADRESH:ADRESL register pair and we calculate it as follows: adc_val=ADRESH; adc_val&=0x03; adc_val*=256; adc_val+=ADRESL; In conclusion, if we want to make an analog conversion we must follow the next steps: - Configure analog pins (ADCON1) - Select A/D input channel (ADCON0) - Turn on A/D module (ADCON0)

- Start conversion: set GO/DONE bit (ADCON0 register) - Wait for A/D conversion to complete, by polling for the GO/DONE bit to be cleared - Read A/D Result registers (ADRESH:ADRESL); This is a simple way to do analog conversion. There are many other parameters that we can set, like: A/D acquisition time (ADCON2), A/D conversion clock (ADCON2), voltage reference. Also, we can use the interrupt routine to control the ADC conversion. 4. Interrupts The interrupts in a microcontroller are special events generated by internal or external sources: analog to digital converter, serial interface, timers, etc. There is an interrupt management system which has the role to interrupt the program flow in order to inform the processor about the event, every time it appears. For every interrupt there are three bits to control it: - Flag bit - indicates that the interrupt event occurred - Enable bit - enables the interrupt. The program flow is interrupted only if this bit is set. - Priority bit- selects the priority level for each interrupt. There is a bit which validates/invalidates all the interrupts GIE(Global Interrupt Enable bit) Interrupt flag bits are set when an interrupt condition occurs (this is made automatically by the interrupt management system) but the user should clear the appropriate interrupt flag bits in the interrupt routine to enable a future interrupt occurrence. One of the most important interrupt sources is the interrupt generated by timer0 module when an overflow occurs in TMR0 register (transition from FFh to 00h - 8 bit mode or 0xffffh to 0x0000h 16 bit mode). The interrupt management system will set the flag bit TMR0IF(register INTCON bit 2=1) and the flow of the program will be interrupted and the interrupt routine is executed(only if the enable bit is set - TMR0IE (register INTCON bit 5=1). In the next example we set the interrupt routine for TIMER0 to occur each 25ms. Timer0 is configured as an 16-bit timer/counter ( bit T08BIT=1 (register T0CON bit6). An easy way to obtain the desired period for TIMER0 is to use the internal prescaler (an 8 bit timer) to divide the internal clock source. The internal frequency is the frequency of external oscillator divided by 4(in our case is 20Mhz/4). If we set the prescaler to 1:8 (010) we obtain 20/32=0,625Mhz, so we will have a timer period of s. If we want to obtain 25ms we must count 25000/16=15625. So, timer0 will be preloaded with 65536-15625=49911 (0xc2f7). T08BIT_bit = 0; T0CS_bit = 0; PSA_bit = 0; T0PS2_bit=0; T0PS1_bit=1; T0PS0_bit=0; TMR0IF_bit = 0; TMR0H = 0xc2; TMR0L = 0xf7; GIE_bit = 1; // 16 bit timer // internal clock // use prescaler // prescaler to 1:8 (010) -> frecquency=FCY/(4*8) =20/32= 0,625 MHz // reset interrupt flag for Timer0 //; preset for Timer0 MSB register // ; preset for Timer0 LSB register // set general enable interupt bit

TMR0IE_bit = 1; TMR0ON_bit = 1;

// set enable interupt bit for timer0 // start timer0

In the interrupt routine we must identify the source of interrupt and we must clear the TMR0IF flag to enable the next interrupt: void interrupt(void) // Rutina de intrerupere { if (TMR0IF_bit) { // find out if the interrupt occurred because of TIMER0 TMR0L = 0xc2//reload timer0 TMR0H = 0xf7; TMR0IF_bit = 0;// clear the interrupt flag } } 5. Serial communication Serial communication is very important for microcontroller because allows the communication with computers (via COM port,USB,etc), peripheral devices or some ICs (such as eeprom, A/D converters,etc.). Most PIC microcontrollers come with build in serial communication protocols such as USART, I2C, SPI. The word USART is the acronym of Universal Synchronous Asynchronous Receive Transmit. Standard COM port uses asynchronous receiver and transmitter. In this mode there are Tx (transmit) and Rx (receive) lines. It can transmit and receive information at the same time from these lines this is called full-duplex communication. Half-duplex is when you have to wait to complete Rx before use Tx or vice versa. To configure USART module we use TXSTA, RCSTA, SPBRG and interrupt registers. In order to make a serial communication via USART we must make the following settings: For transmission: The desired baud rate should be set by using bits BRGH (TXSTA register) and BRG16 (BAUDCTL register) and registers SPBRGH and SPBRG;desired baudrate is calculated as follows: SPBRGH:SPBRG=(FOSC/Desired Baud Rate)/64 The SYNC bit (TXSTA register) should be cleared and the SPEN bit should be set (RCSTA register) in order to enable serial port; On 9-bit data transmission, the TX9 bit of the TXSTA register should be set; Data transmission is enabled by setting bit TXEN of the TXSTA register. Bit TXIF of the PIR1 register is automatically set; If needed the bit TXEN causes an interrupt, the GIE and PEIE bits of the INTCON register should be set;

On 9-bit data transmission, value of the ninth bit should be written to the TX9D bit of the TXSTA register Transmission starts by writing 8-bit data to the TXREG register.

For receiving:

Baud Rate should be set by using bits BRGH (TXSTA register) and BRG16 (BAUDCTL register) and registers SPBRGH and SPBRG; desired baudrate is calculated as follows: SPBRGH:SPBRG=(FOSC/Desired Baud Rate)/64 The SYNC bit (TXSTA register) should be cleared and the SPEN bit should be set (RCSTA register) in order to enable serial port; If it is necessary the data receive causes an interrupt, both the RCIE bit of the PIE1 register and bits GIE and PEIE of the INTCON register should be set; On 9-bit data receive, the RX9 bit of the RCSTA register should be set; Data receive should be enabled by setting the CREN bit of the RCSTA register; The RCSTA register should be read to get information on possible errors which have occurred during transmission. On 9-bit data receive, the ninth bit will be stored in this register; Received 8-bit data is stored in the RCREG register

If we want to send data to a computer, we must ensure that it receives them correctly. The transmission is made using a data-package. Each data-package has a fixed length and the following structure: 1. 0xff (255) 2. Byte0 3. Byte1 .. 25. Byte24 26. CRC_H 27. CRC_L The first byte marks the beginning of the package. This value is the only value on 8 bits, the other ones are splitted in two values represented with maximum 7 bits, in this way we avoid the situation in which a maximum value(0xff) appears in other byte of the package except the first one . So, for each byte we want to send we will use 2 bytes in the package. For example: if we want to send the maximum value, V=255, as a part of the package, we split it in two bytes: V_h=V/128=1 and V_l=V%128=127. The software that receives the package on the computer will find the real value from these two bytes as follows: V=V_h*128+V_l=1*128+127=255. CRC_H and CRC_l are the two bytes (calculated as in the above example) of the cyclic redundancy check(CRC). CRC is a mechanism to protect against common types of errors on communication channels. It can provide quick and reasonable assurance of the integrity of messages delivered. The software from microcontroller calculates the CRC as the 8 bit sum of all the bytes it wants to transmit (Byte0 to Byte1). When the computers detects the beginning of the package, reads the next 25

bytes and calculates their 8 bit sum. Then it calculates CRC_H and CRC_L and compares these values with the last two values of the received package. If these values are equals the package is safe and ready to use. If these values are not the same, the package is ignored.

También podría gustarte