Jump to content
    

Второй день пытаюсь вызвать к жизни SPI1 или 2 на STM32VLDISCOVERY.

Перерыл интернет и даташит до тошноты.

Не пойму что не так:

   RCC->APB2ENR |=  RCC_APB2ENR_IOPBEN; // Разрешить тактирование порта B.
  RCC->APB2ENR |=  RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций GPIO.
//Настройки GPIO	
  GPIOB->CRH   |=  GPIO_CRH_MODE15_1;  // Выход MOSI PB.15
  GPIOB->CRH   &= ~GPIO_CRH_MODE15_0;  // 2MHz
  GPIOB->CRH   &= ~GPIO_CRH_CNF15;		// Push-Pull

  GPIOB->CRH   &= ~GPIO_CRH_MODE14;	// Вход  MISO PB.14
  GPIOB->CRH   &= ~GPIO_CRH_CNF14_0;   //
  GPIOB->CRH   |=  GPIO_CRH_CNF14_1;	 // Pull-Up
  GPIOB->ODR   |=  GPIO_ODR_ODR14;	   // 

  GPIOB->CRH   |=  GPIO_CRH_MODE13_1;	// Выход SCK  PB.13
  GPIOB->CRH   &= ~GPIO_CRH_MODE13_0;  // 2MHz
  GPIOB->CRH   &= ~GPIO_CRH_CNF13;		// Push-Pull

  GPIOB->CRH   &= ~GPIO_CRH_MODE12;	// Вход  NSS  PB.12
  GPIOB->CRH   &= ~GPIO_CRH_CNF12_0;   //
  GPIOB->CRH   |=  GPIO_CRH_CNF12_1;	 // Pull-Up
  GPIOB->ODR   |=  GPIO_ODR_ODR12; 

//Настройки SPI2  
  RCC->APB1ENR |=  RCC_APB1ENR_SPI2EN; //Разрешаем тактирование SPI2

  SPI2->CR1   &= ~SPI_CR1_SPE;		//Отключаем SPI перед изменением настроек
  SPI2->CR1   |=  SPI_CR1_BR_0;		//Задаем скорость
  SPI2->CR1   |=  SPI_CR1_BR_1;		//
  SPI2->CR1   |=  SPI_CR1_CPOL;		//Задаем режим
  SPI2->CR1   |=  SPI_CR1_CPHA;		//
  SPI2->CR1   &= ~SPI_CR1_DFF;		//Формат данных 8 бит
  SPI2->CR1   &= ~SPI_CR1_CRCEN;	//Запрет CRC
  SPI2->CR1   &= ~SPI_CR1_CRCNEXT; //Отключение передачи CRC
  SPI2->CR1   &= ~SPI_CR1_RXONLY;   //и прочих не fullduplex настроек
  SPI2->CR1   &= ~SPI_CR1_SSM;		//на всякий случай..
  SPI2->CR1   &= ~SPI_CR1_SSI;		 //
  SPI2->CR1   &= ~SPI_CR1_LSBFIRST; //MSB вперед
  SPI2->CR1   |=  SPI_CR1_MSTR;		 //В режиме Мастер
  SPI2->CR1   &= ~SPI_CR1_BIDIMODE;//
  SPI2->CR1   &= ~SPI_CR1_BIDIOE;	 //

  SPI2->CR2   &= ~SPI_CR2_SSOE; // Запретить выход SS
			// (на входе задан высокий уровень)

  SPI2->CR1   |=  SPI_CR1_SPE;  // Включаем SPI
.....
//Пробная прием-передача
u8 temp;	 
  while (SPI2->SR & SPI_SR_BSY);
  while (!(SPI2->SR & SPI_SR_TXE));	  
  SPI2->DR = 0x55;				 // Передача данных
  while (SPI2->SR & SPI_SR_BSY);
  while (!(SPI2->SR & SPI_SR_RXNE)); 
  temp = SPI2->DR;				// Чтение принятых данных
.......

 

При отладке видно, что все настройки устанавливаются как прописано в коде,

а в регистр DR данные 0x55 так и не записывается. На ногах процессора молчок.

