QUARTA - 1EM SOCIOLOGIA - Aprender a pesquisar.pptx
055 A 094 Material Auxiliar Para Curso AvançAdo I Msp430
1. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
10. BREVE INTRODUÇÃO A LINGUAGEM C
(http://pt.wikipedia.org/wiki/c_(linguagem_de_programaçao))
C é uma linguagem de programação compilada de propósito geral, estruturada, imperativa,
procedural, de alto nível, e padronizada, criada em 1972, por Dennis Ritchie, no AT&T Bell
Labs, para desenvolver o sistema operacional UNIX (que foi originalmente escrito em
Assembly). A linguagem C é classificada de alto nível pela própria definição desse tipo de
linguagem. A programação em linguagens de alto nível tem como característica não ser
necessário conhecer o processador, ao contrário das linguagens de baixo nível. As
linguagens de baixo nível estão fortemente ligadas ao processador. A linguagem C permite
acesso de baixo nível com a utilização de código Assembly no meio do código fonte. Assim,
o baixo nível é realizado por Assembly e não C. Desde então, espalhou-se por muitos outros
sistemas, e tornou-se uma das linguagens de programação mais usadas, e influenciou
muitas outras linguagens, especialmente C++, que foi originalmente desenvolvida como uma
extensão para C.
10.1. História
Ken Thompson e Dennis Ritchie (da esquerda pra direita), os criadores das linguagens B e
C, respectivamente.
O desenvolvimento inicial de C, ocorreu no AT&T Bell Labs, entre 1969 e 1973. Deu-se o
nome “C” à linguagem, porque muitas de suas características derivaram da linguagem B.
C foi originalmente desenvolvido, para a implementação do sistema UNIX (originalmente
escrito em PDP-7 Assembly, por Dennis Ritchie e Ken Thompson). Em 1973, com a adição
do tipo struct, C tornou-se poderoso o bastante para a maioria das partes do Kernel do
UNIX, serem reescritas em C. Este foi um dos primeiros sistemas que foram implementados
em uma linguagem, que não o Assembly, sendo exemplos anteriores, os sistemas: Multics
(escrito em PL/I) e TRIPOS (escrito em BCPL). Segundo Ritchie, o período mais criativo
ocorreu em 1972.
Página 55
2. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
10.2. K&R C
Em 1978, Brian Kernighan e Dennis Ritchie publicaram a primeira edição do livro The C
Programming Language. Esse livro, conhecido pelos programadores de C, como “K&R”,
serviu durante muitos anos como uma especificação informal da linguagem. A versão da
linguagem C que ele descreve é usualmente referida como “K&R C”. A segunda edição do
livro, cobriu o padrão posterior, o ANSI C. K&R C introduziu as seguintes características na
linguagem:
• Biblioteca padrão de E/S;
• Tipos de dado struct;
• Tipos de dado long int;
• Tipos de dado unsigned int;
• O operador =+ foi alterado para +=, e =- para -= (o analisador léxico do compilador
fazia confusão entre i =+ 10 e i = +10. O mesmo acontecia com =-).
K&R C é freqüentemente considerado a parte mais básica da linguagem, cujo suporte deve
ser assegurado por um compilador C. Durante muitos anos, mesmo após a introdução do
padrão ANSI C, K&R C foi considerado o “menor denominador comum”, em que
programadores de C se apoiavam quando uma portabilidade máxima era desejada, já que
nem todos os compiladores eram atualizados o bastante para suportar o padrão ANSI C.
Nos anos que se seguiram à publicação do K&R C, algumas características “não-oficiais”
foram adicionadas à linguagem, suportadas por compiladores da AT&T e de outros
vendedores. Estas incluíam:
• Funções void e tipos de dados void *;
• Funções que retornam tipos struct ou union;
• Campos de nome struct num espaço de nome separado para cada tipo struct;
• Atribuição a tipos de dados struct;
• Qualificadores const para criar um objecto só de leitura;
• Biblioteca padrão, que incorpora grande parte da funcionalidade implementada por
vários vendedores;
• Enumerações;
• Cálculos de ponto-flutuante em precisão simples (no K&R C, os cálculos
intermediários eram feitos sempre em double, porque era mais eficiente na máquina
onde a primeira implementação do C foi feita).
Página 56
3. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
10.3. ANSI C e ISO C
Durante os finais da década de 1970, a linguagem C começou a substituir a linguagem
BASIC como a linguagem de programação de microcomputadores mais usada. Durante a
década de 1980, foi adaptada para uso no PC IBM, e a sua popularidade começou a
aumentar significativamente. Ao mesmo tempo, Bjarne Stroustrup, juntamente com outros
nos laboratórios Bell, começou a trabalhar num projecto onde se adicionavam construções
de linguagens de programação orientada por objectos à linguagem C. A linguagem que eles
produziram, chamada C++, é nos dias de hoje a linguagem de programação de aplicações
mais comum no sistema operativo Windows da companhia Microsoft; C permanece mais
popular no mundo UNIX.
Em 1983, o instituto norte-americano de padrões (ANSI) formou um comitê, X3J11, para
estabelecer uma especificação do padrão da linguagem C. Após um processo longo e árduo,
o padrão foi completo em 1989 e ratificado como ANSI X3.159-1989 “Programming
Language C”. Esta versão da linguagem é freqüentemente referida como ANSI C. Em 1990,
o padrão ANSI C, após sofrer umas modificações menores, foi adotado pela Organização
Internacional de Padrões (ISO) como ISO/IEC 9899:1990, também conhecido como C89 ou
C90. Um dos objetivos do processo de padronização ANSI C foi o de produzir um
sobreconjunto do K&R C, incorporando muitas das características não-oficiais
subseqüentemente introduzidas. Entretanto, muitos programas tinham sido escritos e que
não compilavam em certas plataformas, ou com um certo compilador, devido ao uso de
bibliotecas de funções não-padrão e ao fato de alguns compiladores não aderirem ao ANSI
C.
10.4. C99
Após o processo da padronização ANSI, as especificações da linguagem C permaneceram
relativamente estáticas por algum tempo, enquanto que a linguagem C++ continuou a
evoluir. (em 1995, a Normative Amendment 1 criou uma versão nova da linguagem C mas
esta versão raramente é tida em conta.) Contudo, o padrão foi submetido a uma revisão nos
finais da década de 1990, levando à publicação da norma ISO 9899:1999 em 1999. Este
padrão é geralmente referido como “C99”. O padrão foi adoptado como um padrão ANSI em
Março de 2000. As novas características do C99 incluem:
• funções em linha
• remoção de restrições sobre a localização da declaração de variáveis (como em C++)
• adição de vários tipos de dados novos, incluindo o long long int (para minimizar
problemas na transição de 32-bits para 64-bits), um tipo de dados boolean explicito
(chamado _Bool) e um tipo complex que representa números complexos
Página 57
4. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
• vetores de dados de comprimento variável (o vetor pode ter um tamanho diferente a
cada execução de uma função, mas não cresce depois de criado)
• suporte oficial para comentários de uma linha iniciados por //, emprestados da
linguagem C++
• várias funções de biblioteca novas, tais como snprintf()
• vários ficheiros-cabeçalho novos, tais como stdint.h
O interesse em suportar as características novas de C99 parece depender muito das
entidades. Apesar do GCC e vários outros compiladores suportarem grande parte das novas
características do C99, os compiladores mantidos pela Microsoft e pela Borland suportam
pouquíssimos recursos do C99, e estas duas companhias não parecem estar muito
interessadas em adicionar tais funcionalidades, ignorando por completo as normas
internacionais. A Microsoft parece preferir dar mais ênfase ao C++.
10.5. Visão Geral
C é uma linguagem imperativa e procedural, para implementação de sistemas. Seus pontos
de design foram para ele ser compilado, fornecendo acesso de baixo nível à memória e
baixos requerimentos do hardware. Também foi desenvolvido para ser uma linguagem de
alto nível, para maior reaproveitamento do código. C foi útil para muitas aplicações que
foram codificadas originalmente em Assembly.
Essa propriedade não foi acidental; a linguagem C foi criada com o objetivo principal em
mente: facilitar a criação de programas extensos com menos erros, recorrendo ao
paradigma da programação algorítmica ou procedimental, mas sobrecarregando menos o
autor do compilador, cujo trabalho complica-se ao ter de realizar as características
complexas da linguagem. Para este fim, a linguagem C possui as seguintes características:
• Uma linguagem nuclear extremamente simples, com funcionalidades não-essenciais,
tais como funções matemáticas ou manuseamento de arquivos, fornecida por um
conjunto de bibliotecas de rotinas padronizada;
• A focalização no paradigma de programação procedimental;
• Um sistema de tipos simples que evita várias operações que não fazem sentido
• Uso de uma linguagem de pré-processamento, o pré-processador de C, para tarefas
tais como a definição de macros e a inclusão de múltiplos ficheiros de código fonte;
• Ponteiros dão maior flexibilidade à linguagem;
• Acesso de baixo-nível, através de inclusões de código Assembly no meio do
programa C;
Página 58
5. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
• Parâmetros que são sempre passados por valor para as funções e nunca por
referência (É possível simular a passagem por referência com o uso de ponteiros);
• Definição do alcance lexical de variáveis;
• Estruturas de variáveis, (structs), que permitem que dados relacionados sejam
combinados e manipulados como um todo.
Algumas características úteis, que faltam em C, podem ser encontradas em outras
linguagens, que incluem:
• Segurança de tipo;
• Coletor de lixo (mais comum em linguagens interpretadas);
• Vetores que crescem automaticamete;
• Classes ou objectos com comportamento (ver orientação a objetos);
• Closures (a closure is a function that is evaluated in an environment containing one or
more bound variables. When called, the function can access these variables);
• Funções aninhadas;
• Programação genérica;
• Sobrecarga de operadores;
• Meta-programação;
• Apoio nativo de multithreading e comunicação por rede.
Apesar da lista de características úteis que C não possui, ser longa, isso não tem sido um
impedimento à sua aceitação, pois isso permite que novos compiladores de C sejam escritos
rapidamente para novas plataformas, e também permite que o programador permaneça
sempre em controle do que o programa está a fazer. Isto é o que por várias vezes permite o
código de C correr de uma forma mais eficiente que muitas outras linguagens. Tipicamente,
só código de assembly “afinado à mão” é que corre mais rapidamente, pois possui um
controle completo da máquina, mas avanços na área de compiladores juntamente com uma
nova complexidade nos processadores modernos permitiram que a diferença tenha sido
rapidamente eliminada. Uma consequência da aceitação geral da linguagem C é que
freqüentemente os compiladores, bibliotecas e até intérpretes de outras linguagens de nível
maior sejam eles próprios implementados em C.
C tem como ponto forte, a sua eficiência, e é a linguagem de programação preferida para o
desenvolvimento de sistemas e softwares de base, apesar de também ser usada para
desenvolver programas de computador. É também muito usada no ensino de ciência da
computação, mesmo não tendo sido projetada para estudantes e apresentando algumas
dificuldades no seu uso. Outra característica importante de C, é sua proximidade do código
de máquina, que permite que um projetista seja capaz de fazer algumas previsões de como
o software irá se comportar, ao ser executado.
Página 59
6. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
C tem como ponto fraco, a falta de proteção que dá ao programador. Praticamente tudo que
se expressa em um programa em C, pode ser executado, como por exemplo, pedir o
vigésimo membro de um vetor com apenas dez membros. Os resultados são muitas vezes
totalmente inesperados, e os erros, difíceis de encontrar.
10.6. Palavras reservadas na Linguagem C
A linguagem C é do tipo “case sensitive”. E além disto, algumas palavras são reservadas,
sendo seu uso limitado apenas as funções ou comandos que elas executam:
O compilador IAR tem também algumas palavras reservadas, o que veremos ao longo deste
treinamento.
11. VARIÁVEIS, TIPOS DE DADOS E OPERADORES EM C
11.1. Tipos de dados
Basicamente apenas 5 tipos de dados que são utilizadas em linguagem C:
• char – caractere – 8 bits, 1 byte;
• int – inteiro – 16 bits, 2 bytes;
• float – ponto flutuante – 32 bits, 4 bytes;
• double – ponto flutuante de precisão dupla – 64 bits, 8 bytes;
• void – sem valor.
Cada uma destes tipos pode ainda ter os seguintes modificadores:
Página 60
7. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
• signed – utilizará o último bit para sinalizar se um dado é positivo ou negativo. Com
isto, o dado sempre estará com um tamanho menor em um bit.
• unsigned – não informa se o dado tem valor positivo ou negativo. Por conseqüência
todos os bits do dado podem ser utilizados como informação;
• short – faz com que o dado passe a ter um tamanho menor do que especificado
em sua definição. Por exemplo: utilizar o shot int pode fazê-lo assumir o valor de
apenas um bit, dependendo do compilador utilizado;
• long – faz com que o dado passe a ter um tamanho maior do que especificado em
sua definição. Por exemplo: utilizar o long int pode fazê-lo assumir o valor de 65536
bits, dependendo do compilador utilizado
11.1.1. Detalhes sobre números em ponto flutuante
A base numérica no padrão IEEE754 é a binária. Neste padrão são adotados dois formatos
para representação de números: precisão simples e precisão dupla. (Na base binária, um
dígito binário é denominado bit e um byte é um conjunto de 8 bits).
Página 61
8. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
Ficou estabelecido que no padrão IEEE754, em precisão simples, um número real seria
representado por 32 bits, (4 bytes), sendo que:
• 1 bit é reservado para o sinal do número (positivo ou negativo);
• 8 bits são reservados para o expoente da base, que é um número inteiro;
• 23 bits são reservados para a mantissa:
Pelo mesmo padrão IEEE754, em precisão dupla, um número real seria representado por 64
bits, (8 bytes), sendo que:
• 1 bit é reservado para o sinal do número (positivo ou negativo);
• 11 bits são reservados para o expoente da base, que é um número inteiro;
• 52 bits são reservados para a mantissa:
Qualquer valor em ponto flutuante é sempre escrito no seguinte formato:
v = S × M × 2E
Onde:
• S = 1 − 2 × sinal
• M = 1 + mantissa × 2-23
• E = expoente − 127
Página 62
9. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
11.2. Declarando variáveis
É necessário, durante o fluxo do programa, declarar as variáveis que serão utilizadas de
acordo com os tipos de dados mostrados anteriormente. Isto pode ser feito das seguintes
maneiras:
TIPO nome_da_variável {,outras_variáveis};
unsigned int tempo;
As variáveis podem ser inicializadas com um determinado valor durante a sua declaração:
unsigned int tempo = 100;
11.2.1. Variáveis locais e globais
Dependendo do local onde é declarada a variável, esta pode assumir uma função global ou
local:
• Variáveis globais são acessíveis de qualquer ponto do programa, por qualquer
função, e devem ser declaradas no corpo principal do programa, fora de qualquer
função, inclusive da main;
• Variáveis locais só podem ser acessadas dentro das funções onde foram criadas. Ao
sair desta função, a linguagem C destrói uma variável local e, portanto ela não será
acessível por outras funções.
O programa a seguir (E-0-1) dá uma demonstração de como as variáveis podem ser
declaradas localmente ou globalmente:
//******************************************************************************
// Exemplo de variáveis globais e locais
// Alessandro Ferreira da Cunha
// Tech Training - Engenharia e Treinamentos
// Dezembro 2008 – Extraído do Livro “PIC – Programação em C”, do Fábio Pereira
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
int somatorio; // VARIÁVEL GLOBAL! SERÁ ACESSADA POR TODAS AS FUNÇÕES
void soma (int valor) //AO ACESSAR ESTA FUNÇÃO, O PARÂMETRO VALOR RECEBE DADOS DE QUEM O CHAMOU
{
int conta; // VARIÁVEL LOCAL! SERÁ ACESSADA APENAS PELA FUNÇÃO SOMA
somatorio = somatorio + valor;
printf("0");
for (conta = 1;(conta<(valor+1));conta++)
{
printf("+%u",conta);
}
printf(" = %urn",somatorio);
}
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int conta; // VARIÁVEL LOCAL! SERÁ ACESSADA APENAS PELA FUNÇÃO MAIN
somatorio = 0; // A VARIÁVEL GLOBAL É INICIALIZADA
for (conta=1;conta<20;conta++)
{
soma(conta); // É CHAMADA A FUNÇÃO SOMA, ONDE É PASSADO O VALOR DE CONTA
}
}
Página 63
10. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
Alguns comentários importantes sobre o programa E-0-1:
• O comando printf chama uma biblioteca que emula o envio de dados pela porta
serial do MSP430. No IAR será possível visualizar estes dados através do Terminal
I/O, acessível em: View Terminal I/O, onde será aberta a janela mostrada abaixo.
Para que ele funcione é necessário incluir a biblioteca padrão stdio.h
O formato do comando printf é:
printf (string, variável);
printf (“O número de tentativas foi %d”, contador);
Onde:
• string: é uma constate de caracteres, sempre declarado entre aspas;
• variável: é a declaração de uma ou mais variáveis que devem ser impressas
juntamente com os caracteres. Para tanto é necessário seguir a formatação %wt,
onde w é o número de caracteres que se deseja imprimir e t é uma das seguintes
opções:
• c = caractere;
• s = string ou caractere;
• u = inteiro sem sinal;
• x = inteiro em formato hexadecimal com letras minúsculas;
• X = inteiro em formato hexadecimal com letras maiúsculas;
• d = inteiro decimal com sinal;
• i = inteiro decimal com sinal;
• o = octal sem sinal;
• e = ponto flutuante em formato exponencial;
• f = ponto flutuante em formado decimal;
• Lx = hexadecimal longo (16 ou 32 bits) com letras minúsculas;
• LX = hexadecimal longo (16 ou 32 bits) com letras maiúsculas;
• Lu = decimal longo (16 ou 32 bits) sem sinal;
• Ld = decimal longo (16 ou 32 bits) com sinal;
• % = símbolo de porcentagem;
Página 64
11. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
Para que todos os caracteres a serem impressos na janela Terminal I/O não fiquem na
mesma linha, são utilizados os caracteres especiais de barra invertida, que são:
• b = retrocesso (backspace);
• f = alimentação de formulário;
• n = nova linha;
• r = retorno do carro;
• t = tabulação horizontal;
• ” = aspas duplas;
• ’ = aspas simples;
• 0 = nulo;
• = barra invertida;
• v = tabulação vertical;
• a = alerta (beep);
• N = constante octal, onde N é o número em octal;
• xN = constante hexadecimal, onde N é o número em hexadecimal;
Agora observe o programa exemplo E-0-2:
//******************************************************************************
// Exemplo de uso da função scanf
//
// Alessandro Ferreira da Cunha
// Tech Training - Engenharia e Treinamentos
// Janeiro 2009
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
char TECLA; // VARIÁVEL LOCAL! SERÁ ACESSADA APENAS PELA FUNÇÃO MAIN
for ( ; ; )
{
printf("DIGITE UMA TECLA... n n ");
scanf("%c",&TECLA);
printf("SUA TECLA É %c!n n",TECLA);
}
}
A novidade aqui é o comando scanf. Enquanto o comando printf, mostrado no exemplo
anterior, emula obenvio de dados pela porta serial do MSP430, o scanf emula o
recebimento destes dados, também pela porta serial.
Isto também será possível visualizar através do Terminal I/O, acessível em: View
Terminal I/O. Assim como no comando anterior, para que ele funcione também é necessário
incluir a biblioteca padrão stdio.h
Página 65
12. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
O formato do comando scanf é:
scanf (string, variável);
scanf (“%d”, contador);
Tendo as mesmas características e controladores vistos no printf.
11.2.2. Modificadores de acesso
Além das declarações como global ou local, as variáveis podem receber dois tipos de
modificadores de acesso, que especificam a forma como o compilador irá acessar o
conteúdo das variáveis:
• const: determina que a variável será tratada como uma constante, não podendo ser
modificada ou alteradas durante a execução do programa. Faz, então, com que a
variável passe a ter um valor fixo, pré-estabelecido durante a declaração da variável.
• volatile: utilizado para indicar ao compilador que a variável por ele indicada pode ter
seu conteúdo alterado a qualquer momento.
volatile unsigned int tempo = 100;
11.2.3. Modificadores de armazenamento
Indicam como o compilador irá tratar o armazenamento das variáveis. São quatro tipos:
• auto: serve para declarar que uma variável é local. Porém, todas as variáveis
declaradas internamente já são locais. Com isto, este modificador de armazenamento
quase nunca é utilizado.
• extern: utilizado para fazer referência a outras variáveis globais que foram declaradas
em outros módulos do programa. Isto é muito útil quando se tem programas extensos
onde módulos cuidam de funcionamentos específicos e precisam passar parâmetros
para outras partes do programa.
• static: indica que a variável ocupará uma posição permanente de memória. Isto
também ocorre quando uma variável é declarada de modo global. Mas numa
declaração de static, a variável é reconhecida apenas localmente, dentro da função
em que foi criada. Se o modificador de armazenamento static for aplicado a uma
variável que já é global, isto fará com que ela seja reconhecida apenas pelo programa
em que está inserida. Caso haja interação deste programa com outros externos, esta
variável não estará acessível.
• register: faz com que o compilador tente gravar esta variável diretamente em um dos
registradores que tem acesso direto a CPU do microcontrolador, ao invés de
armazená-la em uma posição de memória RAM. Com isto, ganha-se em velocidade
de processamento.
static volatile unsigned int tempo = 100;
Página 66
13. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
11.3. Operadores
11.3.1. Operador atribuição
É utilizado para atribuir um determinado valor a uma variável. Seu símbolo é o “ = ” e alguns
exemplos de atribuição são mostrados a seguir:
unsigned int x, y;
x = 10;
y = x;
A atribuição é sempre avaliada da direita para a esquerda. Isto significa que ao final deste
programa o valor da variável y será igual a 10.
11.3.2. Operadores aritméticos
Indica ao compilador que ele deve fazer determinada operação aritmética entre duas
variáveis. São os seguintes:
Um exemplo de utilização pode ser visto no trecho de programa abaixo:
unsigned int x, y, z, w;
x = 10;
y = x ++;
z = y --;
w= x + y;
11.3.3. Operadores relacionais
São utilizados em testes condicionais para determinar a relação existente entre os dados:
Página 67
14. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
11.3.4. Operadores lógicos
São utilizados para fazer conjunções, disjunções ou negações entre elementos durante um
teste condicional.
11.3.5. Operadores lógicos bit a bit
11.3.6. Operadores de memória, ou de ponteiro
Os ponteiros serão tratados em detalhes no estudo dos dados avançados. É possível dizer
que este é um dos pilares fundamentais da linguagem C e portanto gastaremos algumas
horas do nosso treinamento para explicá-los em detalhes. Por hora, vamos apenas conhecer
quais são os símbolos utilizados como operadores de memória, ou de ponteiros, e suas
funcionalidades. As aplicações serão desenvolvidas mais a frente. São dois os símbolos:
• & endereço do operando. É um operador unário utilizado para retornar o
endereço de memória do seu operando. Isto significa que se escrevermos:
endereço_a = &a;
teremos que a variável “endereço_a” conterá o endereço em que está armazenada a
variável a.
• * conteúdo do endereço apontado pelo operando. Este é um operador
unário utilizado para retornar o conteúdo da posição de memória
endereçada pelo operando que segue. Isto significa que se escrevermos:
a = *endereço_a;
teremos que o valor armazenado no local apontado pela variável “endereço_a” seja
atribuído à variável a.
Página 68
15. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
11.3.7. Outros operadores
Outros operadores, que não se encaixam em nenhum dos tipos citados anteriormente, mas
que podem ser utilizados em linguagem C são:
• ? (ponto de interrogação) Operador ternário condicional: pode fazer
um teste condicional, substituindo o comando IF. Sua forma geral é:
variável = expressão1 ? expressão2 : expressão3;
Ele funciona da seguinte maneira: avalie a expressão1. Se ela for verdadeira, atribua
a variável o valor da expressão2. Caso a expressão1 seja falsa, então a variável
recebe o valor da expressão3.
• , (vírgula) Separador de expressões: é utilizado para enfileirar duas ou
mais expressões. Sua forma geral é:
variável = (expressão1 , expressão2 , expressão3);
Uma aplicação, como a seguir, resulta em y = 5.
y = ( x = 0 , x + 5 );
• . (ponto) Separador de estruturas: é utilizado em estruturas de dados
como separador dos elementos e será estudado quando abordarmos os
tipos de dados avançados.
• -> (seta) Ponteiro de elementos de estruturas: é utilizado em
estruturas de dados como ponteiro dos elementos e será estudado quando
abordarmos os tipos de dados avançados.
• (tipo) Operador modelagem de dado: é possível forçar que uma
expressão seja de determinado tipo utilizando um cast cujo formato geral é:
(tipo) expressão;
Onde tipo é qualquer um dos tipos de dados permitidos pela linguagem C e
expressão é a que se quer que resulte no tipo especificado. Por exemplo: para
realizar um cálculo e obrigar que o resultado seja apresentado em ponto flutuante,
pode-se utilizar o seguinte cast:
unsigned int x, y;
x = 10;
y = (float) x / 2;
Página 69
16. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
• sizeof Retorna o tamanho de uma variável: para ter um melhor
controle da quantidade de memória utilizada, pode-se aplicar o operador
sizeof a qualquer variável. Isto fará retornar qual o tamanho que esta
variável ocupa em bytes.
12. EXERCÍCIO 1: Operadores, tipos e variáveis
12.1. Calculadora básica (E-1-1)
Escreva um programa em que o usuário entre com dois números e seja realizada uma
operação matemática básica (multiplicação), mostrando o resultado na tela. Este programa
deve rodar dentro de um loop infinito no formato for ( ; ; );.
O programa deve conter uma mensagem no Terminal I/O solicitando que o usuário digite o
primeiro número. Depois uma mensagem solicita a digitação de um segundo número.
Finalmente, o resultado da multiplicação é mostrado em uma nova linha do Terminal I/O.
12.2. Conversor de moeda do dia (E-1-2)
Escreva um programa em que o usuário entre com a cotação do dólar do dia, digite qual é a
quantidade de dólares que quer converter e seja apresentado na tela do Terminal I/O
apresente o valor convertido em reais.
12.3. Calcular a idade de um usuário – I (E-1-3)
Escreva um programa em que o usuário entre com a data de nascimento no formato na
seguinte seqüência:
• DIA (DD);
• MÊS (MM);
• ANO (AAAA).
Na seqüência, o usuário deve digitar a data de hoje, entrando com os valores de dia, mês e
ano no mesmo formato.
O programa deve, então, calcular a idade do usuário, informando a idade em ANOS, cujo
valor deve ser um inteiro.
12.4. Calcular a idade de um usuário – II (E-1-4)
Modifique o programa anterior de modo que seja mostrado na tela também o valor da idade
em DIAS e MESES.
Página 70
17. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
13. Declarações de controle e repetição
As declarações de controle e repetição são algumas das estruturas mais importantes da
linguagem C. Elas é que garantem um fluxo de programa capaz de tomar decisões e desviar
o programa de acordo com determinadas regras. Veremos neste treinamento estas
estruturas, definidas pelo padrão ANSI C e como utilizá-las.
• Seleção (condicional): if e switch;
• Iteração (laço): while, for e do-while;
• Desvio (salto): break, continue, goto e return;
• Rótulo: case, default e label;
13.1. Verdadeiro ou Falso em linguagem C
Diversos destes comandos de controle e repetição acontecem apenas após um teste
condicional, onde é verificado o status de VERDADEIRO ou FALSO de uma variável. É
necessário entender como o C observa esta condição para compreender perfeitamente
como as decisões são tomadas:
• VERDADEIRO: é considerada uma condição verdadeira para uma variável quando
esta tem qualquer valor diferente de zero, inclusive valores negativos.
• FALSO: é considerada uma condição falsa para uma variável quando esta tem valor
igual a zero.
13.2. If
if (condição) comandoA; {else comandoB}
if (condição)
{
comandoA;
comandoB;
comandoC;
}
else
{
comandoD;
comandoE;
comandoF
}
Página 71
18. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
Veja um exemplo de utilização da função if rodando o programa exemplo E-0-3:
//******************************************************************************
// Exemplo de uso da função if
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
for ( ; ; ) // cria um loop infinito
{
int numero; // número mágico
int palpite; // chute do usuário
numero = rand(); // gera um número aleatório
printf("ADIVINHE QUAL É O NÚMERO... n n ");
scanf("%d",&palpite);
if (palpite == numero) printf ("****CERTO!!!****nn");
else printf ("### ERRADO ###nn");
}
}
Note que para conseguir gerar um número randômico, foi necessário incluir mais uma
biblioteca de funções, a stdlib.h.
13.2.1. If – Else – If comandos aninhados
if (condição1) comandoA;
else if (condição2) comandoB;
else if (condição3) comandoC;
//******************************************************************************
// Exemplo de uso da função if aninhada
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int numero; // número mágico
int palpite; // chute do usuário
numero = rand(); // gera um número aleatório
for ( ; ; ) // cria um loop infinito
{
printf("ADIVINHE QUAL É O NÚMERO... n n ");
scanf("%d",&palpite);
if (palpite == numero) printf ("****CERTO!!!****nn");
else
{
printf ("### ERRADO ###nn");
if (palpite < numero) printf (" --- valor alto --- nn");
else printf (" +++ valor baixo +++ nn");
}
}
}
Página 72
19. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
13.2.2. Uma alternativa: o comando ?
variável = expressão1 ? expressão2 : expressão3;
Ele funciona da seguinte maneira: avalie a expressão1. Se ela for verdadeira, atribua a
variável o valor da expressão2. Caso a expressão1 seja falsa, então a variável recebe o
valor da expressão3.
13.3. Switch
O comando switch difere do comando if porque somente pode testar igualdades. O
comando if pode avaliar uma expressão lógica ou relacional.
switch (variável)
{
case constante1:
comandoA;
comandoB;
....
break;
case constante2:
comandoC;
comandoD;
....
break;
....
default:
comandoE;
comandoF;
....
}
Veja no exemplo E-0-5 como utilizar o comando switch case:
Página 73
20. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
//******************************************************************************
// Exemplo de uso da função switch case
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int digitado; // digitado
for ( ; ; ) // cria um loop infinito
{
printf("DIGITE UM NÚMERO ENTRE 0 E 5: n n ");
scanf("%d",&digitado);
switch (digitado)
{
case 0:
printf("O NÚMERO DIGITADO FOI %d ! n n ",digitado);
break;
case 1:
printf("O NÚMERO DIGITADO FOI %d ! n n ",digitado;
break;
case 2:
printf("O NÚMERO DIGITADO FOI %d ! n n ",digitado;
break;
case 3:
printf("O NÚMERO DIGITADO FOI %d ! n n ",digitado;
break;
case 4:
printf("O NÚMERO DIGITADO FOI %d ! n n ",digitado;
break;
case 5:
printf("O NÚMERO DIGITADO FOI %d ! n n ",digitado;
break;
default:
printf("O NÚMERO DIGITADO NÃO ESTÁ ENTRE 0 E 5! n n ");
}
}
}
13.4. Laço for (para)
for (inicialização ; condição ; incremento) comando;
for (inicialização ; condição ; incremento)
{
comandoA;
comandoB;
....
}
Veja no exemplo E-0-6 como utilizar o laço for:
//******************************************************************************
// Exemplo de uso da laço for
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int conta;
for (conta = 0 ; conta <= 10 ; conta++) printf("%urn",conta);
}
Página 74
21. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
13.4.1. Laço infinito
for ( ; ; );
13.4.2. Cláusula break no comando for
Como sair de um laço infinito? Execute o programa E-0-7 e verifique seu efeito em um laço
infinito:
//******************************************************************************
// Exemplo de uso do comando BREAK em um laço for
//
// Alessandro Ferreira da Cunha
// Tech Training - Engenharia e Treinamentos
// Janeiro 2009
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
char caractere;
for ( ; ; )
{
printf ("digite algo n");
scanf("%c",&caractere); //pega um caractere
if (caractere == 'A') break; //sai do laço
}
printf ("você digitou um A");
}
13.4.3. Cláusula continue no comando for
Qual o efeito de trocar uma cláusula break por uma cláusula continue? Execute o programa
E-0-8 e verifique seu efeito:
//******************************************************************************
// Exemplo de uso da cláusula CONTINUE em um laço for
//
// Alessandro Ferreira da Cunha
// Tech Training - Engenharia e Treinamentos
// Janeiro 2009
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int inicio, fim, x;
printf ("digite o início n");
scanf("%d",&inicio);
printf ("digite o fim n");
scanf("%d",&fim);
for ( x = inicio ; x <= fim ; x++ )
{
if ( x == fim) continue;
printf("%urn",x);
}
printf (" --- ACABOU --- ");
}
Página 75
22. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
13.5. Laço while (enquanto)
while (condição) comando;
while (condição)
{
comandoA;
comandoB;
....
}
Veja no exemplo E-0-9 como utilizar o laço while:
//******************************************************************************
// Exemplo de uso laço while
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int i;
i = 1;
while(i < 6)
{
printf ("ainda está em %d n",i);
i++;
}
printf ("acabou");
}
13.5.1. Cláusulas break e continue no laço while
As cláusulas break e continue podem ser utilizadas também no comando while, tendo o
mesmo efeito que se obteve de seu uso no laço for. Veja o exemplo E-0-10.
//******************************************************************************
// Exemplo de uso das cláusulas break e continue no laço while
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int x, y, w, z;
w = 0 ;
printf("ENTRE COM UM NÚMERO n");
scanf("%d",&x);
printf("ENTRE COM OUTRO NÚMERO n");
scanf("%d",&y);
printf("ENTRE COM A QUANT. DE IMPRESSÕES n");
scanf("%d",&z);
while (w < z)
{
if (x == 0 || y == 0) break;
w++;
x = x * y;
printf("A MULTIPLICAÇÃO É %d n",x);
if (x < 1000) continue;
printf(" ACABOU ");
}
}
Página 76
23. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
13.5.2. Laço infinito
while (1)
{
......
}
13.6. Laço do-while (faça-enquanto)
do comando while (condição);
do
{
comandoA;
comandoB;
....
} while (condição);
Veja no exemplo E-0-11 como utilizar o laço do-while:
//******************************************************************************
// Exemplo de uso laço do-while
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
/* PROGRAMA PARA LANÇAMENTO DE FOGUETES DA NASA. */
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
int start;
printf("ENTRE COM O TEMPO PARA LANÇAMENTO n");
scanf("%d",&start);
/* O LAÇO DE CONTAGEM REGRESSIVA */
do
{
printf("FALTAM %d SEGUNDOS n",start);
start--;
}
while(start>0);
printf("Zero!n FOGO!!n");
}
13.7. Usar um laço while (enquanto) ou um laço for (para)?
Os dois laços, while e for, tem várias similaridades. Na grande maioria das situações o
mesmo problema poderá ser resolvido tanto com um tipo de laço quanto com o outro. Para
uma melhor compreensão do que estamos dizendo, vamos fazer uma equivalência entre os
parâmetros que são ajustados para fazer rodar um laço for e os mesmos parâmetros para
fazer exatamente o mesmo efeito, mas com um laço while.
Página 77
24. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
for ( A ; B ; C) printf (“%dt”,i);
A;
while (B)
{
printf (“%dt”,i);
C;
}
A escolha por um ou outro modelo dependerá apenas do estilo do programador. A forma for
é mais compacta. Já a forma while permite uma visualização mais fácil de todas as partes
envolvidas. Enfim: ambos geram os mesmos efeitos na linguagem C pura e podem ser
considerados iguais pelo programador.
Já a sua aplicação em microcontroladores deve ser analisada com cuidado.
Dependendo do compilador e da forma como o laço é gerado, pode ser obtido programas
em assembly maiores ou menores para executar a mesma tarefa. A velocidade com que o
programa executa o laço também é influenciada pelo estilo de conversão que o compilador
fará para cada um deles.
Um excelente exercício é modificar as opções de otimização do IAR (por velocidade ou por
tamanho de código) e compilar programas com resultados de saída iguais mas que façam
uso de laços diferentes, observando o comportamento do código assembly gerado pelo
compilador.
Página 78
25. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
13.8. Tudo junto?
Veja no exemplo E-0-12 todos os conceitos deste capítulo reunidos em um único programa:
//******************************************************************************
// Exemplo COM TUDO JUNTO
//
// Alessandro Ferreira da Cunha
// Tech Training - Engenharia e Treinamentos
// Janeiro 2009
// Built with IAR Embedded Workbench Version: 4.11.2.9
//******************************************************************************
#include <msp430xG46x.h>
#include <stdio.h>
/* Controle de venda no lobby de um cinema */
void main()
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
char c;
int done;
float total = 0;
printf("Por favor, escolha suas opções:n");
printf("1 -> Refrigerante.n");
printf("2 -> Balas.n");
printf("3 -> Cachorro Quente.n");
printf("4 -> Pipocas.n");
printf("= -> Fechar o pedido.n");
printf("Suas escolhas são:n");
done = 0;
while(!done)
{
scanf("%c",&c);
switch(c)
{
case '1':
printf("RefrigerantetR$8.00n");
total+=8;
break;
case '2':
printf("Balastt$R5.50n");
total+=5.5;
break;
case '3':
printf("Cachorro QuentettR$10.00n");
total+=10;
break;
case '4':
printf("Pipocastt$7.50n");
total+=7.5;
break;
case '=':
printf("= Total R$%.2fn",total);
printf("Por favor passe o cartão.n");
done=1;
break;
default:
printf("Seleção inadequada.n");
} /* end switch */
} /* end while */
}/* end main */
13.9. Comando GOTO (vá para)
goto label;
Página 79
26. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
14. EXERCÍCIO 2: Declarações de controle e repetição
14.1. Configuração básica dos I/Os
As seguintes configurações devem ser observadas para fazer os exercícios propostos:
REGISTRADOR DE ENTRADA (Input Register PxIN)
Cada bit colocado em um pino do microcontrolador tem seu valor refletido neste registrador.
Isto ocorre quando a porta está configurada para entrada, sendo válida as seguintes
informações:
Bit = 0: A entrada está em nível lógico baixo (0 V).
Bit = 1: A entrada está em nível lógico alto (+Vcc).
REGISTRADOR DE SAÍDA (Output Registers PxOUT)
Cada bit escrito neste registrador refletirá em um valor de tensão no pino de saída. Isto
ocorre quando a porta está configurada para saída, sendo válida as seguintes informações:.
Bit = 0: A saída será levada a nível lógico baixo (0 V).
Bit = 1: A saída será levada a nível lógico alto (+Vcc).
REGISTRADOR DE DIREÇÃO (Direction Registers PxDIR)
Este registrador indicará se um pino de I/O será utilizado como entrada ou saída, de acordo
com a seguinte configuração:
Bit = 0: A porta será configurada como entrada.
Bit = 1: A porta será configurada como saída.
REGISTRADORES DE PULL UP / PULL DOWN (Pullup/Pulldown Resistor Enable
Registers PxREN (MSP430x47x only))
Apenas nos dispositivos das famílias MSP430x47x todas as portas tem resistores
programáveis de pull-up/down, cuja habilitação ou não é feita do seguinte modo:
Bit = 0: Os resistores estarão desabilitados.
Bit = 1: Os resistores estarão habilitados.
REGISTRADORES DE SELEÇÃO DE FUNÇÃO (Function Select Registers PxSEL)
Como os pinos de um microcontrolador pode ter múltiplas funções, hora funcionando como
terminal de I/O, hora como interface de algum periférico, é necessário ajustar qual função
será realizada a cada momento. Isto é feito de acordo com os seguintes ajustes:
Bit = 0: O terminal funcionará como um I/O.
Bit = 1: O terminal funcionará como um periférico.
Nota: as interrupções por P1 e P2 são desabilitadas quando PxSEL = 1
Página 80
27. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
Identifique no diagrama elétrico da Experimenter Board, mostrado no item 9, as seguintes
conexões, envolvendo pinos do MSP430FG4618 e hardwares externos:
a) Botão S1 pino P1.0; d) LED2 pino P2.2;
b) Botão S2 pino P1.1; e) LED4 pino P5.1.
c) LED1 pino P2.1;
Com estas informações escrevam programas em linguagem C de modo que aconteçam as
operações solicitadas nos itens a seguir.
14.2. 1 botão e 1 Led (E-2-1)
Ao pressionar o botão S1 deve acender o LED1. Se o botão não estiver pressionado, o
LED1 deve se manter apagado.
14.3. 2 botões e 2 Leds (E-2-2)
Ao pressionar o botão S1 deve apagar o LED1. Se o botão S1 não estiver pressionado, o
LED1 deve se manter aceso. Ao mesmo tempo se o botão S2 for pressionado, o LED2
deve se apagar. Se o botão S2 não estiver pressionado, o LED2 deve se manter aceso.
14.4. 1 botão, 1 Led e temporização simples (E-2-3)
Ao pressionar o botão S2 deve acender o LED1, que deve permanecer aceso por alguns
milissegundos (tempo suficiente para perceber a retenção da informação). Se o botão não
estiver pressionado, o LED1 deve se manter apagado.
14.5. 2 botões, 2 Leds e temporização simples (E-2-4)
Ao pressionar o botão S2 deve apagar o LED1, o que deve acontecer por alguns
milissegundos (tempo suficiente para perceber a retenção da informação). Se o botão não
estiver pressionado, o LED1 deve se manter aceso. Ao mesmo tempo, se o botão S1
estiver pressionado o LED2 deve ficar apagado, o que também deve acontecer por alguns
milissegundos (tempo suficiente para perceber a retenção da informação). Se o botão não
estiver pressionado, o LED2 deve se manter aceso
Página 81
28. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
15. Diretivas e funções do Compilador IAR
Além de todos os comandos, controles e funções da linguagem C, tem-se ainda uma série
de diretivas que são intrínsecas ao Compilador IAR. Para estudá-las, o melhor caminho são
os arquivos de HELP que acompanham o compilador, além dos arquivos USER GUIDE, em
formato .pdf, que podem ser acessados diretamente através do menu Help do compilador.
Dentre estes arquivos destacamos alguns que farão parte do CD que compõe o material
didático deste treinamento.
Apesar da grande quantidade de informação que estes arquivos fornecem, é interessante tê-
los sempre a mão, como uma fonte de consulta, toda vez que se está desenvolvendo um
novo programa.
Dentre as diversas diretivas e funções do compilador IAR, vamos listar dois tipos, que serão
utilizados ao longo do treinamento: as PRAGMAS e as FUNÇÕES INTRINSECAS. As
demais funções deverão ser consultadas pelos estudantes diretamente nos arquivos.
15.1. Pragmas
Pragmas são um modo de passar informações especiais para o compilador e para adicionar
extensões específicas de vendedor à biblioteca do microcontrolador, garantindo assim sua
portabilidade entre diversos chips.
As diretivas #pragma são definidas pelo ISO/ANSI C e fazem, entre outras coisas, o
controle do comportamento do compilador. Por exemplo, ela pode determinar que
quantidade de memória é alocada para cada variável ou função, permitir o uso de palavras
chaves, fornecer mensagens de alerta, etc.
A lista a seguir mostra todas as diretivas #pragma que estão disponíveis no IAR, para a
família MSP430.
É necessário o uso do pré processador #pragma para que estas diretivas sejam entendidas
pelo compilador e passem a ser tratadas como tal.
Página 82
29. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
Pragma directive Description
basic_template_matching Makes a template function fully memory-attribute aware
bis_nmi_ie1 Generates a BIS instruction just before the RETI instruction
bitfields Controls the order of bitfield members
constseg Places constant variables in a named segment
data_alignment Gives a variable a higher (more strict) alignment
dataseg Places variables in a named segment
diag_default Changes the severity level of diagnostic messages
diag_error Changes the severity level of diagnostic messages
diag_remark Changes the severity level of diagnostic messages
diag_suppress Suppresses diagnostic messages
diag_warning Changes the severity level of diagnostic messages
include_alias Specifies an alias for an include file
inline Inlines a function
language Controls the IAR Systems language extensions
location Specifies the absolute address of a variable, or places groups of
functions or variables in named segments
message Prints a message
no_epilogue Performs a local return sequence
object_attribute Changes the definition of a variable or a function
optimize Specifies the type and level of an optimization
pack Specifies the alignment of structures and union members
required Ensures that a symbol that is needed by another symbol is
included in the linked output
rtmodel Adds a runtime model attribute to the module
segment Declares a segment name to be used by intrinsic functions
type_attribute Changes the declaration and definitions of a variable or function
vector Specifies the vector of an interrupt or trap function
Página 83
30. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
15.2. Funções intrínsecas
São um conjunto de funções predefinidas que estão disponíveis no compilador IAR. Elas
permitem um acesso direto ao processamento de baixo nível e podem ser extremamente
úteis em, por exemplo, rotinas que envolvam tempo crítico de execução.
Para serem reconhecidas, é necessário acrescentar o arquivo intrinsics.h, através de um
comando include. Note que o nome destas funções sempre iniciam-se com um duplo
undeline.
Intrinsic function Description
__bcd_add_type Performs a binary coded decimal operation
__bic_SR_register Clears bits in the SR register
__bic_SR_register_on_exit Clears bits in the SR register when an interrupt or monitor
function returns
__bis_SR_register Sets bits in the SR register
__bis_SR_register_on_exit Sets bits in the SR register when an interrupt or monitor
function returns
__data16_read_addr Reads data to a 20-bit SFR register
__data16_write_addr Writes data to a 20-bit SFR register
__data20_read_type Reads data which has a 20-bit address
__data20_write_type Writes data which has a 20-bit address
__delay_cycles Provides cycle accurate code size minimized delay
functionality
__disable_interrupt Disables interrupts
__enable_interrupt Enables interrupts
__even_in_range Makes switch statements rely on the specified value being
even and within the specified range
__get_interrupt_state Returns the interrupt state
__get_R4_register Returns the value of the R4 register
__get_R5_register Returns the value of the R5 register
__get_SP_register Returns the value of the stack pointer
__get_SR_register Returns the value of the SR register
Página 84
31. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
__get_SR_register_on_exit Returns the value that the processor status register will
have when the current interrupt or monitor function returns
__low_power_mode_n Enters a MSP430 low power mode
__low_power_mode_off_on_exit Turns off low power mode when a monitor or interrupt
function returns
__no_operation Inserts a NOP instruction
__op_code Inserts a constant into the instruction stream
__set_interrupt_state Restores the interrupt state
__set_R4_register Writes a specific value to the R4 register
__set_R5_register Writes a specific value to the R5 register
__set_SP_register Writes a specific value to the SP register
__swap_bytes Executes the SWPB instruction
16. ECONOMIZANDO ENERGIA PARA PISCAR O LED
Ao resolver os exercícios propostos anteriormente não fizemos uso da principal
característica do MSP430, que é o baixo consumo de energia. Execute o programa
exemplo E-0-13 em seu kit. Veja o seu funcionamento.
//******************************************************************************
// MSP430xG46x Demo - Software Port Interrupt on P1.4 from LPM4
//
// Description: A hi/low transition on P1.4 will trigger P1_ISR which,
// toggles P5.1. Normal mode is LPM4 ~ 0.1uA. LPM4 current can be measured
// with the LED removed, all unused P1.x/P2.x configured as output or inputs
// pulled high or low, and ensure the P2.0 interrupt input does not float.
// ACLK = 32.768kHz, MCLK = SMCLK = default DCO
//
// K. Quiring/ M. Mitchell
// Texas Instruments Inc.
// October 2006
// Built with IAR Embedded Workbench Version: 3.41A
//******************************************************************************
#include <msp430xG46x.h>
void main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop WDT
P5DIR |= 0x002; // P5.1 output
P1IE |= 0x010; // P1.4 Interrupt enabled
P1IES |= 0x010; // P1.4 hi/low edge
P1IFG &= ~0x010; // P1.4 IFG Cleared
_BIS_SR(LPM4_bits + GIE); // LPM4, enable interrupts
}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port1_ISR (void)
{
P5OUT ^= 0x02; // P5.1 = toggle
P1IFG &= ~0x010; // P1.4 IFG Cleared
}
Página 85
32. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
17. Interrupções
As interrupções no MSP430 são fixas e definidas pelo arranjo modular mostrado na figura
abaixo.
Quanto mais próximo for um módulo da CPU/NMIRS, maior a sua prioridade em interromper
o sistema. Esta prioridade define quem será tratado primeiramente caso ocorram duas
interrupções simultaneamente.
Para o MSP430 são considerados três tipos de interrupção:
• Reset do sistema;
• NMI: interrupções não mascaráveis;
• Interrupções mascaráveis.
E funcionam de acordo com a lógica mostrada na figura a seguir.
17.1. Reset do sistema
O circuito de reset do sistema é mostrado na figura a seguir. Ele fornece como saída duas
fontes de reset: o power-on reset (POR) e o power-up clear (PUC). Diferentes fontes de
eventos e sinais podem disparar o circuito de reset do sistema.
Página 86
33. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
O POR é um reset do dispositivo. Um POR só pode ser gerado caso ocorra um destes três
eventos:
• O dispositivo é alimentado (Powering up);
• Um nível baixo (0 V) é inserido no terminal RST/NMI, quando este pino está
configurado para o modo de reset;
• Um baixo nível de tensão é detectado pelo módulo SVS, quando PORON = 1.
Um PUC sempre é gerado quando um POR é gerado, porém um POR não é gerado quando
acontece um PUC. Um PUC pode ser disparado pelos seguintes eventos:
• Um sinal POR;
• Expirou o tempo estipulado pelo Watchdog timer quando estava em modo watchdog;
• Houve uma violação de segurança do Watchdog timer;
• Houve uma violaçào de segurança no acesso a memória Flash.
O Brownout Reset (BOR) é um hardware capaz de detectar se existem variações na
tensão de alimentação do dispositivo, resetando-o a fim de evitar problemas de
funcionamento.
Página 87
34. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
17.2. NMI – Interrupções não mascaráveis
Estas três interrupções não podem ser desabilitadas pelo bit de controle geral de
interrupções (GIE). Elas têm bits específicos para isto (ACCVIE, NMIIE, OFIE). Quando uma
destas interrupções é aceita, todas as demais tem o seu bit de habilitação resetado.
O programa dará um salto em sua execução para o endereço armazenado no vetor de
interrupção não mascarável (0FFFCh). Será necessário que o software do usuário set
novamente os bits destas interrupções para que elas possam ocorrer novamente.
As interrupções não mascaráveis são:
• Um borda de descida/subida no pino RST/NMI pin, quando este é configurado para o
modo NMI;
• Ocorre um falha no oscilador;
• Ocorre uma violação de acesso a memória flash.
17.3. Interrupções mascaráveis
As interrupções mascaráveis são geradas por todos os periféricos que possuem capacidade
de interrupção, incluindo o watchdog timer. Cada fonte de interrupção mascarável tem um bit
que habilita ou desabilita seu funcionamento, sendo que existe ainda um bit de controle
geral, chamado de GIE (General Interrupt Enable), presente no status register (SR).
17.4. O processamento de uma interrupção
Quando uma interrupção é solicitada por um periférico, é necessário que os bits de
habilitação individual e geral (GIE) estejam setados. Isto fará com que o programa sofra um
desvio para uma rotina de interrupção.
Página 88
35. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
17.4.1. Entrada em uma interrupção
A latência para o tratamento de um interrupção dura 6 ciclos de máquina, começando pela
aceitação de uma interrupção e terminando com a execução da primeira instrução contida
na rotina de atendimento de interrupção. A execução lógica é descrita a seguir:
1) Qualquer instrução que esteja sendo executada é finalizada;
2) O valor do PC, que aponta para a próxima instrução que deveria ser executada, é
salvo na pilha (pushed onto the stack);
3) O valor do SR é salvo na pilha (pushed onto the stack);
4) A interrupção que tiver a maior prioridade é selecionada, caso multiplas
interrupções ocorram simultaneamente;
5) Uma requisição de interrupção reseta o flag de interrupção. As demais
interrupções permanecem com seus flags setados;
6) O registrador SR tem todos os seus bits zerados, com excessão do SCG0, que
não é alterado. Isto retira o microcontrolador de qualquer LPM em que ele se
encontra. Como o GIE também é zerado, as próximas interrupções ficam
desabilitadas.
7) O conteúdo do vetor de interrupção correspondente a quem fez a solicitação é
carregado no PC, que passará a executar o programa a partir do que houver escrito
ali.
17.4.2. Saída de uma interrupção
Toda interrupção é terminada quando uma instrução RETI (return from an interrupt service
routine) é encontrada. Este retorno gasta 5 ciclos de máquina para executar as seguintes
ações:
1) O registrador SR é restaurado da pilha (pops from the stack) com todos os valores
ajustados previamente (GIE, CPUOFF, etc.);
2) O valor do PC é restaurado da pilha (pops from the stack) e inicia a execução no
ponto exato em que parou ao ser interrompido.
Página 89
36. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
O aninhamento de interrupções é habilitado quando, durante o tratamento de uma
interrupção, o usuário seta o bit GIE. Neste caso, havendo uma nova interrupção os
procedimentos mostrados ocorrerão novamente, seguindo a ordem de prioridades de
atendimento de interrupções.
17.5. Os vetores de interrupção
Os vetores de interrupção tem um endereçamento fixo e conhecido em todos os dispositivos
das famílias MSP430, indo de 0FFFFh até 0FFC0h. Nestes dados, que tem 16 bits, são
salvos os endereços onde estarão os programas que farão o atendimento as rotinas de
interrupção. Dependendo do número de periféricos, os dispositivos MSP430 podem ter mais
ou menos vetores de interrupção, por isto é sempre necessária uma consulta ao datasheet
de cada dispositivo.
Página 90
37. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
17.5.1. Vetores de interrupção na família 2 (MSP430F2013)
NOTES:
1. Um reset é gerado toda vez que a CPU tenta carregar um endereço no PC que esteja for
a do range de memória disponível no dispositivo.
2. Fonte de múltiplos flags.
3. A flag de interrupção é alocada no módulo.
4. Não mascarável: o bit de interrupção individual pode ser desabilitado por um evento de
interrupção, mas geralmente isto não é possível.
5. Os endereços de vetores de interrupção entre 0FFDEh e 0FFC0h não são utilizados neste
dispositivo, podendo ser utilizado como área de código regular, onde será armazenado o
programa.
Página 91
38. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
17.5.2. Declaração dos Vetores de interrupção no MSP430F2013
/************************************************************
* Interrupt Vectors (offset from 0xFFE0)
************************************************************/
#define PORT1_VECTOR (2 * 2u) /* 0xFFE4 Port 1 */
#define PORT2_VECTOR (3 * 2u) /* 0xFFE6 Port 2 */
#define USI_VECTOR (4 * 2u) /* 0xFFE8 USI */
#define SD16_VECTOR (5 * 2u) /* 0xFFEA Sigma Delta ADC */
#define TIMERA1_VECTOR (8 * 2u) /* 0xFFF0 Timer A CC1, TA */
#define TIMERA0_VECTOR (9 * 2u) /* 0xFFF2 Timer A CC0 */
#define WDT_VECTOR (10 * 2u) /* 0xFFF4 Watchdog Timer */
#define NMI_VECTOR (14 * 2u) /* 0xFFFC Non-maskable */
#define RESET_VECTOR (15 * 2u) /* 0xFFFE Reset [Highest Priority] */
17.5.3. Vetores de interrupção na família 4 (MSP430FG4618)
Página 92
39. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
NOTES:
1. Fonte de múltiplos flags.
2. A flag de interrupção é alocada no módulo.
3. Um reset é gerado toda vez que a CPU tenta carregar um endereço no PC que esteja for
a do range de memória disponível no dispositivo. (Não mascarável: o bit de interrupção
individual pode ser desabilitado por um evento de interrupção, mas geralmente isto não é
possível.
4. Os endereços de vetores de interrupção entre 0FFDAh e 0FFC0h não são utilizados neste
dispositivo, podendo ser utilizado como área de código regular, onde será armazenado o
programa.
5. Violação na chave de acesso (KEYV e ACCVIFG), somente são aplicáveis aos
dispositivos do tipo F.
17.5.4. Declaração dos Vetores de interrupção no MSP430FG4618
/************************************************************
* Interrupt Vectors (offset from 0xFFC0)
************************************************************/
#define DAC12_VECTOR (14 * 2u) /* 0xFFDC DAC 12 */
#define DMA_VECTOR (15 * 2u) /* 0xFFDE DMA */
#define BASICTIMER_VECTOR (16 * 2u) /* 0xFFE0 Basic Timer / RTC */
#define PORT2_VECTOR (17 * 2u) /* 0xFFE2 Port 2 */
#define USART1TX_VECTOR (18 * 2u) /* 0xFFE4 USART 1 Transmit */
#define USART1RX_VECTOR (19 * 2u) /* 0xFFE6 USART 1 Receive */
#define PORT1_VECTOR (20 * 2u) /* 0xFFE8 Port 1 */
#define TIMERA1_VECTOR (21 * 2u) /* 0xFFEA Timer A CC1-2, TA */
#define TIMERA0_VECTOR (22 * 2u) /* 0xFFEC Timer A CC0 */
#define ADC12_VECTOR (23 * 2u) /* 0xFFEE ADC */
#define USCIAB0TX_VECTOR (24 * 2u) /* 0xFFF0 USCI A0/B0 Transmit */
#define USCIAB0RX_VECTOR (25 * 2u) /* 0xFFF2 USCI A0/B0 Receive */
#define WDT_VECTOR (26 * 2u) /* 0xFFF4 Watchdog Timer */
#define COMPARATORA_VECTOR (27 * 2u) /* 0xFFF6 Comparator A */
#define TIMERB1_VECTOR (28 * 2u) /* 0xFFF8 Timer B CC1-2, TB */
#define TIMERB0_VECTOR (29 * 2u) /* 0xFFFA Timer B CC0 */
#define NMI_VECTOR (30 * 2u) /* 0xFFFC Non-maskable */
#define RESET_VECTOR (31 * 2u) /* 0xFFFE Reset [Highest Priority] */
Página 93
40. Material auxiliar para curso Avançado I de MSP430 – Prof. Alessandro F. Cunha
18. EXERCÍCIO 3: BOTÕES E LEDS EM LOW POWER MODE.
Já foi identificado no diagrama elétrico da Experimenter Board, mostrado no item 9, as
seguintes conexões, envolvendo pinos do MSP430FG4618 e hardwares externos:
a) Botão S1 pino P1.0; d) LED2 pino P2.2;
b) Botão S2 pino P1.1; e) LED4 pino P5.1.
c) LED1 pino P2.1;
Com estas informações faça modificações na seqüência de exercícios 2, de modo que o
programa fique em Low Power Mode e apenas saia deste estado para executar ações,
fazendo economia de energia e realizando as mesmas atividades anteriores.
18.1. 1 botão e 1 Led (E-3-1)
Ao pressionar o botão S1 deve acender o LED1. Se o botão não estiver pressionado, o
LED1 deve se manter apagado.
18.2. 2 botões e 2 Leds (E-3-2)
Ao pressionar o botão S1 deve apagar o LED1. Se o botão S1 não estiver pressionado, o
LED1 deve se manter aceso. Ao mesmo tempo se o botão S2 for pressionado, o LED2
deve se apagar. Se o botão S2 não estiver pressionado, o LED2 deve se manter aceso.
18.3. 1 botão, 1 Led e temporização com Basic Timer 1 (E-3-3)
Ao pressionar o botão S2 deve acender o LED1, que deve permanecer aceso por 500 ms.
Se o botão não estiver pressionado, o LED1 deve se manter apagado.
18.4. 2 botões, 2 Leds e temporização Basic Timer 1 (E-3-4)
Ao pressionar o botão S2 deve apagar o LED1, o que deve acontecer por 500 ms. Se o
botão não estiver pressionado, o LED1 deve se manter aceso. Ao mesmo tempo, se o
botão S1 estiver pressionado o LED2 deve ficar apagado, o que também deve acontecer
por 500 ms. Se o botão não estiver pressionado, o LED2 deve se manter aceso
Página 94