| CODE |
/********************************************* * Chip type : ATmega16 * Clock frequency : 2457600Hz *********************************************/ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #include <inttypes.h> #include <avr/iom16.h> #include "e2prom.h" #define F_OSC 2457600 /* oscillator-frequency in Hz */ #define UART_BAUD_RATE 9600 #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16l)-1) void delay_ms(unsigned short ms) { unsigned short outer1, outer2; outer1 = 200; while (outer1) { outer2 = 1000; while (outer2) { while ( ms ) ms--; outer2--; } outer1--; } } void usart_putc(unsigned char c) { // wait until UDR ready while(!(UCSRA & (1 << UDRE))); UDR = c; // send character } void uart_puts (char *s) { // loop until *s != NULL while (*s) { usart_putc(*s); s++; } } void init(void) { // set baud rate UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8); UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC); // Enable receiver and transmitter; enable RX interrupt UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE); //asynchronous 8N1 UCSRC = (1<<URSEL)|(3<<UCSZ0); } // INTERRUPT can be interrupted // SIGNAL can't be interrupted SIGNAL (SIG_UART_RECV) { // USART RX interrupt unsigned char c; c = UDR; usart_putc(c); } int main(void) { char buffer; char buffer2; init(); sei(); // send initial character while(!(UCSRA & (1 << UDRE))); UDR = 0x43; // "C" while(!(UCSRA & (1 << UDRE))); UDR = 0x0d; eeprom_init(); // write first character to eeprom // buffer = 0x21; // "!" buffer = 0x23; // "#" eeprom_write_byte(10, buffer); delay_ms(500); // write second character to e2prom // buffer = 0x40; // "@" buffer = 0x24; // "$" eeprom_write_byte(11, buffer); delay_ms(500); // read first character from eeprom eeprom_read_byte(10, &buffer2); while(!(UCSRA & (1 << UDRE))); UDR = buffer2; while(!(UCSRA & (1 << UDRE))); UDR = 0x0d; // read second character from e2prom eeprom_read_byte(11, &buffer2); while(!(UCSRA & (1 << UDRE))); UDR = buffer2; while(!(UCSRA & (1 << UDRE))); UDR = 0x0d; // blink LED // enable PD5 as output DDRD |= (1<<PD5); while (1) { // PIN5 PORTD set -> LED on PORTD |= (1<<PD5); delay_ms(500); // PIN5 PORTD clear -> LED off PORTD &= ~(1<<PD5); delay_ms(500); } return 0; } |
| CODE |
// EEPROM functions // NOTE: These are the functions only for a 24C64! // If you use a smaller/bigger E2PROM, the I2C communication works different! // Check the datasheet of the EEPROM you'd like to use and modify the // functions. i.e. smaller I2C EEPROM's already have the high-byte address // information in the inital byte (which is 0xa0 or 0xa1 in this case). #include "e2prom.h" uint8_t twst; void eeprom_init(void) { /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ #if defined(TWPS0) /* has prescaler (mega128 & newer) */ TWSR = 0; #endif TWBR = 6; } int eeprom_read_byte(uint16_t eeaddr, char *buf) { uint8_t n = 0; restart: if (n++ >= MAX_TRIES) return -1; begin: // send start cond. TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if ( (TW_STATUS != TW_REP_START) && (TW_STATUS != TW_START)) { return -1; } // send 0xa0 // 0xa0 = 1010 000 0 // 4 bits: <a..device-indentifier> // 3 bits: <device-address set with chip pins> // last bit: <0..write> TWDR = 0xa0; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_SLA_NACK) goto restart; if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if (TW_STATUS != TW_MT_SLA_ACK) goto error; // send low 8 bits of eeaddr TWDR = eeaddr; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_DATA_NACK) goto restart; if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if (TW_STATUS != TW_MT_DATA_ACK) goto error; // send high 8 bits of eeaddr TWDR = eeaddr << 8; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_DATA_NACK) goto restart; if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if (TW_STATUS != TW_MT_DATA_ACK) goto error; // send start cond. TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if ( (TW_STATUS != TW_REP_START) && (TW_STATUS != TW_START)) { return -1; } // send 0xa1 // 0xa0 = 1010 000 1 // 4 bits: <a..device-indentifier> // 3 bits: <device-address set with chip pins> // last bit: <1..read> TWDR = 0xa1; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MR_SLA_NACK) goto quit; if (TW_STATUS == TW_MR_ARB_LOST) goto begin; if (TW_STATUS != TW_MR_SLA_ACK) goto error; // start read transmission TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); switch ((twst = TW_STATUS)) { case TW_MR_DATA_NACK: // FALLTHROUGH case TW_MR_DATA_ACK: *buf = TWDR; break; default: goto error; } quit: //stop condition TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); return 1; error: //stop condition TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); return -1; } int eeprom_write_byte(uint16_t eeaddr, char buf) { uint8_t n = 0; restart: if (n++ >= MAX_TRIES) return -1; begin: // start cond. TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if ( (TW_STATUS != TW_REP_START) && (TW_STATUS != TW_START)) { return -1; } // send 0xa0 // 0xa0 = 1010 000 0 // 4 bits: <a..device-indentifier> // 3 bits: <device-address set with chip pins> // last bit: <0..write> TWDR = 0xa0; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_SLA_NACK) goto restart; if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if (TW_STATUS != TW_MT_SLA_ACK) goto error; // send low 8 bits of eeaddr TWDR = eeaddr; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_DATA_NACK) goto quit; if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if (TW_STATUS != TW_MT_DATA_ACK) goto error; // send high 8 bits of eeaddr TWDR = eeaddr << 8; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS == TW_MT_DATA_NACK) goto quit; if (TW_STATUS == TW_MT_ARB_LOST) goto begin; if (TW_STATUS != TW_MT_DATA_ACK) goto error; // put byte into data register and start transmission TWDR = buf; TWCR = (1 << TWINT) | (1 << TWEN); while (!(TWCR & (1 << TWINT))); if (TW_STATUS != TW_MT_DATA_ACK) goto error; quit: // send stop condition TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); return 1; error: // send stop condition TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); return -1; } e2prom.h #include <compat/twi.h> #define MAX_TRIES 100 int eeprom_read_byte(uint16_t eeaddr, char *buf); int eeprom_write_byte(uint16_t eeaddr, char buf); void eeprom_init(void); |
| CODE |
MCU=atmega16 CC=avr-gcc OBJCOPY=avr-objcopy # optimize for size: CFLAGS=-g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues #------------------- all: e2prom.o eeprom.hex #------------------- eeprom.hex : eeprom.out $(OBJCOPY) -R .eeprom -O ihex eeprom.out eeprom.hex eeprom.out : eeprom.o $(CC) $(CFLAGS) -o eeprom.out -Wl,-Map,eeprom.map eeprom.o e2prom.o eeprom.o : eeprom.c $(CC) $(CFLAGS) -Os -c eeprom.c e2prom.o : e2prom.c $(CC) $(CFLAGS) -Os -c e2prom.c # you need to erase first before loading the program. # load (program) the software into the eeprom: load: eeprom.hex uisp -dlpt=/dev/parport0 --erase -dprog=dapa -dpart=ATmega16 uisp -dlpt=/dev/parport0 --upload if=eeprom.hex -dprog=dapa -dpart=ATmega16 -v=3 --hash=32 #------------------- clean: rm -f *.o *.map *.out #------------------- |