Curso de C com microcontroladores MCF51QE128 e MC9S08QE128 – Parte 5

Curso de C com microcontroladores

Funções na Linguagem C

Forma geral

As funções em linguagem C podem ser encaradas como algo similar as sub-rotinas em programas escritos em Assembly, guardadas as suas devidas proporções. Sua forma geral, descrita pelo padrão ANSI C, é mostrada a seguir:

Onde:

Tipo da função: especifica o tipo de dado (int, char, float, doble, etc.) que a função irá devolver para o local de onde ela foi chamada.
Nome_da_função: identificador a ser utilizado para referenciar aquela função. Ela passará a ser reconhecida pelo resto do programa por este nome.
Parâmetros: são utilizados para a passagem de valores para que a função possa utilizá-los e efetuar os procedimentos para o qual foi escrita.

Funções do tipo Void

Um dos usos de void é declarar explicitamente funções que não devolvem valores. Isso evita seu uso em expressões e ajuda a afastar um mau uso acidental. Antes de poder usar qualquer função como void, você deve declarar seu protótipo. Se isto não for feito, o C assumirá que ela devolve um valor inteiro e, quando o compilador encontrar de fato a função, ela declarará um erro de incompatibilidade.

O comando return

O comando return tem dois importantes usos. Primeiro, ele provoca uma saída imediata da função que o contém. Isto é, faz com que a execução do programa retorne ao código que o chamou. Se o comando return for executado na função main, então o programa será encerrado.

Segundo, ele pode ser utilizado para devolver um valor a função que o chamou.

Protótipos de função

Em programas profissionais, muito extensos, com diversas funções, pode acontecer de determinada função ser chamada e ainda não ter sido definida. Isto irá gerar um erro no compilador.

Para evitar que isto ocorra, utiliza-se o protótipo da função, que será uma declaração prévia com o intuito de informar ao compilador que mais adiante no programa esta função será definida.

Para isto basta colocar a primeira linha da função, que contem os dados do tipo da função, do nome da função e os parâmetros da função, como pode ser visto abaixo:

Passagem de parâmetros

Fixo (por valor)

Exatamente como vem sendo executado até agora nos programas exemplos.

EXEMPLO 17: Passagem de parâmetros entre funções

Veja no EXEMPLO 17 como é feita a passagem de parâmetros entre diversas funções de um mesmo programa. Além disto, neste exemplo a saída da função SOMA é feita através do parâmetro RETURN.

Para ver os efeitos da execução deste programa, quando o simulador estiver rodando clique em COMPONENT Æ OPEN, e selecione o item TERMINAL IO, como mostrado a seguir:

MCF51QE128-parte-5-01
MCF51QE128-parte-5-02

Após a execução do programa, você deve ter a seguinte tela no TERMINAL IO:

MCF51QE128-parte-5-04

EXEMPLO 18: Passagem de parâmetros entre funções

MCF51QE128-parte-5-05

Após a execução deste programa, deve-se visualizar a seguinte imagem no TERMINAL IO:

MCF51QE128-parte-5-06

Variável (por referência)

Utilizando ponteiros. Estudaremos este tipo de passagem quando vermos o mecanismos de funcionamento dos ponteiros.

Funções recursivas

Um dos recursos sempre lembrados em qualquer estudo sobre linguagem C é que esta linguagem permite a existência de funções recursivas. Uma função é dita recursiva se um comando no corpo da função chamar a si própria.

EXEMPLO 19: Calculo de fatorial com função recursiva

Veja a seguinte função, utilizada no EXEMPLO 19:

MCF51QE128-parte-5-07

Note que para calcular a resposta, a função chama a si mesma! O programa completo pode ser visto na próxima página.

MCF51QE128-parte-5-08

Ao executar este programa, tem-se a seguinte sequência de mensagens no TERMINAL IO:

MCF51QE128-parte-5-09

Para entender completamente o que está acontecendo, observe a sequência de ações que o software tomará se o número que foi gerado é o 4:

MCF51QE128-parte-5-10

Perceba que para número = 4, a função fatorial foi aberta 5 vezes!!!!

Tipos de dados avançados

Ponteiros

Ponteiros são um dos recursos mais poderosos da linguagem C. Qualquer programa de utilidade prática escrito em C dificilmente dispensará o uso de ponteiros. A tentativa de evitá- los implicará quase sempre códigos maiores e de execução mais lenta.

Para quem está começando, pode parecer (e algumas vezes é) um tanto difícil. Mas não há outro caminho senão enfrentar a realidade. São muitas as aplicações de ponteiros. A seguir, relação das mais comuns.

  • Acessar endereços de memória que o programa aloca em tempo de execução.
  • Acessar variáveis que não são visíveis em uma função.
  • Manipulação de arrays.
  • Manipulação de strings.
  • Passar o endereço de uma função para outra.
  • Retornar mais de um valor para uma função.

EXEMPLO 20: Endereços e dados com ponteiros

