NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Saving text to EEPROM

June 20, 2010
by n3ueaEMTP
n3ueaEMTP's Avatar

Greetings all & Happy Fathers day to those of you who are dads! I'm woking on a proejct that will save text to the EEPROM but I'm falling short. The idea is to be able to change the words displayed on the LCD without reprogramming the MCU. Here is the midified keyboard.c code from the tutorial. most of the changes are at the end but I've included the entire program here for reference. Any help would be appriecated. Thanks!!!

// keyboard.c // for NerdKits with ATmega168 // hevans@nerdkits.com // // Designed for use with the USB NerdKit running with ATMega168. Datasheet page // numbers refer to ATMega168 datasheet.

define F_CPU 14745600

include <stdio.h>

include <avr/io.h>

include <avr/interrupt.h>

include <avr/pgmspace.h>

include <inttypes.h>

include <avr/eeprom.h>

include "../libnerdkits/io_328p.h"

include "../libnerdkits/delay.h"

include "../libnerdkits/lcd.h"

include "../libnerdkits/uart.h"

include "keymap.h"

//Keyboard pin out //Green - pin 5 - clock //Yellow - pin 3 - GND //White - pin 1 - data //Red - pin 4 - VCC

//PIN configuration //PC4 (PCINT12) - CLK //PC2 - DATA

volatile uint8_t kbd_data; volatile uint8_t char_waiting; uint8_t started; uint8_t bit_count; uint8_t shift; uint8_t caps_lock; uint8_t extended; uint8_t release; char msg[20];

ISR(PCINT1_vect){

//make sure clock line is low, if not ignore this transition if(PINC & (1<<PC4)){ return; }

//if we have not started, check for start bit on DATA line if(!started){ if ( (PINC & (1<<PC2)) == 0 ) { started = 1; bit_count = 0; kbd_data = 0; //printf_P(PSTR("%d"),started); return; } } else if(bit_count < 8) { //we started, read in the new bit //put a 1 in the right place of kdb_data if PC2 is high, leave //a 0 otherwise if(PINC & (1<<PC2)){ kbd_data |= (1<<bit_count); } bit_count++; return; } else if(bit_count == 8){ //pairty bit //not implemented bit_count++; return; } else { //stop bit //should check to make sure DATA line is high, what to do if not? started = 0; bit_count = 0; }

if(kbd_data == 0xF0){ //release code release = 1; kbd_data = 0; return; } else if (kbd_data == 0x12) { //hanlde shift key if(release == 0){ shift = 1; } else { shift = 0; release = 0; } return; } else { //not a special character if(release){ //we were in release mode - exit release mode release = 0; //ignore that character } else { char_waiting = 1; } }

}

char render_scan_code(uint8_t data){ char to_ret = pgm_read_byte(&(keymap[data])); //grab character from array if(shift){ to_ret -= 0x20; } return to_ret; }

uint8_t read_char(){ while(!char_waiting){ //wait for a character } char_waiting = 0; return kbd_data; }

void init_keyboard(){

started = 0; kbd_data = 0; bit_count = 0;

//make PC4 input pin //DDRC &= ~(1<<PC4); //turn on pullup resistor PORTC |= (1<<PC4);

//Enable PIN Change Interrupt 1 - This enables interrupts on pins //PCINT14...8 see p70 of datasheet PCICR |= (1<<PCIE1);

//Set the mask on Pin change interrupt 1 so that only PCINT12 (PC4) triggers //the interrupt. see p71 of datasheet PCMSK1 |= (1<<PCINT12); }

int main() {

uint8_t i;

//fire up the LCD lcd_init(); FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE); lcd_home();

uart_init(); FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); stdin = stdout = &uart_stream;

init_keyboard();

//enable interrupts sei();

//debug LED - output DDRC |= (1<<PC3);

PORTC |= (1<<PC5); PORTC |= (1<<PC1);

uint8_t key_code = 0;

char str_buf[255]; msg[1] = eeprom_read_byte(10); uint8_t buf_pos = 0; str_buf[0] = str_buf[1] = 0x00; while(1) { if(char_waiting){ key_code = read_char(); if(key_code == 0x5A){ // enter key, clear the line buf_pos = 0; str_buf[0] = str_buf[1] = 0x00; } else if (key_code == 0x66){ //backspace buf_pos--; str_buf[buf_pos] = 0x00; } else { str_buf[buf_pos] = render_scan_code(key_code); buf_pos++; str_buf[buf_pos] = 0x00; //msg[buf_pos] = str_buf[buf_pos]; } }

lcd_home();
fprintf_P(&lcd_stream,PSTR("%-20s"),str_buf);
fprintf_P(&lcd_stream,PSTR("   waiting for char   "));

if(shift){
  lcd_line_two();
  fprintf_P(&lcd_stream,PSTR("SHIFT"));
} else {
  lcd_line_two();
  fprintf_P(&lcd_stream,PSTR("          "));
}
 if((PINC & (1<<PC5)) == 0)
    {
            {
            lcd_line_four();
            eeprom_write_byte(10, str_buf);
            fprintf_P(&lcd_stream,PSTR("%-20s"),str_buf);
            lcd_line_three();
            fprintf_P(&lcd_stream,PSTR("   Message Saved   "));

            }
    }
if((PINC & (1<<PC1)) == 0)
    {
            {
            lcd_home();
            lcd_line_four();
            fprintf_P(&lcd_stream,PSTR("%-20s"),msg);
            }
    }
}

return 0; }

June 21, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi n3ueaEMTP,

It looks like you have the right general idea by using eeprom_write_byte(), however it doesn't look like you are using it quite right. The first argument to the eeprom_write_byte() is a eeprom address in which to put the byte, the second is a pointer to the byte. So your function is saving the first byte of your str_buf to eeprom address 10.

In order to save strings to eeprom you are going to have to work out a way to save the whole string one byte at a time, and a way to keep track of how long they are and where they are saved in the eeprom. I'm sure with a little bit of work you can get something going.

Here is a link to a tutorial on saving stuff to eeprom on avr-freaks that does a great job. You should look at the way the use eeprom_read_block() to save strings to the eeprom.

Hope that helps.

Humberto

Post a Reply

Please log in to post a reply.

Did you know that a motor's no-load current at a given voltage is much less than it's resistance would suggest? Learn more...