
Passo 1 de 7
Definir e chamar uma função própria
Defina uma função void com parâmetro inteiro e diferencie sua definição de uma chamada.
Trilha de aprendizado · Nível 9 · Tutorial 8
Organize operações repetidas em funções próprias com parâmetros e retorno, acompanhando a passagem de valores e a continuação da execução.
Definir e chamar uma função própria
Defina uma função void com parâmetro inteiro e diferencie sua definição de uma chamada. 3 min
Entender argumentos e passagem por valor
Acompanhe argumentos, parâmetros e variáveis locais para prever o que muda em cada chamada. 3 min
Devolver um resultado e continuar a execução
Use o tipo de retorno e <code>return</code> para produzir um valor que o programa chamador pode atribuir ou testar em uma condição. 3 min
Garantir retorno em todos os caminhos
Identifique caminhos sem retorno em uma função que limita valores de 0 a 3 e complete o resultado exigido. 3 min
Declarar a função antes de usá-la
Organize uma função definida depois de sua chamada usando um protótipo explícito compatível. 2 min
Separar o cálculo da ação no LED
Divida uma tarefa entre uma função que calcula um resultado e outra que usa esse resultado para controlar o LED integrado. 3 min
Aplicar e conferir uma sequência de chamadas
Complete, rastreie e teste um sketch que limita pedidos de piscadas e usa o resultado no LED integrado. 5 min

Passo 1 de 7
Defina uma função void com parâmetro inteiro e diferencie sua definição de uma chamada.
Uma função própria é um bloco nomeado para uma tarefa específica. Você a define uma vez e pode chamá-la nos pontos em que a tarefa for necessária.
Neste exemplo, piscarLed recebe uma quantidade inteira e faz o LED integrado piscar essa quantidade de vezes. Como a tarefa comanda o LED, mas não entrega um resultado ao trecho que a chamou, seu tipo de retorno é void.
A definição fica fora de setup() e loop() e, por enquanto, antes do primeiro uso dela.