Тоже самое делал и для SPI1 с учетом бита альтернативной распиновки.

Наверное, если взять библиотеку с функциями инициализации все бы заработало,

но хочу вот так через "stm32f10x.h".

Помогите пожалуйста разобраться.

Edited by IgorKossak
[codebox]

Share this post


Link to post
Share on other sites

зачем же так "долбить" SPI2->CR1 ? ... все можно уместить в пару строк

 // включим тактирование - порт A, SPI1
  RCC->APB2ENR = RCC_APB2ENR_IOPAEN |RCC_APB2ENR_AFIOEN | RCC_APB2ENR_SPI1EN;    
  // set SPI1
  AFIO->MAPR &= 0xFFFFFFFE;     // clear AFIO_MAPR->SPI1_REMAP bit
  SPI1->CR1 = (1<<2)|(5<<3)|(1<<6)|(1<<8)|(1<<9);
  SPI1->CR2 = 0x0000;
  //  set pin
  GPIOA->BSRR = 0x00000010;      
  GPIOA->CRL   = 0xB8B34444;

Share this post


Link to post
Share on other sites

Делал так (под новуб библиотеку периферии). Для работы с AD9832

void SPI1_Init(void)
{

// PA4 - NSS софтовый PA5 - SPI1 SCK	PA7 - SPI1 MOSI  

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);  

// NSS: выход push-pull 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   
GPIO_Init(GPIOA, &GPIO_InitStructure);
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);

// SCK: выход push-pull 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);

// MOSI: выход push-pull 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
 GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

 SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;  //?
 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;   
 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; 

 SPI_Init(SPI1, &SPI_InitStructure);
 SPI_Cmd(SPI1, ENABLE);

 GPIOA->ODR |= GPIO_OTYPER_ODR_4;

}

Запускается без проблем.

Но по ходу вопрос.

Как переназначить GPIO SPI1 на другие ноги?

В новой библиотеке (в предыдущей вроде были) исчезли функции ремапинга. Куда они подевались?

Edited by Acvarif

Share this post


Link to post
Share on other sites

зачем же так "долбить" SPI2->CR1 ? ... все можно уместить в пару строк

Это от безисходности и злобы :rolleyes:

 

Share this post


Link to post
Share on other sites

Это от безисходности и злобы ...
... надеюсь все теперь все ОК ... код из рабочего примера

Как переназначить GPIO SPI1 на другие ноги?
1 - посмотреть в datasheet :) .. на других ногах "висит" JTAG, так что помимо установки AFIO_MAPR->SPI1_REMAP нужно позаботиться о JTAG
Edited by ChipKiller

Share this post


Link to post
Share on other sites

... надеюсь все теперь все ОК ... код из рабочего примера

Благодарю за рабочий код, действительно все заработало, с меня пиво :beer:

Я разобрался в чем была промашка, надо было назначить выходы в режиме альтернативной функции.

   GPIOA->CRL   |=  GPIO_CRL_MODE7;     // Выход MOSI PA.7 (50 MHz)
   GPIOA->CRL   &= ~GPIO_CRL_CNF7_0;    // Push-Pull
   GPIOA->CRL   |=  GPIO_CRL_CNF7_1;    // с альтернативной функцией !!!!!!

Позволю себе выложить весь код тестовой программы в том же стиле.

Такой "долбеж" по регистрам неизбежен на начальном этапе освоения камня,

есть ощущение проникновения в сакральный смысл регистров :biggrin:

#include "stm32f10x.h"
u8 temp;

