#include "stm32c0xx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ================= Function Prototypes =================
void UART2_Init(void);
void UART2_SendString(char *str);
void ADC1_Init(void);
uint16_t ADC1_Read(void);
void Ultrasonic_Init(void);
uint32_t Ultrasonic_Read(void);
void delay_us(uint32_t us);
// ================= Main =================
int main(void)
{
RCC->IOPENR |= (1 << 0); // Enable GPIOA clock
RCC->IOPENR |= (1 << 3); // Enable GPIOD clock
// PA13 = LED output
GPIOA->MODER &= ~(3 << (13 * 2));
GPIOA->MODER |= (1 << (13 * 2));
// PD0 = PIR input (pull-down)
GPIOD->MODER &= ~(3 << (0 * 2));
GPIOD->PUPDR &= ~(3 << (0 * 2));
GPIOD->PUPDR |= (2 << (0 * 2));
UART2_Init();
ADC1_Init();
Ultrasonic_Init();
UART2_SendString("System Ready\r\n");
uint8_t prev_pir = 0;
uint16_t prev_pot = 0xFFFF;
uint32_t prev_distance = 0xFFFFFFFF; // Previous distance
char buf[64];
// Initial PIR check
uint8_t pir_state = (GPIOD->IDR & (1 << 0)) ? 1 : 0;
if (!pir_state)
{
GPIOA->ODR &= ~(1 << 13);
UART2_SendString("Obstacle not detected\r\n");
}
else
{
GPIOA->ODR |= (1 << 13);
UART2_SendString("Obstacle detected\r\n");
}
prev_pir = pir_state;
while (1)
{
pir_state = (GPIOD->IDR & (1 << 0)) ? 1 : 0;
uint16_t pot_value = ADC1_Read();
uint32_t distance = Ultrasonic_Read(); // Fake distance = 151 cm
// === PIR logic ===
if (pir_state && !prev_pir)
{
GPIOA->ODR |= (1 << 13);
UART2_SendString("Obstacle detected\r\n");
}
else if (!pir_state && prev_pir)
{
GPIOA->ODR &= ~(1 << 13);
UART2_SendString("Obstacle not detected\r\n");
}
prev_pir = pir_state;
// === ADC logic ===
if (abs((int)pot_value - (int)prev_pot) > 50)
{
prev_pot = pot_value;
snprintf(buf, sizeof(buf), "Pot: %u\r\n", pot_value);
UART2_SendString(buf);
}
// === Ultrasonic logic (print only if value changes) ===
if (distance != prev_distance)
{
prev_distance = distance;
snprintf(buf, sizeof(buf), "Distance: %lu cm\r\n", distance);
UART2_SendString(buf);
}
for (volatile int i = 0; i < 100000; i++);
}
}
// ================= UART =================
void UART2_Init(void)
{
RCC->APBENR1 |= (1 << 17); // Enable USART2 clock
GPIOA->MODER &= ~((3 << (2*2)) | (3 << (3*2)));
GPIOA->MODER |= ((2 << (2*2)) | (2 << (3*2))); // Alternate function
GPIOA->AFR[0] &= ~((0xF << (4*2)) | (0xF << (4*3)));
GPIOA->AFR[0] |= ((1 << (4*2)) | (1 << (4*3))); // AF1 for USART2
USART2->BRR = 16000000 / 9600; // 9600 baud @ 16MHz
USART2->CR1 = (1 << 0) | (1 << 3); // UE, TE
}
void UART2_SendString(char *str)
{
while (*str)
{
while (!(USART2->ISR & (1 << 7))); // Wait TXE
USART2->TDR = *str++;
}
}
// ================= ADC =================
void ADC1_Init(void)
{
RCC->APBENR2 |= (1 << 20); // Enable ADC clock
GPIOA->MODER |= (3 << (5 * 2)); // PA5 analog mode
ADC1->CR |= (1 << 0); // ADEN
while (!(ADC1->ISR & (1 << 0))); // Wait ADRDY
}
uint16_t ADC1_Read(void)
{
ADC1->CHSELR = (1 << 5); // Channel 5 (PA5)
ADC1->CR |= (1 << 2); // ADSTART
while (!(ADC1->ISR & (1 << 2))); // Wait EOC
return ADC1->DR;
}
// ================= Ultrasonic =================
void Ultrasonic_Init(void)
{
// PA10 = TRIG (output)
// PA11 = ECHO (input)
GPIOA->MODER &= ~((3 << (10*2)) | (3 << (11*2)));
GPIOA->MODER |= (1 << (10*2)); // PA10 as output
// PA11 input (default)
}
uint32_t Ultrasonic_Read(void)
{
// Simulate Ultrasonic Trigger pulse
GPIOA->ODR &= ~(1 << 10);
delay_us(2);
GPIOA->ODR |= (1 << 10);
delay_us(10);
GPIOA->ODR &= ~(1 << 10);
// === Return fake fixed value ===
return 151; // Fixed fake distance in cm
}
// ================= Delay (approx microseconds) =================
void delay_us(uint32_t us)
{
for (volatile uint32_t i = 0; i < (us * 16); i++);
}