Olá, pessoal. Muito tempo sem postar por aqui...
Bem, estive ocupado em meu serviço tentando descobrir como criar um servidor Web usando os microcontroladores da família PIC. O grande lance destes microcontroladores é que a Microchip já fornece gratuitamente as bibliotecas necessárias para fazer isto. A questão é que não é muito simples de se configurar, sem muita documentação sobre isto. Por isto resolvi fazer uma descrição sobre este tema aqui.
Preparando terreno
Para que todos possam entender como se configura este projeto a partir do zero, resolvi detalhar todo o processo a partir do download dos arquivos necessários, no site da Microchip.
Assim, o primeiro passo é fazer o download, para quem ainda não fez, do MPLAB, que é a IDE para desenvolvimento de projetos no PIC. Para mim, este é um passo fundamental, já que através do MPLAB, você configura e depura projetos com o PIC muito facilmente. O link para o download do MPLAB (última versão), está aqui:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002
Mas este não será o único download no site da Microchip. É importante também fazer o download de algum compilador C deste fabricante. Como este compilador dependerá do microcontrolador que você irá usar, então haverá escolhas diferentes aqui. Como exemplo, irei usar o compilador C18. A página abaixo possui um link para os vários compiladores disponíveis:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en534868&page=wwwCompilers
Pode-se fazer o download da versão
lite destes compiladores, que são versões que não usam todas as otimizações do compilador versão
full. Para mim está de bom tamanho para fazer este tipo de desenvolvimento, já que estes compiladores costumam ser muito caros para hobistas.
Tendo feito o download do compilador, resta agora fazer o download das bibliotecas da Microchip para TCP/IP e outros. Isto pode ser feito no link abaixo:
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=2680&dDocName=en547784
Muito bem, terminamos com as etapas de downloads... Agora vamos para a parte de instalação, que não é muito complicada. Só para garantir que tudo dará certo, vamos instalar o MPLAB primeiro, o C18 depois e por fim as bibliotecas da Microchip. Não tenho nenhuma observação a fazer aqui, embora eu recomende que deixe que as instalações sejam feitas na raiz da unidade C, para diminuir o caminho a ser incluido nos projetos. Agora estamos prontos para iniciar nosso projeto.
Iniciando o projeto
Quando procurei saber como iniciar um projeto de servidor HTTP no PIC, encontrei várias sugestões me indicando o projeto
TCPIP Demo App, que é instalado junto com as bibliotecas da Microchip. Pessoalmente não gostei muito disto, pois o projeto por se tratar de uma demonstração, foi feito para incluir vários tipos de demonstração. Acho que não é necessário copiar todos os arquivos desta pasta. Os arquivos que são necessários para o projeto são os arquivos
TCPIPConfig.h e
HardwareProfile.h. Através destes arquivos, você poderá configurar seu projeto. Você precisará mudar manualmente o arquivo
HardwareProfile.h.
Eu por exemplo tenho aqui uma placa Explorer16BR, da Mosaico. Todo mundo poderia achar que pelo fato de haver uma definição EXPLORER_16 neste arquivo, bastaria habilitá-la para que tudo funcione perfeitamente, certo? Bem, a verdade é que a Mosaico andou alterando alguns pinos nesta placa, e entre eles está justamente o pino de habilitação do Driver Ethernet. Portanto, se alguém estiver usando esta placa, procure pela definição
#else // SPI1 for all other processors
#define ENC_CS_TRIS (TRISDbits.TRISD14)
#define ENC_CS_IO (LATDbits.LATD14)
E altere para:
#else // SPI1 for all other processors
#define ENC_CS_TRIS (TRISCbits.TRISC4)
#define ENC_CS_IO (LATCbits.LATC4)
Há também a opção de se criar o arquivo do zero. Neste caso, a pessoa deve criar algumas definições obrigatórias neste arquivo, como está abaixo:
#ifndef __HARDWARE_PROFILE_H
#define __HARDWARE_PROFILE_H
#include "GenericTypeDefs.h"
#include "Compiler.h"
// Define os fusíveis de configuração (apenas uma vez)
#if defined(THIS_IS_STACK_APPLICATION)
#if defined(__18CXX)
#if defined(__EXTENDED18__)
#pragma config XINST=ON
#elif !defined(HI_TECH_C)
#pragma config XINST=OFF
#endif
#pragma config WDT=OFF, FOSC2=ON, FOSC=HSPLL, ETHLED=ON
#endif
#endif // Previne a definição de mais de uma vez dos mesmos fusíveis
// Valor da frequência de clock.
// Este valor é usado para calcular o valor de Tick Counter
#define GetSystemClock() (41666667ul) // Hz
#define GetInstructionClock() (GetSystemClock()/4)
#define GetPeripheralClock() GetInstructionClock()
No caso, as definições que devem ser feitas são as definições de clock do sistema. Você precisa verificar qual as configurações de frequência você está usando, para criar estas definições.
Feito isto, podemos agora configurar a parte de TCP/IP. Para isto, a Microchip desenvolveu um executável que faz toda a configuração para nós. Este executável se encontra na pasta:
[Diretório instalado]\Microchip Solutions\Microchip\TCPIP Stack\Utilities
E o executável se chama
TCPIPConfig.exe. Execute ele e forneça o caminho para seu projeto. Não se esqueça de marcar a opção
Show Advanced Settings, para podermos configurar nosso projeto nos mínimos detalhes. Na próxima tela teremos várias opções de projeto:
Selecionaremos apenas Web Server. Selecionando
Next, teremos várias opções de códigos de exemplo. Não iremos selecionar nenhuma destas opções aqui. Clicando-se novamente em Next, teremos uma seleção de módulos:
Aqui selecionamos
ICMP Client,
ICMP Server e o
NetBIOS Name Service. Os dois ICMP são necessários para que a aplicação possa fazer PING em computadores e para que ela possa também responder a este comando, muito útil para verificar a conectividade de dispositivos. O
NetBIOS Name Service será importante para que você possa acessar seu dispositivo pelo Browser digitando o nome deste dispositivo na barra de endereços.
É na próxima tela que você configurará o endereço IP de seu projeto, nome do dispositivo, máscara de sub-rede, endereço MAC, etc...
Configure de forma que o dispositivo seja reconhecido em sua rede. Assim que isto for feito, clique em
Next, e você será perguntado sobre qual biblioteca HTTP você pretende usar em seu projeto.
Vamos usar o HTTP2, pois ele traz inúmeras vantagens, como a possibilidade de usar métodos POST em formulários e o uso de variáveis dinâmicas. Feito isto, na próxima tela temos a seleção de configurações da biblioteca:
Como é um teste simples, vamos habilitar apenas os métodos POST. A página inicial será a página
index.htm, e permitiremos apenas duas conecções por vez. Na próxima tela temos a seleção do sistema de arquivos, mas o HTTP2 da Microchip possibilita apenas o uso do sistema de arquivos MPFS2. Depois desta seleção, podemos escolher onde os arquivos serão gravados. No meu projeto, preferi salvar os arquivos dentro da Flash de programa do microcontrolador, que tinha espaço suficiente para todos os arquivos. Outras opções são:
O próximo passo é o mais complicado. Neste passo, você determinará a quantidade de memória usada para cada conecção.
Como não usamos nenhum outro tipo de conecção, determinaremos memória apenas para o HTTP_SERVER. Verifique se os outros tipos de Sockets estão com seu
Count diferente de 0. O
Count determina quantas conecções daquele tipo existirão. Como só temos duas conecções HTTP, só neste tipo de Socket é que deveremos ter um valor diferente de 0. A próxima tela permite você escolher quantas conecções UDP sua aplicação terá, e finalmente você poderá concluir esta configuração. O programa vai sobreescrever os valores disponíveis no seu arquivo
TCPIPConfig.h. Estamos prontos para dar início a nosso projeto.
Arquivo principal do projeto
O arquivo principal do projeto deverá seguir alguns procedimentos básicos. O primeiro é que ele deve trazer a seguinte definição:
#define THIS_IS_STACK_APPLICATION
Isto indicará ao compilador qual é o arquivo principal. O segundo passo é que sua aplicação deverá definir uma instância da estrutura APP_CONFIG chamada de AppConfig. Esta estrutura contém as configurações de TCP/IP do projeto. Adicione a linha:
APP_CONFIG AppConfig;
Esta será uma variável global.
Nós temos também que definir o tratamento de interrupções de tempo, pois o Stack TCP/IP da Microchip usa os
timers para o gerador de
ticks. O tratamento de interrupção pode ser feito através do seguinte código:
#pragma interruptlow LowISR
void LowISR(void)
{
TickUpdate();
}
#pragma interruptlow HighISR
void HighISR(void)
{
}
#pragma code lowVector=0x18
void LowVector(void){_asm goto LowISR _endasm}
#pragma code highVector=0x8
void HighVector(void){_asm goto HighISR _endasm}
#pragma code // Volta para a seção padrão de códigoPara um servidor HTTP, as funções de tratamento de mensagens GET e POST (quando habilitadas) serão chamadas. Mas as bibliotecas da Microchip deixam a definição destas funções a cargo da aplicação, para que o programador trate destas mensagens da forma que ele deseja. Como estamos no início do projeto e a intenção é apenas gerar um servidor sem formulários no começo, vamos definir funções que não fazem nenhum tratamento:
HTTP_IO_RESULT HTTPExecuteGet(void)
{
return HTTP_IO_DONE;
}
HTTP_IO_RESULT HTTPExecutePost(void)
{
return HTTP_IO_DONE;
}Retornando HTTP_IO_DONE em ambas funções, dizemos às bibliotecas TCP/IP da microchip que o tratamento destas funções foi bem-sucedido, o que não deixa de ser verdade.
Como antes criamos uma instância da estrutura APP_CONFIG, precisamos agora preenchê-la com os dados necessários à aplicação. Os detalhes desta função podem ser vistos no programa de demonstração da Microchip, mas para facilitar esta tarefa, estarei colocando a função que criei aqui:
static ROM BYTE SerializedMACAddress[6] = {MY_DEFAULT_MAC_BYTE1, MY_DEFAULT_MAC_BYTE2, MY_DEFAULT_MAC_BYTE3, MY_DEFAULT_MAC_BYTE4, MY_DEFAULT_MAC_BYTE5, MY_DEFAULT_MAC_BYTE6};
static void InitAppConfig(void)
{
AppConfig.Flags.bIsDHCPEnabled = TRUE;
AppConfig.Flags.bInConfigMode = TRUE;
memcpypgm2ram((void*)&AppConfig.MyMACAddr, (ROM void*)SerializedMACAddress, sizeof(AppConfig.MyMACAddr));
AppConfig.MyIPAddr.Val = MY_DEFAULT_IP_ADDR_BYTE1 | MY_DEFAULT_IP_ADDR_BYTE2<<8ul | MY_DEFAULT_IP_ADDR_BYTE3<<16ul | MY_DEFAULT_IP_ADDR_BYTE4<<24ul; AppConfig.DefaultIPAddr.Val = AppConfig.MyIPAddr.Val; AppConfig.MyMask.Val = MY_DEFAULT_MASK_BYTE1 | MY_DEFAULT_MASK_BYTE2<<8ul | MY_DEFAULT_MASK_BYTE3<<16ul | MY_DEFAULT_MASK_BYTE4<<24ul; AppConfig.DefaultMask.Val = AppConfig.MyMask.Val; AppConfig.MyGateway.Val = MY_DEFAULT_GATE_BYTE1 | MY_DEFAULT_GATE_BYTE2<<8ul | MY_DEFAULT_GATE_BYTE3<<16ul | MY_DEFAULT_GATE_BYTE4<<24ul; AppConfig.PrimaryDNSServer.Val = MY_DEFAULT_PRIMARY_DNS_BYTE1 | MY_DEFAULT_PRIMARY_DNS_BYTE2<<8ul | MY_DEFAULT_PRIMARY_DNS_BYTE3<<16ul | MY_DEFAULT_PRIMARY_DNS_BYTE4<<24ul; AppConfig.SecondaryDNSServer.Val = MY_DEFAULT_SECONDARY_DNS_BYTE1 | MY_DEFAULT_SECONDARY_DNS_BYTE2<<8ul | MY_DEFAULT_SECONDARY_DNS_BYTE3<<16ul | MY_DEFAULT_SECONDARY_DNS_BYTE4<<24ul; memcpypgm2ram(AppConfig.NetBIOSName, (ROM void*)MY_DEFAULT_HOST_NAME, 16); FormatNetBIOSName(AppConfig.NetBIOSName);
}
Por fim, nossa função
main. Aqui há algumas observações a se fazer... As funções de inicialização do protocolo devem seguir uma ordem para serem executadas, pois do contrário o nosso servidor não funcionará. A ordem é a seguinte:
InitAppConfig();
TickInit();
MPFSInit();
StackInit();
O
loop principal de seu programa deve executar estas duas funções:
StackTask();
StackApplications();
São estas as funções que devem ser usadas no seu projeto.
Configurando o projeto
Devemos incluir os arquivos para o projeto. Antes disto, devemos configurar o projeto para que inclua os cabeçalhos da Microchip na hora de compilar. Vamos ao menu
Project, Build Options... Em
Directories, clicando no menu
Drop Down, selecionamos a opção
Include Search Path. Vamos incluir aqui o diretório do projeto ".", o diretório de includes da Microchip Solutions, e o diretório de includes do C18. Em
Library Search Path incluiremos também o diretório de livrarias do C18. Feito isto, estamos prontos para incluir os arquivos do projeto.
Para compilar o projeto, precisamos incluir os seguintes arquivos:
ARP.c, Delay.c, DNS.c, ENC28J60.c, Helpers.c, HTTP2.c, ICMP.c, IP.c, MPFS2.c, NBNS.c, StackTsk.c, TCP.c, Tick.c, UDP.c. Agora nos resta criar os arquivos
html para o servidor web.
Arquivos do servidor
Na sua pasta de projeto, crie uma pasta para guardar os arquivos
html do servidor. É importante criar o arquivo
index.htm que nós colocamos antes como o arquivo inicial do servidor. Neste primeiro passo, vamos criar apenas arquivos estáticos.
Assim que os arquivos forem criados, poderemos voltar na pasta Utilities onde encontramos o executável de configuração de TCP/IP. Agora vamos executar o programa
MPFS2.exe.
Este programa irá converter os arquivos da pasta que você indicar para o sistema de arquivos MPFS. Como desejamos gravar na memória de programa do PIC, iremos converter nossos arquivos em um arquivo .c, que deverá ser incluído também no projeto. Assim que você clicar
Generate, dois arquivos serão criados na pasta de projeto que você especificou. Depois disto, inclua o arquivo
HTTPPrint.h que o programa gerar.
Pronto! Nosso projeto está completo e poderá ser compilado.
Voltaremos a falar sobre este tema posteriormente, explicando como usar formulários e variáveis dinâmicas. Por fim, ensinaremos a usar AJAX com nosso servidor web.