void main()
{
  RCC->APB2ENR |=  RCC_APB2ENR_IOPAEN; // Разрешить тактирование порта A.
  RCC->APB2ENR |=  RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций GPIO.
  GPIOA->CRL   |=  GPIO_CRL_MODE7;	 // Выход MOSI PA.7 (50 MHz)
  GPIOA->CRL   &= ~GPIO_CRL_CNF7_0;	// Push-Pull
  GPIOA->CRL   |=  GPIO_CRL_CNF7_1;	// с альтернативной функцией !!!!!!

  GPIOA->CRL   &= ~GPIO_CRL_MODE6;	 // Вход  MISO PA.6
  GPIOA->CRL   &= ~GPIO_CRL_CNF6_0;	//
  GPIOA->CRL   |=  GPIO_CRL_CNF6_1;	// with Pull-Up

  GPIOA->CRL   |=  GPIO_CRL_MODE5;	 // Выход SCK  PA.5 (50 MHz)
  GPIOA->CRL   &= ~GPIO_CRL_CNF5_0;	// Push-Pull
  GPIOA->CRL   |=  GPIO_CRL_CNF5_1;	// с альтернативной функцией !!!!

  GPIOA->CRL   |=  GPIO_CRL_MODE4;	 // Выход NSS  PA.4 (50 MHz)
  GPIOA->CRL   &= ~GPIO_CRL_CNF4;	  // Push-Pull General Purpose
  GPIOA->BSRR   =  GPIO_BSRR_BS4;	  // 

  AFIO->MAPR   &= ~AFIO_MAPR_SPI1_REMAP; //Сбрасываем REMAP для SPI на PA4-7
  RCC->APB2ENR |=  RCC_APB2ENR_SPI1EN;

  SPI1->CR1   &= ~SPI_CR1_SPE;		 //Запрещаем SPI перед изменениями настроек
  SPI1->CR1   |=  SPI_CR1_BR_0;		//Задаем скорость
  SPI1->CR1   |=  SPI_CR1_BR_1;
  SPI1->CR1   |=  SPI_CR1_CPOL;		//Задаем режим
  SPI1->CR1   |=  SPI_CR1_CPHA;		//
  SPI1->CR1   &= ~SPI_CR1_DFF;		 //Формат данных 8 бит
  SPI1->CR1   &= ~SPI_CR1_CRCEN;	   //Запрет CRC
  SPI1->CR1   &= ~SPI_CR1_CRCNEXT;	 //Отключение передачи CRC
  SPI1->CR1   &= ~SPI_CR1_RXONLY;	  //и прочих не fullduplex настроек
  SPI1->CR1   &= ~SPI_CR1_SSM;		 //на всякий случай..
  SPI1->CR1   &= ~SPI_CR1_SSI;
  SPI1->CR1   &= ~SPI_CR1_LSBFIRST;	//MSB вперед
  SPI1->CR1   |=  SPI_CR1_MSTR;		//В режиме Мастер
  SPI1->CR1   &= ~SPI_CR1_BIDIMODE;
  SPI1->CR1   &= ~SPI_CR1_BIDIOE;

  SPI1->CR1   |=  SPI_CR1_SPE;		 // Включаем SPI

  while(1)
{
  while (SPI1->SR & SPI_SR_BSY);
  while (!(SPI1->SR & SPI_SR_TXE));	  
  SPI1->DR = 0x55;				 // Передача данных
  while (SPI1->SR & SPI_SR_BSY);
  while (!(SPI1->SR & SPI_SR_RXNE)); 
  temp = SPI1->DR;				 // Чтение принятых данных
}
}

 

Кстати, пошагово в отладчике программа не проходит проверку на RXNE и попадает в бесконечный цикл.

Видать, где-то, RXNE успевает сброситься.

Сам кусок кода с записью и чтением я взял на форуме ST здесь

Автор утверждает, что у него код работает только в этом порядке, хотя в мануале RM0041 не рекомендуют проверять

BSY при каждой посылке и приеме.

 

Note: Do not use the BSY flag to handle each data transmission or reception. It is better to use the

TXE and RXNE flags instead.

Edited by IgorKossak
[codebox]

Share this post


Link to post
Share on other sites

Добрый вечер.

Тоже разбираюсь с SPI.

 

Вроде все делаю как в рабочем примере, но почему то не работает.

Припаял SPI флешку, но при отправлении данных при отладке программы в регистр ODR записывается 00FF, и так и остается.

Уже два дня мучаюсь, что может быть не так?

 

