Data saving in USERROW in AVR128DA48.

Go To Last Post
20 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi There, 

I want to save the calibrated data of mv sensor. So i have coded like below

< while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
                         FLASH_0_write_eeprom_byte(0x1080,value);
                         value = value >> 8;
                         while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
                         FLASH_0_write_eeprom_byte(0x1081,value);>

Also for reading 

<while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
    value1 = FLASH_0_read_eeprom_byte(0x1080);
    while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
    value1 |= (FLASH_0_read_eeprom_byte(0x1081)) << 8;
    while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
    P.RANGE = value1;>

 

After calibration I can read the values ok.

but after power reset. The values get offset at each power cycle of 20.

Also next day if i check the values are gone. I get nothing.  below fuses  setting

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know what code FLASH_0_XXXX_eeprom_byte is.
But my chip's USERROW works fine and the data is retained.

 

Since USERROW is not EEPROM, overwriting it will result in AND with the original data.
At the break-4 position in the sample below, 0xAA is overwritten in the 0x55 cell, resulting in 0x00.

 

#include <avr/io.h>
#include <avr/cpufunc.h>

#define DATA_0  0x55
#define DATA_1  0xAA

int main(void){
    _NOP(); // break-1

    // Erase USERROW
    while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    USERROW.USERROW0 = 0;
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
    
    _NOP(); // break-2

    // Write 2 byte
    while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    USERROW.USERROW0 = DATA_0;
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    USERROW.USERROW1 = DATA_1;

    _NOP(); // break-3

    // Byte 0 overwrite
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    USERROW.USERROW0 = DATA_1;

    _NOP(); // break-4

    // Close NVMCTRL
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);

    _NOP(); // break-5

    while (1);
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you & how to read from Memory?

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just read the members of the structure.

uint8_t data = USERROW.USERROW0;

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes I did but then also values are changing. its taking the offset.

right now what i am doing i have put the 5k pot connected to PD3. the 3.3v supply to the pot is given from another power source(if connected to pcb 3.3 v then pcb voltage drops. third pin of POT is connected to GND). GND of pcb and power source is shorted. 

     When i first start the external power source and then pcb supply then pcb hangs. So i have to start first pcb supply and then external power. My values are saving during calibration but takes offset after power cycle.

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The external power supply flowing from PD3 may be causing the abnormality.
Did you set BOD?
Why use a low quality PCB power supply that drops voltage just with a POT?
At least USERROW is not bad.

It's a hard and / or soft bug.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Card is AVR128DA48 NANO and it is connected to pc by usb. Yes i set the BOD to 2.75 VDC. Please see the first post. is fuse configuration and BOD parameters are correct? . Please help me.

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There's no code or schematic, so I don't know what's going on with you.

 

"Post a minimal compileable code that reproduces your problem."
This is the principle when asking a question.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi there,

please see the attachment. shall I set the data code?

 

Attachment(s): 

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

It doesn't make sense because it has already been posted to # 1.

The code you're using right now doesn't make sense either.

It should be complete code that can be compiled, and it should be the smallest code that can confirm the problem.

You may discover the cause in the process of editing that code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi there,

please see the code.

/*
 * main.c
 * CURSER
 * Created: 1/21/2021 4:12:08 PM
 *  Author: servi
 */ 
#include <avr/io.h>
//#include <avr/cpufunc.h>
#include <stdbool.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <xc.h>
#include <string.h>
#include <atmel_start.h>
#include <nvmctrl_basic.h>
#include <avr/eeprom.h>
#include <stdio.h>

//#include "CLOCK_functions.h"
//#include <my_uart.h>
//#define USART1_BAUD_RATE(BAUD_RATE) (((float)F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)

// #define F_CPU           4000000UL  /* Main clock frequency */
//#define START_TOKEN     0x03        /* Start Frame Token */
//#define END_TOKEN       0xFC        /* End Frame Token */
#define D_I_SET   PORTB_OUT |= PIN0_bm
#define D_I_RESET PORTB_OUT &= ~PIN0_bm
#define R_W_SET   PORTB_OUT |= PIN1_bm
#define R_W_RESET   PORTB_OUT &= ~PIN1_bm
#define E_SET       PORTB_OUT |= PIN2_bm
#define E_RESET     PORTB_OUT &= ~PIN2_bm
#define ENTER       ~PORTB.IN & PIN3_bm
#define UP_ARROW    ~PORTB.IN & PIN4_bm
#define DOWN_ARROW  ~PORTB.IN & PIN5_bm
#define P1   PORTC_OUT
//uint8_t FLASH_0_write_flash_byte1(flash_adr_t flash_adr,uint8_t data);
//uint8_t FLASH_0_read_flash_byte1(flash_adr_t flash_adr);
void write_string(const char *str);
void curser(uint8_t set);
void CLKCTRL_init(void);
void VREF0_init(void);
void ADC0_init(void);
void USART1_init(void);
int16_t ADC0_read(void);
float ADCConvert(void);
float ADCConvert1(void);
void ADC0_start(void);
void USART1_Write(const uint8_t data);
static void PORT_init(void);
void command(char i);
void write (char i);
void nybble();
void init();
void set_curser(uint8_t set);
void write_num(char c);
void PORT_init1(void);
void DisplayRow (int row,const char *str);
void write_value(int i);
void PORT_init2(void);
void clock_update(void);
void seconds(void);
void seconds1(void);
void RTC_init(void);
//struct parameter;
int16_t read_memory(void);
int16_t write_memory(void);
int16_t calibrate(void);
int num[10];
float FINAL_VALUE;
float O2_VALUE;
uint16_t time_test             = 0;
uint8_t volatile second_passed = 0;
uint8_t sec                    = 0;
uint8_t min                    = 0;
uint8_t hour                   = 0;
uint8_t volatile button        = 0;
uint8_t button_timer_started   = 0;
uint8_t volatile timer         = 0;
uint8_t volatile time_pressed  = 0;
uint8_t selection              = 0;
uint8_t testb                  = 0;
int t = 0;
//8-bit Initialization:
/**********************************************************/

