Explorando Conceitos de Programação e Hardware em Notas de Estudo

Esta seção contém notas de estudo abrangendo diversos tópicos técnicos, com a intenção de registrar aprendizados e descobertas. O material pode incluir referências a fontes externas, e qualquer infração de direitos autorais será tratada prontamente mediante notificação.

2 de Setembro

A diferença entre compiladores C e C++ na geração de nomes de funções é fundamental para o entendimento de recursos como a sobrecarga de funções (function overloading). Enquanto o compilador C gera um nome simples, como _foo para uma função void foo(int x, int y);, o compilador C++ pode gerar um nome mais elaborado, como _foo_int_int. Essa nomenclatura estendida, que incorpora informações sobre os tipos e a quantidade de argumentos, é o que permite ao C++ suportar a sobrecarga de funções, onde múltiplas funções podem compartilhar o mesmo nome desde que seus parâmetros sejam distintos.

Para facilitar a interoperabilidade entre C e C++, a diretiva extern "C" é utilizada. Ao prefixar uma declaração de função com extern "C", o compilador C++ é instruído a nomear a função de acordo com as convenções do C (como _foo), tornando-a chamável a partir de código C.

O C/C++ também oferece macros pré-definidas que fornecem informações contextuais sobre o código em tempo de compilação:

  • __FILE__: O nome do arquivo fonte atual como uma string.
  • __LINE__: O número da linha atual no arquivo fonte como um inteiro.
  • __DATE__: A data da compilação como uma string (e.g., "Sep 2 2023").
  • __TIME__: A hora da compilação como uma string (e.g., "17:49:18").
  • __STDC__: Um valor não-zero se o compilador estiver em conformidade com o padrão ANSI C.

Em termos de dispositivos de hardware, a distinção entre dispositivos de caractere e de bloco é importante. Dispositivos de caractere transmitem e recebem dados em formato de caracteres individuais, enquanto dispositivos de bloco operam com blocos inteiros de dados, geralmente armazenados em buffers.

4 de Setembro

A verificação de paridade ímpar/par é um método rudimentar de detecção de erros. Ela consiste em adicionar um bit extra a um conjunto de bits binários para que o número total de '1's (incluindo o bit de paridade) seja sempre par ou sempre ímpar, conforme a convenção estabelecida. Isso permite identificar se um único bit foi alterado durante a transmissão de dados.

5 de Setembro

A função sscanf em C é uma ferramenta poderosa para analisar strings e extrair dados formatados. Sua assinatura é:

int sscanf(const char *buffer, const char *format [, argument ] ... );

Ela lê dados de uma string (buffer) de acordo com um formato especificado (format) e armazena os valores extraídos nos argumentos subsequentes.

