//Bibliotecas:
#include <stdint.h>
#define __AVR_ATmega2560__ /* programa para o microcontrolador ATmega2560 */
#ifndef F_CPU /* se não foi definida a frequência de relógio do microcontrolador */
#define F_CPU 16000000UL /* definimos a frequência de relógio da placa Arduino Mega: 16 MHz */
#endif /* F_CPU */
#include <avr/io.h> /* definições das entradas e saídas */
#include <avr/pgmspace.h> /* usamos procedimentos que acessam a memória FLASH: pgm_read_byte()*/
#include <stdlib.h> /* usamos os procedimentos não padrão utoa e dtostre */
//---------------------------------------------------------------------------------------------
// Programa para 1) configurar a USART0, 2) enviar e receber caracteres pela
// USART0 e 3) transmitir strings da memória FLASH e RAM.
// Veja página 206 do manual de especificações do ATMega2560
/**
@brief Configura o periférico USART no modo assíncrono e quadros no formato 8N1. A taxa de transmissão é 57600 BAUD,
considerando uma frequência de relógio de 16 MHz. Habilita a USART para receber e transmittir (full-duplex)
*/
// Página 220 para as informações de USART0_configura
void USART0_configura(void)
{
UBRR0 = 0x022; //UBRR0H = 0 e UBRR0H = 0x22
UCSR0A = 0x02; // RXC0=0, TXC0=0, UDRE0=0, FE0=0, DOR0=0, UPE0=0, U2X0=1 e MPCM0 = 0
UCSR0B = 0x18; // RXCIE0=0, TXCIE0=0, UDRIE0=0, RXEN0=1, TXEN0=1, UCSZ0[2]=0, RXB80=0 e TXB80=0
UCSR0C = 0x06; //UMSEL0[1:0]=00, UPM0[1:0]=00, USBS0=0, UCSZ0[1:0]=11 e UCPOL0=0
}
// Veja a página 207 do manual de especificações do ATMega2560
void USART0_transmite(uint8_t dado)
{
while (!(UCSR0A & (1 << UDRE0))) // esperamos o buffer de transmissão ficar vazio
;
UDR0 = dado; // colocamos o dado a ser transmitido no buffer de transmissão
}
// Veja a página 210 do manual de especificações do ATMega2560
uint8_t USART0_recebe(void)
{
while (!(UCSR0A & (1 << RXC0))) // espera o dado ser recebido
;
return UDR0; // retorna o dado recebido no buffer de recepção
}
void USART0_transmite_string_RAM(uint8_t *str)
{
uint8_t ch;
// Este laço while é executado até que o caractere ch = 0x00, marcando o final da string
while (ch = *str++) // carregamos um caractere da string e apontamos para o próximo caractere
{
USART0_transmite(ch); // transmite o caractere pelo terminal TX da USART0
}
}
void USART0_transmite_nova_linha(void) {
USART0_transmite('\n');
}
/**
* @brief Envia pela USART0 o prefixo 0x para os números em hexadecimais
*/
void USART0_transmite_0x(void) {
USART0_transmite('0');
USART0_transmite('x');
}
/**
* @brief Envia pela USART0 um byte como dois caracteres hexadecimais
*
* @param dado valor que será transmitido como uma string hexadecimal
*/
void USART0_transmite_hex_byte(uint8_t dado) {
static const char hex_digitos[] PROGMEM = "0123456789ABCDEF";
uint8_t digito;
digito = pgm_read_byte(&(hex_digitos[(dado & 0xF0) >> 4]));
USART0_transmite(digito);
digito = pgm_read_byte(&(hex_digitos[dado & 0x0F]));
USART0_transmite(digito);
}
/**
* @brief Transmite pela USART0 um número como uma string hexadecimal no formato
0xdd, onde d é um caractere entre '0' e 'F', representando um dígito
hexadecimal entre 0 e F.
*
* @param dado valor que será transmitido como uma string hexadecimal no formato 0xdd
*/
void USART0_transmite_hex_uint8(uint8_t dado) {
USART0_transmite_0x();
USART0_transmite_hex_byte(dado);
}
void USART0_transmite_hex_uint16(uint16_t dado) {
USART0_transmite_0x();
USART0_transmite_hex_byte((dado & (uint16_t)0xFF00) >> 8);
USART0_transmite_hex_byte(dado & (uint16_t)0x00FF);
}
/**
* @brief Transmite pela USART0 uma string de um número decimal
*
* @param dado Valor que é transmitido como uma string decimal
*/
void USART0_transmite_dec_uint16(uint16_t dado) {
char buffer[6]; // buffer para 5 digitos decimais e o caractere nulo.
utoa(dado, buffer, 10); // convertemos dado de binário para uma string decimal. Esta função não é padrão ISO C
USART0_transmite_string_RAM(buffer); // transmite a string com o valor decimal de dado
}
void USART0_transmite_dec_uint8(uint8_t dado) {
char buffer[4]; // buffer para 3 digitos decimais e o caractere nulo.
utoa(dado, buffer, 10); // convertemos dado de binário para uma string decimal. Esta função não é padrão ISO C
USART0_transmite_string_RAM(buffer); // transmite a string com o valor decimal de dado
}
/**
* @brief Transmite pela USART0 uma string de um número tipo float, no formato [-]d.dddE±dd
*
* @param dado valor (tipo float) que será trasmitido
*/
void USART0_transmite_float(float dado) {
char buffer[11]; // buffer para armazenar o número no formato [-]d.dddE±dd e o caractere nulo
dtostre(dado, buffer, 3, DTOSTR_UPPERCASE); // convertemos de float para uma string. Esta não é uma função ISO C
USART0_transmite_string_RAM(buffer); // transmite a string com o valor dp float
}
/**
* @brief
*
* @return int Este procedimento não retorna
*/
int main(void) {
// configuramos a USART0 para transmitir a 57600 Baud, quadros 8N1, para um microcontrolador a 16 MHz
USART0_configura();
// trasmitimos alguns valores de teste
USART0_transmite_hex_uint8(0xA5); // (a) uint8_t em hexadecimal
USART0_transmite_nova_linha(); // Pulamos para a próxima linha
USART0_transmite_dec_uint8(220); //(b) uint8_t como uma string decimal
USART0_transmite_nova_linha(); // Pulamos para a próxima linha
USART0_transmite_hex_uint16(0xA5A5); // (c) uint16_t em hexadecimal
USART0_transmite_nova_linha(); // Pulamos para a próxima linha
USART0_transmite_dec_uint16(65500); // (d) uint16_t como uma string decimal
USART0_transmite_nova_linha(); // Pulamos para a próxima linha
USART0_transmite_float(1.2345e-20); // (e) um número float
USART0_transmite_nova_linha(); // Pulamos para a próxima linha
while (1) // terminamos as intruções do programa, permanecendo nesta linha, sem retornar
;
return 0; // este procedimento não deve retornar
}