Skocz do zawartości

[C] STM32F051 SPI nie odbiera danych z kości pamięci.


Pomocna odpowiedź

Napisano

Cześć. Borykam się z SPI w układzie stm32f051. Komunikuję się z układem zewnętrznej pamięci flash w celu zapisu rekordów pomiaru dalmierza. Natrafiłem na dziwną przypadłość. Układ startuje i wysyła dane do układu prawidłowo (sprawdzone analizatorem). Układ też chętnie odpowiada zgodnie z oczekiwaniami. Ale gdy chcę sprawdzić co odebrał, w debuggerze wyświetla mi się 0x00 lub 0xFF tak jak by noga była zwarta do masy lub do plusa (połączenie pewne, pomiar analizatora dokonany niedaleko wyprowadzenia). Oczywiście dzieje się tak tylko w momencie gdy zakomentuję while-a czekającego na reset flagi odebrania danych. W innym wypadku program zawiesi się na tym etapie. Dodaję kod:

/**
 ******************************************************************************
 * @file    main.c
 * @author  Ac6
 * @version V1.0
 * @date    01-December-2013
 * @brief   Default main function.
 ******************************************************************************
*/


#include "stm32f0xx.h"
#include "stm32f0_discovery.h"

volatile uint32_t timer_ms = 0;
#define PCS		1
#define NCS		0



void SysTick_Handler()		//handler przerwania
{
if (timer_ms) {
timer_ms--;
}
}

void delay_ms(int time)
{
timer_ms = time;
while (timer_ms) {};
}

uint8_t spi(uint8_t byte,uint8_t mode){

uint8_t data_rev;

GPIO_ResetBits(GPIOA, GPIO_Pin_4); //cs to low


 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
 SPI_SendData8(SPI1, byte);

 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
 data_rev=SPI_ReceiveData8(SPI1);

 if(mode==PCS) GPIO_SetBits(GPIOA, GPIO_Pin_4); //cs to high

return data_rev;
}


void flash_init(){

spi(0x06,PCS);
delay_ms(50); //small delay
spi(0x66,PCS);
delay_ms(50);
spi(0x99,PCS);
delay_ms(50);
}

uint8_t flash_read(uint8_t addr){
uint8_t data;

spi(0x03,NCS);
spi(0x00,NCS);
spi(0x00,NCS);
spi(addr,NCS);
data = spi(0xFF,PCS);

return data;
}



void flash_write(uint8_t addr, uint8_t data){

spi(0x02,NCS);
spi(0x00,NCS);
spi(0x00,NCS);
spi(addr,NCS);
spi(data,PCS);
}


int main(void)
{
//sys clock config
SysTick_Config(SystemCoreClock / 1000); //przerwanie co 1ms

//spi config

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

SPI_InitTypeDef SPI_InitTypeDefStruct;


SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft;
SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8 ;
SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_Init(SPI1, &SPI_InitTypeDefStruct);


RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

GPIO_InitTypeDef GPIO_InitTypeDefStruct;

GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);

GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_4;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOA, &GPIO_InitTypeDefStruct);

GPIO_SetBits(GPIOA, GPIO_Pin_4); //cs to high


SPI_Cmd(SPI1, ENABLE);

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);

GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOC, &GPIO_InitTypeDefStruct);
GPIO_ResetBits(GPIOC, GPIO_Pin_4);


//flash init
delay_ms(2000);

flash_init();
uint8_t data=0;

while (1) {
 flash_write(0x01,0x33);
 delay_ms(100);
 data=flash_read(0x01);

 if (data==0x33)
 {
	 GPIO_SetBits(GPIOC, GPIO_Pin_9);
 }else{
	 GPIO_ResetBits(GPIOC, GPIO_Pin_9);
 }

 delay_ms(1000);
}

}

A testowałeś swój SPI na innych operacjach z ta pamięcią? Jakieś odczyty rejestru stanu? Zawartość wygląda sensownie? Chodzi mi o odróżnienie, czy problem leży w samych funkcjach SPI czy może w interfejsie do pamięci, kodach operacji (choć 0x03 i 0x02 wydają się typowe) czy niezrozumieniu protokołu.

Czy odczyt jakiegoś dziewiczego bloku pokazuje ciąg 0xFF?

Napisz jaka to kostka, bo szeregowe FLASHe potrafią być całkiem skomplikowane i są różne. Odblokowałeś zapis? Kasujesz sektory/bloki przed zapisem? Ta operacja zajmuje trochę czasu i wymaga odczytu rejestru stanu. Jeśli komunikacja działa, po starcie kasowania dostaniesz niegotowość pamięci (bit w rejestrze stanu) a po jakimś czasie gotowość. Przynajmniej będzie widać, że pamięć żyje a Twoje funkcje działają.

Nie testuj pamięci FLASH wciąż na tej samej komórce i tym samym sektorze. Do komórki FLASHa możesz "doprogramowywać" tylko bity zerowe. Nie możesz odwrócić na jeden inaczej jak tylko przez skasowanie dużego obszaru.

Jest to kość pochodząca z płytki esp8266. Na analizatorze po wywołaniu komendy zapisu wartości np. 0x33 po wysłaniu komendy odczytu, z przebiegów wynika że układ odpowiada wartością 0x33 więc układ jest inicjalizowany i odpowiada prawidłowo. Tylko nie wiem dlaczego to co było na kablu, nie trafia do bufforu.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...