Exemplos de uso:

  1. Leitura de uma string completa: Para ler uma palavra de uma string. ``` char bufferExtraido[512]; sscanf("123456 ", "%s", bufferExtraido); printf("%s\n", bufferExtraido); // Saída: 123456
  2. Leitura de uma string com comprimento máximo: Para limitar o número de caracteres lidos. ``` char bufferExtraido[512]; sscanf("123456 ", "%4s", bufferExtraido); printf("%s\n", bufferExtraido); // Saída: 1234
  3. Leitura até um caractere específico: Para extrair caracteres até encontrar um delimitador, como um espaço. ``` char bufferExtraido[512]; sscanf("123456 abcdedf", "%[^ ]", bufferExtraido); // %[^ ] lê qualquer caractere que não seja espaço. printf("%s\n", bufferExtraido); // Saída: 123456
  4. Leitura de caracteres de um conjunto específico: Para extrair apenas caracteres que pertencem a um conjunto definido. ``` char bufferExtraido[512]; sscanf("123456abcdedfBCDEF", "%[1-9a-z]", bufferExtraido); // Lê apenas dígitos de 1 a 9 e letras minúsculas. printf("%s\n", bufferExtraido); // Saída: 123456abcdedf
  5. Leitura até um caractere de um conjunto específico: Para extrair caracteres até encontrar um caractere de um conjunto específico. ``` char bufferExtraido[512]; sscanf("123456abcdedfBCDEF", "%[^A-Z]", bufferExtraido); // Lê qualquer caractere que não seja uma letra maiúscula. printf("%s\n", bufferExtraido); // Saída: 123456abcdedf
  6. Filtrar prefixos e extrair sub-strings: Para extrair uma parte específica de uma string complexa. ``` char bufferExtraido[512]; sscanf("iios/12DDWDFF@122", "%[^/]/%[^@]", bufferExtraido); // %[^/] ignora tudo até '/', '/' consome o caractere '/', %[^@] lê tudo até '@'. printf("%s\n", bufferExtraido); // Saída: 12DDWDFF
  7. Ignorar a primeira palavra: Para processar apenas a segunda palavra em uma string. ``` char bufferExtraido[512]; sscanf("hello, world", "%*s%s", bufferExtraido); // %*s ignora a primeira palavra. printf("%s\n", bufferExtraido); // Saída: world
    
     Note que `%*s` consome a primeira sequência de caracteres não-espaço. Se não houver espaço, o comportamento pode variar. A eficiência de `sscanf` reside na sua capacidade de utilizar padrões semelhantes a expressões regulares para análise de strings.
    
    

6 de Setembro

A funcionalidade de comutação de clock em sistemas embarcados permite aos desenvolvedores alternar dinamicamente entre diferentes fontes de clock para otimizar o desempenho e o consumo de energia. Para garantir uma inicialização rápida e segura, muitos microcontroladores são configurados, após a redefinição, para usar uma fonte de clock interna de alta velocidade (HSI) dividida (por exemplo, HSI/8). Essa configuração inicial, com um divisor, assegura a estabilidade do sistema mesmo sob condições de tensão de alimentação menos ideais. Uma vez que o clock principle se estabiliza, o software do usuário pode então selecionar outra fonte de clock mais apropriada para a operação contínua.

18 de Setembro

Ao desenvolver para microcontroladores como o STM8 e compará-lo com plataformas como PC, 51, AVR e STM32, é crucial notar a diferença em ordem de bytes (endianness). O STM8 utiliza a ordem de bytes big-endian, onde o byte mais significativo é armazenado no endereço de memória mais baixo. Em contraste, PCs, 51, AVR e STM32 geralmente empregam a ordem little-endian, onde o byte menos significativo ocupa o endereço mais baixo. Essa diferença pode causar problemas na comunicação e na interpretação de dados multi-byte entre esses sistemas.

24 de Setembro

O Timer 1 (TIM1) é um periférico avançado em muitos microcontroladores, composto por um contador auto-reload de 16 bits e um prescaler programável. Suas funcionalidades são diversas:

  • Temporização básica: Execução de tarefas em intervalos regulares.
  • Medição de Pulso: Captura da largura de pulsos de sinais de entrada (Input Capture).
  • Geração de Ondas: Produção de formas de onda de saída, incluindo PWM (Pulse Width Modulation) e modo de pulso único (Output Compare, PWM, One-Pulse Mode).
  • Interrupções: Geração de interrupções baseadas em eventos como captura, comparação, overflow e brake.
  • Sincronização: Sincronização com outros timers (TIM5/TIM6) ou sinais externos (clock, reset, trigger, enable).

Timers de controle avançado são ideais para aplicações que exigem controle preciso, como o modo PWM com alinhamento central, que suporta saídas complementares e controle de tempo morto (dead-time control).

Em registradores de hardware, a distinção entre registradores de pré-carga (preload registers) e registradores sombra (shadow registers) é vital para a sincronização. Um registrador de pré-carga é diretamente acessível pelo software para escrita e leitura. O registrador sombra, por outro lado, é um registrador interno que realmente controla a operação do periférico e não é diretamente visível ao programador. A vantagem desse design é que todas as atualizações de registradores (por exemplo, para múltiplos canais de um timer) podem ocorrer simultaneamente em um evento de atualização. Isso garante a sincronia entre os canais. Sem registradores sombra, as atualizações diretas poderiam levar a inconsistências temporais, especialmente em aplicações com interrupções ou quando o software não consegue atualizar múltiplos registradores exatamente no mesmo instante.

27 de Setembro

NFC (Near Field Communication) é uma tecnologia de comunicação sem fio de curto alcance desenvolvida conjuntamente pela Philips e Sony. Ela permite a troca de informações e acesso a conteúdos e serviços de forma simples e intuitiva entre dispositivos móveis, eletrônicos de consumo, PCs e dispositivos inteligentes, operando a poucos centímetros de distância.

29 de Setembro

As mensagens de compilação do IAR Embedded Workbench fornecem informações sobre a alocação de memória do código compilado. Por exemplo, uma mensagem como:


25 345 bytes of readonly code memory
  6 271 bytes of readonly data memory
  3 556 bytes of readwrite data memory

Indica o seguinte:

  • 25 345 bytes: Espaço ocupado pelo código executável (armazenado na memória Flash).
  • 6 271 bytes: Espaço ocupado por dados constantes (como strings literais, constantes globais, também na memória Flash).
  • 3 556 bytes: Espaço ocupado por variáveis que podem ser modificadas durante a execução (armazenadas na memória RAM).

Tags: C C++ Compiladores Embarcados Hardware

Publicado em 6-18 16:49