commit a6ab36790f1aff0b936c2a008e41097e2375d11e Author: Imbus <> Date: Fri Feb 9 02:14:45 2024 +0100 Initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9e64c4c --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# Compiled object files +*.o +*.hex + +# Executables +*.exe +*.out +*.elf + +# Build directories +build/ +bin/ + +# IDE and editor files +.vscode/ +.idea/ +*.sublime-project +*.sublime-workspace + +# Dependency directories +lib/ +vendor/ + +# Log files +*.log + +# OS generated files +.DS_Store +Thumbs.db diff --git a/main.c b/main.c new file mode 100644 index 0000000..bbd7081 --- /dev/null +++ b/main.c @@ -0,0 +1,141 @@ +/* + * This code utilizes the AVR libraries for I2C and UART communication. + * Make sure to connect the SDA and SCL pins of the ATmega328P to the + * corresponding pins of your I2C temperature sensor. Additionally, you might + * need pull-up resistors for the I2C lines. + */ + +#include +#include +#include + +#define LED_PIN PB5 // Define the pin connected to the LED +#define TEMP_SENSOR_ADDR 0x48 +#define TEMP_REG_ADDR 0x00 +#define BAUD 9600 + +void initI2C() { + // Set the prescaler to 1 + TWSR &= ~(1 << TWPS0); + TWSR &= ~(1 << TWPS1); + // Set the bit rate to 100kHz + TWBR = ((F_CPU / 100000) - 16) / 2; +} + +void I2C_start() { + // Send the start condition + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); + // Wait for the start condition to be sent + while (!(TWCR & (1 << TWINT))) + ; +} + +void I2C_stop() { + // Send the stop condition + TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); + // Wait for the stop condition to be sent + while (TWCR & (1 << TWSTO)); +} + +void I2C_write(uint8_t data) { + // Load the data into the data register + TWDR = data; + // Start transmission of data + TWCR = (1 << TWINT) | (1 << TWEN); + // Wait for the data to be sent + while (!(TWCR & (1 << TWINT))); +} + +uint8_t I2C_read(uint8_t ack) { + // Enable TWI, generate ACK (if ack = 1) and clear TWI interrupt flag + TWCR = (1 << TWINT) | (1 << TWEN) | (ack << TWEA); + // Wait until TWI finish its current job (read operation) + while (!(TWCR & (1 << TWINT))); + // Return received data + return TWDR; +} + +void initUART() { + // Set baud rate + UBRR0H = (uint8_t)(F_CPU / (BAUD * 16UL) - 1) >> 8; + UBRR0L = (uint8_t)(F_CPU / (BAUD * 16UL) - 1); + // Enable receiver and transmitter + UCSR0B |= (1 << RXEN0) | (1 << TXEN0); + // Set frame format: 8 data, 1 stop bit + UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00); +} + +void UART_transmit(uint8_t data) { + // Wait for empty transmit buffer + while (!(UCSR0A & (1 << UDRE0))); + // Put data into buffer, sends the data + UDR0 = data; +} + +void UART_println(const char *str) { + // Transmit each character until NULL character is encountered + while (*str) UART_transmit(*str++); + // Transmit carriage return and line feed characters + UART_transmit('\r'); + UART_transmit('\n'); +} + +float readTemperature() { + uint16_t temperature; + + // Send start condition + I2C_start(); + // Send device address with write operation + I2C_write((TEMP_SENSOR_ADDR << 1) | 0); + // Send temperature register address + I2C_write(0x00); + // Repeat start + I2C_start(); + // Send device address with read operation + I2C_write((TEMP_SENSOR_ADDR << 1) | 1); + // Read temperature data MSB + temperature = (uint16_t)(I2C_read(1)) << 8; + // Read temperature data LSB + temperature |= I2C_read(0); + // Send stop condition + I2C_stop(); + + // Convert raw data to temperature in Celsius + return (float)temperature * 0.0625; +} + +int main(void) { + initI2C(); + initUART(); + + float temperature; + + while (1) { + temperature = readTemperature(); + // Print temperature over UART + UART_println("Temperature: "); + UART_transmit((uint8_t)(temperature / 10.0) + '0'); + UART_transmit((uint8_t)fmod(temperature, 10.0) + '0'); + UART_println(" °C"); + _delay_ms(1000); // Delay for 1 second + } + + return 0; +} + +void blink() { + // Set the LED pin as output + DDRB |= (1 << LED_PIN); + + while (1) { + // Turn on the LED by setting the pin high + PORTB |= (1 << LED_PIN); + // Delay for 500 milliseconds + _delay_ms(500); + + // Turn off the LED by setting the pin low + PORTB &= ~(1 << LED_PIN); + // Delay for 500 milliseconds + _delay_ms(500); + } +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..272b3ff --- /dev/null +++ b/makefile @@ -0,0 +1,44 @@ +# AVR-GCC compiler +CC = avr-gcc + +# Programmer (change it according to your programmer) +PROGRAMMER = usbasp + +# MCU +MCU = atmega328p + +# Compiler flags +CFLAGS = -std=c99 -Wall -Wno-array-bounds -mmcu=$(MCU) -DF_CPU=16000000UL -O3 + +# Source files +SRCS = main.c + +# Object files +OBJS = $(SRCS:.c=.o) + +# Target file +TARGET = main + +# Default target +all: $(TARGET).hex + +# Compile C files +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Link object files +$(TARGET).elf: $(OBJS) + $(CC) $(CFLAGS) $(OBJS) -o $(TARGET).elf + +# Convert ELF to HEX +$(TARGET).hex: $(TARGET).elf + avr-objcopy -O ihex -R .eeprom $(TARGET).elf $(TARGET).hex + +# Flash the program +flash: $(TARGET).hex + avrdude -p $(MCU) -c $(PROGRAMMER) -U flash:w:$(TARGET).hex + +# Clean +clean: + rm -f $(OBJS) $(TARGET).elf $(TARGET).hex +