struct _parameter {
	float SPAN;
	float RANGE;
	float ZERO;
	float DIVIDE;
	float DIVIDE1;
	float SPAN1;
	float RANGE1;
	float ZERO1;
	};
struct _parameter P;

void curser(uint8_t set)
{
	command(0x02);
	_delay_ms(2);
	command (set);	
	_delay_ms(2);
}
void command(char i)
{ 
	P1 = i; //put data on output Port
	D_I_RESET; //D/I=LOW : send instruction
	R_W_RESET; //R/W=LOW : Write
	E_SET;
	_delay_ms(1); //enable pulse width >= 300ns
	E_RESET; //Clock enable: falling edge
	//P1 = 0;
	//R_W_SET;
}
/**********************************************************/

void write(char i)
{
	P1 = i; //put data on output Port
	D_I_SET; //D/I=HIGH : send data
	R_W_RESET; //R/W=LOW : Write
	E_SET;
	_delay_ms(1); //enable pulse width >= 300ns
	E_RESET; //Clock enable: falling edge
	//P1 = 0;
//	D_I_RESET;
//	_delay_ms(1);
//	P1 = 0;
	//R_W_SET;
	//NVMCTRL.CTRLA;
}
/**********************************************************/
void init()
{
	P1 = 0;
	E_RESET;
	_delay_ms(100); //Wait >40 msec after power is applied
	command(0x30); //command 0x30 = Wake up
	_delay_ms(30); //must wait 5ms, busy flag not available
	command(0x30); //command 0x30 = Wake up #2
	_delay_ms(10); //must wait 160us, busy flag not available
	command(0x30); //command 0x30 = Wake up #3
	_delay_ms(10); //must wait 160us, busy flag not available
	command(0x38); //Function set: 8-bit/2-line
	command(0x10); //Set cursor
	command(0x0c); //Display ON; Cursor ON
	command(0x6); //Entry mode set
	//command(0x20);
}
static void PORT_init(void)
{
	PORTC_DIRSET = 0Xff;
	PORTB_DIRSET |= PIN0_bm;
	PORTB_DIRSET |= PIN1_bm;
	PORTB_DIRSET |= PIN2_bm;
	PORTB_DIRCLR = PIN3_bm;//PORTn.DIR = PORTn.DIR & ~PINx_bm PORTB.DIRCLR = PIN2_bm;
	PORTB_DIRCLR = PIN4_bm;
	PORTB_DIRCLR = PIN5_bm;
PORTD.DIRSET |= PIN0_bm;
PORTB.PIN3CTRL = PORT_PULLUPEN_bm;
PORTB.PIN4CTRL = PORT_PULLUPEN_bm;
PORTB.PIN5CTRL = PORT_PULLUPEN_bm;
}
void set_curser(uint8_t set)
{  command(0x01); 
	_delay_ms(2);
	command(0x6); //Entry mode set
	_delay_ms(1);
	command(0x02); //Display ON; Cursor ON
	_delay_ms(2);
	command(set);
	_delay_ms(2);
}
void PORT_init1(void)
{
	/* Configure PC0 as output for USART1 TX */
	PORTC.DIRSET = PIN0_bm;
	
	/* Disable interrupt and digital input buffer on PD3 */
	PORTD.PIN3CTRL &= ~PORT_ISC_gm;
	PORTD.PIN3CTRL |= PORT_ISC_INPUT_DISABLE_gc;
	
	/* Disable pull-up resistor */
	PORTD.PIN3CTRL &= ~PORT_PULLUPEN_bm;
}

void CLKCTRL_init(void)
{
	/* FREQSEL 4M */
	ccp_write_io((void*)&(CLKCTRL.OSCHFCTRLA), (CLKCTRL.OSCHFCTRLA | CLKCTRL_FREQSEL_4M_gc));
}

/* This function initializes the PORT module */
void PORT_init2(void)
{
	// Configure PC0 as output for USART1 TX 
	PORTC.DIRSET = PIN0_bm;
}

/* This function initializes the VREF module */
void VREF0_init(void)
{
	VREF.ADC0REF = VREF_REFSEL_2V500_gc;  /* Internal 2.048V reference */
}

/* This function initializes the ADC module */
void ADC0_init(void)
{
	ADC0.CTRLC = ADC_PRESC_DIV4_gc;        /* CLK_PER divided by 4 */
	ADC0.CTRLA = ADC_ENABLE_bm             /* ADC Enable: enabled */
	| ADC_RESSEL_12BIT_gc;      /* 12-bit mode */
	ADC0.MUXPOS = ADC_MUXPOS_AIN3_gc;      /* Select ADC channel AIN3 <-> PD3 */
}

/* This function initializes the USART module */
void USART1_init(void)
{
	/* Configure the baud rate: 115200 */
	USART1.BAUD = (uint16_t)USART1_BAUD_RATE(115200);
	USART1.CTRLB = USART_TXEN_bm;           /* Enable TX */
	USART1.CTRLC = USART_CHSIZE_8BIT_gc;    /* Configure character size: 8 bit */
}

