quinta-feira, 27 de junho de 2013

SDCC: Estrutura de um programa para PIC

Não vou entrar nos detalhes de como programar em C. Se você chegou até aqui, eu presumo que você saiba o mínimo necessário para escrever um "Hello World!" em C para qualquer plataforma. E tutorial para programar em C puro tem aos baldes na internet.

C ou C++? C!!! Assim rezado por Ken Thompson e Dennis Ritchie. SDCC não suporta C++. Então aquelas maravilhas de cin/cout não vai te ajudar em nada. Estamos programando para microcontroladores que têm uma memória absurdamente diminuta, então não dá para ficar "dourando a pílula".

Estrutura Mínima

Basicamente um programa em C para PIC no SDCC tem a seguinte estrutura:

- Cabeçalho (headers inclusion)
- Configuração dos bits do microcontrolador (fuses - somente no módulo principal)
- E a função main()

Óbvio que não fica limitado a isso... por isso eu chamo de estrutura mínima.

A função main é a função que será invocada pelo microcontrolador quando esse inicializar. Simplesmente declarado como

void main() {
/* ... */
}

Exemplo:

#define __16F88
#include "pic16regs.h"

typedef unsigned int config;

config __at _CONFIG1 conf1=_HS_OSC & _PWRTE_OFF & _BOREN_OFF & _BODEN_OFF & _WDT_OFF & _MCLR_ON;

int main()
{
TRISB=0xFD;
while(1) {
PORTB=(PORTB^0x02);
}

}

Cabeçalhos 

Se alguma função, constante, tipos definidos, variáveis externas, etc, não declarados no corpo do programa atual forem utilizados, eles terão que ser declarado antes. Para isso serve os arquivos .h (headers)

Para o SDCC com PIC a estrutura mais comum é definir o tipo do microcontrolador e depois incluir os registros necessários.


#define _p16f88 
#include "pic16regs.h"

...


A declaração acima faz com que seja utilizado as definições de registros/registradores para suporte do PIC16F88 somente!

#define _p18f252
#include "pic18fregs.h"

...

De forma similar, mas para o PIC18F252.


Existem programadores que fazem diferente, por exemplo:

#include "pic14/pic16f88.h" 

que faz a mesma coisa da definição que eu utilizo. Fica a teu critério.

Configuração dos Bits (fuses)

Essa é a parte mais confusa. Dependendo da versão de SDCC você terá dores de cabeça. Estou usando a versão 3.3 - então assumo que você tenha essa versão.

O SDCC da versão 3.2 em diante, procurou fazer alguma compatibilidade com o compilador XC da Microchip. Então, para chips mais modernos (18F em diante) a melhor técnica de declarar os fuses é utilizando a diretiva #pragma config

/* para PIC18F252... */
#define _p18f252
#include "pic18fregs.h"

#pragma config OSC=HS, OSCS=OFF, PWRT=OFF, BOR=OFF, WDT=OFF, CCP2MUX=OFF, LVP=OFF, CP0=OFF, CP1=OFF, CP2=OFF, CP3=OFF

/* ... */

As chaves acima, possuem definições bem definidas nos arquivos .inc que estão nos diretórios do gputils!

Para microcontroladores antigos, ainda vale a antiga forma de declarar, que é mais confusa de todas (pode variar de compilador para compilador).

/* Para PIC16F88 */
#define _p16f88
#include "pic16regs.h"

typedef unsigned int config;

config __at _CONFIG1 conf1=_HS_OSC & _PWRTE_OFF & _BOREN_OFF & _BODEN_OFF & _WDT_OFF & _MCLR_ON;

/* ... */


No caso acima, os registros dos valores e nome das configs, podem ser encontrados no .h respectivo de seu processador (no caso pic16f88.h no diretório de include do SDCC)

NOTA: Dá para usar processadores mais modernos com a notação antiga. Aumenta a confusão e o compilador irá mostrar uma mensagem de warning... mas pode ser ignorado. :)

Free e Non-Free

Alguma coisa mudou e alguém teve que fazer algum ajuste de conduta. Nos novos compiladores SDCC, se você procurar no diretório include ( C:\...\SDCC\include ) você não vai encontrar NENHUM header de pic algum. Somente os wrappers (pic16fregs.h, pic14regs.h, ...). Onde foram parar p16f*, p18f*?

No próprio diretório do SDCC tem um diretório chamado non-free. Lá estão os headers de cada microcontrolador.

VOCÊ NÃO PRECISA FAZER NADA!!! Não precisa copiar os arquivos ou inventar que está organizando o SDCC... não cometa bobagens.

Para fazer compilar o programa, basta passar na linha de comando a flag --use-non-free e pronto. O SDCC vai achar normalmente!

Sem --use-non-free:

c:\Development\SDCC>sdcc -p16f88 -mpic14  blink.c
In file included from blink.c:6:
C:/PROGRA~1/SDCC/bin/../include/pic14/pic16regs.h:163:24: error: pic16f88.h: No
such file or directory
blink.c:14: error 20: Undefined identifier '_CONFIG1'
blink.c:14: error 2: Initializer element is not constant
blink.c:18: error 20: Undefined identifier 'TRISB'
blink.c:20: error 20: Undefined identifier 'PORTB'
blink.c:20: error 20: Undefined identifier 'PORTB'

Deu erro! :(

Com o --use-non-free:

c:\Development\SDCC>sdcc --use-non-free -p16f88 -mpic14  blink.c
message: using default linker script "C:\Program Files (x86)\gputils\lkr\16f88_g.lkr"

c:\Development\SDCC>


Funciona! :)

---

Próximo tópico: Vetores de interrupção

Nenhum comentário:

Postar um comentário