Quellcode ansehen

/*
    (C) 2010.08 jInvent Sofware Development (prog@jinvent.de)
    License: LGPL3
    ATMEGA168, 18.432 MHz, 9600 baud UART
    Interface to ADC values
*/

#define F_CPU       18432000UL
#define BAUDRATE    9600
#define UART_UBRR_CALC(BAUD_, FREQ_) ((uint16_t)rround((FREQ_) / \
        ((BAUD_ / 2) * 16L) - 1, 0))
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <math.h>

float rround(float val, uint8_t digits) {
    float v[] = { 1, 10, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8 };
    return floor(val * v[digits] + 0.5) / v[digits];
}

uint8_t mutex = 0;
uint16_t steps = 0, flashes = 0, delay = 0, delay_steps = 0;

inline void time_init(void) {
    TCCR2A = 0;             /* normal operation mode */
    TCCR2B = (1 << CS22);     /* prescaler: clk/64 */
    TIMSK2 = (1 << TOIE2);    /* enable overflow interrupt */
}

#define TIMER_MSFACTOR (F_CPU / 64 / 256) / 1000

ISR (TIMER2_OVF_vect) {
    if (++steps >= delay_steps) {
        steps = 0;
        mutex = 1;
    }

    if (++flashes >= 500 * TIMER_MSFACTOR) {
        flashes = 0;
        PORTD ^= (1 << PD4);
    }
}

inline void uart_putchar(unsigned char character) {
    while (!(UCSR0A & (1 << UDRE0)));
    UDR0 = character;
}

inline void uart_puts(char *data) {
    while (*data) {
        uart_putchar(*data);
        data++;
    }
}

inline inline void uart_puti(uint16_t integer) {
    char buffer[6];
    uart_puts(utoa(integer, buffer, 10));
}

inline unsigned char uart_getchar(void) {
    if (!(UCSR0A & (1 << RXC0))) return 0;
    return UDR0;
}

uint16_t adc(uint8_t admux) {
    ADCSRA =  (1 << ADEN)  | (1 << ADPS1) | (1 << ADPS0);
    ADMUX = admux;
    ADMUX |= (1 << REFS1) | (1 << REFS0);
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADSC));
    uint16_t val = ADCW;
    ADCSRA &= ~(1 << ADEN);
    return val;
}

char channel = '1'; /* '1' to '6' on atmega168 */

inline void measurement(void) {
    uart_puts("adc ");
    uart_putchar(channel);
    uart_puts(": ");
    uart_puti(adc(channel - '1'));
    uart_putchar('\n');
}

void setdelay(uint16_t d) {
    delay_steps = (delay = d) * TIMER_MSFACTOR;
    uart_puts("delay set to ");
    uart_puti(delay);
    uart_puts(" milliseconds.\n");
}

int main(void) {
    uint8_t automeasure = 0;
    char c;

    /* UART */
    UBRR0H = (uint8_t)(UART_UBRR_CALC(BAUDRATE, F_CPU) >> 8);
    UBRR0L = (uint8_t)UART_UBRR_CALC(BAUDRATE, F_CPU);
    UCSR0A = (1 << UDRE0) | (1 << U2X0);
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    /* LED */
    DDRD = (1 << PD4);

    /* timer */
    time_init();
    sei();

    /* welcome */
    uart_puts("adc measurement module (help with 'h')\n");
    uart_puts("  (C) 2010 jInvent Software Development (prog@jinvent.de)\n");
    setdelay(500);

    while (1) {
        /* user interface */
        _delay_ms(1);
        switch ((c = uart_getchar())) {
            case 0: case 10: break;
            case '1': case '2': case '3': case '4': case '5': case '6':
                channel = c;
                uart_puts("set channel: ");
                uart_putchar(channel);
                uart_putchar('\n');
                break;
            case 32: /* space key */
                measurement();
                break;
            case 'a':
                if ((automeasure = 1 - automeasure))
                   uart_puts("auto measurement activated.\n");
                else
                   uart_puts("auto measurement deactivated.\n");
                mutex = 0;
                break;
            case 'A': setdelay(5); break;
            case 'B': setdelay(20); break;
            case 'C': setdelay(50); break;
            case 'D': setdelay(100); break;
            case 'E': setdelay(200); break;
            case 'F': setdelay(500); break;
            case 'h':
            default:
                uart_puts("help:\n");
                uart_puts("  1 - 6: choose adc channel\n");
                uart_puts("  space key: measure\n");
                uart_puts("  a: toggle auto measurement\n");
                uart_puts("  A - F: choose delay for auto measurement\n");
                uart_puts("    5ms -- 20ms -- 50ms -- 100ms -- 250ms -- 500ms\n");
        }

        /* auto measurement */
        if (automeasure && mutex) {
            mutex = 0;
            measurement();
        }
    }

    return 0;
}

© 2009 Julian von Mendel (http://derjulian.net) | Datum: 16.12.2018