메모리 칩이란 무엇이며 미세 회로를 프로그래밍하는 방법. EEPROM(비휘발성 메모리)을 지우는 방법 eeprom 메모리 사용

지난번에 제가 메가에서 펌웨어를 백업하는 방법에 대한 "질문에 대한 자세한 답변"을 썼을 때 그들은 EEPROM 백업에 대해 언급하지 않았다고 비난했습니다. 그땐 의식적으로 하지 않았으니까... 초기 "발사체 접근"단계에서 모든 것을 복잡하게 만들 필요가 없다고 올바르게 판단했습니다. 사실 펌웨어를 컴파일하고 업로드할 때 EEPROM이 플래시되지 않는다는 것이 모든 사람에게 분명하지는 않습니다. 아두이노 IDE. 즉, 이는 펌웨어가 IDE에서 업로드될 때 EEPROM에 아무 것도 업로드되지 않음을 의미합니다. 그리고 EEPROM을 사용한 조작(펌웨어에서 사용이 활성화된 경우)은 완전히 다른 수준에서 수행됩니다. 따라서 베어 펌웨어를 백업하지 않고 미세 조정, 아마도 (아마도) EEPROM에 저장할 수 있지만 베어 펌웨어만 저장하는 것만으로도 충분했습니다. 그러나 질문이 생겼으니 그것을 "씹어"보는 것은 어떨까요? 순서대로 살펴보겠습니다. EEPROM은 무엇이며 이에 대해 이야기하는 이유는 무엇입니까?
EEPROM - 정보를 쓰고 읽을 수 있는 마이크로 컨트롤러의 비휘발성 메모리의 (Electrically Erasable Programmable Read-Only Memory) 영역입니다. 작동 중에 변경될 수 있으며 전원이 꺼진 후에도 저장해야 하는 프로그램 설정을 저장하는 데 자주 사용됩니다.

3D 프린터는 EEPROM을 어떻게 사용합니까?
Marlin을 예로 들어보면 Marlin 펌웨어에는 EEPROM이 사용되지 않으며 이를 사용할 수 있는 기능이 포함된 구성 매개변수(Configuration.h)는 기본적으로 주석 처리되어 있습니다.

#EEPROM_SETTINGS 정의
#EEPROM_CHITCHAT 정의

EEPROM 사용이 활성화된 경우 프린터는 다음 설정(부르주아지에서 지정)을 저장하고 사용할 수 있습니다.

  • 밀리미터당 단계 수
  • 최대/최소 이송 속도 [mm/s]
  • 최대 가속도 [mm/s^2]
  • 가속
  • 후퇴 중 가속
  • PID 설정
  • 원점 오프셋
  • 이동 중 최소 이송 속도 [mm/s]
  • 최소 구간 시간 [ms]
  • 최대 속도 점프 X-Y 축[mm/초]
  • Z축 최대 속도 점프 [mm/s]
프린터 화면과 컨트롤을 사용하여 이러한 설정을 편집할 수 있습니다. EEPROM 사용이 활성화되면 메뉴에 다음 항목이 표시되어야 합니다.
  • 메모리 저장
  • 메모리 로드
  • 안전 장치 복원
GCode를 사용하여 Pronterface를 통해 직접 작업할 수도 있습니다.
  • M500 다음 시작 또는 M501 명령까지 현재 설정을 EEPROM에 저장합니다.
  • M501 EEPROM에서 설정을 읽습니다.
  • M502 Configurations.h에 지정된 기본값으로 설정을 재설정합니다. 이후에 M500을 실행하면 EEPROM에 기본값이 입력됩니다.
  • M503 현재 설정을 표시합니다 - ""EEPROM에 기록된 설정""
Repitier 펌웨어에서 EEPROM에 대해 읽을 수 있습니다.

EEPROM에 데이터를 읽고 쓰는 방법은 무엇입니까?
키를 이용한 펌웨어 백업 방법에서 설명한 방법과 유사합니다. -유. 이 경우에만 EEPROM을 읽어야 함을 나타내는 포인터가 표시됩니다.

avrdude.exe -p atmega2560 -c 배선 -PCOM5 -b115200 -Ueeprom:r:"printer_eeprom".eep:i

이 명령은 EEPROM 데이터를 "printer_eeprom.eep" 파일로 읽어 들입니다. 성공하면 화면에 다음과 같은 내용이 표시됩니다.

녹음도 복잡하지 않으며 유사한 명령으로 수행됩니다. 이는 키에서만 다릅니다. -유"r"이 아니라 "w"입니다.

avrdude.exe -p atmega2560 -c 배선 -PCOM5 -b115200 -Ueeprom:w:"printer_eeprom".eep:i

성공하면 화면에 다음과 같은 메시지가 표시됩니다.

EEPROM을 지우는 방법과 이유는 무엇입니까?
우선, “이걸 왜 하는 거지?” 이전 펌웨어에서도 EEPROM을 사용한 경우 EEPROM을 지워야 하며, 메모리에 가비지가 남을 수 있습니다. 어딘가에서 이미 한 펌웨어에서 다른 펌웨어로(Marlin에서 Repitier EMNIP로) 전환한 후 프린터가 "창의적으로" 작동하기 시작한 문제가 있는 사람들을 만났습니다. 이는 서로 다른 펌웨어가 해당 데이터를 아래에 저장한다는 사실 때문입니다. 다른 주소. 그리고 잘못된 주소에서 데이터를 읽으려고 하면 대혼란이 시작됩니다.
펌웨어에서 프로그래밍 방식으로만 EEPROM을 지울 수 있지만, 이렇게 하려면 임시로 특수 스케치를 컨트롤러에 업로드해야 합니다. 이에 대한 자세한 내용은 공식 Arduino 문서에서 확인할 수 있습니다.
EEPROM이 삭제되지 않은 경우 아두이노 보드, 일부 추상 컨트롤러에서는 보드의 특정 컨트롤러에 있는 EEPROM의 크기를 고려하여 스케치 코드를 변경해야 합니다. 이렇게 하려면 "For" 루프의 종료 조건을 변경해야 합니다. 예를 들어, 1kb EEPROM 메모리가 있는 ATmega328의 경우 주기는 다음과 같습니다.
결론.
꽤 오랫동안 방황했는데, 이게 다 뭐죠? 결론적으로 펌웨어를 백업할 때 EEPROM도 저장할 수 있지만 설정을 저장해야 하는 경우에만 가능합니다. 그들을 희생할 준비가 되었다면 잊어버리십시오. 또한 한 펌웨어를 다른 펌웨어로 변경하거나 한 버전에서 다른 버전으로 전환하는 경우 업로드하기 전에 게으르지 말고 EEPROM을 지우십시오. 새로운 펌웨어. 글쎄, 동시에 우리는 많은 새로운 것을 배웠습니다.

퍼니스 컨트롤러는 거의 준비되었습니다. 그러나 지금은 첫 번째 전원을 끄기 5분 전에 모든 설정을 기억하는 "금붕어" 컨트롤러로 남아 있습니다. 전원을 끈 후에도 설정, 설정 온도 및 교정 포인트 값을 기억하려면 비휘발성 메모리인 EEPROM을 사용해야 합니다.
우리 친구들은 EEPROM 작업에 대해 아주 잘 썼습니다.

우리가 알아야 할 가장 중요한 것은 EEPROM 메모리"단순한 메모리"가 아니라 칩에 있는 별도의 내부 장치로 간주하는 것이 좋습니다.
EEPROM 별도의 주소 공간, 이는 프로세서 주소 공간(FLASH 및 SRAM)과 관련이 없습니다. 비휘발성 메모리의 특정 주소에 있는 데이터에 액세스하려면 다음을 실행해야 합니다. 특정 순서다수의 레지스터(주소 레지스터 EEARH 및 EEARL, 데이터 레지스터 EEDR 및 제어 레지스터 EECR)를 사용하는 작업.
데이터시트에 따르면 EEPROM의 특정 주소에 바이트를 쓰려면 다음을 수행해야 합니다.

  1. EEPROM이 데이터를 쓸 준비가 될 때까지 기다립니다(EECR 레지스터의 EEPE 비트가 재설정됩니다).
  2. FLASH 메모리 쓰기가 끝날 때까지 기다립니다(SPMCSR 레지스터의 SELFPRGEN 비트 재설정). 프로그램에 부트로더가 있는 경우 이 작업을 수행해야 합니다.
  3. 써 내려 가다 새 주소 EEAR 레지스터에(필요한 경우)
  4. EEDR 레지스터에 데이터 바이트를 씁니다(필요한 경우).
  5. EECR 레지스터의 EEMPE 비트를 1로 설정합니다.
  6. EEMPE 플래그를 설정한 후 4개의 클록 사이클 내에 EECR 레지스터의 EEPE 비트에 논리 1을 씁니다.

