Вы находитесь на странице: 1из 20

UNIVERSIDADE FEDERAL DO PARAN SETOR DE TECNOLOGIA DEPARTAMENTO DE ENGENHARIA ELTRICA Grupo PET Eltrica

Minicursos Tcnicos PET Eltrica

Apostila de linguagem C p/ microcontroladores

Autor Felipe Gabriel G. Camargo (bolsista do grupo PET Eltrica)

Curitiba 2011

Sumrio

Captulo 1 Como o microcontrolador funciona 1.1. Introduo 1.2. Esquematizando o projeto 1.3. O processo de compilao 1.4. Memrias

Captulo 2 A Linguagem C 2.1. Introduo 2.2. A sintaxe bsica da linguagem C 2.2.1. Pr-compilao 2.2.1.1. #include Cabealhos 2.2.1.2. #define Macros e constantes 2.2.1.3. #pragma 2.2.2. Tipos bsicos de variveis e seus modificadores 2.2.2.1. Variveis multidimensionais 2.2.3. Lista de operadores da linguagem C 2.2.4. Estruturas de controle de fluxo (if,else,switch) 2.2.5. Laos de repetio (for,while,do..while) 2.2.6. Funes 2.2.7. Operaes bit a bit 2.2.7.1. Mscara de bits 2.2.7.2. Macros para mscaras 2.2.7.3. Campos de bit

Captulo 1 - Como o microcontrolador funciona

1.1. Introduo Grosso modo microcontroladores so sistemas computacionais programveis de uso genrico e hardware reduzido e destinados a aplicaes dedicadas. Todo microcontrolador deve ter pelo menos CPU, memria e interfaces de entrada e sada. A CPU responsvel por todas as operaes que o microcontrolador ou microcomputador venha a executar. Toda CPU possui um conjunto de operaes que ela pode realizar e todo e qualquer programa se baseia nessas operaes ou em uma mistura dessas operaes. Tais operaes recebem o nome de instrues e cada arquitetura de CPU tem um conjunto especfico de instrues. Dentre as instrues genricas a qualquer processador podemos citar as operaes aritmticas de soma e subtrao, operaes lgicas e condicionais e a movimentao de dados da memria. A CPU processa sequencialmente uma instruo de cada vez, salvo os processadores com mais de um core e saltos condicionais, respectivamente. Um programa de computador nada mais que uma lista de tarefas (instrues) que a CPU deve executar. As linguagens de programao surgiram para criar uma camada de abstrao maior para a criao de programas, uma vez que seria muito complicado desenvolver e manter aplicaes mais complexas escritas diretamente em linguagem de mquina (binria). As linguagens de programao podem ser classificadas segundo seu nvel de estruturao. Quanto mais alto o nvel de abstrao da linguagem mais prxima linguagem humana ela e menos dependente do hardware ela fica.

Classificao das linguagens de programao quanto ao grau de abstrao


Baixo nvel Mdio nvel Alto nvel

Cdigo binrio (linguagem de mquina), Assembly (mnemnicos)

C, C++

PHP, Java, C#

Exemplos: Veja como fica um programa que soma o nmero 2 com outro nmero 2 e armazena o resultado em um terceiro lugar em trs tipos diferentes de linguagem de programao. Linguagem de mquina (binrio) OPCODE 0100 0100 0101 0100 OPERANDO 1 00000010 00000010 00010001 00011001 OPERANDO 2 00010001 00011001 00011001 00100000

Sequencialmente: 0100000000100001000101000000001000011001010100010001000110010100000110010010 0000 Assembly MOV #02h,R1 MOV #02h,R2 ADD R1,R2 MOV R2,R4 C int var1 = 2, var2 = 2, var3 = 0; var3 = var2 + var1;

Blocos internos de um microcontrolador