//////////=================SPI===============
void SPI_INIT(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
/* Deinitialize SPI3 peripheral */
SPI_I2S_DeInit(SPI3);

// SCK: выход push-pull PC10
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SCK;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, PIN_SCK , GPIO_AF_SPI3);

// MOSI: выход push-pull PC12
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MOSI;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, PIN_MOSI , GPIO_AF_SPI3);

// MISO: выход push-pull PC11
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MISO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, PIN_MISO , GPIO_AF_SPI3);

//NSS: выход push-pull - use general GPIO for CS A4
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SPI_CS;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//SPI3
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI3, &SPI_InitStructure);

SPI_Cmd(SPI3, ENABLE);
}

 

Отсылаю так

//////////================FOR READ_WRITE SPI=================////////////
void EEPROMSend(char byte){
SPI_I2S_SendData(SPI3, byte);
while (SPI_GetFlagStatus(SPI3, SPI_FLAG_TXE) == RESET);
}

void EEPROMSendByte(char byte){
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
SPI_I2S_SendData(SPI3, byte);
while (SPI_GetFlagStatus(SPI3, SPI_FLAG_RXNE) == RESET);
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
}

char EEPROMReceive(){
char byte;
byte = SPI_I2S_ReceiveData(SPI3);
while (SPI_GetFlagStatus(SPI3, SPI_FLAG_RXNE) == RESET);
return byte;
}


volatile static uint8_t data=0;

int main()
{
int i= 10;
__enable_irq();				//Включаем прерывания
LedInit();
SPI_INIT();
NVIC_SetPriority(SPI3_IRQn, 2);		//Устанавливаем приоритет прерываний от SPI1
NVIC_EnableIRQ(SPI3_IRQn); 				//Включаем прерывания от SPI1

//Write Status Register (WRSR) Instruction Sequence
i++;
EEPROMSendByte(0x06); //command for write sequence EEPROM

//for i
//Write to EEPROM
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
EEPROMSend(0x02);	  //00000010 - write command
EEPROMSend(0x00);						//address
EEPROMSend(0x00);						//address
EEPROMSend(0x00);						//address
EEPROMSend(0x00);						//data
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
delay(120*5000);
///

//Read from EEPROM
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
EEPROMSend(0x03);						//read command
EEPROMSend(0x00);						//address
EEPROMSend(0x00);						//address
EEPROMSend(0x00);						//address
data =  EEPROMReceive();		//fake read
data =  EEPROMReceive();		//read
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
data++;

Edited by IgorKossak
[codebox] для длинного кода!!!

Share this post


Link to post
Share on other sites

// MISO: выход push-pull PC11

Master Input Slave Output

 

Оно?

Share this post


Link to post
Share on other sites

Обновил библиотеки - заработало MOSI, CS и SCLK

Сейчас посмотрел на осциллографе, MISO кстати и не работает. Сразу после записи команды чтения CS уходит в 1, то есть строчки

    data =  EEPROMReceive();        //fake read
    data =  EEPROMReceive();        //read

Вообще пропускаются.

MISO стабильно выдает 1,7 на всем протяжении)

 

Может я что то не понимаю, но при отладке в строчках

void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
  /* Check the parameters */
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
  
  /* Write in the DR register the data to be sent */
  SPIx->DR = Data;
}

 

DR приравнивается 0xFE, хотя Data=0x06? :smile3046:

Edited by dfyz.s

Share this post


Link to post
Share on other sites

в приведённом коде miso программировался на вывод. Должен быть входом.

Edited by Genadi Zawidowski

Share this post


Link to post
Share on other sites

На отладчик забил

Понял, в чем был косяк.

 

uint8_t EEPROMSend(uint8_t byte){
    while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI3, byte);
  while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
    return SPI_I2S_ReceiveData(SPI3);
    }

void EEPROMSendByte(uint8_t byte){
    GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
    EEPROMSend(byte);
    GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
}

uint8_t EEPROMReceive(void)
{
  return (EEPROMSend(DUMMY_BYTE));
}

 

Необходимо просто отправлять байт и читать одновременно.

 