/* This function returns the ADC conversion result */
int16_t ADC0_read(void)
{
	/* Wait for ADC result to be ready */
	while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
	/* Clear the interrupt flag by reading the result */
	return ADC0.RES;
}


void DisplayRow (int row,const char *str)
{
	
/*
	pass pointer to 16 character string
	displays the message on line1 or line2 of LCD, depending on whether row is 1 or 2.
*/

	//unsigned char k ;

	if (row == 1)
	{
		set_curser(0x80) ;
	}
	else if(row == 2)
	{
		set_curser(0xC0) ;
	}
	else if(row == 3)
	{
		set_curser(0x94) ;
	} else
	{
		set_curser(0xD4) ;
	}

	int i;
	for(i =0;i < strlen(str);){
	write(str[i]);
	i++;}
}
void write_string(const char *str)
{
	int i;
	for(i =0;i < strlen(str);){
	write(str[i]);
	i++;}
	
}
/* This function returns the temperature value in degrees C *//**/
float ADCConvert(void)
{
	  P.SPAN = P.RANGE - P.ZERO;
	 P.DIVIDE = 21.5/P.SPAN;
	O2_VALUE = ADC0_read();
	FINAL_VALUE = O2_VALUE * P.DIVIDE;
	return FINAL_VALUE;
}
float ADCConvert1(void)
{
	  P.SPAN1 = 4095;
	 P.DIVIDE1 = 21.5/P.SPAN1;
	O2_VALUE = ADC0_read();
	FINAL_VALUE = O2_VALUE * P.DIVIDE1;
	return FINAL_VALUE;
}

/* This function starts the ADC conversions*/
void ADC0_start(void)
{
	/* Start conversion */
	ADC0.COMMAND = ADC_STCONV_bm;
}

/* This function transmits one byte through USART */
void USART1_Write(const uint8_t data)
{
	/* Check if USART buffer is ready to transmit data */
	while (!(USART1.STATUS & USART_DREIF_bm));
	/* Transmit data using TXDATAL register */
	USART1.TXDATAL = data;
}
void write_value(int i)
{ 
	
	unsigned char c;
	int p;
	int k=0;
	while(i>0)
	{
		num[k]=i%10;
		i=i/10;
		k++;
	}
	k--;
	for (p=k;p>=0;p--)
	{   
		//command(0x01);
		//_delay_ms(2);
		c=num[p]+48;
			write_num(c);
		}
}
void write_num(char c)
{
	PORTC_OUT = 0;
	PORTC_OUT &= ~PIN7_bm;
	PORTC_OUT &= ~PIN6_bm;
	PORTC_OUT |= PIN5_bm;
	PORTC_OUT |= PIN4_bm;
	
	//if(c & 0x128) PORTC_OUT |= PIN7_bm; else PORTC_OUT &= ~PIN7_bm;
	//if(c & 0x64) PORTC_OUT |= PIN6_bm; else PORTC_OUT &= ~PIN6_bm;
	//if(c & 0x32) PORTC_OUT |= PIN5_bm; else PORTC_OUT &= ~PIN5_bm;
	//if(c & 0x16) PORTC_OUT |= PIN4_bm; else PORTC_OUT &= ~PIN4_bm;
	if(c & 0x08) PORTC_OUT |= PIN3_bm; else PORTC_OUT &= ~PIN3_bm;
	if(c & 0x04) PORTC_OUT |= PIN2_bm; else PORTC_OUT &= ~PIN2_bm;
	if(c & 0x02) PORTC_OUT |= PIN1_bm; else PORTC_OUT &= ~PIN1_bm;
	if(c & 0x01) PORTC_OUT |= PIN0_bm; else PORTC_OUT &= ~PIN0_bm;
	D_I_SET; //D/I=HIGH : send data
	R_W_RESET; //R/W=LOW : Write
	E_SET;
	_delay_ms(1); //enable pulse width >= 300ns
	E_RESET; //Clock enable: falling edge
	//D_I_RESET;
	P1 =0;
	//R_W_SET;
}

int16_t calibrate(void)
{
	int i,y;
	volatile uint16_t value = 0;
		DisplayRow(1,"CALIBRATION");
		_delay_ms(3000);
		DisplayRow(1,"SPAN CALIBRATION");
		_delay_ms(3000);
		DisplayRow(1,"PRESS UP OR DOWN BUTTON");
		 i = 0;
		 y = 0;
		while(1){
		if (UP_ARROW || DOWN_ARROW)
		{
			DisplayRow(3,"ITS WORKING");
			while(i == 0){
				DisplayRow(1,"APPLY FRESH AIR");
						seconds();
						 i = 1;
						 ADC0_start();
						 value = ADC0_read();
						 _delay_ms(100);
						 if(value > 3294){
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW0 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP();
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW1 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP();
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW2 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP();
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW3 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP(); // break-2
							 // _NOP(); // break-2

							  // Write 2 byte
							  while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							  _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
							  while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							  USERROW.USERROW0 = value;
							  value = value >> 8;
							  while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							  USERROW.USERROW1 = value;
						/* while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
						 FLASH_0_write_eeprom_byte(0x1080,value);
						 value = value >> 8;
						 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
						 FLASH_0_write_eeprom_byte(0x1081,value);*/
					DisplayRow(3,"   ");
					DisplayRow(4, "SPAN SET");}
					else { DisplayRow(4, "SPAN ERROR");
						   curser(0x80);
						   write_string("READ SENSOR MiliVOLT");
						   curser(0x94);
						   write_string("ABOVE 12.5");
						}
					_delay_ms(3000);
					}
		}
					while(i == 1){
						DisplayRow(1,"APPLY 0% NITROGEN");
						seconds1();
					i = 2;
					ADC0_start();
					value = ADC0_read();
					_delay_ms(100);
					if(value < 200){
						while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
						_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
						while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
						USERROW.USERROW2 = value;
						value = value >> 8;
						while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
						USERROW.USERROW3 = value;
						_NOP();
						/*while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
						FLASH_0_write_eeprom_byte(0x1082,value);
						value = value >> 8;
						while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
						FLASH_0_write_eeprom_byte(0x1083,value);*/
						DisplayRow(3,"   ");
					DisplayRow(4, "ZERO SET");y = 1;break;}
					else { DisplayRow(4, "ZERO ERROR");
						curser(0x80);
						write_string("READ SENSOR MiliVOLT");
						curser(0x94);
						write_string("BELOW 1");}
					_delay_ms(3000);y = 1;break;
		}
		if(y == 1){
		break;}}
}
	
