Skip to content

Instantly share code, notes, and snippets.

@cpjobling

cpjobling/main.c Secret

Last active October 27, 2023 08:09
Show Gist options
  • Save cpjobling/db5e3e157b6e6153f7cb75157dae1e94 to your computer and use it in GitHub Desktop.
Save cpjobling/db5e3e157b6e6153f7cb75157dae1e94 to your computer and use it in GitHub Desktop.
EG-151 - Lecture 6: Atmel ATmega326 ADC Example
/*
PORTD maps to Arduino digital pins 0 to 7
DDRD - The Port D Data Direction Register - read/write
PORTD - The Port D Data Register - read/write
PIND - The Port D Input Pins Register - read only
PORTB maps to Arduino digital pins 8 to 13 The two high bits (6 & 7) map to the crystal pins and are not usable
DDRB - The Port B Data Direction Register - read/write
PORTB - The Port B Data Register - read/write
PINB - The Port B Input Pins Register - read only
PORTC maps to Arduino analog pins 0 to 5. Pins 6 & 7 are only accessible on the Arduino Mini
DDRC - The Port C Data Direction Register - read/write
PORTC - The Port C Data Register - read/write
PINC - The Port C Input Pins Register - read only
*/
#include <stdint.h>
//I/O and ADC Register definitions taken from datasheet
#define PORTB (*(volatile uint8_t *)(0x25))
#define DDRB (*(volatile uint8_t *)(0x24))
#define PINB (*(volatile uint8_t *)(0x23))
#define ADMUX (*(volatile uint8_t *)(0x7C))
#define ADCSRA (*(volatile uint8_t *)(0x7A))
#define ADCRSB (*(volatile uint8_t *)(0x7B))
#define ADCH (*(volatile uint8_t *)(0x79))
#define ADCL (*(volatile uint8_t *)(0x78))
#define DIDR0 (*(volatile uint8_t *)(0x7E))
uint16_t adc_result, previous_result = 0;
uint8_t adc_result_low, adc_result_high;
int main(void)
{
// Set Data Direction Registers
DDRB = DDRB | 0b00111111; //Setup bits 0 - 5 of port B as outputs
// Turn all LEDs off
PORTB = PORTB & 0b11000000; // Pins B0 (D8) - B5 (D13) start low
// Set up ADC on pin A0
DIDR0 = DIDR0 | 0b00000001; // Disable pin A0 as a digital input
ADMUX = 0b01000000; // Select reference voltage, right adjusted result and select channel ADC0 - A0
ADCSRA = ADCSRA | 0b00000111; // Select ADC Prescaler
ADCSRA = ADCSRA | 0b10000000; // Enable ADC
for(;;)
{
ADCSRA = ADCSRA | 0b01000000; //start conversion by writing 1 to the ADSC bit
while((ADCSRA & 0b01000000) != 0) { } //wait until the ADSC bit changes to 0
adc_result_low = ADCL; //read the low byte of the result into adc_result_low
adc_result_high = ADCH; //read the high byte of the result into adc_result_high
/* shift whole 8 bits of ADC high byte into most significant byte of ADC result and
add in ADC low byte using bitwise OR. */
adc_result = (adc_result_high<<8) | adc_result_low;
if (previous_result < adc_result)
{
if (adc_result >= 854) {PORTB = PORTB | 0b00111111;}
else if (adc_result >= 684) {PORTB = PORTB | 0b00011111;}
else if (adc_result >= 513) {PORTB = PORTB | 0b11001111;}
else if (adc_result >= 342) {PORTB = PORTB | 0b11000111;}
else if (adc_result >= 171) {PORTB = PORTB | 0b11000011;}
else if (adc_result >= 1) {PORTB = PORTB | 0b11000001;}
else PORTB = PORTB & 0b11000000;
}
else if (previous_result > adc_result)
{
if (adc_result >= 854) {PORTB = PORTB & 0b11111111;}
else if (adc_result >= 684) {PORTB = PORTB & 0b11011111;}
else if (adc_result >= 513) {PORTB = PORTB & 0b11001111;}
else if (adc_result >= 342) {PORTB = PORTB & 0b11000111;}
else if (adc_result >= 171) {PORTB = PORTB & 0b11000011;}
else if (adc_result >= 1) {PORTB = PORTB & 0b11000001;}
else PORTB = PORTB & 0b11000000;
}
else{}
previous_result = adc_result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment