EEPROM не записывает данные должным образом Atmega32 C - PullRequest
0 голосов
/ 02 августа 2020

У меня есть программа, которая считывает датчики температуры и давления и выполняет на них внутреннее преобразование AD C, затем сохраняет данные в EEPROM, затем конвертирует обратно в исходное значение и отображает его на ЖК-дисплее. Проблема в том, что когда я отлаживаю программу в Atmel, кажется, что она работает нормально. Но на самом деле кода нет в моей схеме. Кажется, он правильно записывает и читает только первые 2 байта, а затем просто записывает один и тот же байт снова и снова.

Вот мой код для записи данных. Я использую включенную библиотеку eeprom.h и записываю 16-битное значение путем разделения на младшие и старшие байты.

void WriteToEEPROM(uint16_t value, int address){
    
    uint8_t low_value = value;
    uint8_t high_value = (value & 0xFF00) >> 8;
    if ((address == 0) || (address == 100)){}
    else {address++;}
    
    while(!eeprom_is_ready()){}
    eeprom_write_byte((uint8_t*)address, low_value);
    while(!eeprom_is_ready()){}
    address++;
    eeprom_write_byte((uint8_t*)address, high_value);
    while(!eeprom_is_ready()){}
}

Это содержимое EEPROM после завершения записи значений. Обратите внимание, что значение не должно меняться, потому что я сохраняю его постоянным. Правильные значения должны быть 0x134 при «0x0000» и 0x0073 при 0x0064. Я не понимаю, почему это не работает.

Любая помощь приветствуется!

enter image description here

full code

#define __DELAY_BACKWARD_COMPATIBLE__
#define F_CPU 8000000UL
#define  eeprom_is_ready()  
#include <avr/io.h>
#include <avr/delay.h>
#include <stdint.h>
#include <avr/eeprom.h>
#include <stdio.h>

//******************LCD PROGRAM STARTS*********************//
#define LCD_DATA PORTD  // port D is selected as LCD data port
#define ctrl PORTC  // port C is selected as LCD command port
#define en PC2  // enable signal is connected to port D pin 7
#define rw PC1  // read/write signal is connected to port D pin 6
#define rs PC0  // register select signal is connected to port D pin 5

void LCD_cmd(unsigned char cmd);
void init_LCD(void);
void LCD_write(unsigned char data);
void LCD_write_string(char*str);
void WriteToEEPROM(uint16_t value, int address);


void scaled_delay(int delay){
    _delay_ms(delay * 1000);
}

void setup(void){
     DDRA = 0x00;               //PORTA is set as an input
     DDRD = 0xFF;               //PORTD is set as an output
     DDRC = 0xFF;
}

//Temperature sensor output connected to PA0
void ReadTemp(int address){
        
    ADCSRA = ADCSRA | 0b10000111;       //enable ADC, CLK/128 conversion speed
    ADMUX  = ADMUX | 0b01000000;        //Use internal 2.56V Vref and PA0 as input, right-hand justified
        
    ADCSRA |= (1 << ADSC);              //start conversion

    while(!(ADCSRA & (1 << ADIF))) {}
    
    WriteToEEPROM(ADC, address);
}

//Temperature sensor output connected to PA1
void ReadPressure(int address){
    
    ADCSRA = ADCSRA | 0b10000111;       //enable ADC, CLK/128 conversion speed
    ADMUX  = ADMUX | 0b01000001;        //Use AVCC and PA0 as input, right-hand justified
        
    ADCSRA |= (1 << ADSC);              //start conversion
        
    while(!(ADCSRA & (1 << ADIF))){}        // wait until process is finished
    address = address + 100;
    WriteToEEPROM(ADC, address);     
}

void WriteToEEPROM(uint16_t value, int address){
    
    uint8_t low_value = value;
    uint8_t high_value = (value & 0xFF00) >> 8;
    if ((address == 0) || (address == 100)){}
    else {address++;}
    
    while(!eeprom_is_ready()){}
    eeprom_write_byte((uint8_t*)address, low_value);
    while(!eeprom_is_ready()){}
    address++;
    eeprom_write_byte((uint8_t*)address, high_value);
    while(!eeprom_is_ready()){}
}

void ReadEEPROM_Temp(uint8_t address){
    
    uint8_t temp_value_low;
    uint8_t temp_value_high;

    char value_buffer_temp[100] = "";

    if(address != 0) {address++;}
    
    temp_value_low = eeprom_read_byte((uint8_t*)address);       
    address++;
    temp_value_high = eeprom_read_byte((uint8_t*)address);          
    
    uint16_t temp_value = (temp_value_high << 8) | temp_value_low;
    int temperature = (temp_value * 4.88) / 10;

    sprintf(value_buffer_temp,"%s %d %s  ", "Temp ", temperature, "C");
        
    init_LCD();
    LCD_cmd(0x0C);
    _delay_ms(100);
    
    LCD_write_string(value_buffer_temp);
}