void seconds(void){
	sec = 0;
	while(sec < 30){
		
		ADC0_start();
	O2_VALUE = ADCConvert1();
	if(O2_VALUE < 9.99 && t == 0){
		set_curser(0x94);
		DisplayRow(1,"APPLY FRESH AIR");
		t =1;}
		else if(O2_VALUE > 9.99 && t == 1){t = 0;}
			curser(0x80);
			write_string("APPLY FRESH AIR");
		curser(0x94);
		write_value(sec);
		curser(0xD4);
		write_value(O2_VALUE);
	}
	}
void seconds1(void){
	sec = 0;
	while(sec < 30){
		
		ADC0_start();
		O2_VALUE = ADCConvert1();
		if(O2_VALUE < 9.99 && t == 0){
			set_curser(0x94);
			DisplayRow(1,"APPLY 0% NITROGEN");
		t =1;}
		else if(O2_VALUE > 9.99 && t == 1){t = 0;}
		curser(0x80);
		write_string("APPLY 0% NITROGEN");
		curser(0x94);
		write_value(sec);
		curser(0xD4);
		write_value(O2_VALUE);
	}
}
ISR(RTC_CNT_vect)
{
	sec++;
	RTC.INTFLAGS = RTC_OVF_bm;
	
}
int main(void)
{ 
	_delay_ms(5000);
	uint16_t value1 =  0;
	O2_VALUE =0;
	//uint16_t value = 254;
	//int i =4564;
	int k =1;
//float O2_VALUE;
//int16_t adcVal;
	 CLKCTRL_init();
	 PORT_init();
	 PORT_init1();
	 PORT_init2();
	 VREF0_init();
	 ADC0_init();
	 RTC_0_init();
	 FLASH_0_init();
	 init();
	 /* Start the ADC conversion */
	 ADC0_start();
	 sei();
	
	DisplayRow(1,"        ");
	_delay_ms(5000);
	//while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm))
		//;
	//FLASH_0_write_eeprom_byte(0x1080,value);
//	value = value >> 8;
//	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm))
	//	;
	//FLASH_0_write_eeprom_byte(0x1081,value);
	//_delay_ms(10000);
	
	
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = USERROW.USERROW0;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (USERROW.USERROW1) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	P.RANGE = value1;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = USERROW.USERROW2;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (USERROW.USERROW3) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	P.ZERO = value1;
	
    while(1)
    {
		if(ENTER){
			while(k){
		calibrate();
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = FLASH_0_read_eeprom_byte(0x1080);
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (FLASH_0_read_eeprom_byte(0x1081)) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	P.RANGE = value1;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = FLASH_0_read_eeprom_byte(0x1082);
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (FLASH_0_read_eeprom_byte(0x1083)) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	P.ZERO = value1;
		DisplayRow(1,"CALIBRATION COMPLETED");
		k =0;}
		}
		DisplayRow(1,"     ");
		//_delay_ms(5000);
		ADC0_start();
		O2_VALUE = ADCConvert();
		_delay_ms(100);
		curser(0xD4);
		write_value(O2_VALUE);
		curser(0xC0);
		write_value(P.RANGE);
		curser(0x94);
		write_value(P.ZERO);
		//curser(0x94);
		//write_value(P.ZERO);
		_delay_ms(3000);
       }
		
       //TODO:: Please write your application code 
}


 

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's up to you to remove unnecessary code.
Do you want me to read and debug this huge code?
It's unpleasant.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, 

I removed the comments and what i want to do is calibration data is to be stored in userrow and it gets stored in calibration function. even if power supply recycle, the range and zero data will be read and stored in struct parameter variable. and in ADCConvert() it will be converted to value (O2_value) of sensor to be displayed. This is the main program. I have used 20 X 4 LCD display to display the value. Your help is required.

/*
 * main.c
 * CURSER
 * Created: 1/21/2021 4:12:08 PM
 *  Author: servi
 */ 
#include <avr/io.h>
//#include <avr/cpufunc.h>
#include <stdbool.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <xc.h>
#include <string.h>
#include <atmel_start.h>
#include <nvmctrl_basic.h>
#include <avr/eeprom.h>
#include <stdio.h>

//#include "CLOCK_functions.h"
//#include <my_uart.h>
//#define USART1_BAUD_RATE(BAUD_RATE) (((float)F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)