Но на осциле MISO все равно не работает. Что то дергается, но невысокий уровень. Может Open Drain попробовать?

 

в приведённом коде miso программировался на вывод. Должен быть входом.

 

// MISO: выход push-pull PC11
    GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MISO;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /// Сконфигурирован как MISO. Надо как IN Сделать?
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /// ???? или здесь Open Drain поставить?
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

Share this post


Link to post
Share on other sites

Нет, именно входом. А как это делается на NXP я понятия не имею... как и на STM32.

Но знаю точно, что долго искать не пришлось бы, будь я за Вашим компютером.

Edited by Genadi Zawidowski

Share this post


Link to post
Share on other sites

Нет, именно входом. А как это делается на NXP я понятия не имею... как и на STM32.

Но знаю точно, что долго искать не пришлось бы, будь я за Вашим компютером.

 

Где то так. Для SPI2.

  GPIOB->CRH &= ~(GPIO_CRH_CNF15 | GPIO_CRH_MODE15);
  GPIOB->CRH |= GPIO_CRH_CNF15_1 | GPIO_CRH_MODE15; //mosi
  GPIOB->CRH &= ~(GPIO_CRH_CNF14 | GPIO_CRH_MODE14);
  GPIOB->CRH |= GPIO_CRH_CNF14_0; //miso
  GPIOB->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);
  GPIOB->CRH |= GPIO_CRH_CNF13_1 | GPIO_CRH_MODE13; //sck
  GPIOB->CRH &= ~(GPIO_CRH_CNF12 | GPIO_CRH_MODE12);
  GPIOB->CRH |= GPIO_CRH_MODE12; //cs

Share this post


Link to post
Share on other sites

  GPIOB->CRH &= ~(GPIO_CRH_CNF15 | GPIO_CRH_MODE15);
  GPIOB->CRH |= GPIO_CRH_CNF15_1 | GPIO_CRH_MODE15; //mosi
  GPIOB->CRH &= ~(GPIO_CRH_CNF14 | GPIO_CRH_MODE14);
  GPIOB->CRH |= GPIO_CRH_CNF14_0; //miso
  GPIOB->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13);
  GPIOB->CRH |= GPIO_CRH_CNF13_1 | GPIO_CRH_MODE13; //sck
  GPIOB->CRH &= ~(GPIO_CRH_CNF12 | GPIO_CRH_MODE12);
  GPIOB->CRH |= GPIO_CRH_MODE12; //cs

Это для серии stm32f1xx. У меня же stm32f207.

Спасибо за советы, но у меня уже было настроено на вход как видно по моим примерам.

 

В итоге разобрался. Дело было в том, что ядро контроллера работает на частоте 120 МГц и порт не успевает выводить значения, которые задаешь подряд. Приходиться делать задержку.

 

Итоговый код программы. Может кому-то пригодиться

#include <stm32f2xx_conf.h>
#include <stdio.h>

//HSE 25 MHz
//HSI 16 MHz
// PLL configure 120 MHz signal
// PCLK1 - HSE/4 - 30 MHz(APB1); PCLK2 - HSE/2 - 60 MHz(APB2)

#define DUMMY_BYTE  0xA5
#define PIN_EEPROM_SPI_CS GPIO_Pin_4
#define PIN_TAMPER GPIO_Pin_13
#define PIN_EEPROM_MOSI GPIO_Pin_12
#define PIN_EEPROM_MISO GPIO_Pin_11
#define PIN_EEPROM_SCK GPIO_Pin_10
#define PIN_SPI_CS 0x0010
#define PIN_SCK GPIO_PinSource10
#define PIN_MISO GPIO_PinSource11
#define PIN_MOSI GPIO_PinSource12

void delay(volatile uint32_t time)
{
for (; time != 0; time --);
}

void Led_Init(void)
{
RCC		->	AHB1ENR |= RCC_AHB1ENR_GPIOFEN;
GPIOF ->	MODER  	|= GPIO_MODER_MODER6_0 |
			 GPIO_MODER_MODER7_0 |
			 GPIO_MODER_MODER8_0 ;
GPIOF ->	OTYPER 	&= ~(GPIO_OTYPER_OT_6  |
			 GPIO_OTYPER_OT_7  |
			 GPIO_OTYPER_OT_8);
GPIOF	->	OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6 |
			 GPIO_OSPEEDER_OSPEEDR7 |
			 GPIO_OSPEEDER_OSPEEDR8	;
}

