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:
- 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
- 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
- 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
- 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
- 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
- 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
- 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).