// #define F_CPU           4000000UL  /* Main clock frequency */
//#define START_TOKEN     0x03        /* Start Frame Token */
//#define END_TOKEN       0xFC        /* End Frame Token */
#define D_I_SET   PORTB_OUT |= PIN0_bm
#define D_I_RESET PORTB_OUT &= ~PIN0_bm
#define R_W_SET   PORTB_OUT |= PIN1_bm
#define R_W_RESET   PORTB_OUT &= ~PIN1_bm
#define E_SET       PORTB_OUT |= PIN2_bm
#define E_RESET     PORTB_OUT &= ~PIN2_bm
#define ENTER       ~PORTB.IN & PIN3_bm
#define UP_ARROW    ~PORTB.IN & PIN4_bm
#define DOWN_ARROW  ~PORTB.IN & PIN5_bm
#define P1   PORTC_OUT
//uint8_t FLASH_0_write_flash_byte1(flash_adr_t flash_adr,uint8_t data);
//uint8_t FLASH_0_read_flash_byte1(flash_adr_t flash_adr);
void write_string(const char *str);
void curser(uint8_t set);
void CLKCTRL_init(void);
void VREF0_init(void);
void ADC0_init(void);
void USART1_init(void);
int16_t ADC0_read(void);
float ADCConvert(void);
float ADCConvert1(void);
void ADC0_start(void);
void USART1_Write(const uint8_t data);
static void PORT_init(void);
void command(char i);
void write (char i);
void nybble();
void init();
void set_curser(uint8_t set);
void write_num(char c);
void PORT_init1(void);
void DisplayRow (int row,const char *str);
void write_value(int i);
void PORT_init2(void);
void clock_update(void);
void seconds(void);
void seconds1(void);
void RTC_init(void);
//struct parameter;
int16_t read_memory(void);
int16_t write_memory(void);
int16_t calibrate(void);
int num[10];
float FINAL_VALUE;
float O2_VALUE;
uint16_t time_test             = 0;
uint8_t volatile second_passed = 0;
uint8_t sec                    = 0;
uint8_t min                    = 0;
uint8_t hour                   = 0;
uint8_t volatile button        = 0;
uint8_t button_timer_started   = 0;
uint8_t volatile timer         = 0;
uint8_t volatile time_pressed  = 0;
uint8_t selection              = 0;
uint8_t testb                  = 0;
int t = 0;
//8-bit Initialization:
/**********************************************************/

struct _parameter {
	float SPAN;
	float RANGE;
	float ZERO;
	float DIVIDE;
	float DIVIDE1;
	float SPAN1;
	float RANGE1;
	float ZERO1;
	};
struct _parameter P;

void curser(uint8_t set)
{
	command(0x02);
	_delay_ms(2);
	command (set);	
	_delay_ms(2);
}
void command(char i)
{ 
	P1 = i; //put data on output Port
	D_I_RESET; //D/I=LOW : send instruction
	R_W_RESET; //R/W=LOW : Write
	E_SET;
	_delay_ms(1); //enable pulse width >= 300ns
	E_RESET; //Clock enable: falling edge
	//P1 = 0;
	//R_W_SET;
}
/**********************************************************/

void write(char i)
{
	P1 = i; //put data on output Port
	D_I_SET; //D/I=HIGH : send data
	R_W_RESET; //R/W=LOW : Write
	E_SET;
	_delay_ms(1); //enable pulse width >= 300ns
	E_RESET; //Clock enable: falling edge
	//P1 = 0;
//	D_I_RESET;
//	_delay_ms(1);
//	P1 = 0;
	//R_W_SET;
	//NVMCTRL.CTRLA;
}
/**********************************************************/
void init()
{
	P1 = 0;
	E_RESET;
	_delay_ms(100); //Wait >40 msec after power is applied
	command(0x30); //command 0x30 = Wake up
	_delay_ms(30); //must wait 5ms, busy flag not available
	command(0x30); //command 0x30 = Wake up #2
	_delay_ms(10); //must wait 160us, busy flag not available
	command(0x30); //command 0x30 = Wake up #3
	_delay_ms(10); //must wait 160us, busy flag not available
	command(0x38); //Function set: 8-bit/2-line
	command(0x10); //Set cursor
	command(0x0c); //Display ON; Cursor ON
	command(0x6); //Entry mode set
	//command(0x20);
}
static void PORT_init(void)
{
	PORTC_DIRSET = 0Xff;
	PORTB_DIRSET |= PIN0_bm;
	PORTB_DIRSET |= PIN1_bm;
	PORTB_DIRSET |= PIN2_bm;
	PORTB_DIRCLR = PIN3_bm;//PORTn.DIR = PORTn.DIR & ~PINx_bm PORTB.DIRCLR = PIN2_bm;
	PORTB_DIRCLR = PIN4_bm;
	PORTB_DIRCLR = PIN5_bm;
PORTD.DIRSET |= PIN0_bm;
PORTB.PIN3CTRL = PORT_PULLUPEN_bm;
PORTB.PIN4CTRL = PORT_PULLUPEN_bm;
PORTB.PIN5CTRL = PORT_PULLUPEN_bm;
}
void set_curser(uint8_t set)
{  command(0x01); 
	_delay_ms(2);
	command(0x6); //Entry mode set
	_delay_ms(1);
	command(0x02); //Display ON; Cursor ON
	_delay_ms(2);
	command(set);
	_delay_ms(2);
}
void PORT_init1(void)
{
	/* Configure PC0 as output for USART1 TX */
	PORTC.DIRSET = PIN0_bm;
	
	/* Disable interrupt and digital input buffer on PD3 */
	PORTD.PIN3CTRL &= ~PORT_ISC_gm;
	PORTD.PIN3CTRL |= PORT_ISC_INPUT_DISABLE_gc;
	
	/* Disable pull-up resistor */
	PORTD.PIN3CTRL &= ~PORT_PULLUPEN_bm;
}