그런 다음 프로세서는 다음 명령을 실행하기 전에 2개의 클록 사이클을 건너뜁니다.
프로그램에 부트로더가 있는 경우 두 번째 사항을 수행해야 합니다. 사실 EEPROM에 쓰는 작업은 FLASH 메모리에 쓰는 작업과 동시에 수행할 수 없으므로 EEPROM에 쓰기 전에 FLASH 메모리 프로그래밍이 완료되었는지 확인해야 합니다. 마이크로컨트롤러에 부트로더가 없으면 FLASH 메모리의 내용을 절대 변경하지 않습니다(avr에는 프로그램 메모리(FLASH)와 데이터 메모리(SRAM)가 분리되어 있는 Harvard 아키텍처가 있다는 점을 기억하세요).
기록 주기의 기간은 칩의 내부 RC 발진기의 주파수, 공급 전압 및 온도에 따라 달라집니다. 일반적으로 ATmega48x/88x/168x 모델의 경우 이는 3.4ms(!)이고 일부 구형 모델의 경우 8.5ms(!!!)입니다.
또한 EEPROM에 쓸 때 위의 일련의 작업을 실행하는 동안 인터럽트를 호출하는 데 문제가 발생할 수 있으므로 EEPROM에 쓰는 동안 인터럽트를 비활성화하는 것이 좋습니다.
비휘발성 메모리를 읽는 것이 조금 더 간단합니다.

  1. EEPROM이 데이터를 읽을 준비가 될 때까지 기다립니다(EECR 레지스터의 EEWE 비트가 재설정됨).
  2. EEAR 레지스터에 주소를 씁니다.
  3. EECR 레지스터의 EERE 비트를 1로 설정합니다.
  4. EEDR 레지스터에서 데이터를 읽습니다(실제로 요청된 데이터가 데이터 레지스터로 이동하면 하드 리셋조금 EERE; 그러나 EEPROM의 읽기 작업은 항상 한 클럭 주기로 수행되므로 이 비트의 상태를 모니터링할 필요가 없습니다.

EERE의 비트를 1로 설정한 후 프로세서는 다음 명령을 실행하기 전에 4클럭 사이클을 건너뜁니다.
보시다시피, 비 휘발성 기억 장치– 프로세스에 시간이 많이 걸립니다. EEPROM에서 데이터를 자주 쓰고 읽는 경우 프로그램 속도가 느려질 수 있습니다.

그러나 우리는 IAR 환경에서 프로그램을 작성하고 있으며 운이 좋게도 EEPROM에서 읽고 쓰는 모든 작업은 개발 환경에서 수행됩니다. iar에는 비휘발성 메모리에 변수를 생성하는 "__eeprom" 수정자가 있습니다. - 그런 다음 "영구" 변수에서 "현재" 변수로 읽거나(컨트롤러를 초기화할 때) "현재" 변수에서 "상수" 변수로 쓰면 됩니다. 즉, 현재 값이 변경되면 비휘발성 메모리의 변수도 변경해야 합니다.
새 변수는 다음과 같습니다.

Eeprom uint16_t EEP_MinTemperature;

몇 가지 일반적인 단어: eeprom 변수에 대한 포인터를 가정하지는 않지만 eeprom은 별도의 주소 공간이라는 점을 기억해야 하며 eeprom에 대한 포인터를 생성하려면(컴파일러에서 이를 허용함) 이는 eeprom의 주소에 대한 포인터임을 나타내야 합니다.

Uint16_t __eeprom *EEP_MinTemperatureAdr;

스토브 컨트롤러와 EEPROM으로 돌아가 보겠습니다. 우리의 경우에는 EEPROM이 없습니다. 가상 기기물론 예상되지는 않습니다. 또한 비휘발성 메모리를 사용하기 위해 별도의 라이브러리가 필요한지 여부를 고려해 볼 가치가 있습니다. 이는 녹음 프로그램 전체에 너무 "흩어져" 있습니다. 중요한 설정; 별도의 라이브러리를 만들려면 상호 참조를 만들어야 합니다. EEPROM용 라이브러리에서 ADC 라이브러리, 발열체 및 전역 설정을 연결합니다. 이러한 주변 장치 라이브러리에서 EEPROM 라이브러리를 연결하는 것은 그다지 좋은 접근 방식이 아닙니다.
또 다른 옵션은 설정을 저장해야 하는 각 라이브러리에 eeprom 변수를 추가하고 해당 설정을 직접 저장하는 것입니다. 가상 머신. 이 옵션을 구현하겠습니다.
먼저 EEPROM에 저장해야 하는 변수를 나열해 보겠습니다.

  1. 교정 포인트
  2. 최대-최소 설정온도 및 온도설정단계의 값
  3. 온도 값 설정
  4. PID 컨트롤러 계수

우리는 주방 타이머의 값을 저장하지 않습니다. 사용자가 전원을 끈 후 매번 스토브 타이머를 설정해야 한다고 가정합니다.
이러한 모든 설정은 사용자가 인코더를 돌린 다음 사용자 버튼을 짧게 눌러 설정합니다. 동시에 EEPROM 읽기-쓰기 주기 수는 여전히 제한되어 있으므로 동일한 정보를 다시 덮어쓰지 마십시오(예: 사용자가 일부 설정에서 동일한 값을 선택한 경우). 따라서 __eeprom 변수를 변경할 때마다 다시 작성해야 하는지 여부를 확인합니다.

//값이 변경된 경우 비휘발성 메모리에 덮어씁니다. if (ADCTemperature.atMinTemperatureValue != (uint16_t)VMEncoderCounter.ecntValue) ( ​​​​ADCTemperature.atMinTemperatureValue = (uint16_t)VMEncoderCounter.ecntValue; EEP_MinTemperature = ADCTemperature.atMinTemperatureV alue; )

EEPROM에서 설정을 읽는 것도 간단합니다. "현재" 설정을 초기화할 때 비휘발성 메모리에서 값을 읽기만 하면 됩니다.

ADCTemperature.atMinTemperatureValue = EEP_MinTemperature;

장치가 처음부터 EEPROM에 일부 설정을 가지도록 하려면 첫 번째 부팅을 위한 프로젝트를 다음 변수를 초기화하여 컴파일할 수 있습니다.

Eeprom uint16_t EEP_MinTemperature = 20; ... //비휘발성 메모리에 교정 포인트를 저장하기 위한 배열 __eeprom TCalibrationData EEP_CalibrationData = ((20, 1300), (300, 4092));

이 경우 컴파일러는 main 함수 작업을 시작하기 전에 __eeprom 변수를 초기화합니다. 비휘발성 메모리(.eep)가 있는 파일을 얻으려면 다음 설정으로 이동해야 합니다.
프로젝트->옵션..->링커->추가 옵션
"명령줄 옵션 사용" 확인란이 선택되어 있지 않으면 확인하고 해당 줄을 추가합니다.
-Ointel-standard,(XDATA)=.eep
먼저 초기화된 변수로 프로젝트를 컴파일하고 eep 파일을 별도로 저장합니다. 그런 다음 변수를 생성할 때 초기화를 제거합니다.

그게 전부입니다. 스토브가 준비되었습니다!

Arduino는 온 가족입니다 다양한 장치전자 프로젝트를 만드는 데 사용됩니다. 마이크로컨트롤러는 사용이 매우 편리하고 초보자도 쉽게 배울 수 있습니다. 각 마이크로컨트롤러는 보드, 작동을 위한 프로그램, 메모리로 구성됩니다. 이번 글에서는 아두이노에서 사용되는 비휘발성 메모리에 대해 살펴보겠습니다.

EEPROM 메모리 설명

Arduino는 사용자에게 세 가지 유형의 내장 장치 메모리를 제공합니다. 고정 RAM(랜덤 액세스 메모리 또는 SRAM - 정적 랜덤 액세스 메모리) - 사용 중 데이터를 기록하고 저장하는 데 필요합니다. 플래시 카드 - 이미 녹음된 패턴을 저장하기 위한 것입니다. – 데이터 저장 및 후속 사용을 위해.

RAM에 있는 모든 데이터는 기기를 재부팅하거나 전원을 끄는 즉시 삭제됩니다. 두 번째 두 개는 덮어쓰기 전에 모든 정보를 저장하고 필요한 경우 검색할 수 있도록 합니다. 요즘에는 플래시 드라이브가 매우 일반적입니다. EEPROM 메모리를 더 자세히 고려해 볼 가치가 있습니다.

약어는 Electrically Erasable Programmable Read-Only Memory의 약자이며 러시아어로 문자 그대로 번역하면 전기적으로 지울 수 있는 프로그래밍 가능한 읽기 전용 메모리를 의미합니다. 제조업체는 마지막 정전 후 수십 년 동안 정보의 안전성을 보장합니다(일반적으로 장치 충전량이 감소하는 비율에 따라 20년이 제공됩니다).

그러나 장치에 다시 쓸 수 있는 능력은 제한되어 있으며 100,000회를 초과할 수 없다는 점을 알아야 합니다. 따라서 입력한 데이터에 주의를 기울이고 다시 덮어쓰지 않는 것이 좋습니다.

최신 미디어에 비해 메모리 양은 매우 적으며 마이크로 컨트롤러마다 다릅니다. 예를 들면 다음과 같습니다.

  • ATmega328 – 1kB
  • ATmega168 및 ATmega8 – 512바이트,
  • 및 ATmega1280 – 4kB.

이렇게 설계된 이유는 각 마이크로컨트롤러가 특정 작업량을 위해 설계되었고 연결용 핀 수가 다르며 그에 따라 필요한 메모리 양도 다르기 때문입니다. 또한 이 금액은 일반적으로 생성되는 프로젝트에 충분합니다.

EEPROM에 쓰는 데는 상당한 시간이 필요합니다. 3ms. 녹음 중에 전원을 끄면 데이터가 전혀 저장되지 않거나 잘못 녹음될 수 있습니다. 작동 중 오류를 방지하기 위해 입력된 정보를 추가로 항상 확인해야 합니다. 데이터 읽기 속도가 훨씬 빨라지고 메모리 리소스가 줄어들지 않습니다.

도서관

EEPROM 메모리 작업은 Arduino용으로 특별히 제작된 라이브러리를 사용하여 수행됩니다. 주요한 것은 데이터를 쓰고 읽는 능력입니다. 명령으로 활성화됨 #EEPROM.h 포함.

  • 을 위한 기록– EEPROM.write(주소, 데이터);
  • 을 위한 독서– EEPROM.read(주소).

이 스케치에서: 주소 – 두 번째 인수 데이터의 데이터가 입력되는 셀의 데이터가 있는 인수입니다. 읽을 때 정보를 읽어야 하는 위치를 나타내는 하나의 인수인 주소가 사용됩니다.

기능 목적
읽다(주소) EEPROM에서 1바이트를 읽습니다. 주소 – 데이터를 읽는 주소(0부터 시작하는 셀)
쓰기(주소, 값) 주소에 있는 메모리에 값(1바이트, 0부터 255까지의 숫자)을 씁니다.
업데이트(주소, 값) 이전 내용이 새 내용과 다른 경우 주소의 값을 바꿉니다.
get(주소, 데이터) 주소의 메모리에서 지정된 유형의 데이터를 읽습니다.
put(주소, 데이터) 지정된 유형의 데이터를 주소의 메모리에 씁니다.
EEPROM "EEPROM" 식별자를 배열로 사용하여 메모리에 데이터를 쓰고 메모리에서 읽을 수 있습니다.

정수 쓰기

비휘발성 EEPROM 메모리에 정수를 쓰는 것은 매우 간단합니다. 기능이 실행될 때 숫자를 입력합니다. EEPROM.write(). 필수 데이터는 괄호 안에 표시됩니다. 이 경우 0부터 255까지의 숫자와 255를 넘는 숫자는 다르게 표기됩니다. 첫 번째 항목은 간단히 입력됩니다. 해당 볼륨은 1바이트, 즉 하나의 셀이 필요합니다. 후자를 작성하려면 가장 높은 바이트에 대해 highByte() 연산자를 사용하고 가장 낮은 바이트에 대해 lowByte() 연산자를 사용해야 합니다.

숫자는 바이트로 나누어 셀에 별도로 기록됩니다. 예를 들어 숫자 789는 두 개의 셀에 기록됩니다. 첫 번째 셀에는 요소 3이 포함되고 두 번째 셀에는 누락된 값이 포함됩니다. 결과는 필수 값입니다.

3 * 256 + 21 = 789

을 위한 « 재결합' 큰 정수 적용 단어 기능(): int val = 단어(안녕하세요, 낮음). 녹음할 수 있는 최대 정수는 65536(즉, 2의 16제곱)이라는 점을 읽어야 합니다. 아직 다른 항목이 없는 셀에서는 모니터에 각각 255라는 숫자가 표시됩니다.

부동 소수점 숫자 및 문자열 작성

부동 소수점 및 문자열 숫자는 가수와 지수로 표현되는 실수 작성 형식입니다. 이러한 숫자는 기능을 활성화하여 비휘발성 EEPROM 메모리에 기록됩니다. EEPROM.put(), 읽기, 각각 – EEPROM.get().

프로그래밍할 때 부동 소수점 숫자 값은 float로 지정되는데, 이는 명령이 아니라 숫자라는 점에 주목할 필요가 있습니다. Char 유형(문자 유형) - 문자열을 나타내는 데 사용됩니다. 모니터에 숫자를 쓰는 프로세스는 setup()을 사용하여 시작되고 읽기-loop()를 사용하여 시작됩니다.

이 과정에서 '과잉'을 의미하는 ovf 값과 '누락'을 의미하는 nan 값이 모니터 화면에 나타날 수 있다. 숫자 값" 이는 셀에 기록된 정보를 부동 소수점 숫자로 재생할 수 없음을 의미합니다. 어떤 유형의 정보가 어떤 셀에 기록되는지 확실하게 알면 이러한 상황이 발생하지 않습니다.

프로젝트 및 스케치의 예

예 1

스케치는 직렬 포트에서 최대 16자를 쓰고 루프의 EEPROM에서 16자를 출력합니다. 덕분에 EEPROM에 데이터가 기록되고 비휘발성 메모리의 내용이 모니터링됩니다.

// EEPROM의 동작을 확인 #include int i, d; void setup() ( Serial.begin(9600); // 포트 초기화, 속도 9600 ) void loop() ( // EEPROM을 읽고 16개의 데이터를 직렬 포트에 출력 Serial.println(); Serial.print("EEPROM = " ); i= 0; while(i< 16) { Serial.print((char)EEPROM.read(i)); i++; } // проверка есть ли данные для записи if (Serial.available() != 0) { delay(50); // ожидание окончания приема данных // запись в EEPROM i= 0; while(i < 20) { d= Serial.read(); if (d == -1) d= " "; // если символы закончились, заполнение пробелами EEPROM.write(i, (byte)d); // запись EEPROM i++; } } delay(500); }

예 2

더 나은 이해를 위해 비휘발성 메모리 작업 방법을 이해하는 데 도움이 되는 작은 스케치를 만들 수 있습니다. 우리는 이 기억의 모든 세포를 센다. 셀이 비어 있지 않으면 직렬 포트로 출력됩니다. 그런 다음 셀을 공백으로 채웁니다. 그런 다음 직렬 포트 모니터를 통해 텍스트를 입력합니다. EEPROM에 기록하고 다음에 전원을 켤 때 읽습니다.

#포함하다 int 주소 = 0; // eeprom 주소 int read_value = 0; // eeprom에서 읽은 데이터 char serial_in_data; // 직렬 포트 데이터 int led = 6; // LED용 라인 6 int i; void setup() ( pinMode(led, OUTPUT); // 라인 6은 출력으로 구성됩니다. Serial.begin(9600); // 직렬 포트 9600의 전송 속도 Serial.println(); Serial.println("EEPROM의 이전 텍스트 : -"); for(주소 = 0; 주소< 1024; address ++) // считываем всю память EEPROM { read_value = EEPROM.read(address); Serial.write(read_value); } Serial.println(); Serial.println("WRITE THE NEW TEXT: "); for(address = 0; address < 1024; address ++) // заполняем всю память EEPROM пробелами EEPROM.write(address, " "); for(address = 0; address < 1024;) // записываем пришедшие с последовательного порта данные в память EEPROM { if(Serial.available()) { serial_in_data = Serial.read(); Serial.write(serial_in_data); EEPROM.write(address, serial_in_data); address ++; digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); } } } void loop() { //---- мигаем светодиодом каждую секунду -----// digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); }

예 3

두 개의 정수를 메모리에 쓰고 EEPROM에서 읽어 직렬 포트로 출력합니다. 함수를 사용하여 0부터 255까지의 숫자가 1바이트의 메모리를 차지합니다. EEPROM.write()원하는 셀에 기록됩니다. 255보다 큰 숫자의 경우 다음을 사용하여 바이트로 나누어야 합니다. 하이바이트()그리고 로우바이트()각 바이트를 자체 셀에 씁니다. 이 경우 최대 수는 65536(또는 2 16)입니다.

#포함하다 // EEPROM 라이브러리 연결 void setup() ( int smallNum = 123; // 0에서 255 사이의 정수 EEPROM.write(0, smallNum); // 셀 0에 숫자 쓰기 int bigNum = 789; // 숫자 분할 > 255 x 2바이트(최대 65536) byte hi = highByte(bigNum); // 상위 바이트 byte low = lowByte(bigNum); // 하위 바이트 EEPROM.write(1, hi); // EEPROM의 상위 바이트 쓰기 셀 1에 .write(2, low); // 셀 2에 하위 바이트 쓰기 Serial.begin(9600); // 직렬 포트 초기화 ) void loop() ( for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (для Arduino UNO 1024) byte val = EEPROM.read(addr); // считываем 1 байт по адресу ячейки Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция Serial.println(val); // выводим значение в послед. порт } delay(60000); // задержка 1 мин }

예 4

부동 소수점 숫자 및 문자열 작성 - 방법 EEPROM.put(). 독서 - EEPROM.get().

#포함하다 // 라이브러리 연결 void setup() ( int addr = 0; // 주소 float f = 3.1415926f; // 부동 소수점 숫자(float 유형) EEPROM.put(addr, f); // 주소에 숫자 f 쓰기 addr addr += sizeof(float); // 다음 여유 메모리 셀 계산 char name = "Hello, SolTau.ru!"; // 문자 배열 생성 EEPROM.put(addr, name); // 배열 쓰기 to EEPROM Serial.begin (9600); // 직렬 포트 초기화 ) void loop() ( for (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (1024Б=1кБ) Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция float f; // переменная для хранения значений типа float EEPROM.get(addr, f); // получаем значение типа float по адресу addr Serial.print(f, 5); // выводим с точностью 5 знаков после запятой Serial.print("\t"); // табуляция char c; // переменная для хранения массива из 20 символов EEPROM.get(addr, c); // считываем массив символов по адресу addr Serial.println(c); // выводим массив в порт } delay(60000); // ждём 1 минуту }

예 번호 5

EEPROM을 배열로 사용합니다.

#포함하다 void setup() ( EEPROM = 11; // 첫 번째 셀에 쓰기 EEPROM = 121; // 두 번째 셀에 쓰기 EEPROM = 141; // 세 번째 셀에 쓰기 EEPROM = 236; // 네 번째 셀에 쓰기 Serial .begin(9600 ); ) void loop() ( for (int addr=0; addr<1024; addr++) { Serial.print(addr); Serial.print("\t"); int n = EEPROM; // считываем ячейку по адресу addr Serial.println(n); // выводим в порт } delay(60000); }

EEPROM 작업

앞서 언급했듯이 EEPROM 메모리는 제한되어 있습니다. 비휘발성 메모리의 수명을 연장하려면 write() 함수 대신 update 함수를 사용하는 것이 좋습니다. 이 경우 새로 쓴 값과 값이 다른 셀에 대해서만 다시 쓰기가 수행됩니다.

문제의 마이크로 컨트롤러 메모리의 또 다른 유용한 기능은 바이트 저장 셀을 통합 EEPROM 어레이의 일부로 사용하는 기능입니다. 어떤 형식으로 사용하든 기록된 데이터의 무결성을 지속적으로 모니터링해야 합니다.

Arduino의 이러한 메모리는 컨트롤러 및 장치 작동에 가장 중요한 사항을 표준적으로 저장합니다. 예를 들어, 이러한 기반으로 온도 컨트롤러가 생성되고 초기 데이터가 잘못된 것으로 판명되면 장치는 기존 조건에 "부적절하게" 작동하여 온도를 크게 과소평가하거나 과대평가하게 됩니다.

EEPROM에 잘못된 데이터가 포함된 상황은 여러 가지가 있습니다.

  1. 초기 활성화 시 아직 항목이 없었습니다.
  2. 통제할 수 없는 정전이 발생하면 데이터의 일부 또는 전체가 기록되지 않거나 잘못 기록됩니다.
  3. 가능한 데이터 다시 쓰기 주기가 완료된 후.

불쾌한 결과를 피하기 위해 비상 코드 데이터 적용, 시스템 완전히 끄기, 오작동 신호 보내기, 이전에 생성된 복사본 사용 등 여러 가지 작업 옵션에 대해 장치를 프로그래밍할 수 있습니다.

정보의 무결성을 제어하기 위해 시스템 제어 코드가 사용됩니다. 이는 원본 데이터 기록을 기반으로 생성되며, 확인되면 데이터를 다시 계산합니다. 결과가 다르면 오류입니다. 이러한 검사의 가장 일반적인 버전은 체크섬입니다. 즉, 모든 셀 값을 추가하기 위해 간단한 수학 연산이 수행됩니다.

숙련된 프로그래머는 이 코드에 E5h와 같은 추가 "배타적 OR"를 추가합니다. 모든 값이 0이고 시스템이 실수로 원본 데이터를 재설정한 경우 이 트릭을 사용하면 오류가 드러납니다.

이는 Arduino 마이크로컨트롤러용 비휘발성 EEPROM 메모리 작업의 기본 원칙입니다. 특정 프로젝트의 경우 이 유형의 메모리만 사용하는 것이 좋습니다. 장점과 단점이 모두 있습니다. 쓰기와 읽기 방법을 익히려면 간단한 작업부터 시작하는 것이 좋습니다.

Mega 제품군의 모든 마이크로 컨트롤러에는 비휘발성 메모리( EEPROM메모리). 이 메모리의 용량은 ATmega8x 모델의 512바이트부터 구형 모델의 4KB까지 다양합니다. EEPROM메모리는 자체 주소 공간에 위치하며 RAM과 마찬가지로 선형적으로 구성됩니다. 함께 일하다 EEPROM메모리는 주소 레지스터, 데이터 레지스터, 제어 레지스터 등 세 가지 I/O 레지스터를 사용합니다.

주소 등록

주소 등록 EEPROM메모리 EEAR(EEPROM 주소 레지스터)물리적으로 두 곳에 위치 RVV EEARH:EEARL, 따라 위치
각각 $1F($3F) 및 $1E($3E)를 주소로 지정합니다. 이 레지스터에는 액세스할 셀의 주소가 로드됩니다. 주소 레지스터는 쓰기와 읽기가 모두 가능합니다. 동시에 등록부에 EEARH최하위 비트만 사용됩니다(관련된 비트 수는 볼륨에 따라 다름). EEPROM메모리). 사용되지 않은 레지스터 비트 EEARH읽기 전용이며 "0"을 포함합니다.

데이터 레지스터

데이터 레지스터 EEPROM메모리 EEDR(EEPROM 데이터 레지스터)$1D($3D)에 위치합니다. 이 레지스터에 쓸 때, 다음에 배치되어야 하는 데이터가 로드됩니다. EEPROM, 그리고 읽을 때, 읽은 데이터는 EEPROM.

제어 레지스터

제어 레지스터 EEPROM메모리 EECR(EEPROM 제어 레지스터)$1C($3C)에 위치합니다. 이 레지스터는 다음 용도로 사용됩니다.
액세스 제어 EEPROM메모리. 이에 대한 설명은 아래 표에 나와 있습니다.

해고하다 이름 설명
7..4 - 사용되지 않음, "0"으로 읽음
3 기분 나쁜 EEPROM에서 인터럽트를 활성화합니다. 이 비트는 EEPROM 쓰기 사이클이 완료될 때 발생하는 인터럽트 생성을 제어합니다. 이 비트가 "1"로 설정되면 인터럽트가 활성화됩니다(레지스터의 I 플래그가
SREG도 "1"로 설정됩니다.) EEWE 비트가 지워지면(자세한 내용은
표) 인터럽트가 지속적으로 생성됩니다.
2 EEMWE EEPROM에서 쓰기 권한을 제어합니다. 이 비트의 상태는 EEWE 쓰기 활성화 플래그의 작동을 결정합니다. 이 비트가 "1"로 설정된 경우 EEWE 비트 "1"에 쓸 때 데이터가 EEPROM에 기록됩니다. 그렇지 않으면 EEWE를 "1"로 설정해도 아무런 효과가 없습니다. 소프트웨어 설치 후 EEMWE 비트는 다음을 통해 하드웨어에 의해 재설정됩니다.
4개의 기계 사이클
1 에웨 EEPROM에 쓰기를 허용합니다. 이 비트가 "1"로 설정되면 데이터가 EEPROM에 기록됩니다(EEMWE가 "1"인 경우).
0 에레 EEPROM의 읽기 권한입니다. 이 비트를 "1"로 설정한 후 EEPROM에서 데이터를 읽습니다. 읽기가 완료되면 이 비트는 하드웨어에 의해 재설정됩니다.

EEPROM에 1바이트를 쓰려면 다음이 필요합니다.

1. EEPROM이 데이터를 쓸 준비가 될 때까지 기다리십시오(EECR 레지스터의 EEWE 플래그가 재설정될 때까지 기다리십시오).

2. FLASH 프로그램 메모리에 쓰기가 완료될 때까지 기다립니다(SPMCR 레지스터의 SPMEN 플래그가 재설정될 때까지 기다림).

3. 데이터 바이트를 EEDR 레지스터에 로드하고 필요한 주소를 EEAR 레지스터에 로드합니다(필요한 경우).

4. EECR 레지스터의 EEMWE 플래그를 "1"로 설정합니다.

5. EECR 레지스터의 EEWE 비트에 로그를 기록합니다. 4개의 기계 사이클에 대해 "1"입니다. 이 비트를 설치한 후 프로세서
다음 명령을 실행하기 전에 2개의 기계 주기를 건너뜁니다.

EEPROM에서 1바이트를 읽으려면 다음이 필요합니다.

1. EEWE 플래그의 상태를 확인합니다. 사실 EEPROM 메모리에서 쓰기 작업이 수행되는 동안(EEWE 플래그가 설정됨) EEPROM 메모리를 읽거나 주소 레지스터를 변경하는 것은 수행될 수 없습니다.

2. 필요한 주소를 EEAR 레지스터에 로드합니다.

3. EECR 레지스터의 EERE 비트를 "1"로 설정합니다.

요청된 데이터가 EEDR 데이터 레지스터에 배치되면 이 비트의 하드웨어 재설정이 발생합니다. 그러나 EEPROM의 읽기 작업은 항상 하나의 머신 사이클에서 완료되므로 읽기 작업이 완료되는 시기를 결정하기 위해 EERE 비트의 상태를 모니터링할 필요는 없습니다. 또한 EERE 비트를 "1"로 설정한 후 프로세서는 다음 명령어를 시작하기 전에 4개의 기계 주기를 건너뜁니다.

AVR Studio GCC 환경에는 EEPROM 작업을 위한 표준 라이브러리가 있으며, 이는 파일을 연결하여 활성화됩니다. . 주요 기능은 eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word().예를 들어, 0부터 9까지의 미니 카운터에 대한 프로그램을 작성해 보겠습니다. 여기서 하나의 버튼을 누르면 값이 추가되고 다른 버튼은 이 값을 메모리에 저장합니다. Atmega8 마이크로 컨트롤러는 8MHz 주파수의 내부 클록 생성기에서 작동합니다. 공통 양극이 있는 한 자리 7세그먼트 표시기는 전류 제한 저항 R1-R7을 통해 포트 B에 연결되고, 공통 양극은 전원 공급 장치 플러스에 연결됩니다. 다이어그램은 다음과 같습니다.

