PIC18 (ou PIC18F) é uma das famílias de microcontroladores de 8 bits da Microchip. Entre as famílias de 8 bits, os PIC18 são os que tem os recursos mais avançados, e por este motivo são muito utilizados no mercado.
O clock é algo essencial nos microcontroladores, é ele o responsável por gerar a base de tempo que mantém o funcionamento ordenado do microcontrolador. Sem o clock nenhum microcontrolador funciona, ou ainda, caso o clock não for preciso não é possível ter um controle do sistema.
Nos PICs da família 18F, existem várias fontes de clock e configurações possíveis. Neste artigo conheceremos o sistema de clock dos microcontroladores da família PIC18 e tomaremos como base o PIC18F4550, mas os conceitos são os mesmos para os demais chips dessa família.
Os Microcontroladores PIC18F
Existe uma série de microcontroladores dentro desta família, cada um com seu conjunto de periféricos internos, quantidade de memória FLASH, RAM e EEPROM, tensão de trabalho, etc. Abaixo vemos uma imagem que mostra um breve resumo da capacidade dos micros da série 18F:
Para o PIC18F4550, que será usado para este artigo, temos as seguintes configurações:
- 32KB de FLASH, 2KB de RAM e 256B de EEPROM;
- 35 pinos de IO que são multiplexados com os periféricos;
- USB 2.0 que pode funcionar como Low Speed (1.5 Mbps) ou Full Speed (12 Mbps);
- 4 timers sendo um de 8 bits e três de 16 bits;
- Até dois módulos CCP (Capture / Compare / PWM);
- 1 UART e 1 Módulo MSSP que pode ser configurado para funcionar como SPI ou I2C;
- 1 conversor AD de 10 bits multiplexado para até 13 canais;
- tensão de alimentação de 2 V a 5,5 V.
Maiores detalhes sobre este microcontrolador podem ser obtidos no seu datasheet.
Sistema de clock do PIC18F4550
O sistema de clock do PIC18F4550 pode operar de diversas formas, a imagem abaixo mostra o seu diagrama de blocos:
As fontes de clock possíveis para os PIC18 são basicamente 3:
- Oscilador interno;
- Oscilador primário e;
- oscilador secundário;
Vamos a uma análise de cada um deles.
Oscilador interno
O bloco oscilador interno do PIC18F4550 tem duas fontes de clock, uma de 8MHz e outra de 31KHz. O bloco de 8MHz tem ligado em série com ele um módulo divisor de frequência. Dessa forma o clock que é enviado para a CPU pode ser de 125KHz, 250KHz, 500KHz, 1MHz, 2MHz, 4MHz e 8MHz.
O bloco de 8MHz é calibrado pelo fabricante em fábrica, porém esta frequência pode variar de acordo com a tensão de alimentação e a temperatura, por esse motivo os PIC18 contam com um ajuste interno, que pode ser feito por meio do registrador OSCTUNE, e um bit (IOFS) para sinalizar que a frequência está estável.
Já o bloco que fornece 31KHz não tem sua frequência dividida, e pode ser liberada diretamente para a CPU.
Oscilador Secundário
O oscilador secundário faz uso do timer1 para gerar o clock do sistema. Esse modo de funcionamento é muito utilizado em dois tipos de aplicação, uma delas é em aplicações que exigem baixo consumo, já que para utilizar essa fonte de clock deve-se colocar o timer 1 em modo low power e ligar aos pinos RC0 e RC1 um cristal de baixa frequência (cerca de 32KHz). Essa fonte de clock continua funcionando mesmo que o PIC seja colocado em um modo de baixo consumo (sleep mode). A outra aplicação para o oscilador secundário é ligar aos pinos do timer1 um cristal de 32.768KHz para gerar a base de tempo, com isso podemos implementar um RTC com o nosso chip. Para saber mais sobre RTC eu indico o artigo Módulo Tiny RTC I2C – Parte 1 publicado aqui mesmo no embarcados pelo Francesco Sacco.
Oscilador Primário
O oscilador primário no PIC18F4550 funciona basicamente com três possíveis fontes de clock:
- HS (High Speed): É usado para ter um clock de frequência elevada, para isso pode ser ligado um cristal ou ressonador de frequência maior que 4MHz;
- XT (Xtal): Projetado para funcionar com uma frequência menor que o modo HS, para isso ligamos um cristal ou ressonador de 1MHz a 4MHz;
- EC (External Oscilator): Esse modo é usado quando utilizamos alguma outra fonte de clock para o nosso microcontrolador, um outro CI por exemplo ou um circuito oscilador. Essa fonte de clock gera um maior consumo de energia.
É importante mencionar que o consumo do microcontrolador é proporcional à frequência de clock, ou seja, quanto maior a frequência, maior será o consumo.
USB
O PIC18F4550 dispõe de uma USB interna que pode funcionar em dois modos, um deles é o Low-Speed, que para isso é necessário ter uma fonte de clock de 6MHz, o outro é Full-Speed, que neste caso precisa de um clock de 48MHz.
O projetista pode usar um cristal que forneça o clock necessário, mas para atender a necessidade da USB, este PIC conta com um circuito PLL (Phase Locked Loop) interno, que a partir de um cristal de 4MHz ou um de seus múltiplos até 48MHz, gera uma frequência de 96MHz. Esse valor pode ser dividido por 2, resultando em 48MHz, que pode ser utilizado para fornecer a base de clock para o sistema e para a USB funcionar em modo Full-Speed.
Capacitores
Os cristais e os ressonadores, para obter um bom funcionamento, precisam de um par de capacitores ligados a eles. A seguir vemos os valores de capacitores sugeridos pela Microchip para utilização com cristais e ressonadores:
Em sequência, segue o circuito de montagem dos cristais ou ressonadores no PIC:
Configurações
A configuração de cada modo de funcionamento do circuito de clock é feita por meio do Configurations Bits. Irei mostrar cada uma das configurações possíveis para o sistema de clock. Se você não está familiarizado com o MPLAB X e o compilador XC8, o ideal é ler os artigos escritos pelo Fábio Souza aqui no embarcados (Parte 1 e Parte 2), para este caso indico principalmente a parte 2 da série.
Os modos de funcionamento possíveis e suas respectivas configurações são as seguintes:
XT – Cristal ou ressonador:
#pragma config FOSC = XT_XT // Oscilador XT ou #pragma config FOSC = XTPLL_XT // Oscilador XT com PLL habilitado
HS – High Speed Cristal ou ressonador:
#pragma config FOSC = HS // Oscilador HS ou #pragma config FOSC = HSPLL_HS // Oscilador HS com PLL habilitado
EC – Clock Externo:
#pragma config FOSC = ECIO_EC // Oscilador EC, pino RA6 como IO ou #pragma config FOSC = EC_EC // Oscilador EC, pino RA6 como saída de clock (Fosc/4) ou #pragma config FOSC = ECPLLIO_EC // Oscilador EC, pino RA6 como IO e PLL habilitado ou #pragma config FOSC = ECPLL_EC // Oscilador EC, pino RA6 como saída de clock e PLL habilitado
INTHS – Oscilador interno para o sistema de clock e HS para a USB:
#pragma config FOSC = INTOSC_HS // Oscilador interno, HS usado para USB ou #pragma config FOSC = INTOSC_XT // Oscilador interno, XT usado para USB ou #pragma config FOSC = INTOSCIO_EC // Oscilador interno, EC usado para USB com RA6 como IO ou #pragma config FOSC = INTOSC_EC // Oscilador interno, EC para USB e RA6 como saída de clock
As configurações para o circuito PLL podem ser:
#pragma config PLLDIV = 1 #pragma config PLLDIV = 2 #pragma config PLLDIV = 3 #pragma config PLLDIV = 4 #pragma config PLLDIV = 5 #pragma config PLLDIV = 6 #pragma config PLLDIV = 10 #pragma config PLLDIV = 12
Devemos definir também a divisão do clock do sistema e dos 96MHz gerados pelo circuito PLL:
#pragma config CPUDIV = OSC1_PLL2 // Oscilador do sistema / 1 e 96MHz do circuito PLL / 2 #pragma config CPUDIV = OSC2_PLL3 // Oscilador do sistema / 2 e 96MHz do circuito PLL / 3 #pragma config CPUDIV = OSC3_PLL4 // Oscilador do sistema / 3 e 96MHz do circuito PLL / 4 #pragma config CPUDIV = OSC4_PLL6 // Oscilador do sistema / 4 e 96MHz do circuito PLL / 6
Quando o oscilador interno de 8MHz é usado, um sistema de divisão seleciona qual o clock vai ser usado para o sistema. Essa seleção é feita escrevendo nos bits IRCF0, IRCF1 e IRCF2 do registrador OSCCON. Esse registrador e seus bits podem ser vistos na imagem a seguir:
Depois de configurar o clock do sistema é hora de testar, e nada melhor para isso do que o famoso pisca led. Vamos usar dois códigos parecidos para piscar um led, mudando apenas a configuração do clock do sistema.
Usaremos a macro __delay_ms() para gerar um delay de 1 segundo, e para utilizá-la devemos incluir a biblioteca xc.h e dizer ao compilador qual o clock do sistema pela definição de _XTAL_FREQ.
A macro __delay_ms() usada no compilador XC8 tem uma limitação de 179.200 ciclos de máquina para a família PIC18, por conta dessa limitação essa macro não pode ser usada para grandes valores de tempo, sendo assim, usaremos um laço for() para conseguirmos o intervalo de 1 segundo.
Como exemplo, vamos criar um código para um microcontrolador PIC18F4550 utilizando um cristal de 20MHz como oscilador primário e com PLL desativado:
#include <stdint.h>
#include <xc.h>
#include <p18f4550.h>
#define LED_ON PORTDbits.RD3 = 1 // Macro para ligar o LED
#define LED_OFF PORTDbits.RD3 = 0 // Macro para desligar o LED
#define _XTAL_FREQ 20000000 // Definição do clock do sistema
#pragma config PLLDIV = 1
#pragma config CPUDIV = OSC1_PLL2 // Oscilador do sistema / 1 e 96MHz do circuito PLL / 2
#pragma config FOSC = HS // Oscilador HS
void main(void) {
uint8_t i; // Cria variável de contagem
TRISCbits.RC2 = 0; // Define pino como saída
while(1){
LED_ON; // Liga o LED
for(i=0; i<100; i++) __delay_ms(10); // Delay de 1 segundo
LED_OFF; // Desliga o LED
for(i=0; i<100; i++) __delay_ms(10); // Delay de 1 segundo
}
}
Agora vamos usar o oscilador interno como clock do sistema, e usar o divisor para ter um clock de 1MHz:
#include <stdint.h>
#include <xc.h>
#include <p18f4550.h>
#define LED_ON PORTDbits.RD3 = 1 // Macro para ligar o LED
#define LED_OFF PORTDbits.RD3 = 0 // Macro para desligar o LED
#define _XTAL_FREQ 1000000 // Definição do clock do sistema
#pragma config FOSC = INTOSCIO_EC // Oscilador interno, EC usado para USB com RA6 como IO
void main(void) {
uint8_t i; // Cria variável de contagem
TRISCbits.RC2 = 0; // Define pino como saída
OSCCON = 0b01000111; // Configuração: utilizar o oscilador interno e
// usar poscaler para gerar clock de 1Mhz
while(1){
LED_ON; // Liga LED
for(i=0; i<100; i++) __delay_ms(10); // Delay de 1 segundo
LED_OFF; // Desliga LED
for(i=0; i<100; i++) __delay_ms(10); // Delay de 1 segundo
}
}
Existem muitas outras possibilidades de configuração, entre elas temos as várias possibilidades de utilização do divisor do oscilador interno, utilizar o timer 1 como fonte de clock, utilizar um clock externo ou um cristal ou ressonador com as várias combinações do multiplicador PLL e divisor de clock.
Resumo
O sistema de clock nos PICs da família PIC18 é muito versátil e permite uma grande variedade de formas para gerar o clock do sistema, cada uma delas com sua característica particular, e com certeza uma delas cabe no seu projeto.
Teste as várias possibilidades que os PICs lhe oferecem e poste aqui seus resultados. E se tiver problemas na configuração, descreva nos comentários que tentaremos ajudá-lo.
E fique no aguardo de novos artigos sobre a arquitetura dos microcontroladores PIC18 e utilização de seus periféricos, ainda existe muita coisa a ser explorada nessa família de microcontroladores.