void CLKCTRL_init(void)
{
	/* FREQSEL 4M */
	ccp_write_io((void*)&(CLKCTRL.OSCHFCTRLA), (CLKCTRL.OSCHFCTRLA | CLKCTRL_FREQSEL_4M_gc));
}

/* This function initializes the PORT module */
void PORT_init2(void)
{
	// Configure PC0 as output for USART1 TX 
	PORTC.DIRSET = PIN0_bm;
}

/* This function initializes the VREF module */
void VREF0_init(void)
{
	VREF.ADC0REF = VREF_REFSEL_2V500_gc;  /* Internal 2.048V reference */
}

/* This function initializes the ADC module */
void ADC0_init(void)
{
	ADC0.CTRLC = ADC_PRESC_DIV4_gc;        /* CLK_PER divided by 4 */
	ADC0.CTRLA = ADC_ENABLE_bm             /* ADC Enable: enabled */
	| ADC_RESSEL_12BIT_gc;      /* 12-bit mode */
	ADC0.MUXPOS = ADC_MUXPOS_AIN3_gc;      /* Select ADC channel AIN3 <-> PD3 */
}

/* This function initializes the USART module */
void USART1_init(void)
{
	/* Configure the baud rate: 115200 */
	USART1.BAUD = (uint16_t)USART1_BAUD_RATE(115200);
	USART1.CTRLB = USART_TXEN_bm;           /* Enable TX */
	USART1.CTRLC = USART_CHSIZE_8BIT_gc;    /* Configure character size: 8 bit */
}

/* This function returns the ADC conversion result */
int16_t ADC0_read(void)
{
	/* Wait for ADC result to be ready */
	while (!(ADC0.INTFLAGS & ADC_RESRDY_bm));
	/* Clear the interrupt flag by reading the result */
	return ADC0.RES;
}


void DisplayRow (int row,const char *str)
{
	
/*
	pass pointer to 16 character string
	displays the message on line1 or line2 of LCD, depending on whether row is 1 or 2.
*/

	//unsigned char k ;

	if (row == 1)
	{
		set_curser(0x80) ;
	}
	else if(row == 2)
	{
		set_curser(0xC0) ;
	}
	else if(row == 3)
	{
		set_curser(0x94) ;
	} else
	{
		set_curser(0xD4) ;
	}

	int i;
	for(i =0;i < strlen(str);){
	write(str[i]);
	i++;}
}
void write_string(const char *str)
{
	int i;
	for(i =0;i < strlen(str);){
	write(str[i]);
	i++;}
	
}
/* This function returns the temperature value in degrees C *//**/
float ADCConvert(void)
{
	  P.SPAN = P.RANGE - P.ZERO;
	 P.DIVIDE = 21.5/P.SPAN;
	O2_VALUE = ADC0_read();
	FINAL_VALUE = O2_VALUE * P.DIVIDE;
	return FINAL_VALUE;
}
float ADCConvert1(void)
{
	  P.SPAN1 = 4095;
	 P.DIVIDE1 = 21.5/P.SPAN1;
	O2_VALUE = ADC0_read();
	FINAL_VALUE = O2_VALUE * P.DIVIDE1;
	return FINAL_VALUE;
}

/* This function starts the ADC conversions*/
void ADC0_start(void)
{
	/* Start conversion */
	ADC0.COMMAND = ADC_STCONV_bm;
}

/* This function transmits one byte through USART */
void USART1_Write(const uint8_t data)
{
	/* Check if USART buffer is ready to transmit data */
	while (!(USART1.STATUS & USART_DREIF_bm));
	/* Transmit data using TXDATAL register */
	USART1.TXDATAL = data;
}
void write_value(int i)
{ 
	
	unsigned char c;
	int p;
	int k=0;
	while(i>0)
	{
		num[k]=i%10;
		i=i/10;
		k++;
	}
	k--;
	for (p=k;p>=0;p--)
	{   
		//command(0x01);
		//_delay_ms(2);
		c=num[p]+48;
			write_num(c);
		}
}
void write_num(char c)
{
	PORTC_OUT = 0;
	PORTC_OUT &= ~PIN7_bm;
	PORTC_OUT &= ~PIN6_bm;
	PORTC_OUT |= PIN5_bm;
	PORTC_OUT |= PIN4_bm;
	
	//if(c & 0x128) PORTC_OUT |= PIN7_bm; else PORTC_OUT &= ~PIN7_bm;
	//if(c & 0x64) PORTC_OUT |= PIN6_bm; else PORTC_OUT &= ~PIN6_bm;
	//if(c & 0x32) PORTC_OUT |= PIN5_bm; else PORTC_OUT &= ~PIN5_bm;
	//if(c & 0x16) PORTC_OUT |= PIN4_bm; else PORTC_OUT &= ~PIN4_bm;
	if(c & 0x08) PORTC_OUT |= PIN3_bm; else PORTC_OUT &= ~PIN3_bm;
	if(c & 0x04) PORTC_OUT |= PIN2_bm; else PORTC_OUT &= ~PIN2_bm;
	if(c & 0x02) PORTC_OUT |= PIN1_bm; else PORTC_OUT &= ~PIN1_bm;
	if(c & 0x01) PORTC_OUT |= PIN0_bm; else PORTC_OUT &= ~PIN0_bm;
	D_I_SET; //D/I=HIGH : send data
	R_W_RESET; //R/W=LOW : Write
	E_SET;
	_delay_ms(1); //enable pulse width >= 300ns
	E_RESET; //Clock enable: falling edge
	//D_I_RESET;
	P1 =0;
	//R_W_SET;
}

