Prévia do material em texto
<p>1) Descreva a estrutura básica de um sistema computacional. Você pode utilizar diagramas para</p><p>ilustrar a estrutura e destacar os componentes básicos.</p><p>R: A sua estrutura básica é formada pelos seguintes componentes, a CPU, memória, sendo ela,</p><p>principal (RAM) ou memória secundária (Armazenamento), dispositivos de entrada e saída e o</p><p>barramento de dados.</p><p>2) Discorra sobre os barramentos, que são as ligações físicas usadas para a comunicação paralela</p><p>entre os componentes de um microcontrolador. Destaque o barramento de dados (DATA BUS),</p><p>de endereços (ADDRESS BUS) e de controle (CONTROL BUS). Use diagramas para auxiliar na</p><p>explicação.</p><p>R: Os sistemas computacionais comumente são classificados pelo tamanho de seu barramento,</p><p>onde este é dado pelo seu número de bits, ditando o tráfego de informações pelo sistema e</p><p>quantidade máxima de endereços de memória para dispositivos de I/O.</p><p>Atualmente, é comum encontrarmos MCUs de 8bits, mas além deste temos os de 16 e 32 bits.</p><p>A capacidade de memória é dada por 2^n, sendo n o número de bits do barramento.</p><p>O barramento de controle é composto por três sinais: RD (Read)– leitura. WR (Write)– escrita.</p><p>IORD (I/O Request)– requisição</p><p>BARRAMENTODEDADOS(DATABUS)</p><p>Onde todos os dispositivos estão ligados e por onde trocam informações. Todos os dispositivos</p><p>ligados no data bus são lidos ou escritos pela CPU, que controla todo o processo.</p><p>BARRAMENTODEENDEREÇOS(ADDRESSBUS)</p><p>Permite o processador endereçar, ou seja, indicar qual dispositivo será acessado.</p><p>BARRAMENTODECONTROLE(CONTROL BUS)</p><p>Indica se o acesso é de leitura ou escrita, pois muitas vezes um mesmo endereço de memória</p><p>ou de I/O pode ser lido ou escrito. O barramento de controle indica se está sendo acessado um</p><p>endereço de memória ou dispositivo de I/O, já que eles utilizam o mesmo barramento de</p><p>endereço</p><p>3) Discorra sobre a arquitetura Von Neumann. Apresente aspectos históricos, elementos básicos,</p><p>um diagrama da arquitetura e fale sobre a filosofia CISC (Complex Instruction Set Computer).</p><p>CPU</p><p>Memória</p><p>Dispositivos</p><p>de I/O</p><p>Barramento de dados</p><p>R: A arquitetura de Von Neumann ainda é utilizada atualmente para os sistemas computacionais</p><p>convencionais. Nesta arquitetura, tanto a memória principal, quanto a de armazenamento, são</p><p>acessadas através do mesmo barramento de dados, assim como os portais de I/O. As instruções</p><p>são divididas em dois momentos, o primeiro da leitura da instrução e operandos, já a segunda se</p><p>trata da execução da instrução, além de geralmente terem o mesmo tamanho do barramento de</p><p>dados. Logo, o processador estará em parte ocupado com a leitura da memória de uma</p><p>determinada rotina e não executará o firmware o tempo todo. Processadores do tipo CISC, tem</p><p>um grande conjunto de instruções complexas e capacidade de executá-las, que seria justamente</p><p>o caso da arquitetura em questão.</p><p>4) Faça um comparativo entre as arquiteturas Von Neumann e Harvard. Apresente as vantagens e</p><p>desvantagens de cada arquitetura.</p><p>R: Harvard é mais veloz, mas exige mais um barramento. Assim o custo de produção das placas</p><p>que utilizam este tipo de processadores é maior. Von Neuman utiliza apenas um</p><p>barramento, mas não pode efetuar acessos simultâneos às memórias.</p><p>Von Neuman tem conjunto de instruções complexas, que realizam uma grande sequência</p><p>de ações (CISC). Essa arquitetura é usada em um computador pessoal (PC) . Já Harvard tem</p><p>conjunto de instruções reduzida (RISC). Essa arquitetura é utilizada tipicamente em</p><p>microcontroladores.</p><p>5) Discorra sobre o conjunto básico de instruções em um microprocessador e suas funções:</p><p>instruções de transferência de dados, aritméticas e lógicas, de desvio e de controle.</p><p>R: O conjunto básico de instruções em um microprocessador abrange operações essenciais para</p><p>mover dados, realizar cálculos, tomar decisões baseadas em condições, e controlar o fluxo de</p><p>execução do programa. Essas instruções são fundamentais para a operação de qualquer sistema</p><p>computacional e permitem a construção de programas complexos a partir de operações simples e</p><p>diretas. Entre elas vale destacar as técnicas de bitwise de Set bit, Clear bit e Toggle bit, que são</p><p>referente as operações lógicas com bits.</p><p>6) Discorra sobre a estrutura de dados em pilha (Stack).</p><p>R: Uma pilha (ou stack) é uma estrutura de dados que segue o princípio LIFO (Last In, First</p><p>Out), onde o último elemento a ser inserido é o primeiro a ser removido. Essa estrutura é</p><p>fundamental na computação e tem diversas aplicações, como na gestão da memória.</p><p>As pilhas podem ser implementadas de várias maneiras, como utilizando arrays ou listas ligadas,</p><p>dependendo das necessidades de armazenamento dinâmico ou fixo.</p><p>7) Considere os registradores de I/O que contemplam todos os terminais de entrada e saída do</p><p>ATMega328P. Elabore um programa em linguagem C que configure todos os bits do PORTD</p><p>como saídas digitais. A rotina de programa deve fazer com que os bits pares e ímpares alterem</p><p>entre nível alto e nível baixo.</p><p>R:</p><p>int main(void) {</p><p>DDRD = 0b11111111;</p><p>while (1) {</p><p>PORTD = 0b01010101;</p><p>PORTD = 0b10101010;</p><p>}</p><p>}</p><p>8) Construa um código em C para um registrador de deslocamento que é acionado sempre que a</p><p>leitura do terminal 8 do ATMega328P fornecer nível alto (isso simula um botão de pull-down).</p><p>Para cada vez que o botão for pressionado, um bit alto deve deslocar do LSB no sentido do MSB</p><p>do registrador. Quando o bit alto atingir o bit 7, o próximo bit em deslocamento só poderá se</p><p>deslocar até o bit 6. Esse processo deve se repetir até que todos os bits do registrador estejam em</p><p>nível alto.</p><p>R:</p><p>#define F_CPU 16000000 // frequência do oscilador externo 16MGhrtz</p><p>#include <avr/io.h></p><p>// #include <util/delay.h> biblioteca de temporização</p><p>int counter = 0;</p><p>int lastcounter = 8;</p><p>int main(void)</p><p>{</p><p>DDRD = 0b11111111;</p><p>DDRB = 0b00000000;</p><p>PORTB = (0<<0);</p><p>while (1)</p><p>{</p><p>if (PINB & (1 << 0) & (counter < lastcounter)){</p><p>PORTD |= (1 << counter);</p><p>counter++;</p><p>} else {</p><p>for(int i =0; i < (lastcounter-1); i++){</p><p>PORTD = (1<< lastcounter);</p><p>}</p><p>if(lastcounter >= 0){</p><p>lastcounter = counter - 1;</p><p>}</p><p>counter = 0;</p><p>}</p><p>}</p><p>}</p><p>9) Considerando o importante trabalho com os bits para a programação de sistemas embarcados</p><p>com microcontroladores, implemente em linguagem C as MACROS para set_bit, clear_bit,</p><p>toggle_bit e test_bit usando a diretiva #define.</p><p>R:</p><p>#define BitSet(arg, bit) ((arg) |= (1<<bit))</p><p>#define BitClear(arg, bit) ((arg) &= ~(1<<bit))</p><p>#define ToggleBit(arg, bit) ((arg) ^= (1<<bit))</p><p>#define TestBit(arg, bit) ((arg) >> bit & 1)</p><p>a) 0b00111100 & ~(0b00111100);</p><p>10) Considere as técnicas de bitwise em linguagem C. Fazendo uso do operador de shift left, crie a</p><p>operação descrita a seguir nos registradores de 8 bits:</p><p>a) Configurar bit alto no PORTD0;</p><p>b) Configurar bit alto em PORTD1, PORTD3, PORTD5 e PORTD7;</p><p>c) Limpar o PORTD3;</p><p>d) Testar se o PORTB1 está em nível alto.</p><p>R: a) PORTD |= (1 << PORTD0); // Usa shift left para colocar 1 no bit 0 (PORTD0)</p><p>// b) Configurar bit alto em PORTD1, PORTD3, PORTD5 e PORTD7</p><p>PORTD |= (1 << PORTD1) | (1 << PORTD3) | (1 << PORTD5) | (1 << PORTD7);</p><p>// c) Limpar o PORTD3</p><p>PORTD &= ~(1 << PORTD3); // Usa shift left para colocar 0 no bit 3 (PORTD3)</p><p>D) if (PINB & (1 << PORTB1)) {</p><p>sysout(“nível alto”);</p><p>}</p><p>11) Descreve a função de cada linha do programa mostrado a seguir e qual rotina está sendo</p><p>executada.</p><p>R: Define os PinD como de pinos de leitura, seta as portas digitals D em nível baixo, define as</p><p>portas digitais B de 0 à 6 para nível alto. A função sei() habilita as interrupções globais,</p><p>configurando são registradores utilizados para configurar e controlar interrupções externas.</p><p>EICRA</p><p>igual à 01, habilitam a interrupção externa do vetor INT0, que qualquer mudança no</p><p>INT0 gera uma interrupção. counter é uma variável que armazena valores, iniciando de 0 até</p><p>10, que vai mandando bit alto para o PortB até 10 e reinicia depois disso.</p><p>12) Considere um conversor analógico digital (ADC) de 10 bits. Para um sinal analógico que varia</p><p>de 0 a 5 V, qual a menor variação de tensão que esse conversor é capaz de detectar?</p><p>R: Número de níveis de Quantização para um ADC de 10 bits é igual à 2^10 = 1024</p><p>Resolução = Intervalo de tensão/ Número de níveis de Quantização</p><p>Resolução = 5V / 1024 = 0,0048828125V = 4,88mV</p><p>13) Considere um sensor analógico de temperatura que opera de forma linear numa faixa de 0 a 300</p><p>°C. Considere um ADC de 12 bits empregado nesta aplicação. Crie a rotina responsável por</p><p>converter a leitura do ADC (valor digital com resolução de 12 bits) em um valor de temperatura</p><p>em °C. Qual o menor valor de temperatura que esse sistema sensor será capaz de distinguir?</p><p>R: Número de níveis de Quantização para um ADC de 12 bits é igual à 2^12 = 4096</p><p>Resolução = Intervalo de tensão/ Número de níveis de Quantização</p><p>Resolução = 300Cº / 4096 = 0,07324Cº</p><p>14) Descreva o protocolo de comunicação serial SPI (Serial Peripheral Interface).</p><p>R: O SPI é um protocolo de comunicação síncrona. Ou seja, precisa de um clock. Diferentemente</p><p>do UART, o SPI permite a comunicação de um mestre com vários dispositivos (escravos).</p><p>No protocolo UART, precisamos apenas de três conexões (três condutores): Tx, Rx e GND. Já</p><p>no protocolo SPI, na configuração mais simples, são necessários quatro condutores: clock,</p><p>MISO, MOSI e GND.</p><p>Pinos usados no protocolo SPI:</p><p>MISO – Master In Slave Out (do mestre para o escravo)</p><p>MOSI – Master Out Slave In (do escravo para o mestre)</p><p>SS – Slave Select (Seleção do escravo)</p><p>GND</p><p>Características:</p><p>Precisa de um pino dedicado para cada escravo;</p><p>O mestre define a velocidade da comunicação (não precisa combinar com o escravo);</p><p>A leitura da mensagem do Mestre pode ser configurada para a borda de descida ou de subida</p><p>do clock;</p><p>15) Grande parte dos protocolos de comunicação serial se utilizam da checagem de integridade para</p><p>garantir que a mensagem está correta. Uma delas é realizar a soma de todos os valores da</p><p>mensagem e enviar esse resultado por último. Para indicar o começo de uma mensagem é comum</p><p>se utilizar de um valor padrão, por exemplo o número 13, e um segundo número padrão é</p><p>utilizado para marcar o final da mensagem, por exemplo 21. Utilizando essas informações</p><p>podemos verificar, por exemplo, que a MSG1 abaixo está correta pois o somatório dos números</p><p>entre o 13 e o 21, é igual a 28, conforme escrito na posição depois do número 24. Já a MSG2</p><p>está errada pois a soma retorna 20 e não 21 como representado.</p><p>MSG1 13 01 02 05 08 01 03 10 21 28</p><p>MSG2 13 00 01 02 03 05 09 10 21 25</p><p>Dado que a biblioteca “serial.h” permite ao programador ler qualquer informação que for</p><p>recebida pela serial, faça um programa em C que realize ciclicamente a leitura dos valores</p><p>recebidos pela serial e calcule se a mensagem está correta ou errada. O tamanho da mensagem</p><p>pode variar. As únicas informações confiáveis são de que a mensagem sempre começa com um</p><p>número 13, e termina com um número 21 seguido de um número com o somatório dos números</p><p>intermediários.</p><p>A biblioteca serial possui duas funções disponíveis: void StartSerial(void), que inicializa a</p><p>comunicação serial e int ReadSerial(void), que retorna o último número recebido.</p><p>#include <stdio.h></p><p>#include "serial.h" // Supondo que "serial.h" é a biblioteca que gerencia a comunicação serial</p><p>void StartSerial(void);</p><p>int ReadSerial(void);</p><p>int main(void) {</p><p>int received_value;</p><p>int sum = 0;</p><p>int start_detected = 0;</p><p>int expected_sum = 0;</p><p>StartSerial(); // Inicializa a comunicação serial</p><p>while (1) { // Loop infinito para leitura contínua dos dados</p><p>received_value = ReadSerial(); // Lê o próximo valor da serial</p><p>if (received_value == 13) { // Detecção do início da mensagem</p><p>start_detected = 1;</p><p>sum = 0; // Reseta a soma para a nova mensagem</p><p>continue;</p><p>}</p><p>if (start_detected) {</p><p>if (received_value == 21) { // Detecção do fim da mensagem</p><p>expected_sum = ReadSerial(); // Lê o valor que deveria ser a soma dos valores</p><p>intermediários</p><p>if (sum == expected_sum) {</p><p>printf("Mensagem correta. Soma calculada: %d, Soma esperada: %d\n", sum,</p><p>expected_sum);</p><p>} else {</p><p>printf("Mensagem incorreta. Soma calculada: %d, Soma esperada: %d\n", sum,</p><p>expected_sum);</p><p>}</p><p>start_detected = 0; // Reseta para aguardar a próxima mensagem</p><p>} else {</p><p>sum += received_value; // Acumula o valor na soma</p><p>}</p><p>}</p><p>}</p><p>return 0;</p><p>}</p>