#include <stdint.h>
#include <stdio.h>
// Definições de registradores
#define RCC_BASE 0x40021000
#define GPIOC_BASE 0x40011000
#define USART1_BASE 0x40013800
#define RCC_APB2ENR (*(volatile uint32_t *)(RCC_BASE + 0x18))
#define GPIOC_CRH (*(volatile uint32_t *)(GPIOC_BASE + 0x04))
#define GPIOC_BSRR (*(volatile uint32_t *)(GPIOC_BASE + 0x10))
#define USART1_SR (*(volatile uint32_t *)(USART1_BASE + 0x00))
#define USART1_DR (*(volatile uint32_t *)(USART1_BASE + 0x04))
#define USART1_BRR (*(volatile uint32_t *)(USART1_BASE + 0x08))
#define USART1_CR1 (*(volatile uint32_t *)(USART1_BASE + 0x0C))
// Definições de bit para os registradores
#define RCC_APB2ENR_IOPCEN (1 << 4)
#define RCC_APB2ENR_USART1EN (1 << 14)
#define GPIOC_CRH_MODE13 (1 << 20)
#define GPIOC_CRH_CNF13_0 (1 << 22)
#define GPIOC_CRH_CNF13_1 (1 << 23)
#define USART1_CR1_UE (1 << 13)
#define USART1_CR1_TE (1 << 3)
#define USART1_SR_TXE (1 << 7)
void delay(volatile uint32_t count)
{
while (count--)
;
}
void usart1_send(char ch)
{
while (!(USART1_SR & USART1_SR_TXE))
; // Espera até o buffer estar vazio
USART1_DR = ch; // Envia o caractere
}
void usart1_send_string(const char *str)
{
while (*str) {
usart1_send(*str++);
}
}
int main(void)
{
// Habilita o clock para GPIOC e USART1
RCC_APB2ENR |= RCC_APB2ENR_IOPCEN | RCC_APB2ENR_USART1EN;
// Configura PC13 como saída push-pull, máxima velocidade 2 MHz
GPIOC_CRH &= ~(0xF << 20);
GPIOC_CRH |= (GPIOC_CRH_MODE13 | GPIOC_CRH_CNF13_0);
// Configura USART1: Baud rate 9600, 8N1
USART1_BRR = 0x1D4C; // Configuração para 72 MHz
USART1_CR1 |= (USART1_CR1_UE | USART1_CR1_TE);
while (1) {
// Liga o LED (PC13 é ativo baixo)
GPIOC_BSRR = (1 << 13) << 16;
usart1_send_string("LED ON\r\n");
delay(1000);
// Desliga o LED
GPIOC_BSRR = (1 << 13);
usart1_send_string("LED OFF\r\n");
delay(1000);
}
}