int16_t calibrate(void)
{
	int i,y;uint16_t value1 =  0;
	volatile uint16_t value = 0;
		DisplayRow(1,"CALIBRATION");
		_delay_ms(3000);
		DisplayRow(1,"SPAN CALIBRATION");
		_delay_ms(3000);
		DisplayRow(1,"PRESS UP OR DOWN BUTTON");
		 i = 0;
		 y = 0;
		while(1){
		if (UP_ARROW || DOWN_ARROW)
		{
			DisplayRow(3,"ITS WORKING");
			while(i == 0){
				DisplayRow(1,"APPLY FRESH AIR");
						seconds();
						 i = 1;
						 ADC0_start();
						 value = ADC0_read();
						 _delay_ms(100);
						 if(value > 3294){
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW0 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP();
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW1 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP();
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW2 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP();
							 while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 USERROW.USERROW3 = 0;
							 while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							 _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);
							 _NOP(); 

							  // Write 2 byte
							  while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
							  _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
							  while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							  USERROW.USERROW0 = value;
							  value = value >> 8;
							  while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
							  USERROW.USERROW1 = value;
						
					DisplayRow(3,"   ");
					DisplayRow(4, "SPAN SET");}
					else { DisplayRow(4, "SPAN ERROR");
						   curser(0x80);
						   write_string("READ SENSOR MiliVOLT");
						   curser(0x94);
						   write_string("ABOVE 12.5");
						}
					_delay_ms(3000);
					}
		}
					while(i == 1){
						DisplayRow(1,"APPLY 0% NITROGEN");
						seconds1();
					i = 2;
					ADC0_start();
					value = ADC0_read();
					_delay_ms(100);
					if(value < 200){
						while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
						_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
						while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
						USERROW.USERROW2 = value;
						value = value >> 8;
						while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
						USERROW.USERROW3 = value;
						_NOP();
						
						DisplayRow(3,"   ");
					DisplayRow(4, "ZERO SET");y = 1;break;}
					else { DisplayRow(4, "ZERO ERROR");
						curser(0x80);
						write_string("READ SENSOR MiliVOLT");
						curser(0x94);
						write_string("BELOW 1");}
					_delay_ms(3000);y = 1;break;
		}
		if(y == 1){
		break;}}
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
		value1 = FLASH_0_read_eeprom_byte(0x1080);
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
		value1 |= (FLASH_0_read_eeprom_byte(0x1081)) << 8;
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
		P.RANGE = value1;
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
		value1 = FLASH_0_read_eeprom_byte(0x1082);
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
		value1 |= (FLASH_0_read_eeprom_byte(0x1083)) << 8;
		while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
		P.ZERO = value1;
		DisplayRow(1,"CALIBRATION COMPLETED");
}
	
void seconds(void){
	sec = 0;
	while(sec < 30){
		
		ADC0_start();
	O2_VALUE = ADCConvert1();
	if(O2_VALUE < 9.99 && t == 0){
		set_curser(0x94);
		DisplayRow(1,"APPLY FRESH AIR");
		t =1;}
		else if(O2_VALUE > 9.99 && t == 1){t = 0;}
			curser(0x80);
			write_string("APPLY FRESH AIR");
		curser(0x94);
		write_value(sec);
		curser(0xD4);
		write_value(O2_VALUE);
	}
	}
void seconds1(void){
	sec = 0;
	while(sec < 30){
		
		ADC0_start();
		O2_VALUE = ADCConvert1();
		if(O2_VALUE < 9.99 && t == 0){
			set_curser(0x94);
			DisplayRow(1,"APPLY 0% NITROGEN");
		t =1;}
		else if(O2_VALUE > 9.99 && t == 1){t = 0;}
		curser(0x80);
		write_string("APPLY 0% NITROGEN");
		curser(0x94);
		write_value(sec);
		curser(0xD4);
		write_value(O2_VALUE);
	}
}
ISR(RTC_CNT_vect)
{
	sec++;
	RTC.INTFLAGS = RTC_OVF_bm;
	
}
int main(void)
{ 
	_delay_ms(5000);
	uint16_t value1 =  0;
	O2_VALUE =0;
	
	int k =1;

	 CLKCTRL_init();
	 PORT_init();
	 PORT_init1();
	 PORT_init2();
	 VREF0_init();
	 ADC0_init();
	 RTC_0_init();
	 FLASH_0_init();
	 init();
	 /* Start the ADC conversion */
	 ADC0_start();
	 sei();
	
	DisplayRow(1,"        ");
	_delay_ms(5000);
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = USERROW.USERROW0;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (USERROW.USERROW1) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	P.RANGE = value1;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = USERROW.USERROW2;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (USERROW.USERROW3) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	P.ZERO = value1;
	
    while(1)
    {
		if(ENTER){
			while(k){
		calibrate();
		k =0;}
		}
		DisplayRow(1,"     ");
		
		ADC0_start();
		O2_VALUE = ADCConvert();
		_delay_ms(100);
		curser(0xD4);
		write_value(O2_VALUE);
		curser(0xC0);
		write_value(P.RANGE);
		curser(0x94);
		write_value(P.ZERO);
		
		_delay_ms(3000);
       }
		
       //TODO:: Please write your application code 
}


 

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your question in this thread is about the "user row". 95% of that code is nothing to do with the user row. I suggest you make something like a 10 line test program that illustrates the issue you are having so that others can help. No one is going to try and wade through several hundred lines of irrelevance.

 

