+7(960) 250-82-68 spam@mirossa.ru


 mirossa        1С           C         PHP       JAVA       MCU  


Статьи
 
 
решение задачи 6.2 по учебнику Discovering the STM32 Microcontroller by Geoffrey Brown

STM32. Запись и чтение из EEPROM 25LC160. Интерфейс SPI.

При нажатии на синюю кнопку пропускаем время дребезга контакта и начинаем процесс записи и чтения. Вначале тестируем отклики модуля памяти на команды. Записываем. Читаем.
Data-sheet 25AA160/25LC160/25C160

Весь исходный код. ide CooCox.

connection STM32 and 25LC160

некоторые модули:

/*file main.c*/

#include <stm32f10x.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_spi.h>
#include "eeprom.h"
#include <string.h>

uint8_t txbuf[4], rxbuf[4];
uint16_t txbuf16[4], rxbuf16[4];

void otherInit(void);

void Delay(uint32_t nTime);
uint8_t debounce(uint8_t last);

#define rlen 80

int main(void)
{
	uint8_t currentButton;
	uint8_t lastButton;

	uint8_t len;
	uint8_t rbuf[rlen], rs;
	char mes[] = "The Read Status Register (RDSR) instruction provides access to the Status register.";

	lastButton = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
	currentButton = lastButton;

	otherInit(); // Initialize user button
	eepromInit();

	// Configure SysTick Timer
	if (SysTick_Config(SystemCoreClock / 1000))
			while (1);

	while (1)	{

		currentButton = debounce(lastButton);

		if ( lastButton == Bit_RESET && currentButton == Bit_SET ){

			// test. begin
			eepromWriteEnable();

			if (WEL(rs = eepromReadStatus())) // check if WREN operation worked
				eepromWriteDisable();
			else
				assert_failed(__FILE__, __LINE__);

				// (Когда на pin WP высокий сигнал)
				// Установка битов BP0 and BP1.
				if (!WEL((rs = eepromReadStatus()))){ // check if WRDI operation worked
					eepromWriteEnable();
					eepromWriteStatus( 4 | 8); // BP0 | BP1
				} else
					assert_failed(__FILE__, __LINE__);

				rs = eepromReadStatus();  // BP0 and BP1 are set. (value of Read Status Register is 00001100.

				if ((rs & ( 4 | 8))){ // check if WRSR operation worked

					//если биты BP0 and BP1 не сбрасывать, то данные в память не записать
					//(согласно установленному сочетанию BP0 and BP1).
					//В этом случае (когда нужно записать данные) после "применения"
					// записи ( chip select to high) бит WEL не сбрасывается.
					// в dataSheet 25AA160/25LC160/25C160 это последний вариант в
					// TABLE 3-3: WRITE-PROTECT FUNCTIONALITY MATRIX
					eepromWriteEnable();
					eepromWriteStatus(0x00); // reset status register for subsequent operations
				}else
					assert_failed(__FILE__, __LINE__);

			rs = eepromReadStatus();
			//test. end


			len = (uint8_t)strlen(mes);
			eepromWrite(mes, len, 4 ); //записать с адреса 4

			eepromRead(rbuf, rlen, 0 ); // прочитать с адреса x00 80 байт


		}

		lastButton = currentButton;

	}//while

    return 0;
}

void otherInit(void){
	GPIO_InitTypeDef GPIO_InitStructure;


	// user button A0
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_Init(GPIOA,	&GPIO_InitStructure);
}

static __IO uint32_t TimingDelay;

void Delay(uint32_t nTime){
	TimingDelay = nTime;
	while(TimingDelay != 0);
}

void SysTick_Handler(void){
	if (TimingDelay != 0x00)
		TimingDelay--;
}

uint8_t debounce(uint8_t last){
	uint8_t current = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
	  if ( last != current ){
		  Delay(5);
		  current = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
	  }
  return current;
}

#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
	/* Infinite loop */
	/* Use GDB to find out why we're here */
	while (1);
}
#endif
Под отладкой. Прочитанные 80 байт

/*file eeprom.c*/

#include <stm32f10x.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_spi.h>
#include "eeprom.h"
#include "spi.h"

#define EEPROM_PORT GPIOC
#define EEPROM_CS GPIO_Pin_10
#define EEPROM_SPI SPI2
#define EEPROM_SPEED SPI_SLOW

#define PAGESIZE 16
// по смещению вычисляем, сколько байт можно вместить на текущую страницу
// а дальше размещать на следующих страницах.
#define MAX_NO_WRITES(x) (PAGESIZE - (x % PAGESIZE))

void eepromInit(void){

	 GPIO_InitTypeDef GPIO_InitStructure;

	 //slave select
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE); // изменить при смене EEPROM_PORT
	 GPIO_StructInit(&GPIO_InitStructure);
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	 GPIO_InitStructure.GPIO_Pin =  EEPROM_CS;
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	 GPIO_Init(EEPROM_PORT, &GPIO_InitStructure);

	 GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1); //включаю высокий сигнал
	 
	 /*Initialise SPI*/
	 spiInit(EEPROM_SPI);
}

enum eepromCMD {cmdREAD = 0x03, cmdWRITE = 0x02,
				cmdWREN = 0x06, cmdWRDI = 0x04,
				cmdRDSR = 0x05, cmdWRSR = 0x01};

uint8_t eepromReadStatus(void){
	uint8_t cmd[] = {cmdRDSR, 0xff};
	uint8_t res[2];
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
	spiReadWrite(EEPROM_SPI, res, cmd, 2, EEPROM_SPEED);
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1);
	return res[1];
}

void eepromWriteEnable(void){
	uint8_t cmd = cmdWREN;

	while (WIP(eepromReadStatus()));
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
	spiReadWrite(EEPROM_SPI, 0, &cmd, 1, EEPROM_SPEED);
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1);

}

void eepromWriteDisable(void){
	uint8_t cmd = cmdWRDI;
	
	while (WIP(eepromReadStatus()));
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
	spiReadWrite(EEPROM_SPI, 0, &cmd, 1, EEPROM_SPEED);
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1);
	
}

void eepromWriteStatus(uint8_t status){
	uint8_t cmd[] = {cmdWRSR, status};

	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
	spiReadWrite(EEPROM_SPI, 0, cmd, 2, EEPROM_SPEED);
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1);
}

int eepromWrite(uint8_t *buf, uint8_t cnt, uint16_t offset){

	uint8_t cmd = cmdWRITE, rs;
	uint16_t factn, tail;
	uint16_t maxn = MAX_NO_WRITES(offset);

	while (WIP(eepromReadStatus()));
	while ( !WEL(eepromReadStatus()) )
		eepromWriteEnable(); // be set Write Enable Latch (WEL)

		factn = ( maxn > cnt) ?  cnt: maxn;
		// запись начала данных с середины страницы до конца страницы
		GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
		spiReadWrite(EEPROM_SPI, 0, &cmd, 1, EEPROM_SPEED);
		spiReadWrite16(EEPROM_SPI, 0, &offset, 1, EEPROM_SPEED);
		spiReadWrite(EEPROM_SPI, 0, buf, factn, EEPROM_SPEED);
		GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1);

		offset += factn;

	//rs = eepromReadStatus();

		tail = cnt - factn;

			while ( tail > 0 ){
				//запись оставшихся данных с начала страницы
				factn = ( tail > PAGESIZE) ?  PAGESIZE: tail;

				while (WIP(eepromReadStatus()));
				 //здесь можно проверить, если бит WEL установлен, то
				// запись не завершилась успешно (например, блокирование от записи)

				//включить бит WEL, сброшенный после успешной записи
				while ( !WEL(eepromReadStatus()) )
					eepromWriteEnable(); // will be set Write Enable Latch (WEL)
				//rs = eepromReadStatus();

				GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
				spiReadWrite(EEPROM_SPI, 0, &cmd, 1, EEPROM_SPEED);
				spiReadWrite16(EEPROM_SPI, 0, &offset, 1, EEPROM_SPEED);
				spiReadWrite(EEPROM_SPI, 0, buf+maxn, factn, EEPROM_SPEED);
				GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1); //применение записи

				rs = eepromReadStatus();

				offset += factn;
				maxn += factn;
				tail -= factn;
			}

	while (WIP(eepromReadStatus()));
	if ( !WEL(eepromReadStatus()) )
		return 0; // при успешном завершении записи WEL сбрасывается.
	else {
		eepromWriteDisable();
		return 1;
	}
}

int eepromRead(uint8_t *buf, uint8_t cnt, uint16_t offset){
	uint8_t cmd = cmdREAD;
	
	while (WIP(eepromReadStatus()));

	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 0);
	spiReadWrite(EEPROM_SPI, 0, &cmd, 1, EEPROM_SPEED);
	spiReadWrite16(EEPROM_SPI, 0, &offset, 1, EEPROM_SPEED);
	spiReadWrite(EEPROM_SPI, buf, 0, cnt, EEPROM_SPEED);
	GPIO_WriteBit(EEPROM_PORT, EEPROM_CS, 1);
	
	return 0;
}

Комментарии




information