- Preparando o Hardware
- Compreendendo a pinagem GPIO em STM8S103F
- Descrição da pinagem e dicas para seleção de STM8S103F GPIO
- Programação STM8S para entrada e saída GPIO usando SPL
- Carregando e testando o programa
Para microcontroladores, um programa de LED piscando é equivalente ao programa “hello world”. Em nosso tutorial anterior, aprendemos como começar com a placa de desenvolvimento STM8S103F3 e como configurar o IDE e o compilador para programar nossos controladores STM8S. Também aprendemos como usar as bibliotecas periféricas padrão e como compilar e carregar o código em nosso microcontrolador. Com todos os fundamentos cobertos, vamos começar a escrever código. Neste tutorial, aprenderemos como executar funções GPIO gerais em controladores STM8S. A placa já tem um LED integrado conectado ao pino 5 da porta B, vamos aprender a piscar este LED e também adicionar um LED externo e controlá-lo com um botão de pressão. Se você for completamente novo, é altamente recomendável ler o tutorial anterior antes de prosseguir.
Preparando o Hardware
Antes de mergulharmos no programa, vamos preparar as conexões de hardware. Como mencionado anteriormente, usaremos dois LEDs aqui, um é um LED integrado que piscará continuamente e o outro é um LED externo que será alternado com um botão de pressão. A ideia é aprender todas as funcionalidades do GPIO em uma configuração simples. O Led on-board já está conectado no PB5 (pino 5 do PORTB), então acabei de conectar um LED no PA3 e um botão no PA2, como você pode ver no diagrama abaixo.
Mas, de todos os pinos de saída disponíveis em nosso controlado, por que selecionei PA3 para saída e PA2 para entrada? As perguntas são válidas e explicarei isso mais adiante neste artigo. Minha configuração de hardware para este tutorial é mostrada abaixo. Como você pode ver, também conectei meu programador ST-link a pinos de programação que não apenas programarão nossa placa, mas também funcionarão como fonte de alimentação.
Compreendendo a pinagem GPIO em STM8S103F
Agora voltando à questão, por que PA2 para entrada e por que PA3 para saída? Para entender isso, vamos dar uma olhada mais de perto na pinagem do microcontrolador que é mostrada abaixo.
De acordo com o diagrama de pinagem, temos quatro portas em nosso microcontrolador, a saber, PORT A, B, C e D denotadas por PA, PB, PC e PD respectivamente. Cada pino GPIO também possui alguma outra funcionalidade especial. Por exemplo, o PB5 (pino 5 da PORTA B) pode funcionar não apenas como um pino GPIO, mas também como um pino SDA para comunicação I2C e como um pino de saída do temporizador 1. Portanto, se usarmos esse pino para fins simples de GPIO, como conectar um LED, não poderemos usar I2C e o LED ao mesmo tempo. Infelizmente, o LED on-board está conectado a este pino, então não temos muita escolha aqui e, neste programa, não vamos usar I2C, então não é um grande problema.
Descrição da pinagem e dicas para seleção de STM8S103F GPIO
Na verdade, não faria mal nenhum usar PA1 como um pino de entrada e ele funcionaria apenas como pino. Mas eu mencionei isso deliberadamente para me dar a oportunidade de mostrar algumas armadilhas comuns nas quais você pode cair ao selecionar os pinos GPIO em um novo microcontrolador. O melhor para evitar as armadilhas é ler os detalhes e a descrição dos pinos fornecidos na folha de dados STM8S103F3P6. Para a descrição do pino do microcontrolador STM8S103F3P6, os detalhes mencionados na folha de dados são mostrados nas imagens abaixo.
Os pinos de entrada em nosso microcontrolador podem ser flutuantes ou pull-up fraco e os pinos de saída podem ser Open Drain ou Push-pull. A diferença entre os pinos de drenagem aberta e saída push-pull já foi discutida, portanto, não entraremos em detalhes sobre isso. Para simplificar, um pino de saída de drenagem aberta pode tornar a saída apenas tão baixa, não tão alta, enquanto um pino de saída push-pull pode tornar a saída tão alta quanto alta.
Além do que está na tabela acima, você também pode notar que um pino de saída pode ser uma saída rápida (10 MHz) ou uma saída lenta (2 MHz). Isso determina a velocidade GPIO, se você quiser alternar seus pinos GPIO entre alto e baixo muito rápido, podemos escolher a saída rápida.
Alguns pinos GPIO em nosso controlador suportam True Open Drain (T) e High Sink Current (HS), conforme mencionado na imagem acima. Uma diferença considerável entre Dreno Aberto e Dreno Aberto Verdadeiro é que a saída conectada ao dreno aberto não pode ser puxada mais alto do que a tensão operacional do microcontrolador (Vdd), enquanto um pino de saída de dreno aberto verdadeiro pode ser puxado mais alto do que Vdd. Pinos com alta capacidade de dissipação significam que ele pode absorver mais corrente. A fonte e o dissipador de corrente de qualquer pino GPIO HS é de 20 mA, enquanto a linha de alimentação pode consumir até 100 mA.
Olhando mais de perto a imagem acima, você notará que quase todos os pinos GPIO são do tipo High Sink Current (HS), exceto PB4 e PB5, que são True Open Drain Type (T). Isso significa que esses pinos não podem ser feitos altos, eles não serão capazes de fornecer 3,3 V mesmo quando o pino for alto. É por isso que o led integrado está conectado a um 3,3 V e aterrado através do PB5 em vez de alimentá-lo diretamente do pino GPIO.
Consulte a página 28 na folha de dados para obter a descrição detalhada dos pinos. Conforme mencionado na imagem acima, PA1 é automaticamente configurado como um pull-up fraco e não é recomendado para ser usado como um pino de saída. De qualquer forma ele pode ser usado como um pino de entrada junto com um botão de pressão, mas decidi usar PA2 apenas para tentar habilitar o pull up do programa. Estas são apenas algumas coisas básicas que serão úteis quando escrevermos programas muito mais complicados. Por enquanto, não há problema se muitas coisas ricochetearem em sua cabeça, vamos abordar isso em outros tutoriais.
Programação STM8S para entrada e saída GPIO usando SPL
Crie uma área de trabalho e um novo projeto conforme discutimos em nosso primeiro tutorial. Você pode adicionar todos os arquivos de cabeçalho e de origem ou apenas adicionar os arquivos gpio, config e stm8s. Abra o arquivo main.c e comece a escrever seu programa.
Certifique-se de incluir os arquivos de cabeçalho conforme mostrado na imagem acima. Abra o arquivo main.c e inicie o código. O código main.c completo pode ser encontrado na parte inferior desta página e você também poderá baixar o arquivo do projeto a partir daí. A explicação do código é a seguinte; você também pode consultar o manual do usuário SPL ou o vídeo vinculado na parte inferior desta página se estiver confuso sobre a parte de codificação.
Desinicializando a porta necessária
Começamos nosso programa de-Initializing as portas necessárias. Conforme discutimos anteriormente, cada pino GPIO terá muitas outras funções associadas a ele, além de funcionar como uma entrada e saída normal. Se esses pinos foram usados anteriormente para alguns outros aplicativos, ele deve ser Desinicializado antes de usá-los. Não é obrigatório, no entanto, é uma boa prática. As duas linhas de código a seguir são usadas para De-Initialize Port A e Port B. Basta usar a sintaxe GPIO_DeInit (GPIOx); e mencione o nome da porta no lugar de x.
GPIO_DeInit (GPIOA); // prepara a porta A para funcionar GPIO_DeInit (GPIOB); // prepara a porta B para funcionar
Declaração GPIO de entrada e saída
A seguir, temos que declarar quais pinos serão usados como entrada e quais como saída. No nosso caso, o pino PA2 será usado como entrada, também declararemos este pino com pull-up interno para que não tenhamos que usar um externamente. A sintaxe é GPIO_Init (GPIOx, GPIO_PIN_y, GPIO_PIN_MODE_z); . Onde x é o nome da porta, y é o número do pino ez é o modo GPIO Pin.
// Declara PA2 como pino de recepção de entrada GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);
A seguir, temos que declarar os pinos PA3 e PB5 como saída. Novamente, muitos tipos de declaração de saída são possíveis, mas usaremos “GPIO_MODE_OUT_PP_LOW_SLOW”, o que significa que o declararemos como um pino de saída do tipo push-pull com velocidade lenta. E, por padrão, o valor será baixo. A sintaxe será a mesma.
GPIO_Init (GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW); // Declara PB5 como pino de saída push pull GPIO_Init (GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);
O instantâneo abaixo do manual do usuário SPL menciona todos os modos GPIO possíveis (z).
Loop infinito
Após a declaração do pino, precisamos criar um loop infinito dentro do qual continuaremos piscando o LED para sempre e monitoraremos o status do botão de pressão para alternar o LED. O loop infinito pode criar com um while (1) ou com um for (;;) . Aqui eu usei while (1).
enquanto (1) {}
Verificando o status do pino de entrada
Temos que verificar o status do pino de entrada, a sintaxe para fazer isso é GPIO_ReadInputPin (GPIOx, GPIO_PIN_y); onde x é o nome da porta ey é o número do pino. Se o pino for alto, obteremos '1' e se o pino for baixo, obteremos '0'. Usamos para dentro de um loop if para verificar se o pino está alto ou baixo.
if (GPIO_ReadInputPin (GPIOA, GPIO_PIN_2)) // se o botão for pressionado
Tornando um pino GPIO alto ou baixo
Para tornar um pino GPIO alto ou baixo, podemos usar GPIO_WriteHigh (GPIOx, GPIO_PIN_y); e GPIO_WriteLow (GPIOx, GPIO_PIN_y); respectivamente. Aqui, fizemos o LED acender se o botão for pressionado e desligar se o botão não for pressionado.
if (GPIO_ReadInputPin (GPIOA, GPIO_PIN_2)) // se o botão for pressionado GPIO_WriteLow (GPIOA, GPIO_PIN_3); // LED ON else GPIO_WriteHigh (GPIOA, GPIO_PIN_3); // LED apagado
Alternando um PIN GPIO
Para alternar um pino GPIO, temos GPIO_WriteReverse (GPIOx, GPIO_PIN_y); chamar esta função mudará o status do pino de saída. Se o pino for alto, ele será alterado para baixo e, se estiver baixo, será alterado para alto. Estamos usando esta função para piscar o LED integrado no PB5.
GPIO_WriteReverse (GPIOB, GPIO_PIN_5);
Função de Atraso
Ao contrário do Arduino, o compilador cósmico não possui uma função de atraso predefinida. Portanto, temos que criar um por conta própria. Minha função de atraso é fornecida abaixo. O valor doe o atraso será recebido na variável ms e usaremos dois for loop to hold ou execução do programa. Assim como _asm (“nop”) é uma instrução de montagem que significa nenhuma operação. Isso significa que o controlador entrará em loop no loop for sem realizar nenhuma operação, criando assim um atraso.
void delay (int ms) // Definição da função {int i = 0; int j = 0; for (i = 0; i <= ms; i ++) {for (j = 0; j <120; j ++) // Nop = Fosc / 4 _asm ("nop"); // Não execute nenhuma operação // código de montagem}}
Carregando e testando o programa
Agora que nosso programa está pronto, podemos carregá-lo e testá-lo. Depois de carregado, meu hardware estava funcionando conforme o esperado. O LED vermelho na placa piscava a cada 500 milissegundos e o LED verde externo acendia toda vez que eu pressionava o botão.
O trabalho completo pode ser encontrado no vídeo no link abaixo. Depois de chegar a este ponto, você pode tentar conectar o switch e o LED a pinos diferentes e reescrever o código para entender o conceito. Você também pode brincar com o tempo de atraso para verificar se entendeu os conceitos claramente.
Se você tiver alguma dúvida, por favor, deixe-a na seção de comentários abaixo e para outras questões técnicas, você pode usar nossos fóruns. Obrigado por seguir por, nos vemos no próximo tutorial.