Moderator

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for late reply. Please see the code.

/*
 * main.c
 * CURSER
 * Created: 1/21/2021 4:12:08 PM
 *  Author: servi
 */ 
#include <avr/io.h>
#include <avr/cpufunc.h>
#include <util/delay.h>
#include <xc.h>
#include <stdio.h>

uint16_t read(void);
void CLKCTRL_init(void);
#define F_CPU           4000000UL   /* Main clock frequency */ 
#define START_TOKEN     0x03        /* Start Frame Token */
#define END_TOKEN       0xFC        /* End Frame Token */
#define ENTER       ~PORTB.IN & PIN3_bm
#define USART1_BAUD_RATE(BAUD_RATE) (((float)F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
float O2_VALUE,FINAL_VALUE;
void USART1_init();
void USART1_Write(const uint8_t data);
uint16_t value1 =  0;
uint16_t value2 = 0;
struct _parameter {
	float SPAN;
	float RANGE;
	float ZERO;
	float DIVIDE;
	float DIVIDE1;
	float SPAN1;
	float RANGE1;
	float ZERO1;
	};
struct _parameter P;

/**********************************************************/

void CLKCTRL_init(void)
{
	/* FREQSEL 4M */
	ccp_write_io((void*)&(CLKCTRL.OSCHFCTRLA), (CLKCTRL.OSCHFCTRLA | CLKCTRL_FREQSEL_4M_gc));
}
void USART1_init()
{
    /* Configure the baud rate: 115200 */
    USART1.BAUD = (uint16_t)USART1_BAUD_RATE(115200);
    USART1.CTRLB = USART_TXEN_bm;           /* Enable TX */
    USART1.CTRLC = USART_CHSIZE_8BIT_gc;    /* Configure character size: 8 bit */
}
void USART1_Write(const uint8_t data)
{
    /* Check if USART buffer is ready to transmit data */
    while (!(USART1.STATUS & USART_DREIF_bm));
    /* Transmit data using TXDATAL register */
    USART1.TXDATAL = data;
}
uint16_t read(void)
{
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 = USERROW.USERROW0;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	value1 |= (USERROW.USERROW1) << 8;
	while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
	return value1;
	
}
int main(void)
{ 
	P.RANGE = 1111;
	
	O2_VALUE =0;
	 CLKCTRL_init();
	  USART1_init();
	   PORTC.DIRSET = PIN0_bm;
	 PORTB_DIRCLR = PIN3_bm; // ENTER INIT
	 PORTB.PIN3CTRL = PORT_PULLUPEN_bm; //ENTER INIT

	read();
	//P.RANGE1 = value1;
	
    while(1)
    {
		if(ENTER){
			uint16_t value = P.RANGE;
			while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
			_PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);
			while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
			USERROW.USERROW0 = value;
			value = value >> 8;
			while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
			USERROW.USERROW1 = value;
			_NOP();
		}
		 value2 = read();
		USART1_Write(START_TOKEN);
			USART1_Write(value2);
			USART1_Write(value2 >> 8);
			USART1_Write(END_TOKEN);
		
       }
		
       //TODO:: Please write your application code 
}


 

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It looks like it works, but what's wrong?

By the way, you haven't entered the erase command, so if the "value" is different from the previous one, you won't get the correct save result.

Also, when reading, there is no need to check the status.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll fix it a little.

 

Define F_CPU before delay.h.

#define F_CPU   4000000UL   /* Main clock frequency */
#include <util/delay.h>

 

 

You do not need to check the status when reading USERROW.

uint16_t read(void){
    value1 = ((uint16_t)USERROW.USERROW1 << 8) | USERROW.USERROW0;
    return value1;
}

 

And update correctly.

if(ENTER){
    uint16_t value = P.RANGE;

    // Erase USERROW
    while (NVMCTRL.STATUS & (NVMCTRL_EEBUSY_bm | NVMCTRL_FBUSY_bm));
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLPER_gc);  // Enter erase mode
    USERROW.USERROW0 = 0;                                       // trigger page(32byte) Erase
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);   // Leave erase mode

    // Write USERROW
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_FLWR_gc);   // Enter write mode
    USERROW.USERROW0 = value;                                   // Write ROW0
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    USERROW.USERROW1 = value >> 8;                              // Write ROW1
    while (NVMCTRL.STATUS & NVMCTRL_FBUSY_bm);
    _PROTECTED_WRITE_SPM(NVMCTRL.CTRLA, NVMCTRL_CMD_NONE_gc);   // Leave write mode

    _NOP();
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you. That solved my problem. Is that possible to erase only 8 byte of flash?

Madhusudan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do not know.

The method may be in the data sheet.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Madhusudan Jadhav wrote:
Is that possible to erase only 8 byte of flash?

The minimum amount of flash that can be erased is 1 page. The size of a flash page varies from chip to chip, you need to check the datasheet to find out how much it is.

 

For the AVR-Dx it's 512 bytes IIRC.

Last Edited: Mon. Feb 22, 2021 - 01:38 PM