//////////=================SPI===============
void SPI_INIT(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
/* Deinitialize SPI3 peripheral */
SPI_I2S_DeInit(SPI3);

GPIO_PinAFConfig(GPIOC, PIN_SCK , GPIO_AF_SPI3);
GPIO_PinAFConfig(GPIOC, PIN_MOSI , GPIO_AF_SPI3);
GPIO_PinAFConfig(GPIOC, PIN_MISO , GPIO_AF_SPI3);

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

// SCK: выход push-pull PC10
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SCK;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// MISO: выход push-pull PC11
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MISO;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// MOSI: выход push-pull PC12
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MOSI;
GPIO_Init(GPIOC, &GPIO_InitStructure);

//NSS: выход push-pull - use general GPIO for CS A4
GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SPI_CS;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//SPI3
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_Init(SPI3, &SPI_InitStructure);
SPI_Cmd(SPI3, ENABLE);
}
//////////////============================================================


//////////================FOR READ_WRITE SPI=================////////////

uint8_t EEPROM_Send(uint8_t byte){
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI3, byte);
 while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI3);
}

void EEPROM_SendByte(uint8_t byte){
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
EEPROM_Send(byte);
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
delay(2000);
}

uint8_t EEPROM_Receive(void)
{
 return (EEPROM_Send(DUMMY_BYTE));
}

uint8_t EEPROM_ReadStatReg(void)
{
uint8_t byte;
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
EEPROM_Send(0x05);
byte=EEPROM_Receive();
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
delay(2000);
return (byte);
}

void EEPROM_BulkErase(void)
{
EEPROM_SendByte(0xC7);
while(EEPROM_ReadStatReg() & 1);
}
/////=========================================================

volatile static uint8_t data=0;
volatile static uint8_t RegStat=0;

//////===================MAIN
int main()
{
__enable_irq();				//Включаем прерывания
Led_Init();
SPI_INIT();

EEPROM_BulkErase();

//Write enable (WREN) Instruction Sequence
EEPROM_SendByte(0x06); //command for write sequence EEPROM
//Write to EEPROM
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
EEPROM_Send(0x02);      			//00000010 - write command
EEPROM_Send(0x00);			//address
EEPROM_Send(0x00);			//address
EEPROM_Send(0x00);			//address
EEPROM_Send(0xAA);			//data
EEPROM_Send(0xBB);			//data
EEPROM_Send(0xCC);			//data
while (SPI1->SR & SPI_SR_BSY);
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
delay(2000);
while (SPI1->SR & SPI_SR_BSY);
while(EEPROM_ReadStatReg() & 1);

///
GPIOF->ODR |= GPIO_OTYPER_ODR_6;

//Read from EEPROM
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET);
EEPROM_Send(0x03);			//read command
EEPROM_Send(0x00);			//address
EEPROM_Send(0x00);			//address
EEPROM_Send(0x00);			//address
data =  EEPROM_Receive();		//read
data =  EEPROM_Receive();		//read
data =  EEPROM_Receive();		//read
data =  EEPROM_Receive();		//read
data =  EEPROM_Receive();		//read
GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET);
delay(2000);

///
GPIOF->ODR |= GPIO_OTYPER_ODR_8;
delay(8000000);
GPIOF->ODR &= ~GPIO_OTYPER_ODR_8;
delay(8000000);
GPIOF->ODR |= GPIO_OTYPER_ODR_8;
GPIOF->ODR &= ~GPIO_OTYPER_ODR_6;
delay(8000000);

while(1){};
}


 

Думал, что это как то просчитанно.

А так в общем все в проге было ОК :=)

Edited by IgorKossak
форматирование (лишние табы)

Share this post


Link to post
Share on other sites