void ReadEEPROM_Pres(uint8_t address){
    
    uint8_t pres_value_low;
    uint8_t pres_value_high;
    
    char value_buffer_pres[100] = "";
    
    if(address != 100) {address++;}
    
    pres_value_low = eeprom_read_byte((uint8_t*)address);  
    address++;
    pres_value_high = eeprom_read_byte((uint8_t*)address);  
    
    uint16_t pres_value = (pres_value_high << 8) | pres_value_low;
    int v_out =  (pres_value * 4.88)/1000;
    int pressure = ((v_out/5.1) + 0.095) / 0.009;
    
    sprintf(value_buffer_pres,"%s %d %s  ", "Pres ", pressure, "kPa");
    LCD_cmd(0xC0);
    _delay_ms(100);
    LCD_write_string(value_buffer_pres);
}

void init_LCD(void){
    LCD_cmd(0x38);
    // initialization in 8bit mode of 16X2 LCD
    _delay_ms(1);
    LCD_cmd(0x01);
    // make clear LCD
    _delay_ms(1);
    LCD_cmd(0x02);
    // return home
    _delay_ms(1);
    LCD_cmd(0x06);
    // make increment in cursor
    _delay_ms(1);
    LCD_cmd(0x80);
    // “8” go to first line and “0” is for 0th position
    _delay_ms(1);
    return;
}

//**************sending command on LCD***************//

void LCD_cmd(unsigned char cmd){

    LCD_DATA = cmd; // data lines are set to send command
    PORTC   &= ~(1<<rs);    // RS sets 0
    PORTC   &= ~(1<<rw);    // RW sets 0
    PORTC   |= (1<<en); // make enable from high to low
    _delay_ms(100);
    PORTC   &= ~(1<<en);
    return;
}

//*****************write data on LCD*****************//

void LCD_write(unsigned char data){

    LCD_DATA=   data;   // data lines are set to    send command
    PORTC   |=  (1<<rs);    // RS sets  1
    PORTC   &=  ~(1<<rw);   //  RW sets 0
    PORTC   |=  (1<<en);    //  make enable from high   to low
    

    _delay_ms(100);

    PORTC &= ~(1<<en);

    return ;
}
//store address value of the string in pointer *str
void LCD_write_string(char *str) {
    
    int i=0;

    for(i; str[i]!=0; i++){
        // loop will go on till the NULL character in the string
        LCD_write(str[i]); // sending data on LCD byte by byte i++;
    }
    return;
}

int main(void)
{   
    setup();
    int counter = 0;
   while (1)
   {  
        scaled_delay(1);            //delay 1 hour
        ReadTemp(counter);          //get temperature reading
        ReadPressure(counter);      //get pressure reading
        counter++;                  //keep track of number of conversions
        //get reading 24 times                  
        if(counter == 23){
            counter = 0;
            while (counter  != 24)
            {
                ReadEEPROM_Temp(counter);
                ReadEEPROM_Pres(counter + 100);
                counter++;
            }
            counter = 0;
        }
   }
}



Ответы [ 2 ]

1 голос
/ 02 августа 2020

Кажется, есть ошибка в адресной переменной. Он имеет тип int, но должен иметь тип unsigned int (адрес не может быть отрицательным). Можете ли вы попробовать следующий код:

void WriteToEEPROM(unsigned int value, unsigned int address)
{   
  unsigned char low_value = (unsigned char)value;
  unsigned char high_value = (unsigned char)(value>>8);

  eeprom_write_word((unsigned char*)address ,value);
  address++;
  address++;
}

Пожалуйста, также измените путь delay.h на

#include <util/delay.h>

Функция чтения может также содержать некоторые ненужные вещи:

void ReadEEPROM_Temp(unsigned int address)
{
  char buffer[100];

  unsigned int temp = eeprom_read_word((unsigned char*)address) * 4.88 / 10UL;
  address++;
  address++;

  sprintf(buffer,"Temp %5d C", temp);

  init_LCD();
  LCD_cmd(0x0C);
  _delay_ms(100);

  LCD_write_string(buffer);
}

ПРЕДУПРЕЖДЕНИЕ:

Возможно, что ваша EEPROM в настоящее время уничтожена, потому что вы несколько раз пишете в одно и то же место адреса в своей основной процедуре :

while (1)
{
  scaled_delay(1);            // !!!THIS CREATES A DELAY OF 1 SECOND
  ReadTemp(counter);          // WRITE DATA TO EEPROM
  ReadPressure(counter);      // WRITE DATA TO EEPROM
// ...

Обычно, если ваши функции выше подпрограммы main , нет необходимости объявлять прототипы. Вы разрабатываете с Atmel Studio?

0 голосов
/ 02 августа 2020

Попробуйте использовать программу очистки EEPROM и повторите попытку.

...