Genericamente, um ponteiro é uma variável utilizada para guardar o endereço de outra variável, ou seja, um ponteiro é um apontador de outra variável. Veja como este conceito é abordado no programa EXEMPLO 20:

MCF51QE128-parte-5-11

Ao executar este programa, deve ter as seguintes mensagens no TERMINALO IO:

MCF51QE128-parte-5-12

EXEMPLO 21: Endereços e dados com ponteiros

É interessante notar como os comandos * e & são tratados e que resultados trazem da manipulação dos ponteiros. Veja no EXEMPLO 21 como eles se comportam.

Ao executar o programa, as seguintes mensagens aparecerão no TERMINAL IO:

EXEMPLO 22: Endereços e dados com ponteiros

É possível fazer a manipulação de dados e de endereços através dos ponteiros, como pode ser visto no EXEMPLO 22:

EXEMPLO 23: Mudança de parâmetros de funções por ponteiros

É possível também que outras funções façam a manipulação dos dados e dos endereços tratados por ponteiros, como mostra o EXEMPLO 23:

Note que são chamadas as funções valor(nr) e ponteiro(prt_nr), mostradas na janela a seguir:

Ao executar o programa, serão mostradas as seguintes mensagens na tela do TERMINAL IO:

EXEMPLO 24: Aritmética com ponteiros

Outra aplicação muito útil é a aritmética com ponteiros. Com isto pode-se percorrer uma tabela de dados, incrementando ou decrementando os endereços da mesma, por exemplo.

Uma maneira de manipular aritmeticamente os ponteiros é mostrada no EXEMPLO 24:

Perceba que os conceitos explorados neste exemplo podem ser melhor compreendidos observando a figura abaixo:

MCF51QE128-parte-5-23

EXEMPLO 25: Ponteiros para ponteiros

Outra utilização excelente dos ponteiros é o caso de ponteiros para ponteiros, como mostrado no EXEMPLO 25, que quando for executado gerará as seguintes mensagens no TERMINAL IO:

O que parece ser apenas algumas palavras impressas no TERMINAL IO, na verdade foi montado como um conjunto de matrizes lineares, através do código mostrado na próxima página.

Matrizes de dados

Uma matriz é uma estrutura de dados que pode armazenar vários valores do mesmo tipo. A sintaxe para declarar uma matriz é:

Onde:

  • TIPO: é o tipo dos dados que serão armazenados na matriz. Todos os dados colocados na matriz devem ser deste tipo.
  • NOME: é o nome a ser dado a matriz. Este nome identificará a matriz no código do programa.
  • QUANTIDADE: é a quantidade máxima de itens a ser armazenados.

Exemplo:

Os valores armazenados na matriz são chamados de "elementos da matriz". O primeiro elemento da matriz é indexado como item zero e o último é indexado como QUANTIDADE menos 1. Assim, para nossa matriz nota, mostrada no exemplo acima, o primeiro elemento é nota[0] e o último elemento é nota[29]. Você pode inicializar os elementos de uma matriz na sua declaração usando a sintaxe:

Em muitas literaturas sobre a linguagem C, considera-se uma matriz de apenas uma linha como sendo um VETOR.

EXEMPLO 26: Como se comportam os elementos de uma matriz

EXEMPLO 27: Modos de manipulação de elementos de uma matriz

Praticamente o mesmo efeito obtido pelo exemplo anterior pode ser obtido de modo muito mais eficiente pelo próximo programa EXEMPLO-27:

Ao executar o programa, serão mostradas as seguintes mensagens no TERMINAL IO:

EXEMPLO 28: Modos de manipulação de elementos de uma matriz – Strings são matrizes lineares

Uma STRING (conjunto de caracteres) na verdade é uma matriz, como pode ser percebido através do programa EXEMPLO 28.

EXEMPLO 29: Modos de manipulação de elementos de uma matriz

A manipulação dos elementos de uma matriz pode acontecer por outra função, como mostrado no EXEMPLO 29.

O TERMINAL IO mostrará as seguintes informação:

Matrizes bi dimensionais

magine uma matriz bidimensional como uma tabela de linhas e colunas. Por exemplo, a matriz:

Ela pode ser imaginada como o seguinte arranjo de linhas e colunas, formando células:

Observe que o primeiro índice ([3]) indica as linhas da matriz e o segundo ([5]) indica as colunas. Como sabemos que [3] varia de zero a 2 e [5] varia de zero a 4, fica fácil determinar os índices de cada posição da matriz:

Visto a posição de cada índice vamos preencher nossa matriz pesos com valores:

De tudo que foi exposto acima podemos entender que:

Para preencher nossa matriz com os valores mostrados na tabela acima podemos usar uma declaração como:

EXEMPLO 30: Manipulação de matrizes bidimensionais

Podemos manipular os elementos de nossa matriz bidimensional usando duas variáveis e um laço for da mesma maneira que fizemos com as matrizes comuns. Observe o código do programa (EXEMPLO 30):

EXEMPLO 31: Passando uma matriz bi dimensional para uma função