A chamada pede a execução; a função contém os comandos da tarefa.
A primeira linha da definição é o cabeçalho:
void piscarLed(int quantidade)
void: a função não devolve valor.piscarLed: nome escolhido para a função.int quantidade: parâmetro; ele informa que a função recebe um inteiro.As chaves delimitam o corpo. Dentro dele, o for repete os comandos de acender, esperar, apagar e esperar. Esses comandos só serão executados quando houver uma chamada para piscarLed.
Definição de uma função antes de setup().
void piscarLed(int quantidade) {
for (int contador = 0; contador < quantidade; contador++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
piscarLed(2);
delay(1000);
}Em loop(), a instrução piscarLed(2); é a chamada. O valor 2 está entre parênteses porque a função foi definida com um parâmetro inteiro.
A execução chega à chamada, entra no corpo de piscarLed, realiza duas piscadas e então retorna ao ponto seguinte de loop(): delay(1000).
Sem a chamada, escrever apenas a definição não faz o LED piscar.

A chamada transfere temporariamente a execução para o corpo da função; ao final, o programa continua depois da chamada.
Complete o tipo de retorno, o tipo do parâmetro e a chamada que solicita três piscadas.
piscarLed( quantidade) {
for (int contador = 0; contador < quantidade; contador++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
}
void loop() {
}
Passo 2 de 7
Acompanhe argumentos, parâmetros e variáveis locais para prever o que muda em cada chamada.
Quando você chama uma função, os valores entre parênteses são os argumentos. Na definição, as variáveis que recebem esses valores são os parâmetros.
Na chamada piscar(3, 200), os argumentos são 3 e 200. No cabeçalho void piscar(int vezes, int pausaMs), vezes e pausaMs são parâmetros.
A associação ocorre pela posição: o primeiro argumento vai para o primeiro parâmetro, e assim por diante. A quantidade deve corresponder, e os valores precisam ser compatíveis com os tipos esperados. Os nomes podem ser completamente diferentes.

Os nomes podem mudar; a posição e os tipos orientam a ligação.
Para valores escalares, como int, a função recebe uma cópia do argumento. Portanto, alterar um parâmetro altera somente a cópia local daquela chamada.
Observe: quantidade vale 2 antes da chamada. Dentro de ajustar, o parâmetro valor começa com uma cópia desse 2 e é alterado para 3. Ao voltar para setup, quantidade continua valendo 2.
Não confunda a mudança do parâmetro com uma mudança na variável usada no argumento.
A função recebe uma cópia de quantidade.
void ajustar(int valor) {
valor = valor + 1;
}
void setup() {
int quantidade = 2;
ajustar(quantidade);
// quantidade ainda vale 2
}
void loop() {
}Dica
Pense em duas caixas: a caixa quantidade pertence a setup; a caixa valor é criada para a chamada de ajustar. Elas começam com o mesmo número, mas são caixas diferentes.
Cada chamada cria seus próprios parâmetros e variáveis locais automáticas. Eles não guardam, por conta própria, o valor da chamada anterior.
No exemplo, contadorLocal é inicializado com 0 toda vez que marcar começa. Em cada chamada, ele passa a valer 1 e a função termina. A variável solicitado, no chamador, não é modificada.
Rastreie cada chamada separadamente.
void marcar(int recebido) {
int contadorLocal = 0;
recebido = recebido + 1;
contadorLocal = contadorLocal + 1;
}
void setup() {
int solicitado = 2;
marcar(solicitado);
marcar(solicitado);
// solicitado ainda vale 2
}
void loop() {
}Acompanhe os valores enquanto uma chamada ainda está ativa e, depois, quando a execução retorna a setup(). Após o retorno, os locais daquela chamada não existem mais.
| Momento | solicitado em setup | recebido local | contadorLocal |
|---|---|---|---|
| Antes da 1ª chamada | 2 | não existe | não existe |
| Imediatamente antes do fim da 1ª chamada | 2 | 3 | 1 |
| Após o retorno da 1ª chamada | 2 | não existe | não existe |
| Início da 2ª chamada | 2 | 2 | 0 |
| Imediatamente antes do fim da 2ª chamada | 2 | 3 | 1 |
| Após o retorno da 2ª chamada | 2 | não existe | não existe |
Complete as duas atribuições usando o parâmetro e a variável local apropriados.
void marcar(int recebido) {
int contadorLocal = 0;
= recebido + 1;
= contadorLocal + 1;
}Considere int original = 4; e a chamada aumentar(original). Dentro da função, o parâmetro valor executa valor++;. Depois que a função termina, original vale 5.

Passo 3 de 7
Use o tipo de retorno e return para produzir um valor que o programa chamador pode atribuir ou testar em uma condição.
Uma função com retorno entrega um valor ao código que a chamou. O tipo antes do nome declara qual é esse valor: int para um inteiro, bool para verdadeiro ou falso.
Em uma função int, return deve entregar uma expressão inteira. Ao executar return, a chamada atual termina; o valor produzido volta ao ponto onde a função foi chamada.

A chamada produz um valor que pode ocupar seu lugar em uma expressão do chamador.
A chamada dobro(4) é avaliada como 8. Portanto, a atribuição efetivamente guarda 8 em resultado. A execução continua na próxima instrução do chamador.
int dobro(int valor) {
return valor * 2;
}
void setup() {
int resultado = dobro(4);
int proximo = resultado + 1;
}
void loop() {
}Dica
O return não altera automaticamente a variável que foi usada como argumento. Ele apenas entrega um resultado.
Por exemplo, se int pedido = 4; e você escreve int resultado = dobro(pedido);, então pedido continua valendo 4 e resultado recebe 8. Para substituir o valor de pedido, faça uma atribuição explícita: pedido = dobro(pedido);.
Escolha o tipo de retorno pela necessidade de quem chama a função. Se o chamador precisa usar um resultado, a função deve devolvê-lo. Se a função somente realiza uma ação, use void.
Exemplo
Funções void também podem ter efeitos, como comandar o LED. Elas não entregam um valor para uma atribuição. Ao chegar à chave final, uma função void termina. Também é válido usar return;, sem valor, para encerrá-la antes.
Qual assinatura é mais adequada para uma função que recebe uma leitura inteira e informa se ela é maior que 10, para ser usada em uma condição if?
Escreva pelo menos 10 caracteres (0/10).
Complete o código para devolver o dobro de 5 e usar esse retorno no cálculo seguinte.
int dobro(int valor) {
valor * 2;
}
void setup() {
int resultado = (5);
int seguinte = + 1;
}
void loop() {
}Ordene o que ocorre em int resultado = dobro(4);.

Passo 4 de 7
Identifique caminhos sem retorno em uma função que limita valores de 0 a 3 e complete o resultado exigido.
Uma função com retorno precisa entregar um valor compatível em todo caminho que possa ser alcançado. Não basta existir return em apenas alguns ramos.
Vamos limitar uma quantidade ao intervalo de 0 a 3:
Se a execução chegar ao fim de uma função int sem devolver valor, não considere isso um retorno automático de zero nem a preservação de um resultado de uma chamada anterior.

Os três conjuntos de valores precisam alcançar um retorno compatível com int.
Nesta versão, os retornos antecipados cobrem valores abaixo de 0 e acima de 3. Porém, para solicitada igual a 0, 1, 2 ou 3, as duas condições são falsas. A execução então alcança a chave final sem devolver o int exigido.
Um return antecipado encerra a chamada atual imediatamente. Assim, quando o primeiro teste é verdadeiro, o segundo if e qualquer instrução posterior daquele caminho não são executados.
Trecho incompleto para analisar
int limitarPiscadas(int solicitada) {
if (solicitada < 0) {
return 0;
}
if (solicitada > 3) {
return 3;
}
// E se solicitada estiver entre 0 e 3?
}Confira os grupos de entrada antes de corrigir o código.
| Valor de solicitada | Caminho executado | Resultado necessário |
|---|---|---|
| -2 | Primeiro if | 0 |
| 0, 1, 2 ou 3 | Nenhum if | O próprio valor |
| 5 | Segundo if | 3 |
Qual conjunto de entradas alcança o fim da função incompleta sem executar um return?
A correção é adicionar um retorno final para o caminho restante. Ele só é alcançado depois de confirmar que o valor não está abaixo de 0 nem acima de 3; portanto, nessa altura, ele já pertence ao intervalo válido.
Os retornos dentro dos if resolvem os extremos e encerram suas chamadas imediatamente. O retorno final atende somente à faixa central.
Preencha o retorno que atende à faixa de 0 a 3.
int limitarPiscadas(int solicitada) {
if (solicitada < 0) {
return 0;
}
if (solicitada > 3) {
return 3;
}
}
Passo 5 de 7
Organize uma função definida depois de sua chamada usando um protótipo explícito compatível.
Quando a definição aparece depois de setup(), apresente antes ao compilador a interface da função com um protótipo.
; e não tem corpo.dobro(4).Assim, ao encontrar a chamada, o compilador já sabe qual função existe e quais valores ela recebe e devolve.

O protótipo anuncia a interface; a chamada usa a função; a definição fornece o corpo.
Neste exemplo, setup() chama dobro() antes de sua definição. O protótipo resolve essa organização.
int dobro(int valor);
void setup() {
int resultado = dobro(4);
}
void loop() {
}
int dobro(int valor) {
return valor * 2;
}Há duas organizações válidas:
No protótipo e na definição, o tipo de retorno e os tipos dos parâmetros precisam corresponder. Por exemplo, int dobro(int valor); deve corresponder a uma definição que também devolve int e recebe um int.
Em sketches .ino, o Arduino costuma gerar protótipos automaticamente como conveniência. Ainda assim, escrever o protótipo de modo explícito torna a organização visível e é uma prática que não depende dessa conveniência do ambiente.
Associe cada elemento ao seu papel no programa.
Toque em um item e depois no par correspondente.
Complete o protótipo compatível com a definição posicionada depois de setup().
dobrar( valor);
void setup() {
int resultado = dobrar(4);
}
void loop() {
}
int dobrar(int valor) {
return valor * 2;
}
Passo 6 de 7
Divida uma tarefa entre uma função que calcula um resultado e outra que usa esse resultado para controlar o LED integrado.
Uma tarefa pode ficar mais clara quando é dividida em duas responsabilidades:
A função de cálculo recebe a quantidade solicitada e devolve uma quantidade entre 0 e 3. Ela não precisa conhecer pinos, LED nem delay.
Já a função de ação recebe uma quantidade pronta e comanda o LED_BUILTIN. Como seu trabalho é produzir um efeito, e não entregar um dado ao chamador, ela pode ser void.

O chamador conecta as duas funções: recebe o resultado do cálculo e o fornece à ação.
A função abaixo apenas limita um número. Cada caminho devolve um int, e não há comandos de GPIO nela.
Trecho para estudar: esta função não controla nenhum pino.
int limitarPiscadas(int solicitada) {
if (solicitada < 0) {
return 0;
}
if (solicitada > 3) {
return 3;
}
return solicitada;
}A próxima função tem outra responsabilidade: usar uma quantidade válida para alterar o estado do LED. Ela termina sem devolver valor, mas produz o efeito de piscar. Os delay mantêm a execução bloqueada durante cada espera.
A quantidade recebida é usada como limite do laço.
void piscarLed(int quantidade) {
for (int i = 0; i < quantidade; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(250);
digitalWrite(LED_BUILTIN, LOW);
delay(250);
}
}No chamador, deixe o fluxo explícito em duas etapas: primeiro capture o retorno; depois passe esse valor à função de ação. Assim, é possível conferir o cálculo com valores conhecidos antes de observar o LED.
solicitada permanece com o valor original. O retorno é guardado em outra variável.
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
int solicitada = 5;
int quantidadeValida = limitarPiscadas(solicitada);
piscarLed(quantidadeValida);
}
void loop() {
}Para solicitada = 5, a função de cálculo devolve 3. Portanto, quantidadeValida recebe 3 e a função de ação faz três piscadas. A variável solicitada continua valendo 5: receber um argumento por valor não a altera automaticamente.
| Etapa | Valor relevante | Resultado |
|---|---|---|
| Chamador | solicitada = 5 | Solicita uma quantidade |
| limitarPiscadas | parâmetro solicitada = 5 | Devolve 3 |
| Chamador | quantidadeValida = 3 | Guarda o retorno |
| piscarLed | parâmetro quantidade = 3 | Pisca três vezes |
Qual organização separa corretamente as responsabilidades?
Complete as chamadas para primeiro limitar a quantidade e depois executar as piscadas.
int solicitada = 4;
int quantidadeValida = (solicitada);
(quantidadeValida);
Passo 7 de 7
Complete, rastreie e teste um sketch que limita pedidos de piscadas e usa o resultado no LED integrado.
Agora você vai reunir as duas responsabilidades já praticadas: uma função calcula uma quantidade segura de piscadas; a outra realiza a ação no LED integrado.
O sketch solicita primeiro 5 piscadas, mas limita o resultado ao intervalo de 0 a 3. Depois, solicita 2 piscadas. No Uno R3, use somente o cabo USB como alimentação e não conecte componentes externos: LED_BUILTIN controla o LED presente na placa.

Cada pedido é limitado antes de ser usado pela ação no LED.
Crie um sketch novo na IDE Arduino e digite o código completo. As funções aparecem antes de setup(), então este exemplo não precisa de protótipos.
limitarPiscadas calcula e devolve um valor entre 0 e 3. piscarLed produz um efeito no hardware e, por isso, é void. Os delay tornam esta demonstração bloqueante.
Sketch completo para testar no Uno R3
int limitarPiscadas(int solicitada) {
if (solicitada < 0) {
return 0;
}
if (solicitada > 3) {
return 3;
}
return solicitada;
}
void piscarLed(int quantidade) {
for (int contador = 0; contador < quantidade; contador++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
int pedido1 = 5;
int valido1 = limitarPiscadas(pedido1);
piscarLed(valido1);
delay(1200);
int pedido2 = 2;
int valido2 = limitarPiscadas(pedido2);
piscarLed(valido2);
}
void loop() {
}LED_BUILTIN — resultado visual esperado: 1. 3 piscadas, com cerca de 0,4 s por piscada. 2. LED apagado por cerca de 1,4 s entre os grupos. 3. 2 piscadas, com cerca de 0,4 s por piscada. 4. Nenhuma repetição: loop() está vazio. A sequência ocorre uma vez após gravar o sketch ou reiniciar a placa.
A saída é visual: observe o LED integrado. O intervalo apagado visual entre os grupos é de cerca de 1,4 s: os 200 ms finais da terceira piscada, somados ao `delay(1200)` em `setup()`.
Exemplo
Compile e grave o sketch com o Uno R3 e a porta correta selecionados na IDE. Após a gravação ou um reset, observe três piscadas, um intervalo apagado de aproximadamente 1,4 s e duas piscadas. Esse intervalo combina os 200 ms apagados ao fim da terceira piscada com os 1200 ms do delay seguinte.
Como loop() está vazio, a sequência não se repete até um novo reset ou uma nova gravação.
Complete os elementos essenciais mantendo o contrato das duas funções. A função de cálculo precisa tratar valores negativos, valores dentro da faixa e valores acima de 3. A função de ação recebe a quantidade pronta e não devolve resultado.
Complete os tipos, o retorno do limite superior e o valor usado no limite do laço.
limitarPiscadas(int solicitada) {
if (solicitada < 0) {
return 0;
}
if (solicitada > 3) {
3;
}
return solicitada;
}
piscarLed(int quantidade) {
for (int contador = 0; contador < ; contador++) {
// acende e apaga o LED
}
}Antes de avaliar a observação no LED, rastreie a passagem de valores. A chamada cria um parâmetro local chamado solicitada; o resultado devolvido é então guardado em valido1 ou valido2.
O código não contém uma atribuição a pedido1 nem a pedido2. Assim, os pedidos continuam registrando os valores originalmente solicitados.
Valores após cada chamada de cálculo:
| Etapa | 1ª chamada | 2ª chamada |
|---|---|---|
| Argumento | 5 | 2 |
| Parâmetro local `solicitada` | 5 | 2 |
| Resultado de `limitarPiscadas` | 3 | 2 |
| Variável que recebe o retorno | `valido1 = 3` | `valido2 = 2` |
| Próxima chamada | `piscarLed(3)` | `piscarLed(2)` |
| Pedido depois da chamada | `pedido1 = 5` | `pedido2 = 2` |
Por que pedido1 continua valendo 5, embora valido1 receba 3? Explique usando a atribuição que aparece em setup().
Escreva pelo menos 30 caracteres (0/30).
Registre sua verificação prática: qual sequência você previu para o LED, qual sequência observou depois de gravar o sketch e houve alguma divergência? Se houve, descreva-a brevemente.
Escreva pelo menos 50 caracteres (0/50).
Resumo
Uma função bem definida tem uma tarefa específica, parâmetros claros e um retorno adequado quando quem chama precisa usar um resultado. Para rastrear o programa, acompanhe a sequência: argumento → parâmetro local → retorno → variável que recebe → próxima instrução.
Neste sketch, limitarPiscadas calcula sem acessar o LED, enquanto piscarLed altera o LED sem devolver valor. Essa separação permite prever o cálculo antes de observar o efeito físico.
Parabéns! Você concluiu: Funções com parâmetros e retorno
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks