Baixe o app para aproveitar ainda mais
Prévia do material em texto
CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II 2018 CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Laboratório de Eletrônica Digital Professor: Enderson Neves Cruz Índice UNIDADE 6 – PROGRAMAÇÃO C PARA MCU ............................................................ 5 6.1. Alocação de variáveis em C ................................................................................. 5 6.2. Funções .............................................................................................................. 16 6.3. Estruturas de repetição ...................................................................................... 22 6.3.1 Identificadores ................................................................................................. 23 6.3.2 Tipos ................................................................................................................ 23 6.3.3 Operadores...................................................................................................... 26 6.3.3.1 Operadores básicos ..................................................................................... 26 6.3.3.2 Operadores de deslocamento ...................................................................... 27 6.3.3.3 Operadores bit a bit ...................................................................................... 28 6.3.3.4 Operador de atribuição ................................................................................. 28 6.3.3.5 Operadores relacionais ................................................................................ 28 6.3.3.5 Operadores lógicos ...................................................................................... 29 6.4. Estruturas de tomada de decisão ....................................................................... 31 6.5. Resistores de pull up e pull down internos do MSP ............................................ 37 6.6. Repique de chave (bounce)................................................................................ 40 REFERÊNCIAS BIBLIOGRÁFICAS ............................................................................. 52 AUTORES: 1ª versão – 2017 Prof. John Kennedy Schettino de Souza Profa. Rosângela Fátima da Silva Prof. Enderson Neves Cruz REVISORES: Prof. DennyCollina Prof. Marcos Antônio da Silva Pinto CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 5 de 52 UNIDADE 6 – PROGRAMAÇÃO C PARA MCU OBJETIVOS Estudar a estrutura de um programa em C Correlacionar Algoritmo e código C. 6.1. Alocação de variáveis em C Estudo de programação é um grande desafio devido à amplitude de técnicas, ferramentas, plataformas e o objetivo da aplicação. Este material se destina as pessoas familiarizadas com conceitos de algoritmo. Nosso alvo é o estudo da linguagem C aplicado para sistemas microcontrolados. Como já estudamos na unidade 5 um projeto de sistemas dedicados é constituído de uma etapa de modelamento e uma etapa de implementação. Esta segunda etapa pode ser realizada exclusivamente por hardware ou por uma solução conjugada de software e hardware. A adoção de uma implementação conjugada nos remete a um problema: como especificar para uma máquina as tarefas que serão realizadas? Isto pode ser feito através de uma linguagem de programação. Esta linguagem, excetuando a linguagem de máquina, é escrita na linguagem humana e consequentemente não poderá será compreendida pelo computador. Deverá então passar um processo de tradução para que possa ser executada. Na unidade 5, onde utilizamos a linguagem Assembly, tínhamos um montador, ou tradutor, que traduzia cada linha do código fonte em uma instrução para o processador executar. Agora utilizando a linguagem C teremos um compilador que irá traduzir cada linha do código fonte em um ou mais comandos para o processador executar. O código fonte nada mais é que um texto escrito pelo programador através de editor de texto padrão ASCII. Também pode ser escrito através de uma ferramenta integrada de desenvolvimento que utilizaremos ao longo do nosso curso. Como tudo na vida a programação C também tem sua história (Pappas, 1990). A linguagem C está relacionada ao desenvolvimento do sistema operacional UNIX. O sistema operacional tinha como objeto tornar a máquina, PDP-7 da Bell, algo mais accessível ao programador. Então 1969, nos Laboratórios da Bell em New Jersey, foi desenvolvido o sistema operacional UNIX, escrito inteiramente em linguagem montadora do PDP-7. Logo após o desenvolvimento do UNIX, Ken Thompson implementou um nova linguagem denominada B que juntamente com o sistema UNIX permitiram o desenvolvimento software de forma mais simples. Entretanto, logo após o lançamento de uma nova máquina, o PDP-11, os projetistas encontraram muitas dificuldades na transferência do UNIX e do B para mesma. Este fato foi o elemento motivador para criação de uma nova linguagem que permitisse transferências de software de forma mais simples. Foi então que Dennis Ritchie em 1972, no laboratório da Bell, desenvolveu a linguagem C. Seu grande mérito foi criar uma linguagem que oferece recursos de baixo nível que permite especificar cada um dos detalhes da lógica do algoritmo para conseguir CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 6 de 52 eficiência máxima do computador. Por outro lado também oferece recursos de alto nível que permite ocultar os detalhes da arquitetura do computador tornando o hardware um pouco mais abstrato para o programador. Comparada às demais linguagens a linguagem C é constituída de um pequeno conjunto de regras de sintaxe. Existem mais operadores e combinações de operadores em C do que palavras-chave. A linguagem C foi criada com apenas 27 palavras-chave e foi posteriormente inserida mais cinco palavras na criação do C ANSI (American National Standards Institute). O C ANSI foi implementado na tentativa de criar um padrão para linguagem criada por B. Kernighan e D. Ritchie. O papel do C ANSI foi retirar ambiguidades inseridas em sua versão inicial por diversas entidades na criação de seus compiladores C. A linguagem C não dispõe de recursos embutidos dentro da própria linguagem, entretanto, faz uso de uma série de funções presentes em sua biblioteca. Esta biblioteca tem como papel base poupar o programador no processo de desenvolvimento, pois possui uma série de funções prontas que poderão ser utilizadas pelo programador. Sendo a linguagem C muito próxima do hardware é muito comum que os compiladores gerem códigos eficientes o que será refletido na velocidade de execução do programa. Embora seja uma linguagem próxima do hardware apresenta estruturas básicas de controle e faz o gerenciamento de escopo de dados. Suporta programação modular, garantido assim que apenas o código alterado seja recompilado independentemente do seu restante. Possibilita a inserção de código Assembly dentro do corpo do programa assim como a chamada de rotinas em Assembly com passagem de parâmetros. Apresenta um conjunto de operadores para manipulação de bits. Permite o acesso flexível a um mesmo dado com tipos distintos. Utiliza ponteiros para endereçamento de área do sistema permitindo também operações aritméticas com ponteiros. Por fim devemos destacar a sua portabilidade como elemento chave desta linguagem, ou seja, um mesmo código poderáser executado qualquer computador ou sistema operacional. Apesar das características citadas ainda poderíamos nos perguntar por que estudar a linguagem? Além do seu potencial a linguagem vem resistindo às diversas mudanças no universo software para sistemas de uso geral, como os computadores pessoais. Já para os sistemas dedicados a linguagem C vem apresentando uma curva crescente de usuários devido a sua simplicidade em relação à linguagem Assembly e ao aumento de memória RAM nos microcontroladores. Alguns passos também têm sido dados no intuito da utilização de C++ em microcontroladores, entretanto nos limitaremos ao estudo da linguagem C que será extremamente útil para um futuro aprendizado da linguagem C++. Antes de começarmos a falar da linguagem C é fundamental identificarmos a plataforma alvo onde o programa criado será executado. A utilização rotineira da linguagem C em computadores pessoais nos leva a crer que a programação C está associada aos CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 7 de 52 computadores pessoais, o que não é bem verdade. A crescente utilização de software no desenvolvimento de sistemas e a diversidade de aplicações fomentaram o aparecimento de novas linguagens de programação. Um exemplo típico é a linguagem HTML (HyperText Markup Language) utilizada na construção de páginas na internet (world wide web). Ela oferece ao programador recursos de mais simples manipulação comparados com os presentes na linguagem C, o que a torna mais simples no desenvolvimento de aplicações para este fim. Se por um lado a linguagem C tem concorrentes na plataforma de computador pessoal, ela também começa a invadir a plataforma de microcontroladores. Isto se dá devido ao aumento significativo de memória nos microcontroladores. Nosso curso tem o foco no segmento dos microcontroladores, desta forma ele irá se diferenciar significativamente da maioria dos cursos e mesmo livros C encontrados no mercado. Para ilustrar tal diferença de abordagem vamos utilizar o exemplo inicial de todo curso de programação C que é envio de mensagem para tela do computador por meio da função printf. #include <stdio.h> /* Primeiro Programa */ void main () { printf ("Botafogo Campeão"); } Avaliando este simples código de envio de mensagem identifica-se a característica base da linguagem C que é a programação funcional onde temos uma função principal responsável pelas chamadas às demais funções do sistema que trabalharão de forma colaborativa a fim de executar uma tarefa. Neste caso, a função principal (main) faz a chamada à função printf, cujo papel, é envio de mensagem para tela do computador. Entretanto, para que um programa C seja compilado e executado corretamente basta que a função principal esteja presente. O que diferencia este código quando aplicado em plataformas distintas? Para responder tal pergunta é fundamental a compreensão de alguns conceitos de sistema microprocessado. Um sistema microprocessado é constituído de um conjunto de dispositivos básicos, entretanto podemos destacar quatro elementos: CPU (Central Processing Unit), memória, I/O e barramentos (dados, endereço e controle). Existem diversos sistemas microprocessados e estamos mais familiarizados com o computador pessoal cujo diagrama pode ser visto na Figura 6.1. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 8 de 52 Figura 6.1- Arquitetura básica de um computador. Olhando externamente os computadores pessoais podemos observar na Figura 6.2 dois modelos básicos o de mesa (desktop) e o portátil (laptop). Figura 6.2 – Computadores pessoais desktop (A) e laptop (B). (A) (B) Embora os computadores pessoais representem uma fatia significativa dos sistemas microprocessados presentes no nosso cotidiano eles não são os únicos. Diariamente estamos em contato com diversos sistemas microprocessados, sendo alguns mais comuns como o celular e o GPS (Figura 6.3) e outros que são mais comuns em ambientes industriais (Figura 6.4). Com base no que estudamos até o momento, podemos agora refazer a pergunta sobre programação C que ficou em aberto: O que diferencia este código quando aplicado em plataformas distintas? O código em questão é o que imprime na tela do nosso sistema microprocessado a mensagem “Botafogo campeão”. Se executarmos este código no desktop ou no laptop (Figura 6.2), teremos o resultado esperado. Já no CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 9 de 52 celular e no GPS (Figura 6.3) temos algo em comum com os computadores pessoais, que é a tela gráfica para exibição de mensagem. Desta forma, utilizando o compilador C para as respectivas plataformas também é possível a exibição da mensagem. Já para os sistemas microprocessados da Figura 6.4 temos uma diferença significativa dos dispositivos de saída destas plataformas com as demais. Figura 6.3 – Sistemas microprocessados do nosso cotidiano: celular (A) e GPS (B) (A) (B) Figura 6.4 – Sistemas microprocessados presentes em ambientes industriais: controlador de pressão e temperatura (A) e conta giros (B). (A) (B) Para o caso do controlador de pressão e temperatura, embora o display não seja gráfico, é possível a escrita de uma mensagem no formato texto, entretanto para o caso do conta giros não existe um número de displays suficientes para a exibição da mensagem. Sendo assim, qual seria o resultado da execução da função printf nas plataformas da Figura 6.4. Na prática é bem provável que seus respectivos compiladores nem possuam a função printf, o que gera um erro durante a compilação e consequentemente o programa não poderia ser executado. Entretanto, vale lembrar que a inexistência da função printf no compilador não inviabiliza a escrita de uma função que esteja em conformidade com cada uma destas plataformas. Esta nova função printf atenderia exatamente as características dos respectivos hardwares e trabalharia com suas respectivas limitações. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 10 de 52 Nossa plataforma para o aprendizado da linguagem C é o LaunchPad MSP-EXP430G2 (Intruments, 2010) que suporta os microcontroladores da família MSP430G (Intruments, 2013). No nosso laboratório utilizamos o MSP430G2553 que possui 16K de memória flash (programa), 512 de RAM (dados). Já seus dispositivos de I/O são: temporizador, comparador, conversor A/D e canal serial de comunicação. Além destes periféricos também possui duas portas (P1 e P2) de 8 bits. Utilizaremos as portas P1 e P2 durante o aprendizado da linguagem C. Por meio destas portas poderemos acionar dispositivos conectados ao MSP ou mesmo ler informações do mundo externo. Considerando que os terminais (pinos) das portas P1 e P2 possam assumir o papel de entrada (I) ou saída (O), vale lembrar que esta condição é exclusiva, ou seja, se um determinado terminal da porta P1 for configurado como saída ele não poderá trabalhar simultaneamente como entrada. O estudo da linguagem C tem uma relação muito estreita não só com a plataforma de hardware alvo, mas também com o compilador, cujo papel é a tradução do texto do programa para o código de máquina do processador (CPU) do sistema microprocessado. O compilador utilizado neste material é da IAR (Ingenjörsfirman Anders Rundgren), que significa Companhia de Engenharia Anders Rundgren. Existem outros compiladores para o MSP como o Code Composer da Texas, Cross Works da Rowley Associatese a versão livre GCC. Na prática o que diferencia os compiladores é o volume recursos que o mesmo disponibiliza. Para quem já conhece algum compilador poderá se deparar com algumas limitações impostas pelo compilador da IAR. Antes de seguir em frente com a plataforma do MSP e o ambiente de programação da IAR vamos aproveitar o primeiro exemplo de código para avaliar alguns elementos básicos da programação C. O primeiro programa apresentado é constituído da função principal main e de uma função secundária denominada printf. Nosso primeiro problema é compreender o que significa uma função. A palavra Função definida no dicionário Michaelis seria: “Ação natural ou própria de qualquer coisa. Atividade especial, serviço, encargo, emprego, missão”. Poderíamos adotar como função a palavra missão, ou seja, o que deve ser realizado pelo main. Sabendo-se que a missão da função printf é imprimir algo em tela, nós teríamos que a missão do main é chamar uma função de impressão que coloque na tela a mensagem “Botafogo Campeão”. Para que a função main possa executar sua missão é necessário que a mesma seja definida segundo a sintaxe da linguagem C. Retorno Nome_da_Função() Em sua sintaxe toda função além de executar sua missão retornará uma resposta informado algo relativo à sua missão. Entretanto, como podemos ver neste caso, a função main não necessita informar nada ao sistema após a execução de sua missão, desta forma, foi associada à função main o retorno void (nada), que significa nenhum retorno. Outro aspecto importante de uma função é que ela apresenta delimitadores que indicam o seu início e seu fim. Neste exemplo podemos identificar os delimitadores representados pelas chaves { }. Então tudo que se encontra delimitado pelas chaves deverá ser executado pela função, levando sempre em consideração a lógica de controle quando esta existir. Além da função main escrita de forma textual uma segunda função está sendo utilizada que é a função printf. Esta função está contida na biblioteca do C. Existe uma série de funções presentes na biblioteca do C que têm como papel agilizar a escrita de código. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 11 de 52 Desta forma, o programador não necessita saber como o envio de mensagem é feito para o terminal de vídeo do sistema, mas apenas utilizar o recurso ou função que faz tal tarefa. Para utilizar uma função presente na biblioteca é necessário indicar no código fonte qual é o protótipo da função em questão. O protótipo apresenta o formato da função. Estaremos entrando em maiores detalhes sobre este assunto ao estudarmos o item Função. Neste programa o protótipo da função está sendo informado através da linha de programa: #include <stdio.h>. A palavra include informa ao compilador para inserir durante o processo de compilação o arquivo stdio.h no arquivo corrente. Caso o arquivo stdio.h seja aberto no editor de texto o programador poderá observar os diversos protótipos de funções presentes no stdio.h. Para concluir a análise deste programa temos ainda a seguinte linha: /* Primeiro Programa */ Ela está delimitada pelo conjunto de caracteres /* e */. Tudo que estiver entre estes delimitadores será ignorado pelo compilador e não irá gerar código para ser executado. Seu papel é basicamente permitir que o programador coloque comentários para auxiliá- lo em uma futura leitura deste programa. Caso você tenha interesse de estudar C para o ambiente PC existem alguns materiais didáticos para este fim (Schildt, 1997)(Pappas, 1990). Podemos agora focar na plataforma de trabalho e estudarmos os diversos conceitos relativos à programação C. Como primeiro exemplo, descrito nos fluxogramas da (Figura 6.5) temos a construção e apresentação da sequência de Fibonacci que já foi explorada no estudo da linguagem Assembly. Este exemplo nos permitirá enfocar apenas nos aspectos da linguagem C, uma vez que, tanto a plataforma como a lógica dos fluxogramas já foram amplamente estudadas. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 12 de 52 Figura 6.5 – Sequência de Fibonacci (a) Calcula e mostra sequência (b) Gerador de sequência de Fibonacci (c) Converte e mostra valores nos displays (d) Configuração dos dispositivos de I/O Configura Display Configura I/Os Apaga Display0 Apaga Display1 Retorna CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 13 de 52 Atividade 6.1 PROGRAMA FIBONACCI E DISPLAY NA LINGUAGEM C 1 – Faça a conexão dos displays de sete segmentos conforme a Figura 6.6. Figura 6.6 – Diagrama de conexões das portas do MSP ao kit 2 - A partir do arquivo de projeto carregue o programa display C no IAR. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 14 de 52 3 – Verifique se o projeto encontra-se configurado em modo emulação e faça o download do programa no KIT. 4 – Execute a primeira linha do programa a opção step over ( F10) e anote o endereço inicial reservado para o armazenamento da lista de Fibonacci (variável Lista). 5 – Execute o programa passo a passo utilizando a opção step over ( F10) até a linha de código “mostra_display(lista[indice]);”. Insira na janela Watch as variáveis da especificadas na tabela a seguir e preencha as colunas Value e Location. Value Location elementos indice P1DIR P2DIR Avalie os valores encontrados e justifique para cada caso os valores anotados tanto para a coluna Value como para coluna Location. 6 – Agora, ainda em modo passo a passo, mas com a opção step into ( F11), e entre na função mostra_display e continue a execução até atingir a instrução “while (unidade > 9)”. Anote os valores das variáveis especificadas na tabela a seguir. Value Location elementos indice unidade dezena 7 - A variável dezena foi carregada com o valor “0”, compatível com a linha de instrução “dezena=0;”, mas de onde veio a informação carregada na variável unidade? CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 15 de 52 8 – As informações relativas às variáveis elementos e índice estão corretas? 9 – Execute, em modo passo a passo, com a opção step into ( F11), até que a linha de execução seja posicionada sobre a instrução “P1OUT=cod[unidade];”. Anote os valores das variáveis unidade e dezena. Continue a execução com a opção step into até atingir o delimitador de saída “}” da função mostradisplay. Anote os valores de P1OUT e P2OUT. Value unidade dezena P1OUT P2OUT Os valores encontrados para as variáveis estão compatíveis? Justifique. 10 – Execute com a opção step over ( F10) até que o cursor de execução seja novamente posicionado na instrução “mostra_display(lista[indice]);”. Value Location indice lista[indice] Avalie os valores encontrados e justifique para cada caso os valores anotados tanto para a coluna Value como para coluna Location. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 16 de 52 OBJETIVOS Estudar estrutura de uma função. Modelar uma função. Flexibilizar a função com passagem de parâmetros. 6.2. Funções A linguagem C como já foi dito no início é fundamentada nas funções.À medida que você começa a trabalhar com a linguagem C o conceito de função passa a fazer parte de sua forma de pensar. A estratégia do uso de funções nos permite escrever programas complexos através de pequenos blocos, ou funções, de menor complexidade. Todo programa escrito em C será composto de no mínimo uma função que é a main, seguido das demais funções. Assim como durante o estuda da linguagem Assembly os programas eram compostos de sub-rotinas, aqui no C teremos o mesmo conceito, sendo agora denominado função. Entretanto, uma das grandes vantagens da utilização da linguagem C é que o seu compilador já possui uma série de funções que pouparão o trabalho do programador. Durante o estudo da linguagem Assembly nos deparamos com a necessidade de criar subrotinas para executar as operações de multiplicação e de divisão. A boa notícia é que na programação C, mesmo para operações matemáticas mais complexas tais como: seno, arco tangente, raiz quadrada, logaritmo entre outras, não seria necessário criar o algoritmo e a respectiva codificação para executar tal procedimento, pois o próprio compilador C já possui um conjunto de funções pertencentes a biblioteca matemática. Desta forma, o trabalho do programador se restringirá em desenvolver as funções não providas pelo compilador. Desta forma, caberá ao programador a escrita de novas funções não providas pelo compilador C, que por sua vez, poderão compor uma nova biblioteca, para que sejam utilizadas nos próximos desenvolvimentos de sistemas. Vale ressaltar também que o compilador C possui não só a biblioteca matemática (math) como uma série de outras para manipulação: data e hora (time), cadeia de caracteres (string), operações de entrada e saída (stdio), dentre outras. No primeiro exemplo em C que foi estudado, foi necessária além da função main, mais quatro funções: tempo, config_display, mostra_display e Fibonacci. Observe que as funções criadas não são providas pelo compilador C. Antes de estudarmos cada função, vale ressaltar, que além do seu papel central de executar uma tarefa específica ela também permite estabelecer uma organização na escrita do código do programa. Para entendermos mais claramente este conceito vamos avaliar a função config_display. Esta função é chamada apenas uma única vez no programa e seu papel é definir como os dispositivos de I/O do MSP irão se comportar ao longo da execução do programa. Ela é constituída de cinco comandos que poderiam estar escritos no próprio programa principal. Entretanto, para garantir uma organização no programa, separamos toda etapa de configuração dos dispositivos de I/O envolvidos neste projeto e sua condição inicial de funcionamento em uma função específica. O processo de codificação de uma função inicia pela escrita do seu algoritmo, neste caso um fluxograma. Em seguida é necessário o formato da função: void config_display(void) Esta linha de código informa ao compilador que esta função não necessita de nenhuma informação para executar sua tarefa, ou seja, basta que seja chamada para que sua tarefa seja realizada. Isto é determinado pela palavra void presente entre parênteses CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 17 de 52 após o nome da função. Uma segunda informação importante é que após a execução da função ela não dará nenhuma resposta a função que a chamou. Isto é determinado pela palavra void presente antes do nome da função. Observe que a palavra void é uma palavra reservada do compilador C e não poderá ser utilizada como nome de uma variável ou função no seu programa. Esta linha de programa deve ser colocada no início do programa. Após a definição do formato da função são escritas as linhas de código delimitadas pelas chaves, conforme programa a seguir. /*---------------------------------------------------------------------------- NOME: config_display DESCRICAO: CONFIGURA AS PORTAS P1 E P2 DO MSP430 COMO SAIDAS ENTRADA: - SAIDA: - ---------------------------------------------------------------------------- */ void config_display(void) { P1DIR=0XFF; //CONFIGURA P1 E P2 COMO SAÍDAS P2DIR=0XFF; P2SEL=0; P1OUT=0; //APAGA DISPLAYS P2OUT=0; } Não menos importante, embora não interfira no código da função, é necessário a escrita do cabeçalho. Constituído de quatro partes onde o programador vai descrever o funcionamento da função, para que esta função possa ser utilizada no futuro pelo próprio programador ou por terceiros. Nesta função, como não existem parâmetros de entrada e saída, os mesmo têm suas descrições suprimidas. Vamos avaliar a função mostra_display presente no código a seguir. /*---------------------------------------------------------------------------- NOME: mostra_display DESCRICAO: APRESENTA EM DOIS DISPLAYS DE 7 SEGMENTOS O VALOR DA DEZENA E UNIDADE DE QUALQUER NÚMERO DE 2 DÍGITOS DECIMAL ENTRADA: valor - NÚMERO EM HEXADECIMAL QUE SERÁ MOSTRADO SAIDA: - ---------------------------------------------------------------------------- */ void mostra_display(unsigned char valor) { unsigned char unidade=valor,dezena=0; while (unidade > 9) { dezena=dezena+1; unidade=unidade-10; } P1OUT=cod[unidade]; P2OUT=cod[dezena]; } Conforme indicado no próprio cabeçalho o formato da função indica que ela necessita da informação atribuída a variável valor para executar sua tarefa, entretanto, ao término da função ela não retornará nada a quem a chamou. Será de responsabilidade da função que fará a chamada a função mostra_display informar o que será carregado na variável valor. É importante observar que o valor a ser atribuído a variável valor deve respeitar o tipo definido entre parênteses, ou seja, um byte sem sinal que significa um número entre 0 e 255. Neste programa a função mostra_display é chamada pela função main por meio da seguinte instrução: mostra_display(lista[indice]); CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 18 de 52 Onde lista[índice] é um elemento do vetor lista que foi previamente carregado pela função fibonacci, com sua respectiva sequência. Um exemplo distinto das duas primeiras funções é a função de fibonacci apresentada no código a seguir. /*----------------------------------------------------------------------------- NOME: FIBONACCI DESCRICAO:Calcula a sequencia de Fibonacci e carrega no vetor LISTA a sequência ENTRADA: unsigned char limite - Limite para o cálculo da sequência SAIDA: unsigned char - Numero de elementos da sequência -----------------------------------------------------------------------------*/ unsigned char fibonacci(unsigned char limite) { unsigned char indice=0,penultimo=0,ultimo=1,novo=0; lista[indice]=penultimo; indice++; lista[indice]=ultimo; while (novo<limite) { indice++; novo=penultimo+ultimo; lista[indice]=novo; penultimo=ultimo; ultimo=novo; } return(indice); } Ao contrário das duas funções anteriores, esta função além de receber um parâmetro de entrada, que definirá o limite para o caçulo da sequência de Fibonacci, ao término da função ela também retornará o número de elementos que foram obtidos, considerando o limite adotado no parâmetro de entrada. Para o retorno do número de elementos é necessário utilizar a instrução return e entre parênteses o informação que se deseja retornar. A chamada da função fibonacci é realizada na função main pela seguinte linha de código: unsigned char elementos=fibonacci(40); Esta linha de código deve ser avaliada em duas partes distintas: fibonacci(40) Chamada da função fibonacci com a passagem do parâmetro de entrada, que definirá até que limite a sequência de Fibonacci será calculada. unsigned char elementos= variável elementos que foi criada com o tamanho de um byte, para armazenar o valor retornado pela função fibonacci. Tanto na função mostra_display como na função fibonacci foram passadas informações para que as funções pudessem realizar suas respectivas tarefas. Esta técnica de passagem de parâmetro torna a função mais flexível, pois permite que a mesma possa executar sua tarefa para valores de entrada distintos. Na função de fibonacci foram utilizadas algumas variáveis podem ser classificadas segundo o seu escopo como local ou global. As variáveis: limite, indice, ultimo, penultimo e novo são classificadas como local, pois estas variáveis só existirão enquanto a função fibonacci estiver sendo executada. As demais funções não terão acesso a estas variáveis. Já a variável lista[índice], não pertence a função fibonacci. Ela foi criada no início do programa fora do escopo das demais funções, desta forma ela é CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 19 de 52 classificada como global. Ou seja, qualquer função poderá ler ou escrever informações na mesma. A utilização de variáveis locais em aplicações com microcontroladores é extremamente importante, pois o recurso de memória RAM é limitado e a utilização de variáveis temporária permite que uma mesma área de RAM seja utilizada em momentos distintos por diversas variáveis temporárias. Isto evita que uma área de memória seja alocada de forma permanente levando em algumas situações a falta de memória no sistema. A alocação temporária é realizada na pilha do sistema. Para o programador a utilização da pilha ocorre de forma transparente, pois o compilador cuidará deste processo. Cabe ao programador somente definir suas variáveis dentro do escopo “{ }” das funções . Até o momento já utilizamos algumas funções em C. Assim como podemos utilizar algumas funções da biblioteca do C também podemos, ou melhor, devemos criar nossas próprias bibliotecas. Elas nos pouparão ao longo dos anos de desenvolvimento um bom tempo de trabalho. Montar nossa biblioteca não é uma tarefa difícil, mas lembrar como utilizá-la após alguns dias, meses ou anos é que é o grande desafio. O segredo para utilização desta biblioteca está na sua construção. Devemos “perder” um pouco de tempo hoje no processo de documentação, pois com certeza iremos colher frutos deste trabalho. O processo de documentação passa pela construção do algoritmo (fluxograma, máquina de estados, pseudocódigo) seguido pela codificação. Mas não se esqueça de criar o cabeçalho da função. Basta para cada função o seu respectivo cabeçalho que apresentará basicamente quatro tópicos: Nome da função: nome dado para a chamada da função. Descrição: o que esta função faz. Entrada: todos os parâmetros necessários para a chamada da função com seus respectivos tipos. Saída: o que esta função retorna como resposta e o seu tipo de dado. A função tempo listada a seguir não possui parâmetros, entretanto possui uma variável local de 16 bits, que é designado pelo tipo “int”. /*---------------------------------------------------------------------------- NOME: TEMPO DESCRICAO: FAZ UMA CONTAGEM DE 65535. ENTRADA: - SAIDA: - -----------------------------------------------------------------------------*/ void tempo(void) { unsigned int cont=0xFFFF; while(cont!=0) cont=cont-1; } Esta função, cujo papel é realizar uma contagem, provoca um atraso no processamento da sequência de execução do programa principal. Considerando que CPU é responsável pelo decremento da variável cont, ela terá que realizar 65535 decrementos nesta variável, para que possa encerrar a função tempo. Eventos de temporização são comuns em sistemas microprocesados, para atender demandas como a de visualização de informações, como ocorre neste programa. Entretanto, funções com temporizações constantes podem limitar muito o funcionamento dos sistemas. Suponha que fosse necessário dobra o tempo de visualização da temporização, bastaria chamar de forma consecutiva a função de tempo conforme a Figura 6.7a. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 20 de 52 Figura 6.7 – Temporizações por software (a) Fixo (b) Configurável Entretanto, caso fosse necessário uma contagem que não fosse diferente da rotina de tempo, não poderíamos utilizar a mesma função de temporização. Para resolver situações com contagens distintas é necessário aplicar a técnica de passagem de parâmetro para a função de temporização. Desta forma, a função de temporização deverá receber o valor da contagem que será realizada e a função que for utilizar esta função deverá enviar para mesma o valor da contagem (Figura 6.7b). CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 21 de 52 Atividade 6.2 PASSAGEM DE PARÂMETRO 1 – A função tempo permite a inserção de um tempo fixo entre a apresentação de dois valores nos displays. Este tempo é determinado pelo valor associado a variável “cont”. Altere a função tempo de tal forma que ela possa receber como parâmetro o valor que será atribuído a variável “cont”. Tire como exemplo para esta implementação as funções fibonacci e mostra_display. 2 – Utilizando o projeto DisplayC, crie uma nova função denominada ímpares que receberá como parâmetro de entrada um valor inteiro entre 10 e 100. A função deverá preencher o vetor Lista com os valores ímpares compreendidos entre 0 e o valor limite passado como parâmetro. Utilize as funções já existentes para exibir os valores da lista nos displays. Obs: Não apague a função fibonacci do seu projeto, apenas crie a nova função ímpares, mantendo em seu projeto as duas funções. Na função principal, troque a chamada da função fibonacci pela chamada da função ímpares. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 22 de 52 OBJETIVOS Estudar as estruturas de repetição. Criar variáveis. Estudar os operadores. 6.3. Estruturas de repetição Na função tempo foi aplicada a estrutura de repetição while para realizar uma contagem na variável cont variando do valor inicial 65535 até o valor final 0. Para que a variável cont seja decrementada é necessário que a condição definida entre parênteses seja verdadeiro. /*---------------------------------------------------------------------------- NOME: TEMPO DESCRICAO: FAZ UMA CONTAGEM DE 65535. ENTRADA: - SAIDA: - -----------------------------------------------------------------------------*/ void tempo(void) { unsigned int cont=0xFFFF; while(cont!=0) cont=cont-1; } Esta mesma função pode ser reescrita com outras duas estruturas de repetição: • do – while void tempo( void ) { int cont=10000; do cont=cont-1; while (cont!=0) } • for void tempo( void ) { int cont; for (cont=10000; cont>0;cont--); } Até o momento utilizamos nos códigos das funções diversas variáveis e diferentemente do montador Assembly o compilador C oferece uma série de funcionalidades que nos permite abstrair de como as variáveis são criadas e manipuladas. No montador Assembly é papel do programador determinar se uma variável será alocada em registro ou em memória. Já neste momento da codificação em C inicia-se a abstração, tornando este procedimento transparente para o programador. O próprio compilador irá definir se é mais adequada a alocação em registro ou memória. O programador, se desejar poderá interferir neste procedimento, mas caso não queira ounão saiba isto será provido pelo próprio compilador. Tanto na programação Assembly e C o programador será responsável por determinar a capacidade de armazenamento das variáveis, mas o compilador C, após definido o tamanho da variável, irá provê para o programador o tratamento das informações armazenadas nas variáveis tais como: CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 23 de 52 positivos, negativos e casas decimais, o que não ocorre com o montador Assembly. Desta forma, no montador Assembly, caso seja necessário uma variável armazenar valores positivos e negativos, o próprio programador deverá tratar tal situação. Para criação de uma variável em C é necessário definir um identificador e um tipo. 6.3.1 Identificadores Os identificadores são os nomes que utilizamos não só para representar as variáveis, mas também constantes e funções do programa. Um identificador é constituído de uma sequência de caracteres começando por letra e intercalado ou não com números. Os identificadores poderão ter qualquer número de caracteres, mas apenas os 31 primeiros serão significativos para o compilador. O compilador C é sensível às letras maiúsculas e minúsculas, isto significa dizer que o compilador faz diferença entre elas. Desta forma, os identificadores GOL, gol e Gol são diferentes. Os identificadores podem ser compostos, por exemplo: GolBotafogo, GolAtlético, GolCruzeiro. Também podem ser declarados utilizando sublinhas: Gol_Botafogo, Gol_Atlético, Gol_Cruzeiro, mas nunca com espaçamento entre as palavras: Gol Botafogo, Gol Atlético, Gol Cruzeiro. Neste caso, o identificador Gol apareceria repetido três vezes gerando erro de compilação. Além do que foi apresentado os identificadores têm as seguintes restrições: • Não podem ser iguais a uma palavra chave do C ou presente em sua biblioteca, exemplo main. • Não poderão ser utilizados caracteres especiais que representem um operador, exemplo “*” operador de multiplicação. Na função tempo é possível destacar os identificadores: cont e tempo, enquanto na função fibonacci temos o indice, penultimo, ultimo, novo, limite e fibonacci. 6.3.2 Tipos Além de determinar a quantidade de memória alocada para a variável o tipo determina como a variável será interpretada pelo compilador. Uma variável do tipo char em C corresponde a uma variável de um byte em Assembly definida pela diretiva DB (Define Byte). Caso o valor 0xFF esteja armazenada numa variável do tipo char em C, elá representará o valor -1, pois as variáveis do tipo char representam valores na faixa de -128 a +127. Diversos são os tipos de dados suportados pelo compilador C (Tabela 6.1). CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 24 de 52 Tabela 6.1 – Tipo de dados É necessário que o programador identifique exatamente o papel da variável para que o seu tipo também seja definido. No exemplo da função tempo, a seguir, a variável cont recebe um valor inicial que é decrementado a cada repetição da estrutura while. O tipo associado ao cont foi o int que permite um armazenamento de valores na faixa de 32768 a 32768 conforme Tabela 6.1. Caso fosse necessário aumentar o tempo da contagem, bastaria aumentar o valor do cont. Entretanto, observe que seu valor máximo é 32768. void tempo( void ) { int cont=10000; do cont=cont-1; while (cont!=0) } Sendo assim é necessário incluir o modificador unsigned que transforma este tipo int em um número não sinalizado, readequando a sua faixa de contagem entre 0 e 65535, conforme Tabela 6.1. Vamos explorar um pouco mais a associação do tipo a variável utilizando um exemplo complementar, que é característico para plataforma de computador pessoal (PC). Suponha que tenhamos que calcular a média das notas de um aluno no seu primeiro ano do ensino médio que apresenta as seguintes disciplinas: Português, Inglês, Matemática, Física, Química, Biologia, História e Geografia. Considere que a nota em cada uma das disciplinas assuma valores entre 0 e 100 e que a média poderá receber valor com até duas casas decimais. Nossa tarefa será criar um identificador para nota de cada matéria e outro para receber o valor da média. Na Tabela 6.1 estão listados os tipos básicos presentes no C para que possamos decidir qual o tipo apropriado para cada variável do nosso problema. Observando a Tabela 6.1 poderemos atribuir para cada uma das disciplinas o tipo char, pois o mesmo tem a capacidade de representação das possíveis notas das disciplinas. Já para média como teremos que somar todas as notas, num total de 8 disciplinas, não será possível armazenar em um tipo char. Podemos então assumir o tipo int, pois o valor máximo do somatório das notas será 800. O problema da adoção do tipo int para a Tipo Número de bits Intervalo Início Fim Inteiro int 16 -32.768 32.767 unsigned int 16 0 65.535 long int 32 -2.147.483.648 2.147.483.647 unsigned long int 32 0 4.294.967.295 Ponto Flutuante float 32 -3,40E-38 3.4E+38 double 64 -1,7E+308 1,7E+308 long double 80 -3,4E-4932 3,4E+4932 Caractere char 8 -128 127 unsigned char 8 0 255 Void Void CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 25 de 52 média é que neste caso, quando o somatório das notas for dividido por 8 poderemos obter valor com casas decimais. Nesta situação, um tipo int truncaria a parte decimal da média. Para garantir a resposta correta o tipo indicado seria um float. #include <stdio.h> /* Segundo Programa */ void main () { char Port=60, Ing=97, Mat=89, Fis=75, Qui=80, Bio=95, Hist=80, Geo=95; float media; media = ((float)(Port + Ing + Mat + Fis + Qui + Bio + Hist + Geo)/8); printf ("Média Final %5.2f",media); } Existe um tipo básico que não foi apresentado na tabela que é o void. Ele representa valores que não ocupam espaço em memória e não tem valor algum. Nós já fizemos uso deste tipo ao estudarmos as funções main, config_display, mostra_display e tempo. Ele normalmente é utilizado para definir o tipo de funções que não retornam nenhum valor ou para trabalhar com ponteiros como veremos mais a frente. Para cada um dos tipos de variáveis existem os modificadores de tipo. Os modificadores de tipo do C são quatro: signed, unsigned, long e short. Ao float não se pode aplicar nenhum já ao double pode-se aplicar apenas o long. Os quatro modificadores podem ser aplicados a inteiros. A intenção é que short e long forneçam tamanhos diferentes de inteiro onde isto for prático. Inteiros menores (short) ou maiores (long). O int normalmente terá o tamanho natural para uma determinada máquina. Assim, numa máquina de 16 bits, o tipo int provavelmente terá 16 bits. Na verdade, cada compilador é livre para escolher tamanhos adequados para o seu próprio hardware, com a restrição de que short int e int tenham pelo menos 16 bits, long int pelo menos 32 bits, e short int não pode ser maior que o int, que por sua vez, não pode ser maior que long int. O modificador unsigned serve para especificar variáveis sem sinal. Um unsigned int será um inteiro que assumirá apenas valores positivos. Além dos modificadores de tipo o compilador C oferece o modificador const, que permite a atribuição inicial de um valor a uma variável, entretanto impede que este valor seja alterado durante a execução do programa. A declaração da variável com este modificador tem o seguinte formato: const int MIN=1, MAX=1000; const float JUROS=0,37; A aplicação deste modificador proporciona a alocação da variável em ROM economizando assim área de RAM, que normalmente é um recurso escasso nos MCUs. Embora não se tratede uma variável, podemos utilizar a diretiva define do compilador C para associar um valor a um rótulo: #define ESPERA 10000 Neste caso, durante o processo de compilação do programa toda ocorrência do rótulo ESPERA será substituído pelo valor 10000. Este procedimento é utilizado quando necessitamos utilizar em diversas vezes ao longo do código o valor ESPERA. Sendo assim, caso seja necessário alterar o valor de ESPERA, basta trocar o valor 10000 para o novo valor desejado e recompilar o programa. Desta forma, as ocorrências do rótulo ESPERA serão substituídas por seu novo valor. O compilador C da IAR permite a definição de constante na base decimal e hexadecimal. As constantes na base hexadecimal começam com 0x, enquanto a CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 26 de 52 constante decimal não necessita de caractere adicional para sua representação (Tabela 6.2). Tabela 6.2 – Formato das constantes Constante Tipo 0XE3 Constante Hexadecimal (8 bits) 0x1A34 Constante Hexadecimal (16 bits) 214 Constante Decimal (8 bits) 64225 Constante Decimal (16 bits) 6.3.3 Operadores A principal tarefa que um sistema microprocessado realiza é a manipulação/transformação de dados. Esta tarefa é realizada por meio das variáveis, constantes e com operações aplicadas nas mesmas. Na função de temporização existe um contador, cujo valor deve ser decrementado a cada vez que a estrutura de repetição é executada. Neste caso, utilizamos a variável cont, a constante 1 e o operador de soma (+) para criar uma linha de código no programa: cont=cont-1; Diversos são os operadores oferecidos pelo compilador na realização desta tarefa. 6.3.3.1 Operadores básicos Os operadores de adição e multiplicação são usados para desenvolver operações matemáticas. O C possui operadores unários e binários (Erro! Fonte de referência não encontrada.). Os unários agem sobre uma variável apenas, modificando ou não o seu valor, e retornam o valor final da variável. Os binários usam duas variáveis e retornam um terceiro valor, sem alterar as variáveis originais. O operador binário também poderá atuar sobre duas variáveis e retornar o resultado para uma delas. A soma é um operador binário, pois pega duas variáveis, soma seus valores, podendo ou não alterar o conteúdo de uma delas, e retorna esta soma. Tabela 6.3 – Operadores Operador Ação + Soma (inteira e ponto flutuante) - Subtração ou Troca de sinal (inteira e ponto flutuante) * Multiplicação (inteira e ponto flutuante) / Divisão (inteira e ponto flutuante) % Resto de divisão (de inteiros) ++ Incremento (inteiro e ponto flutuante) -- Decremento (inteiro e ponto flutuante) Podemos observar que um mesmo operador, como por exemplo, o “-“ poderá atuar como um operador binário ou como um operador unário. Como operador unário apenas troca o sinal da variável sobre a qual está aplicada. Já é um operador binário ele implementa a subtração entre duas variáveis. O operador / (divisão) atua sobre as variáveis em função do seu tipo. Quando aplicado a variáveis em ponto flutuante nos fornece o resultado da divisão "real" e quando aplicado sobre variáveis inteiras nos fornecerá valores inteiros. O operador % (resto) fornece o resto da divisão de dois inteiros. O exemplo a seguir ilustra o comportamento desses operadores. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 27 de 52 int a = 17, b = 3; int x, y; float z = 17 , z1, z2; x = a / b; y = a % b; z1 = z / b; z2 = a / b; Após a execução desse programa teremos os seguintes valores: x = 5, y = 2, z1 = 5.666666 e z2 = 5.0. Note que, na linha correspondente a z2, primeiramente é realizada uma divisão inteira (pois os dois operandos são inteiros). O resultado será atribuído a variável float z2, somente após efetuada a divisão. Os operadores de incremento e decremento são unários que alteram a variável sobre a qual estão aplicados. O que eles fazem é incrementar ou decrementar, a variável sobre a qual estão aplicados, de 1. Então: x++; x--; são equivalentes a x=x+1; x=x-1; Estes operadores podem ser pré-fixados ou pós-fixados. A diferença é que nos operadores pré-fixados eles incrementam e retornam o valor da variável já incrementada. Nos pós-fixados, eles primeiro retornam o valor da variável e depois incrementam a variável. Então, nesse programa: x=23; y=x++; teremos, no final, y=23 e x=24. Já neste caso: x=23; y=++x; teremos, no final, y=24 e x=24. Uma curiosidade: a linguagem de programação C++ tem este nome, pois ela seria um "incremento" da linguagem C padrão. A linguagem C++ é igual à linguagem C só que com extensões que permitem a programação orientada a objeto, o que é um recurso extra. 6.3.3.2 Operadores de deslocamento O operador de deslocamento permite que o conteúdo da variável seja deslocado uma posição à direita ou à esquerda (Tabela 6.4). Tabela 6.4 – Deslocamento Operador Ação << Deslocamento à esquerda >> Deslocamento à direita Uma aplicação típica destes operadores é a multiplicação ou divisão por 2. Existe outra aplicação que veremos mais frente em operações de I/O. Suponha seguinte expressão: X << Y, tanto X como Y devem ser valores inteiros e Y não pode ser maior que o número de bits de X, pois caso contrário o resultado da operação é imprevisível. O valor de X será deslocado à esquerda o número de vezes indicado em Y. Serão inseridos 0s a direita de X. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 28 de 52 6.3.3.3 Operadores bit a bit Os operadores bit a bit tratam as variáveis como combinações de bits em vez de números (Tabela 6.5). Estes operadores permitem o acesso a um bit específico na variável. Tabela 6.5 – bi a bit Operador Ação & AND (E) | OR (OU) ^ XOR (EXCLUSIVE OR) Um caso típico de aplicação dos operadores de bit é para operação de I/Os nos MCUs. 6.3.3.4 Operador de atribuição O operador de atribuição do C é o sinal de “=”. Seu papel é pegar o valor à direita e atribuir à variável da esquerda. Isto faz com que as seguintes expressões sejam válidas: x=y=z=1.5; x=y+7; O operador de atribuição pode trabalhar combinado com os demais operadores simplificando o formato da instrução (Tabela 6.6). Tabela 6.6 – Operador de atribuição combinado Operador Ação *= a*=b a=a*b /= a/=b a=a/b %= a%=b a=a%b += a+=b a=a+b -= a-=b a=a-b <<= a<=b a=a<<b >>= a>>=b a=a>>b &= a&=b a=a&b ^= a^=b a=a^b |= a|=b a=a|b 6.3.3.5 Operadores relacionais Diferentemente dos operadores estudados até aqui, os operadores relacionais são utilizados para estabelecer uma relação entre os valores dos operandos (Tabela 6.7). Eles sempre dão como resultado o valor 1 se a relação é verdadeira ou valor igual 0 se a relação é falsa. Tabela 6.7 – Operadores relacionais Operador Ação > Maior do que >= Maior ou igual a < Menor do que <= Menor ou igual a == Igual a != Diferente de Os operadores relacionais retornam verdadeiro se o resultado da relação foi diferente de zero ou falso se zero. Nas linhas de código a seguir: while (cont != 0) cont--; CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 29 de 52 a variável cont será decrementado enquanto o valor de cont for diferente de 0 (zero). 6.3.3.5 Operadores lógicos Assim como os operadores relacionais os operadores lógicos retornam valores lógicos (verdadeiro e falso) em operação entre duas variáveis (Tabela 6.8). Tabela 6.8– Operadores lógicos Operador Ação && AND (E) || OR (OU) ! NOT (NÃO) Aplicando os operadores relacionais e lógicos podemos realizar diversos testes. O programa a seguir ilustra o funcionamento dos operadores lógicos. No trecho de programa a seguir a operação j++ será executada, pois o resultado da expressão lógica é verdadeiro: int i = 5, j =7; if ( (i > 3) && ( j <= 7) && ( i != j) ) j++; Avaliando a expressão V AND V AND V = V Quando montamos expressões temos que levar em consideração a ordem com que os operadores são executados, conforme a tabela de precedências (Tabela 6.9) da linguagem C. Tabela 6.9 – Precedência de operações Maior precedência () [ ] ! ~ ++ -- . -(unário) (cast) *(unário) &(unário) sizeof * / % + - << >> <<= >>= == != & ^ | && || ? = += -= *= /= Menor precedência , Durante a programação caso haja dúvida na precedência dos operandos basta separar as expressões por parênteses. Exemplos de expressões: c= a * b + d/e; c= a * (b+d)/e; CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 30 de 52 Atividade 6.3 ESTRUTURAS DE CONTROLE 1 – Na atividade 6.2.2 você utilizou uma das três estruturas de repetição para criação da função ímpares. Codifique duas novas funções ímpares utilizando as estruturas NÃO aplicadas no exemplo anterior. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 31 de 52 OBJETIVOS Tratar entrada digital. Estudar as estruturas de tomada de decisão. 6.4. Estruturas de tomada de decisão Na unidade 5.9, para que o usuário pudesse visualizar a sequência de Fibonacci, foram configurados os dispositivos de I/O do MSP, em específico, as portas P1 e P2. Entretanto, neste programa só foram realizadas operações de saída, sendo assim os pinos da porta foram configurados exclusivamente para saída de dados, por meio dos registros P1DIR e P2DIR. Na Figura 6.8 é apresentada uma outra configuração de hardware, onde um dispositivo de entrada (chave), encontra-se conectado ao MSP. Figura 6.8 – Diagrama de hardware com entrada de dados Devido a versatilidade dos MCUs os pinos das portas P1 e P2 também podem ser configurados como entrada de dados e por meio das entradas de dados é que um sistema microprocessado poderá realizar as tomadas de decisão. Um caso típico de aplicação seria o monitoramento do estado de uma chave conforme fluxograma da Figura 6.9. Figura 6.9 – Fluxograma para monitoração do estado de uma chave. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 32 de 52 A codificação a seguir descreve o comportamento do fluxograma da Figura 6.8. P1DIR |=0X01; //Configura P1.0 como saída P2DIR &=0XFE; //Configura P2.0 como entrada while(1) { if (P2IN&0x01) P1OUT|=0X01; else P1OUT&=0XFE; } Neste código, foi utilizada a estrutura condicional para selecionar qual ação será executada caso uma determinada condição seja satisfeita. São duas estruturas condicionais utilizadas na linguagem C: if seguido ou não do else e o switch. No comando if a expressão presente na condição será avaliada, caso seja verdadeira será então executada a ação associada à expressão if, caso contrário uma segunda ação, presente após o else será executada. Não existe a obrigatoriedade de associar um else a estrutura if, ou seja, o else é opcional. É possível aninhar uma nova condição a negação, permitindo que a negação só seja executada caso sua condição seja atendida. Este conceito permite que sejam vários níveis de teste utilizando a estrutura if - else if. if (condição_1) declaração_1; else if (condição_2) declaração_2; else if (condição_3) declaração_3; . . . else if (condição_n) declaração_n; else declaração_default; Com a estrutura else if caso a condição_2 seja verdadeira as próximas linhas de programa serão ignoradas. O mesmo não acontece com a estrutura com várias estruturas if – else, dispostas sequencialmente, pois todos as demais condições serão avaliadas independentemente do estado verdadeiro para a condição_2. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 33 de 52 Atividade 6.4 ESTRUTURA DE CONTROLE IF 1 – Conecte o led L0 (Figura 6.10) ao pino P1.0 e a chave CH0 (Figura 6.10) ao pino P2.0 Figura 6.10 – Conexões de Chaves e Leds do Kit didático do Laboratório de SD II 2 – Qual é o papel do resistor R4? 3 – Qual o papel do resistor R8? 4- Carregue o projeto LigDesligLed no IAR. 5 – Rode o programa e verifique se ocorreu o proposto no fluxograma da Figura 6.8. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 34 de 52 6 – Baseado no digrama da Figura 6.11, escreva o algoritmo de um circuito sequencial com um par de LEDs e codifique um novo programa que atenda as seguintes condições: CH2 CH1 Operação OFF OFF L1 e L2 apagados OFF ON L1 e L2 piscando juntos ON OFF L1 e L2 piscando alternados ON ON L1 piscando no dobro da frequência de L2 Figura 6.11 – Diagrama de hardware CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 35 de 52 Uma estrutura condicional alternativa e mais eficiente ao if - else if com várias condições de teste é o switch. Lembre-se que no if - else if caso a opção selecionada não seja a primeira, será testada sequencialmente cada uma delas até que seja encontrada a verdadeira ou que a opção default seja assumida. Na estrutura switch o programa assumirá a opção selecionada sem que seja necessário o teste de cada uma das opções. switch (variável) { case constante_1: declaração_1; break; case constante_2: declaração_2; break; . . . case constante_n: declaração_n; break; default declaração_default; } É importante observar que a estrutura switch não aceita expressões. O switch testa se uma determinada variável corresponde a uma das constantes especificadas no case e executa a respectiva declaração. A declaração default é opcional e será executada apenas se a variável, que está sendo testada, não for igual a nenhuma das constantes. O comando break faz com que o switch seja interrompido assim que uma das declarações seja executada. A omissão do break fará que os demais comandos após a opção selecionada também sejam executados. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 36 de 52 Atividade 6.5 ESTRUTURA DE CONTROLE SWITCH 1 – Crie um novo projeto baseado nas especificações do item 6, da atividade 6.4, e reescreva o código do programa baseado na estrutura de tomada de decisão múltipla switch. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 37 de 52 OBJETIVOS Configurar resistor de pull up/down interno. 6.5. Resistores de pull up e pull down internos do MSP Como estudado na aula anterior as entradas do MCU são importantes no processo de tomada de decisão do sistema, mas para seu funcionamentoadequado é importante definir o estado de uma entrada evitando que a mesma fique flutuando. A solução adotada foi a inserção de resistores de pull up/down. Pensando neste problema, as empresas que projetam MCUs já disponibilizam internamente tal recurso, evitando assim a necessidade de inserir resistores na placa e por consequência reduzindo e trabalho no projeto do hardware. Entretanto, esta tarefa é transferida para o software. Ou seja, caso seja necessário a utilização de resistor de pull up ou pull down no projeto, ele deverá ser configurado via programação. No MSP utilizamos dois registradores para execução desta configuração: PXREN e PXOUT. Para avaliar o papel destes registradores observe o diagrama da Figura 6.12. Cada pino da porta 1 pode ter ou não o resistor de pull up/down configurado individualmente. Figura 6.12 – Diagrama das portas do MSP430G2553 Observe que estando o pino n (um bit 0 a 7) configurado como entrada (P1DIR), teremos nível lógico baixo na entrada da porta AND que em conjunto com o respectivo bit do registro P1REN irá habilitar a conexão do resistor de pull up/down fechando a chave que insere o resistor na malha do respectivo pino. Entretanto, somente esta habilitação não determina se é um resistor de pull up ou down. Sendo assim, o respectivo bit do registro P1OUT, que está inoperante, pois o pino está configurado como saída será utilizado para determinar a seleção do mutiplexador para VSS(0) ou VDD(1). Resumo dos registros envolvidos na configuração do resistor pull up/down interno do MSP430G2553. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 38 de 52 1. Registro de Habilitação de Resistor BIT = 0 Resistor de PullUp/Down desabilitado BIT = 1 Resistor de PullUp/Down habilitado 2. Resistor de saída BIT = 0 Resistor ligado ao terra – Resistor de PullDown BIT = 1 Resistor ligado ao Vcc - Resistor de PullUp Observe que o registro de saída PNOUT tem duas aplicações: 1. Quando o terminal está programado como saída: armazenar o dado do respectivo terminal que será enviado para o dispositivo externo durante a execução do programa. 2. Quando o terminal está programado como entrada: Permite configurar o resistor de Pull Up/Down juntamente com o registro PNREN. Uma vez que o registro PNDIR está configurado como entrada, o registro PNOUT assumirá sua função auxiliar que é determinar a ligação do resistor interno. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 39 de 52 Atividade 6.6 RESISTORES DE PULL UP/DOWN 1 – Conecte o led L0 (Figura 6.10) ao pino P1.0 e utilize a chave push bottom do launch pad conectada ao pino P1.3 (Figura 6.13) para implementar o fluxograma da Figura 6.9. 2 - Desenhe o diagrama elétrico do circuito proposto no item 1. 3 - Configure de forma adequada o resistor do pino P1.3, respeitando a conexão da chave presente na placa. Figura 6.13 – Diagrama elétrico do launch pad MSP430G CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 40 de 52 OBJETIVOS Monitorar entrada por espera ocupada Tratar repique de chave. 6.6. Repique de chave (bounce) O fluxograma da Figuras 6.9 descreve o procedimento de monitoração de chave denominado espera ocupada. O nome desta técnica indica que a CPU estará monitorando continuamente o estado da chave para tomar a decisão de qual tarefa será executada. Este mesmo procedimento pode ser adotado na monitoração das chaves da Figura 6.11. Embora esta técnica seja de construção simples ela demanda uma dedicação intensa da CPU no monitoramento das chaves. Em um momento mais a frente estudaremos uma técnica mais eficiente para tal procedimento. Algo em comum nos dois exemplos acima foi a aplicação das chaves mecânicas que são frequentemente utilizadas para geração de sinal de entrada em nossas montagens. Dentre as chaves utilizadas, destacam-se as chaves push bottom (Figura 6.14a) e a alavanca (Figura 6.14b). Figura 6.14 – Chaves mecânicas (a) Push bottom (b) Alavanca Estas chaves apresentam um comportamento característico denominado trepidação ou repique que podem gerar diversos pulsos a cada acionamento da chave. O repique da chave da Figura 6.15a pode ser observado na Figura 6.15b. Figura 6.15 – Repique ou trepidação (bounce) (a) Circuito (b) Sinal quando a chave é pressionada Este problema pode ser tratado por hardware (Figura 6.16) ou por software. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 41 de 52 Figura 6.16 – Debounce (a) Circuito (b) Sinal quando a chave é pressionada Antes de avaliarmos o tratamento por software, vamos observar a ocorrência da trepidação, utilizando o fluxograma da Figura 6.17, para construção do detector de trepidação. Figura 6.17 – Fluxograma para avaliação do repique de chave. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 42 de 52 Atividade 6.7 IDENTIFICAÇÃO DO REPIQUE DE CHAVE (BOUNCE) 1 – Conecte o led L0 (Figura 6.10) ao pino P1.0 e utilize a chave push bottom do launch pad conectada ao pino P1.3 (Figura 6.13) para implementar o fluxograma da Figura 6.9. 2 - Desenhe o diagrama elétrico do circuito proposto no item 1. 3 - Configure de forma adequada o resistor do pino P1.3, respeitando a conexão da chave presente na placa. 4 - Monte um novo projeto, carregue o programa a seguir que é baseado no fluxograma da Figura 6.17. P1DIR |= 0x01; // programar P1.0 como saída P1DIR &= 0xF7; // programar P1.3 como entrada P1REN |= 0x08; // habilita resistor interno P1OUT |= 0x08; // define com pullup long unsigned cont=0; // zera contador for (;;) { P1OUT |= 0x01; // Liga LED while (P1IN & 0x08); // Espera pressionar o chave cont++; // Incrementa contador P1OUT &= 0xFE; // Desliga LED while (!(P1IN & 0X08)); // Espera soltar chave } 5 - Rode o programa, pressione algumas vezes a chave push bottom da porta P1.3 e pare a execução do programa. Verifique se o conteúdo da variável “cont” corresponde ao número de vezes que a chave foi pressionada. Para verificar seu conteúdo posicione o cursor sobre a variável, clique com o botão direito do mouse e selecione a opção “Add to Watch”. Anote o valor da variável cont. 6 – Conecte uma chave alavanca do kit na porta 1.3. Posicione a chave garantido o estado aberto (LED LIGADO). Rode o programa, troque o estado da chave algumas vezes e verifique se a contagem corresponde ao número de vezes que a chave alavanca teve o seu estado alterado. 7 - Proponha e implemente a solução para o problema encontrado. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 43 de 52 OBJETIVOS Definir uma matriz. Iniciar elementos de uma matriz. Passar matriz como parâmetro. 6.7. Matriz Matriz é uma variável composta e homogênea disposta através de uma estrutura de índice. O que seria uma variável composta? É uma variável que armazena um conjunto de valores, diferentemente de uma variável simples do tipo int ou char,onde só é possível armazenar apenas um valor inteiro ou um caractere respectivamente. O que seria uma variável composta homogênia? É aquele variável é possível guardar várias informações, entretanto as informações têm que ser do mesmo tipo. Sendo assim ao criar uma matriz do tipo int, ela só poderá armazenar valores do respectivo tipo. O mesmo vale para os demais tipos. Por fim o que seria uma estrutura de índice? Considerando que em uma matriz é possível armazenar várias informações, necessitaremos de uma estrutura que torne possível o acesso individual de cada informação. Para que possamos escrever ou ler uma informação da matriz, teremos que executar operações a partir de seus índices. Baseado em suas definições o que uma matriz contribuiria para uma aplicação no contexto de sistemas microcontrolados? Vamos partir de uma aplicação básica neste contexto. Suponha que seja necessário a indicação do resultado de um processamento por meio de um display de 7 segmentos. Antes de analisarmos a atuação da matriz é necessário apresentar o hardware da aplicação (Figura 6.18). Figura 6.18 – Dispositivos envolvido na aplicação de acionamento do display de 7 segmentos Também se faz necessário definirmos as conexões entre o MCU e o display assim como a lógica de acionamento: direta (Figura 6.19A) ou reversa (Figura 6.19B). Figura 6.19 – Acionamento com Lógica Direta (A) e Reversa (B) (A) (B) CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 44 de 52 O acionamento com lógica direta ou reversa conforme a Figura 6.19 define se o segmento será acionado com nível lógico alto ou baixo. Entretanto é necessário considerar a corrente máxima que o MCU poderá fornecer ou drenar. No caso do MSP430G2553 este valor é de ± 48 mA o que limita o brilho dos segmentos quando acionados simultaneamente em 48 / 7 em 6,9 mA, considerando que nenhum outro terminal do MCU esteja conectado a outros dispositivos. Outro aspecto a considerar é que cada pino individualmente do MSP430 só pode fornecer ou drenar 6 mA. Como alternativa as limitações de corrente impostas pelo MSP430 é possível a introdução de um circuito (driver) que evitaria tal situação (Erro! Fonte de referência não encontrada.). Neste caso a corrente de acionamento do segmento seria fornecida pela própria fonte. Figura 6.20 – Acionamento direto com a utilização de um driver Voltando ao contexto da programação, independentemente da utilização ou não do driver o software seria mesmo. Desta forma, para continuar nossa análise vamos adotar as conexões da Figura 6.20, onde cada segmento do display (catódo comum) está associado a um terminal da porta 2 do MSP430G2553. Figura 6.20 – Conexões dos segmentos do display a porta P2 do MSP430G2335 Neste caso, para acionar o dígito 0 seria necessário colocar nível lógico alto nos pinos 0, 1, 2, 3, 4 e 5. Traduzindo em uma linha de código em C: P2OUT=0X3F; A codificação do dígito zero (0X3F) foi gerada a partir da combinação definida na Tabela 6.2: CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 45 de 52 Tabela 6.2 – Combinações para o acionamento dos dígitos Dígito Bits Código 0 0,1,2,3,4 e 5 0X3F 1 1 e 2 0X06 2 0,1,2,3,4 e 6 0X5F 3 0,1,2,3 e 6 0X4F 4 1,2,5 e 6 0X66 5 0,2,3,5 e 6 0X6D 6 2,3,4,5 e 6 0X7C 7 0,1 e 2 0X07 8 0,1,2,3,4,5 e 6 0X7F 9 0,1,2,3,5 e 6 0X6F Suponha que fosse necessário fazer um programa para enviar ciclicamente a sequência de 0 a 9 para o display conectado a porta 2 do MSP. O caminho mais simples seria definir 10 variáveis ou constantes e enviar para o display (Figura 6.21). Figura 6.21 – Programa principal e função para envio de caracteres para o display Utilizando uma matriz unidimensional o algoritmo da função ficaria bem mais simples (Figura 6.21). CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 46 de 52 Figura 6.21 – Função Mostra Seq utilizando o conceito de vetor Nesse caso, o armazenamento dos códigos enviados para o display pode ser feito pela seguinte linha de programa: // 0 1 2 3 4 5 6 7 8 9 unsigned char codigos[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; Para tornar mais claro a compreensão da estrutura de uma matriz vamos apresentar um exemplo. Suponha que façamos a seguinte definição: int numeros[4]; Esta definição garante que a partir da posição de memória atribuída para o rótulo numeros serão armazenadas quatro células de memórias contíguas, onde cada célula de memória poderá receber um valor do tipo inteiro. Para carregar valores nesta variável no momento da sua definição, basta alterar um pouco o exemplo anterior para: int numeros[4]={7,21,13,42}; Baseado neste exemplo podemos agora associar ao diagrama da Figura 6.22. Figura 6.22 – Estrutura de uma matriz 0 321 7 421321 Índice Conteúdo O número “7” está armazenado na primeira posição de memória da matriz. Na verdade o índice indica em que posição da matriz encontra-se cada número. Observe que embora a matriz tenha sido definida para 4 posições, não existe o índice 4, pois o primeiro índice da matriz é definido como 0. Devemos então respeitar as quatro propriedades básicas da matriz: 1. Os itens de dados individuais na matriz são chamados de elementos; 2. Todos os elementos devem ser do mesmo tipo de dado; 3. Todos os elementos são armazenados contiguamente na memória e o índice do primeiro elemento é zero; 4. O nome da matriz é um valor constante que representa o endereço do primeiro elemento. CENTRO FEDERAL DE EDUCAÇÃO TECNOLÓGICA DE MINAS GERAIS Departamento de Eletrônica e Biomédica Curso Técnico de Eletrônica Sistemas Digitais II Versão 1-2018 Página 47 de 52 As matrizes podem ser classificadas de duas formas distintas: unidimensional ou multidimensional. Embora as matrizes possam assumir dimensões maiores, só trataremos das matrizes unidimensionais. A matriz unidimensional já foi apresentada no exemplo anterior. Todas as propriedades estudadas anteriormente se aplicam a matriz unidimensional. É mais comumente chamada de vetor. Embora conhecidas às propriedades de uma matriz, o importante é saber quando utilizar uma matriz unidimensional? Vamos imaginar que você esteja desenvolvendo um sistema para controle de público em um estádio de futebol. Supondo que o estádio possua um total de 50 roletas, teremos que armazenar o público de cada roleta, ou seja, uma variável por roleta e uma variável para armazenar o público total. Como definir tais variávies? unsigned int publico; int rol1; int rol2; int rol3; Que dureza escrever até a roleta 50 !!! Vamos então utilizar um recurso para facilitar nosso trabalho. int ro1, rol2, rol3, rol4, rol5, ... Notícia ruim!!! O compilador não aceita reticências. Então vamos invocar a estrutura de dados matriz para tornar nossa vida mais doce. int rol[50]; Que tal, agora está bom? Entendeu em que situação utilizar uma matriz? Observe o que significa o conceito de dados homogêneos. Todas as roletas são do tipo inteiro, então basta definir um rótulo para todos os elementos e utilizar uma matriz. 6.7.1 Definição de uma matriz Para definir uma matriz basta definir o tipo de dados que a mesma irá armazenar e seu respectivo rótulo. char matUm[5]; int matDois[7]; float matTres[6]; Embora as definições feitas estejam sintaticamente corretas é conveniente em toda definição do número de elementos da matriz associar um rótulo e não apenas colocar um número, pois isto é extremamente útil na manipulação dos conteúdos da
Compartilhar