Uma função que manipula uma matriz bidimensional deve receber a matriz e o número de linhas desta matriz. O número de colunas da matriz também deve estar especificado nesta declaração. Ao chamar a função, deve-se passar a matriz e o número de linhas. Como isto funciona? Veja o programa EXEMPLO 31:

Ao executar o programa, o TERMINAL IO apresentará os seguintes resultados:

Estrutura de dados

As estruturas são utilizadas para agrupar informações relacionadas de tipos de dados diferentes. Digamos que você precisa controlar os seguintes dados relacionados ao estoque de um pequeno estabelecimento comercial:

  • código
  • nome do produto
  • quantidade estocada
  • valor de compra
  • valor a ser vendido
  • lucro
  • observacões sobre o produto

Este seria um caso para o uso de estruturas, pois relacionados a cada produto teremos dados do tipo int(código,quantidade), char(nome, observações) e float(valor de compra, valor de venda, lucro).

A sintaxe para a declaração (ou criação) de uma estrutura é:

Para o caso exemplificado no item anterior poderíamos ter algo como:

É importante observar que a declaração da estrutura não cria, ainda, uma variável. A declaração da estrutura apenas cria um novo tipo de dado. Após criar a estrutura você pode declarar variáveis do tipo de estrutura criado.

Declarando variáveis do tipo de uma estrutura criada

Após a declaração da estrutura você pode declarar variáveis do tipo da estrutura com a sintaxe:

Observe que esta sintaxe obedece a sintaxe normal para a declaração de variáveis:

Sendo que o TIPO da variável, a nova estrutura criada. Você também pode declarar a variável logo após a declaração da estrutura com uma sintaxe do tipo:

EXEMPLO 32: Acessando os campos de uma estrutura

A sintaxe para acessar e manipular campos de estruturas é a seguinte:

Observe o código do programa EXEMPLO 32, mostrado a seguir, para um melhor esclarecimento:

As funções preenche( ) e exibe ( ) trabalham com a struct, como pode ser visto abaixo:

Ao executar o programa, o resultado a ser mostrado no TERMINAL IO é:

Uniões

Em C uma union é uma posição de memória que é compartilhada por duas ou mais variáveis diferentes, geralmente de tipo de diferentes, em momentos diferentes. A definição de uma union é semelhante à definição de estrutura. Sua forma geral é:

Exemplo:

EXERCÍCIOS: Tipos de dados avançados

Identifique no diagrama elétrico da DEMOQE128, mostrado no item 7, as seguintes conexões, envolvendo pinos dos MCUs MC9S08QE128 e MCF51QE128 e seus respectivos hardwares externos

EXERCÍCIO 18: Armazenamento e tratamento de dados

Escreva um programa que gere de modo randômico 20 números. Estes números devem ser armazenados na memória RAM do microcontrolador.

Após a geração dos números, os quatro LEDS PTC2, PTC3, PTC4 e PTC5 devem ficar acesos e a DEMOQE deve aguardar enquanto o usuário não pressionar o botão PTD3.

Após o usuário pressionar o botão PTD3, os quatro LEDS PTC2, PTC3, PTC4 e PTC5 se apagam e os quatro LEDS PTC0, PTC1, PTE6 e PTE7 se acendem. Além disto deve ser mostrada no Terminal IO a seguinte mensagem:

“O menor número gerado foi XX!”

Onde XX é o menor número dentre todos os números randômicos que foram gerados.

Após a mensagem ter sido mostrada no Terminal IO, os quatro LEDS PTC0, PTC1, PTE6 e
PTE7 se apagam, os quatro LEDS PTC2, PTC3, PTC4 e PTC5 se acendem e a DEMOQE deve aguardar enquanto o usuário não pressionar o botão PTD3.

Após o usuário pressionar o botão PTD3, os quatro LEDS PTC2, PTC3, PTC4 e PTC5 se apagam e os quatro LEDS PTC0, PTC1, PTE6 e PTE7 se acendem. Além disto deve ser mostrada no Terminal IO a seguinte mensagem:

“O maior número gerado foi YY!”

Onde YY é o maior número dentre todos os números randômicos que foram gerados.

Após a mensagem ter sido mostrada no Terminal IO, todos os LEDS se apagam e o programa deve retornar ao seu início, gerando novamente outros 20 números aleatórios e executando novamente a sequência de mensagens descritas anteriormente.

Outros artigos da série

<< Curso de C com microcontroladores MCF51QE128 e MC9S08QE128 - Parte 4Curso de C com microcontroladores MCF51QE128 e MC9S08QE128 - Parte 6 >>
Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Software » Curso de C com microcontroladores MCF51QE128 e MC9S08QE128 - Parte 5
Comentários:
Notificações
Notificar
guest
0 Comentários
Inline Feedbacks
View all comments
Talvez você goste:

Séries



Outros da Série

Menu

WEBINAR
 

Soluções inteligentes para acionamento de MOSFETs/IGBTs com família STDRIVE

Data: 08/10 às 15:00h - Apoio: STMicroelectronics
 
INSCREVA-SE AGORA »



 
close-link