먼저 EEPROM을 포함하여 동작에 필요한 라이브러리를 연결합니다. 변수를 정의합니다. 변수 "s"는 표시기에 대한 출력 값을 저장합니다. SB1 버튼을 누르면 이 값은 1씩 증가하지만 10을 초과할 수 없습니다. eeprom_var 변수는 EEPROM과 상호 작용합니다. 전원을 켜면 EEPROM을 읽고 읽은 데이터를 변수 "s"에 할당하고 이를 기반으로 특정 숫자가 표시기에 표시됩니다. SB2를 누르면 변수 "s"의 데이터가 EEPROM에 기록되고 표시등이 한 번 깜박입니다.

#포함하다 #포함하다 #포함하다 #define d0 ~(0x3F) // 0 #define d1 ~(0x06) // 1 #define d2 ~(0x5B) // 2 #define d3 ~(0x4F) // 3 #define d4 ~(0x66) // 4 #define d5 ~(0x6D) // 5 #define d6 ~(0x7D) // 6 #define d7 ~(0x07) // 7 #define d8 ~(0x7F) // 8 #define d9 ~(0x6F) // 9 서명되지 않은 문자; 서명되지 않은 char eeprom_var EEMEM; // EEPROM int main (void)에 변수 정의 ( DDRB = 0xFF; // 출력용 포트 B PORTB = 0xFF; DDRD = 0x00; // 입력용 포트 D PORTD = 0xFF; // 풀업 저항 켜기 s = eeprom_read_byte(&eeprom_var ); // EEPROM에서 바이트를 읽고 "s"에 넣습니다. while(1) ( if((PIND&(1<< PD0)) == 0) // если кнопка SB1 нажата { while((PIND&(1 << PD0)) == 0){} // ждем отпускания кнопки s++; // увеличиваем "s" на единицу _delay_ms(200); } if(s == 10) // Когда дойдет до 10 обнуляем "s" { s = 0; } if((PIND&(1 << PD1)) == 0) // если кнопка SB2 нажата { while((PIND&(1 << PD1)) == 0){} // ждем отпускания кнопки DDRB = 0xFF; // мигаем индикатором _delay_ms(200); DDRB = 0x00; _delay_ms(200); DDRB = 0xFF; eeprom_write_byte(&eeprom_var, s); // записываем "s" в EEPROM _delay_ms(200); } if(s==0) // Выводим цифры на индикатор PORTB = d0; if(s==1) PORTB = d1; if(s==2) PORTB = d2; if(s==3) PORTB = d3; if(s==4) PORTB = d4; if(s==5) PORTB = d5; if(s==6) PORTB = d6; if(s==7) PORTB = d7; if(s==8) PORTB = d8; if(s==9) PORTB = d9; } }