1.2. Esquematizando o projeto A primeira etapa de um projeto com microcontrolador definir quais sero as funes do microcontrolador e assim definir quantos pinos de entrada e sada sero necessrios, se h a necessidade de conversor A/D, de comparadores entre outros perifricos. A partir desses nmeros escalado o microcontrolador que mais corresponde s necessidades do projeto e do oramento. Depois disso faz-se um fluxograma do programa que o microcontrolador ir executar, a fim de criar um caminho lgico para o desenvolvimento do cdigo. Outra regra importante de projeto "dividir para conquistar". sempre importante ir escrevendo o cdigo um pedao de cada vez e ir testando (ou no jargo tcnico debugando) o seu funcionamento. Deste modo fica muito mais fcil encontrar falhas e imediatamente corrigi-las. Alm disso, sempre muito importante organizar e comentar todo o cdigo a fim de deixar todo o projeto muito bem documentado e inteligvel para qualquer um que o leia, inclusive para o prprio programador. Este aspecto torna-se muito mais importante em projetos de mdio e grande porte nos quais geralmente existem mais de uma pessoa trabalhando no cdigo. 1.3. O processo de compilao

O processo de compilao se resume a:

Cdigo fonte: arquivo-texto editado pelo programador. No faz nenhum sentido para o processador, porm descreve para o compilador qual o algoritmo. Pode ser escrito em qualquer linguagem de programao (C, Basic, Pascal, etc.), mas se o programador estiver usando assembly, a etapa de compilao trocada pela montagem. Bibliotecas e cabealhos: so arquivos (providos pelo compilador ou copiados pelo programador) que j contm partes de cdigo interessantes ao programa. Isso facilita muito a vida do programador uma vez que ele no precisa escrever todo o cdigo do zero. Arquivo Assembly (.asm): Arquivo do programa descrito em assembly, com todos os anexos includos. Arquivo hexadecimal (.hex): o arquivo gerado no final da compilao. Ele contm os valores de todos os cdigos de mquina que precisam ser escritos no microcontrolador. Cdigo de mquina: so os dados binrios que fazem sentido para o microcontrolador. So estes cdigos que o processador ir ler e executar quando for ligado.

1.4 Memrias A) No volteis: Memria de programa (instrues): Armazena as instrues e as constantes. Geralmente a maior memria do microcontrolador e do tipo flash. Em tempo de execuo s pode ser lida. (2Kb) EEPROM: uma pequena memria que pode ser acessada em tempo de execuo para gravar informaes importantes e que devem ser recuperadas mesmo se o microcontrolador for resetado. Ela no existe em todos os microcontroladores. B) Volteis: Memria RAM (variveis): Todas as variveis que so declaradas no programa so alocadas na memria RAM do microcontrolador. Ela bem menor que a memria de programa e geralmente do tipo SRAM (256 bits ou 32B). Registradores: a memria mais nobre e mais cara do microcontrolador. Todas as operaes que o microcontrolador efetivamente executa so feitas com os registradores.

Captulo 2 A linguagem C 2.1. Introduo A linguagem C foi inventada em 1972, por Dennis Ritchie, no Bell Labs para desenvolver o sistema operacional UNIX. 2.2. A sintaxe bsica da linguagem C Todo programa escrito em C deve ter a seguinte estrutura bsica: //Adio dos cabealhos que sero utilizados pelo programa #include <xxxx.h> //Todo programa em ANSI C deve conter pelo menos a funo main() int main() { //Coloque seu cdigo aqui return 0; } // A adio de // no incio da linha significa que esta linha de comentrio // Comentrios com mais de uma linha devem comear com /* e //terminar com */ /* Linhas de comentrio so ignoradas pelo compilador no momento da pr-compilao. Elas so teis para documentar o programa e deixa-lo mais fcil de entender e manter */ /* Toda linha de cdigo em C, salvo em aberturas de chaves { }, diretivas de pr-compilao e comentrios devem terminar com ; (ponto-e-vrgula) */ A linguagem C case sensitive, ou seja, diferencia letras MAISCULAS de minsculas. Alm disso, uma linguagem fortemente tipada, uma vez que toda varivel deve ser declarada junto com o seu tipo. 2.2.1 Pr-compilao #include Adio de cabealhos #define Definio de macros e constantes #pragma Instrues de portabilidade 2.2.2 Tipos Bsicos de Variveis e seus modificadores boolean: Pode ter dois valores: TRUE e FALSE e ocupa 8 bits. char: Pode ter valores de -128 at 127 e ocupa 8 bits. geralmente usada para armazenar caracteres alfabticos.