хочу подключить к STM32F4 DISCOVERY дисплей LCD NOKIA 5110

 

использую CooCox

 

в софт SPI подключение проходит (так я проверил строку инициализации дисплея)

 

для хардварного SPI сначала вызываю инициализацию SPI2

используемые ноги:

- PB13 CLK

- PB15 MOSI

- NSS и MISO не использую так как нужно только записывать данные и SPI2 всегда в режиме мастера

 

// Инициализация SPI2
void SPI2_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);  // включили SPI2
    SPI_DeInit(SPI2); // сбрасываем настройки SPI2 на первоначальные

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // включили GPIOB

    GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);   // SPI2_CLK
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);   // SPI2_MOSI

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

// сюда задание альтернативных функций 13 и 15 пина тоже переносил. результата нет
// GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);   // SPI2_CLK
// GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);   // SPI2_MOSI

    // SPI2
    SPI_InitStructure.SPI_Mode        = SPI_Mode_Master;
    SPI_InitStructure.SPI_Direction   = SPI_Direction_1Line_Tx;
    SPI_InitStructure.SPI_DataSize    = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL        = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA        = SPI_CPHA_1Edge;
    SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;
    SPI_Init(SPI2, &SPI_InitStructure);

    SPI_Cmd(SPI2, ENABLE);
}

частота камня 168 мгц поэтому взял максимальный делитель для SPI2 = 256

 

 

далее инициализирую GPIO для других линий дисплея

// Инициализация LCD NOKIA 5110 c помощью SPI2
void lcd5110_init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    unsigned char y, x;

//    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // такт GPIOB, для софт SPI, для хард - делается при ините SPI2

// конфигурируем пины порта B как выход 
// для soft spi
//    GPIO_InitStructure.GPIO_Pin  =GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

// для хардварного SPI
    GPIO_InitStructure.GPIO_Pin  =GPIO_Pin_10 | GPIO_Pin_14;

// общие строки инициализации
    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

 

далее работаю с дисплеем, этот код используется и в софт и хард работе SPI c дисплеем

    // Линии управления LCD в неактивное состояние
    LCD_CS1;            // CS=1
    LCD_RST1;           // RST=1
    delay_ms(10);      // пауза 0.2 сек.

    // сброс дисплея
    LCD_CS0;            // CS=0
    LCD_RST0;           // RST=0
    delay_ms(10);      // пауза 0.2 сек.
    LCD_RST1;           // RST=1
    LCD_CS1;            // CS=1
    delay_ms(10);      // пауза 0.2 сек.

    // последовательность инициализации дисплея
    LCD_DC0;            // передача команды
    LCD_SendData(0x21);
    LCD_SendData(0xC6);
    LCD_SendData(0x06);
    LCD_SendData(0x13);
    LCD_SendData(0x20);
    LCD_SendData(0x0C);

    LCD_DC0;            // передача команд
    LCD_SendData(0x40);
    LCD_SendData(0x80);

    LCD_DC1;            // передача данных
    for (y=0;y<6;y++) for (x=0;x<84;x++) LCD_SendData(0x88);

    LCD_DC0;            // передача команд
    LCD_SendData(0x0C);
}

 

и собственно, сама процедура передачи данных на дисплей

void LCD_SendData(unsigned char data) {
//    unsigned char i;  // для программного SPI

    LCD_CS0;            // включаем выбор дисплея
// хардварный SPI
    SPI_I2S_SendData(SPI2, data);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);


/*   // это реализация программного SPI работает!
       // программный SPI
    for(i=0;i<8;i++)
    {
        if (data & 0x80) LCD_MOSI1; else LCD_MOSI0;
        data = data<<1;
        LCD_SCK0;
        LCD_SCK0;
        LCD_SCK0;
        LCD_SCK1;
        LCD_SCK1;
        LCD_SCK1;
    }
*/
    LCD_CS1;
}

 

процедуры вызываю из main()

   SPI2_Config(); // конфигурация SPI2

    lcd5110_init(); // конфигурация LCD

 

почему не работает аппаратный SPI2?

Edited by ВитГо

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...