코멘트

0 안톤칩 2013년 5월 2일 22:15

나는 Max의 말을 인용한다:

뭔가 헷갈릴 수도 있지만 OA 표시기가 있으면 5V 라인에 저항 하나면 충분합니다. 고전류로부터 보호해야 하는 요소 뒤에 전류 제한 저항을 설치하는 이유는 무엇입니까??


표시기의 한 세그먼트가 이 저항 연결 방식과 다른 저항 연결 방식으로 닫히면 어떻게 될지 상상해 보십시오.

0 안톤칩 2013년 5월 15일 11:16

나는 gydok을 인용합니다 :

eeprom에 2차원 배열을 작성하는 방법은 무엇입니까?


암호:
#포함하다 // 라이브러리 포함

EEMEM unsigned char colors=((1, 2, 3), // EEPROM에 배열 선언
{4, 5, 6}};

eeprom_write_byte(&colors, 1); // EEPROM에 배열 요소 쓰기
eeprom_write_byte(&colors, 2);
eeprom_write_byte(&colors, 3);
eeprom_write_byte(&colors, 4);
eeprom_write_byte(&colors, 5);
eeprom_write_byte(&colors, 6);

서명되지 않은 문자 온도;
temp = eeprom_read_byte(&colors); // EEPROM에서 배열 요소를 추출합니다. 두 번째 행(), 첫 번째 열(), 즉 번호 4

EEPROM 메모리 재설정

이 예에서는 모든 메모리 셀을 반복하고 여기에 0을 씁니다.

// EEPROM과 함께 작동하도록 라이브러리를 연결합니다. #include "EEPROM.h" void setup() ( // 모든 셀(바이트)을 살펴보고 여기에 0을 씁니다. for (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 0); } void loop() { // Пустой цикл... }


공장 초기화

메모리를 공장 설정으로 되돌리려면 0을 255로 바꿔야 합니다. 즉, 0이 아닌 255라는 숫자를 쓴다. 따라서 앞으로 isNaN() 함수를 이용하면 EEPROM 메모리에 쓰기가 되었는지 아닌지 확인할 수 있다.

// EEPROM과 함께 작동하도록 라이브러리를 연결합니다. #include "EEPROM.h" void setup() ( // 모든 셀(바이트)을 탐색하고 그 안에 숫자 255를 씁니다. for (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 255); } void loop() { // Пустой цикл... }

우리에 대해 알려주세요

메시지

Arduino 작업 경험이 있고 실제로 창의력을 발휘할 시간이 있다면 모든 사람이 포털에 게시된 기사의 저자가 되도록 초대합니다. Arduino 실험에 대한 교훈이나 이야기가 될 수 있습니다. 다양한 센서 및 모듈에 대한 설명입니다. 초보자를 위한 팁과 지침. 에 기사를 작성하고 게시하세요.