/* (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 #include #include #include 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; }