tento simular comunicação I2C com DS1307 com pic16f1829 no isis proteus 8 ele gera a comunicação pelo osciloscopio do simulador ao qual visualizo sem problemas o trafego de dados .. porem nao faz leitura dos dados do DS1307 no registro SSP2BUF . Será que pode ser algum bug com esse modelo especifico no proteus isis 8? seria necessario baixar alguma atualizaçao pra este simulador versao 8?
Olá, Josemar.
Muito bom o artigo, mas fiquei com uma dúvida: O LED e o delay de 1 segundo são um teste pra ver se o oscilar está corretamente calibrado, ou é só um teste pra saber se o microcontralador está vivo?
Eu gostaria de saber como faço pra testar se meu oscilador está corretamente calibrado.
Se o delay não estiver preciso, isso quer dizer que o oscilador está mau configurado?
Olá Rogério.
Que bom que gostou do artigo.
Referente às suas dúvidas, o relatório de 1 segundo é só pra ter uma ideia aproximada da frequência de clock do micro.
O oscilador interno de 8 MHz dos pic ja vem calibrado. Você pode apenas ajustar esse oscilador pelo registrador OSCTUNE e verificando se o oscilador está estável pelo bit IOFS do registrador OSCCON.
Se quiser testar um cristal externo é melhor fazer isso com um osciloscópio.
Olá, Josemar. Acho que minha pergunta não ficou bem clara. Eu gostaria de uma forma de saber se eu configurei meu oscilador corretamente. Estou programando um PIC24FJ128GA008 e estou tentando configurar o oscilador interno, do mesmo, através do #pragma config FNOSC = FRCPLL, a princípio, esse pragma configura o oscilador interno para 8MHz com PPL ativado, o que daria 32Mhz. Pra testas, eu configurei o timer 1 para 25ms e um pino de saída digital pra ficar alternando o estado dentro da interrupção do timer, dessa forma, com um osciloscópio, eu esperava ver uma onda quadrada que alterna o estado… Leia mais »
Entendi seu ponto.
Acho que o ponto de partida seria saber se o problema está no clock ou no timer. Para fazer isso eu faria um loop com a função __delay_ms(10) dentro do main para testar o tempo de toggle do pino.
Se o tempo for de 10ms o clock está correto e o problema está no timer. Se não tiver, aí parte para avaliar o clock.
Entendi.
Obrigado pela dica, Josemar.
Continuem com esse baita trabalho que presta um tremendo serviço para muitos desenvolvedores e áreas afins.
Adoro esse site.
Se possível, postem um artigo ensinado a calcular os timers dos microcontroladores PIC. Será de grande utilidade.
Boa tarde Josemar. Estou fazendo um trabalho, onde através de um PAD touch capacitivo feito por nós mesmo, temos a intenção de acender um LED e controlar sua intensidade através do PWM. Vamos fazer a leitura do touch com comparador de frequência. Porém estamos com dificuldade em fazer essa leitura. Temos noção de que temos que comparar a variação da frequência causada pelo toque com a frequência ‘natural’, ou seja, sem o toque. Poderia nos dar uma força? Nosso microcontrolador é um PIC 18F4550 cristal de 20 MHz.
Abraço.
Boa tarde Josemar !
Estou utilizando o PIC18F4520 e o gravador PICKIT3. Fiz um projeto bem simples apenas para verificação e funcionou normalmente enquanto o PIC estava ligado ao gravador. Mas quando eu alimentei ele com uma fonte externa, ele não faz nada. Já liguei o pino MCLR ao Vcc, mas nada mudou. Existe algum segredo para utilizar o PIC alimentado com uma fonte externa?
Muito obrigado.
Ola Carlos.
Não tem nenhum segredo não. Se puder mostre o código que fez e o circuito que está montado, assim podemos avaliar melhor.
Não entendi direito: apenas o oscilador interno de 8MHz varia com a temperatura e tensão ou o de 31kHz também?
Ola Luis Felipe.
Não encontrei nenhuma informação do fabricante sobre interferência de temperatura no oscilador de 31Khz, somente no de 8Mhz.
Boa tarde, estou fazendo um projeto com esse pic, estou com um cristal de 20 MHz, mas gostaria que o pic rodasse a 48 MHz. Tentei fazer a configuração aqui e não funcionou. Seria possível vocês me ajudarem?