voltmeter
changeset 0:d26d73ef2db7
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 27 Jan 2013 10:11:40 +0200 |
parents | |
children | 40b150fedb0e |
files | Makefile voltmeter.c |
diffstat | 2 files changed, 286 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Sun Jan 27 10:11:40 2013 +0200 1.3 @@ -0,0 +1,34 @@ 1.4 +src = $(wildcard *.c) 1.5 +obj = $(src:.c=.o) 1.6 +bin = voltmeter 1.7 +hex = $(bin).hex 1.8 +eep = $(bin).eep 1.9 + 1.10 +mcu_gcc = atmega168 1.11 +mcu_dude = m168 1.12 + 1.13 +CC = avr-gcc 1.14 +OBJCOPY = avr-objcopy 1.15 + 1.16 +CFLAGS = -O2 -pedantic -Wall -mmcu=$(mcu_gcc) 1.17 +LDFLAGS = -Wl,-Map,$(bin).map -mmcu=$(mcu_gcc) -Wl,-u,vfprintf -lprintf_flt -lm 1.18 + 1.19 +.PHONY: all 1.20 +all: $(hex) $(eep) 1.21 + 1.22 +$(bin): $(obj) 1.23 + $(CC) -o $@ $(obj) $(LDFLAGS) 1.24 + 1.25 +$(hex): $(bin) 1.26 + $(OBJCOPY) -j .text -j .data -O ihex -R .eeprom $< $@ 1.27 + 1.28 +$(eep): $(bin) 1.29 + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ 1.30 + 1.31 +.PHONY: program 1.32 +program: $(hex) 1.33 + avrdude -c usbtiny -p $(mcu_dude) -e -U flash:w:$(hex) 1.34 + 1.35 +.PHONY: clean 1.36 +clean: 1.37 + rm -f $(bin) $(obj) $(hex) $(eep) $(bin).map
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/voltmeter.c Sun Jan 27 10:11:40 2013 +0200 2.3 @@ -0,0 +1,252 @@ 2.4 +#define F_CLK 1000000 2.5 +#define F_CPU 1000000 2.6 + 2.7 +#include <stdio.h> 2.8 +#include <avr/io.h> 2.9 +#include <util/delay.h> 2.10 + 2.11 +/* hardware setup 2.12 + * - PORT D: data bits 2.13 + * - PORT C 2.14 + * bit 0: RS 2.15 + * bit 1: R/W 2.16 + * bit 2: E 2.17 + */ 2.18 + 2.19 +#define BIT_RS 3 2.20 +#define BIT_RW 4 2.21 +#define BIT_E 5 2.22 + 2.23 +#define CMD_CLEAR 1 2.24 +#define CMD_RET (1 << 1) 2.25 +#define CMD_ENTRY_MODE (1 << 2) 2.26 +#define CMD_ONOFF (1 << 3) 2.27 +#define CMD_SHIFT (1 << 4) 2.28 +#define CMD_FUNC (1 << 5) 2.29 +#define CMD_CGRAM_ADDR (1 << 6) 2.30 +#define CMD_DDRAM_ADDR (1 << 7) 2.31 + 2.32 +#define FUNC_BUS_4BIT 0 2.33 +#define FUNC_BUS_8BIT (1 << 4) 2.34 +#define FUNC_LINES_1 0 2.35 +#define FUNC_LINES_2 (1 << 3) 2.36 +#define FUNC_FONT_5x8 0 2.37 +#define FUNC_FONT_5x11 (1 << 2) 2.38 + 2.39 +#define ONOFF_DISP (1 << 2) 2.40 +#define ONOFF_CURSOR (1 << 1) 2.41 +#define ONOFF_CURSOR_POS 1 2.42 + 2.43 +void setup_adc(void); 2.44 +long read_adc(void); 2.45 + 2.46 +void lcd_init(void); 2.47 +void lcd_clear(void); 2.48 +void lcd_set_cursor_addr(unsigned int addr); 2.49 +void lcd_putchar(char c); 2.50 +void lcd_putstr(const char *str); 2.51 +int lcd_stream_write(char c, FILE *fp); 2.52 +void lcd_wait_busy(void); 2.53 +static void enable(void); 2.54 +static void set_bit(int bit); 2.55 +static void clear_bit(int bit); 2.56 +void delay(int x); 2.57 + 2.58 +#define NSDELAY() asm volatile ("nop") 2.59 +#define DEBUG(i) (PORTB = (1 << (i))) 2.60 + 2.61 +FILE stream_lcd = FDEV_SETUP_STREAM(lcd_stream_write, NULL, _FDEV_SETUP_WRITE); 2.62 + 2.63 +int main(void) 2.64 +{ 2.65 + stdout = stderr = &stream_lcd; 2.66 + 2.67 + DDRC = 0xfe; 2.68 + PORTC = 0; /* disable pullups */ 2.69 + 2.70 + lcd_init(); 2.71 + lcd_clear(); 2.72 + 2.73 + printf("initializing..."); 2.74 + setup_adc(); 2.75 + 2.76 + for(;;) { 2.77 + long val = read_adc(); 2.78 + double ref = 1.08 * 1.47 / 0.47; 2.79 + double voltage = ref * (double)val / (double)1024; 2.80 + lcd_clear(); 2.81 + 2.82 + if(val == 1023) { 2.83 + printf("*** RANGE *** "); 2.84 + } else { 2.85 + printf("%.2f volts ", voltage); 2.86 + } 2.87 + _delay_ms(500); 2.88 + } 2.89 + return 0; 2.90 +} 2.91 + 2.92 +void setup_adc(void) 2.93 +{ 2.94 + /* disable digital input buffer on ADC0 pin */ 2.95 + DIDR0 = 1; 2.96 + 2.97 + /* use the internal bandgap as a reference */ 2.98 + ADMUX = 3 << REFS0; 2.99 + 2.100 + /* - enable ADC 2.101 + * - set ADC clock prescaler to clock / 8 2.102 + */ 2.103 + ADCSRA = (1 << ADEN) | (3 << ADPS0); 2.104 +} 2.105 + 2.106 +long read_adc(void) 2.107 +{ 2.108 + long low; 2.109 + 2.110 + /* start conversion */ 2.111 + ADCSRA |= (1 << ADSC); 2.112 + 2.113 + /* wait while converting */ 2.114 + while(ADCSRA & (1 << ADSC)); 2.115 + 2.116 + low = ADCL; 2.117 + return low | ((long)ADCH << 8); 2.118 +} 2.119 + 2.120 +void lcd_init(void) 2.121 +{ 2.122 + DDRD = 0x0f; /* port d[0, 3] -> output */ 2.123 + 2.124 + /* make sure the display has time to boot up */ 2.125 + _delay_ms(20); 2.126 + 2.127 + clear_bit(BIT_RW); 2.128 + 2.129 + clear_bit(BIT_E); 2.130 + clear_bit(BIT_RS); 2.131 + PORTD = CMD_FUNC | FUNC_BUS_8BIT | FUNC_LINES_2 | FUNC_FONT_5x8; 2.132 + enable(); 2.133 + lcd_wait_busy(); 2.134 + 2.135 + clear_bit(BIT_RS); 2.136 + PORTD = CMD_ONOFF | ONOFF_DISP | ONOFF_CURSOR; 2.137 + enable(); 2.138 + lcd_wait_busy(); 2.139 + 2.140 + clear_bit(BIT_RS); 2.141 + PORTD = CMD_ENTRY_MODE | (1 << 1); 2.142 + enable(); 2.143 + lcd_wait_busy(); 2.144 +} 2.145 + 2.146 +void lcd_clear(void) 2.147 +{ 2.148 + DDRD = 0xff; /* port d -> output */ 2.149 + 2.150 + clear_bit(BIT_RW); 2.151 + 2.152 + clear_bit(BIT_E); 2.153 + clear_bit(BIT_RS); 2.154 + PORTD = CMD_CLEAR; 2.155 + enable(); 2.156 + lcd_wait_busy(); 2.157 +} 2.158 + 2.159 +void lcd_set_cursor_addr(unsigned int addr) 2.160 +{ 2.161 + DDRD = 0xff; /* port d -> output */ 2.162 + 2.163 + clear_bit(BIT_RW); 2.164 + 2.165 + clear_bit(BIT_E); 2.166 + clear_bit(BIT_RS); 2.167 + PORTD = CMD_DDRAM_ADDR | addr; 2.168 + enable(); 2.169 + lcd_wait_busy(); 2.170 +} 2.171 + 2.172 +void lcd_putchar(char c) 2.173 +{ 2.174 + DDRD = 0xff; /* port d -> output */ 2.175 + 2.176 + clear_bit(BIT_RW); 2.177 + 2.178 + set_bit(BIT_RS); 2.179 + PORTD = c; 2.180 + enable(); 2.181 + lcd_wait_busy(); 2.182 +} 2.183 + 2.184 +void lcd_putstr(const char *str) 2.185 +{ 2.186 + while(*str) { 2.187 + lcd_putchar(*str++); 2.188 + } 2.189 +} 2.190 + 2.191 +int lcd_stream_write(char c, FILE *fp) 2.192 +{ 2.193 + /* TODO terminal shit handling */ 2.194 + lcd_putchar(c); 2.195 + return 0; 2.196 +} 2.197 + 2.198 +void lcd_wait_busy(void) 2.199 +{ 2.200 + unsigned char data; 2.201 + 2.202 + DDRD = 0; /* port d -> input */ 2.203 + PORTD = 0; /* disable pull-ups */ 2.204 + 2.205 + do { 2.206 + NSDELAY(); 2.207 + clear_bit(BIT_E); 2.208 + clear_bit(BIT_RS); 2.209 + set_bit(BIT_RW); 2.210 + /*PIND = 0xff;*/ 2.211 + 2.212 + NSDELAY(); 2.213 + set_bit(BIT_E); 2.214 + NSDELAY(); 2.215 + data = PIND; 2.216 + clear_bit(BIT_E); 2.217 + clear_bit(BIT_RW); 2.218 + 2.219 + } while(data & (1 << 7)); 2.220 + 2.221 + DDRD = 0xff; /* port d -> output */ 2.222 +} 2.223 + 2.224 +static void enable(void) 2.225 +{ 2.226 + NSDELAY(); 2.227 + set_bit(BIT_E); 2.228 + NSDELAY(); 2.229 + clear_bit(BIT_E); 2.230 + NSDELAY(); 2.231 +} 2.232 + 2.233 +static void set_bit(int bit) 2.234 +{ 2.235 + PORTC |= 1 << bit; 2.236 +} 2.237 + 2.238 +static void clear_bit(int bit) 2.239 +{ 2.240 + PORTC &= ~(1 << bit); 2.241 +} 2.242 + 2.243 + 2.244 +void delay(int x) 2.245 +{ 2.246 + int i, j; 2.247 + 2.248 + while(x-- > 0) { 2.249 + for(i=0; i<90; i++) { 2.250 + for(j=0; j<6; j++) { 2.251 + asm volatile("nop"); 2.252 + } 2.253 + } 2.254 + } 2.255 +}