unsigned char: Pode ter valores de 0 at 255 e ocupa 8 bits. int: Armazena valores inteiros de -32.768 at 32.768 e ocupa 16 bits. Por padro qualquer nmero que seja constante e esteja no programa tratado como inteiro e por isso deve obedecer s limitaes de valores dos inteiros. unsigned int: Armazena valores inteiros de 0 at 65.536 e ocupa 16 bits long: Armazena valores inteiros de -2,147,483,648 at 2,147,483,648 e ocupa 32 bits unsigned long: Armazena valores inteiros de 0 at 4,294,967,295 e ocupa 32 bits float: Ocupam 32 bits e tem 6-7 casas decimais de preciso. Por padro toda constante do tipo float deve ser declara com um ponto (.): 10.0 ou 0.0002 double: Ocupam 64 bits. volatile: Precede qualquer um dos tipos listados acima. Indica ao compilador que a varivel SER modificada ao longo do programa e que, portanto deve ter seu espao alocado na memria. Ex: volatile unsigned int a = 0. const: Precede qualquer um dos tipos listados acima. Indica ao compilador que a varivel NO SER modificada ao longo do programa e que, portanto,pode ser substituda por uma constante (pode ser substitudo por um #define var valor). Ex: const unsigned float pi = 3.14. importante ressaltar que os microcontroladores contam com uma memria reduzida e que operaes com float e double demandam muito processamento e espao de memria e portanto devem ter seu uso restringido ao mximo. MUDANA DE BASE Dependendo da situao mais cmodo tratar os nmeros inteiros (constantes) em outras bases que no a decimal. BASE 10 (decimal) 8 (octal) 2 (binrio) 16 (hexadecimal) 123 0173 B1111011 0x7B VALOR

MUDANA DO TIPO DA CONSTANTE TIPO int unsigned int long unsigned long 18000 18000U 18000L 18000UL DADO

2.2.2.1. Variveis multidimensionais Vetores e matrizes Todos os tipos de variveis vistos acima podem ser expandidos para n-dimenses. Por conveno trataremos variveis do tipo [1 x N] como vetores e [M x N] como matrizes. A declarao de um vetor com N posies em C feita da seguinte maneira: tipo vetorA[N]; E de uma matriz com M colunas x N linhas posies feita da seguinte maneira: tipo matrixA[M][N]; Generalizando para uma matriz com qualquer nmero de dimenses: tipo matrixB[M][N][O].....[Z];

/*Declarao, atribuio e acesso a elementos de matrizes e vetores*/ char vetorA[3] = {3,4,5}; char matrixA[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; /* Para acessar um elemento de um vetor ou matriz basta colocar os seus ndices entre colchetes. Os ndices sempre comeam em 0. vetorA[0] == 3 vetorA[2] == 5 matrixA[0][0] == 1 matrixA[2][2] == 9 O mesmo vale para a atribuio de valores: vetorA[0] = 5; //vetorA[0] == 5 */

2.2.3. Lista de operadores da linguagem C OPERADORES ARITIMTICOS SMBOLO = OPERAO Atribuio: atribui um valor a uma varivel. No deve ser confundido com o operador de igualdade (==) Soma Subtrao Multiplicao Diviso Mdulo da diviso Calcula o resto da diviso de um inteiro por outro inteiro Incremento e decremento de 1 Incremento e decremento EXEMPLO int tempo = 0; // tempo==0

+ * / %

X=5+3 X=5-3 X=4*5 X = 10/2 int x = 7 % 2; // x=1;

++ e --

X = 2; X++; //X=3 X=2; X-=3; //X= -1

+= e -=

OPERADORES DE COMPARAO SMBOLO == != < > <= >= OPERAO Igual a Diferente de Menor que Maior que Menor igual que Maior igual que EXEMPLO if(A == 1) ... If(A != 1) ... If(A<100) ... If(A>-10) ... If(A<=20) ... If(A>=B)...

OPERADORES BOOLEANOS SMBOLO && || ! OPERAO E lgico OU lgico NO lgico EXEMPLO if(true && true) ... if(true || false) ... if (!false) ...

OPERAO COM BITS SMBOLO & | ^ ~ << OPERAO E binrio OU binrio XOR binrio NO binrio Deslocamento para esquerda (Multiplicar por 2) Deslocamento para a direita (Dividir por 2) E binrio igual EXEMPLO B110 & B010 -> B010 B110 | B010 -> B110 B110 ^ B010 -> B100 ~B110 -> B001 B0010 << 2 -> B1000

>>

B0110 >> 1 -> B0011

&=

X = B001; X &= B010; //X == B000 X = B001; X |= B010; //X == B011

|=

OU binrio igual

2.2.4. Estruturas de controle de fluxo (if, else, switch case) Estruturas de controle de fluxo so empregadas quando o programa precisar tomar decises em cima de alguns atributos ou especificaes. Por exemplo, o LED do pino digital 13 s ir ascender se o valor lido pelo pino analgico 0 for maior que 100.

IF (se verdade execute tais instrues) Sintaxe: if (TESTE_LGICO_QUE_DEVE_RETORNAR_VERDADEIRO) { //CDIGO A SER EXECUTADO NESTE CASO } Exemplo prtico: int a = 5; if( a > 5) { digitalWrite(13, HIGH); }

IF...ELSE (se verdade execute tais instrues, seno execute estas outras instrues) Sintaxe: if (TESTE_LGICO_QUE_DEVE_RETORNAR_VERDADEIRO) { //CDIGO A SER EXECUTADO NESTE CASO } else { //CDIGO A SER EXECUTADO NESTE OUTRO CASO }

Vale lembrar que podemos aninhar ifs e elses: Se A ..., seno, se B ...., seno, se C...., seno.... Exemplo Prtico: if( analogRead(0) == 0) { digitalWrite(13, HIGH); } else { if( analogRead(0) <= 100 ) digitalWrite(13, LOW); else digitalWrite(12, HIGH); } SWITCH CASE Serve para criar uma lista de opes. Este comando executa uma das opes existentes (case) dependendo do valor da varivel var. A opo default da lista executada caso o valor de var no se enquadre em nenhuma das outras opes. A palavra reservada break; serve para que a opo default da lista no venha a ser executada caso algum dos cases j tenha sido executado. Sintaxe: switch (var) { case 1: //EXECUTE ESTE CDIGO break; // obrigatrio colocar um break; ao final de cada instncia do case case 2: //EXECUTE ESTE OUTRO CDIGO break; default: /*SE O VALOR DE var NO FOR NENHUM DOS ACIMA EXECUTE AQUI*/ break; } Exemplo Prtico switch (Serial.read() ) { case a: Serial.println(Abobrinha); break; case b: Serial.println(Biscoito); break; default: Serial.println(Nao e abobrinha nem biscoito!); break; }

2.2.5. Laos de repetio (for, while, do...while) Laos de repeties ou loops so utilizados quando h a necessidade de executar uma parte do cdigo vrias vezes. Antes de vermos os tipos de laos existentes na linguagem C precisamos entender duas palavras reservadas importantes quando se trabalha com repeties: break e continue. Quando existe um break; dentro de um lao ele faz com que o programa saia do loop e execute a primeira linha de cdigo aps o loop. Este recurso usado em conjunto com um teste condicional (if) para otimizar o lao. Por exemplo, precisamos percorrer um vetor at encontrar algum valor determinado e para isso utilizamos obviamente um lao. Se encontrarmos o valor que procurvamos antes do final do lao no h motivo para continuar a execut-lo, neste instante podemos utilizar um break; para sair do lao e continuar a execuo do programa. J um continue; dentro de um lao significa que o lao deve voltar ao seu incio (primeira linha de cdigo dentro do lao) e no executar o que houver abaixo do continue. No caso de um lao for ainda h o incremento da varivel de controle e no caso do while e do...while h um novo teste lgico. FOR O lao for o mais simples e mais seguro de se usar, mas por s testar o valor da varivel de controle no suficiente para todas as situaes. Sintaxe: for(cont= valor_inicial; cont < valor_final ; cont++) { //CDIGO } Para cont=valor_incial, enquanto cont for menor que valor_final a cada loop completo a varivel cont ser incrementada de 1 e o cdigo dentro do loop ser executado. O incremente no precisa ser necessariamente 1, cabe ao programador escolher o incremento que melhor resolva o problema. Exemplo Prtico int i=0; //Nossa varivel de controle void main() { for(i=0; i<14; i+=2) { pinMode(i, OUTPUT); } }
Este lao define todos os pinos digitais pares de 0 a 13 como pinos de sada atravs de um loop.

WHILE Em conjunto com o do...while contempla uma estrutura de repetio mais completa que o for j que pode fazer qualquer teste lgico. A ideia chave do while : enquanto o teste lgico for verdadeiro continue executando esta parte do cdigo e a cada iterao um novo teste lgico feito. Sua diferena para o do..while que o do...while executado pelo menos uma vez, j que o teste lgico ocorre no final do lao e no no comeo (como no while). Ao trabalhar com o while o programador deve tomar alguns cuidados especiais para no criar loops infinitos dentro do programa, por exemplo: /*Loop infinito por no incremento da varivel de controle. Como no h o incremento da varivel de controle ela sempre ser menor que 10 e nosso teste lgico sempre retornar verdadeiro.*/ unsigned int i = 0; while( i < 10) { digitalWrite(13, HIGH); delay(100); digitalWrite(13, LOW); } Sintaxe: while(TESTE_LGICO_QUE_DEVE_RETORNAR_VERDADEIRO) { //CDIGO } Exemplo Prtico: pinMode(12, INPUT); Serial.being(9600); while(digitalRead(12) == 0 ) { Serial.println(Botao Apertado); delay(10); }
Este cdigo usa o while para evitar o bouncing de um boto mecnico.

DO...WHILE Sintaxe: do { //Coloque seu cdigo aqui

}while(TESTE_LGICO_QUE_DEVE_RETORNAR_VERDADEIRO);

Nem sempre loops infinitos so ruins em projetos com microcontroladores. Como o microcontrolador vai ficar executando seu cdigo indefinidamente (a no ser claro que se interrompa o fornecimento de energia ou em projetos que demandam alta economia de energia) todo cdigo do programa fica encapsulado em um loop infinito. Exemplo: /*Exemplos de loops infinitos*/ while(1) { //Coloque seu cdigo aqui } for( ; ; ) { //Coloque seu cdigo aqui }

2.2.6. Funes Uma funo um trecho de cdigo especializado em algum propsito. Funes podem ser chamadas no decorrer do cdigo e podem ou no receber e ou retornar valores. A funo sempre deve ser declarada antes de ter sido chamada. A esta declarao prvia damos o nome de prottipo da funo. Sintaxe: tipo_do_retorno nome_da_funcao(tipo argumento1, tipo argumento2, ...) { //CDIGO return algo; }

tipo_de_retorno: o tipo da varivel que ser retornada pela funo. nome_da_funcao: o nome que referenciar a funo quando esta for chamada. tipos argumentos: Variveis que sero passadas para a funo e seus tipos. Exemplo: int soma(int a, int b) { return a+b; }

Exemplo Prtico //funo pisca recebe dois argumentos (pino e tempo) //e retorna um valor int int pisca(int pino, int tempo) { digitalWrite(pino, HIGH); delay(tempo); digitalWrite(pino, LOW); delay(tempo); return 1; } void main() { int piscou = 0; piscou = piscar(13, 200); //chamada da funo if(piscou) printf(O led piscou com sucesso); else printf(O led no piscou); }

2.2.7. Operaes bit a bit 2.2.7.1. Mscara de bits Em aplicaes com microcontroladores muito comum ter que carregar um determinado valor em um bit especfico de um registador (escrever ou apagar um determinado bit) e para tanto fazemos uso das operaes bit a bit. Registradores podem ser entendidos como endereos especiais de memria (variveis especiais) que armazenam informaes inerentes s configuraes do microcontrolador.

Usualmente os microcontroladores possuem registradores de 8 ou 16 bits (1 ou 2 bytes respectivamente) e um ou mais bits desses registradores so responsveis por configurar o funcionamento do microcontrolador. Ns podemos setar, resetar, inverter e ler o valor de um determinado bit do registrador. Para efetuarmos tais procedimentos fazemos uso da lgebra booleana e de um artifcio chamado mscara de bits: 1 = B00000001 (1<<3) = B00001000 -> Operao de rotao para a direita em 3 posies com o nmero 1 A partir de uma mscara de bits gerada a partir do rotacionamento do nmero 1 podemos efetuar operaes binrias oportunas: Operao Setar (escrever alto no bit X) Ressetar (escrever baixo no bit X) Trocar (inverter o bit X) Ler (o valor do bit X) Sintaxe REG |= (1<<X) REG &= ~(1<<X) REG ^= (1<<X) REG &= (1<<X)

Suponha-se, por exemplo, que o registrador PxIN armazena os valores da leitura digital dos 8 pinos de entrada digitais de um microcontrolador, ou seja, cada bit desse registrador representa o valor lgico no pino de entrada correspondente. REGISTRADOR PxIN BIT7 1 BIT6 1 BIT5 0 BIT4 0 BIT3 0 BIT2 1 BIT1 0 BIT0 1

Obviamente que o valor de PxIN B11000101, ou 0xC5 ou 197 em decimal. Aqui fica evidente o porqu da utilizao da base binria para representar os bits de um registrador, uma vez que facilmente se percebe quais pinos esto em alto ou em baixo. Para registradores maiores que 8 bits (16, 32, 64, etc) a notao hexadecimal a mais utilizada, em virtude do tamanho do nmero. Suponhamos agora que queremos ler o valor do pino 5 do nosso microcontrolador, que corresponde ao BIT5 do nosso registrador PxIN. Para tanto, efetuaremos a seguinte operao binria:

valor_pin5 = PxIN & (1<<5) 1) Pegamos o nmero 1 e rotacionamos em 5 posies (mscara): B00100000 2) Efetuamos a operao E (&) dessa mscara com o registrador PxIN: B11000101 & B00100000 -------------B00000000 3) Armazenamos o resultado na varivel (tipo char) valor_pin6: valor_pin6 = B00000000

2.2.7.2. Criao de macros p/ as operaes com mscara A diretiva #define (vista anteriormente) da linguagem C serve para definir constantes e macros. Antes de o compilador gerar o arquivo .hex do programa em C que ser enviado para o microcontrolador ele substitui todos os macros e constantes que foram utilizados ao longo do cdigo e que haviam sido previamente definidos. A necessidade constante da utilizao de operaes bit a bit nos leva a definir logo no comeo do cdigo macros para elas. //Setar BIT do registrador REG #define sbi(REG,BIT) REG |= (1<<BIT) //Limpar o bit (clear) #define cbi(REG,BIT) //Trocar o bit #define tgi(REG,BIT) //Ler o bit (read) #define rbi(REG,BIT)

REG &= ~(1<<BIT)

REG ^= (1<<BIT)

REG & (1<<BIT)

O exemplo anterior ficaria da seguinte maneira: valor_pin6 = rbi(PxIN , 5);

2.2.7.3. Campos de bits Outra forma de manipular bits individualmente atravs de structs, que so tipos de dados definidos pelo programador. Este mtodo muito til quando trabalhamos com registradores j que eles possuem endereos de memria fixos. /* Estrutura de bits */ union P1DIR { unsigned char all; struct{ volatile unsigned volatile unsigned volatile unsigned volatile unsigned volatile unsigned volatile unsigned volatile unsigned volatile unsigned }bits;

char char char char char char char char

BIT0 BIT1 BIT2 BIT3 BIT4 BIT5 BIT6 BIT7

: : : : : : : :

1; 1; 1; 1; 1; 1; 1; 1;

}@0x0244 //End. do registrador MSP430F5521 IAR Workbench //Setando o bit P1DIR.bits.BIT0 = 1; //Setando o registrador todo P1DIR.all = 0xFF;

Вам также может понравиться