Перейти к содержанию
    

Здравствуйте, есть проблема, надо подключить HTS221(датчик температуры и влажности) к STM32L100.

Схема соеденения:

HTS221 SCL --------- PB13(SCK2) STM32L100

................RDY---------PC6(RDY2)

................SDA---------PB15(MOSI2)

................CS------------PB12(CS2)

Схема соединения изменению не подлежит.

Инициализация SPI 2:

#define GPIO_Pin_NSS2     GPIO_Pin_12   // NSS (CS)
#define GPIO_Pin_SCK2     GPIO_Pin_13   // SCK
#define GPIO_Pin_MISO2    GPIO_Pin_14   // MISO
#define GPIO_Pin_MOSI2    GPIO_Pin_15   // MOSI
#define GPIOSPI2          GPIOB

#define GPIO_PinSourceSCK2  GPIO_PinSource13
#define GPIO_PinSourceMISO2 GPIO_PinSource14
#define GPIO_PinSourceMOSI2 GPIO_PinSource15

// -- Инициализация GPIO для SPI2 ----------------------------------------------
void init_GPIO_for_SPI2() 
{
 GPIO_InitTypeDef GPIO_InitStructure;  
 GPIO_InitTypeDef GPIO_InitStructure2; 

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // Запуск необходимых GPIO

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_SCK2 | GPIO_Pin_MISO2 | GPIO_Pin_MOSI2;
 GPIO_Init(GPIOSPI2, &GPIO_InitStructure);

 // нога NSS(CS2). она управляется программно, ПОЭТОМУ
 // она конфигурируется как выход
 GPIO_InitStructure2.GPIO_Mode = GPIO_Mode_OUT;
 GPIO_InitStructure2.GPIO_Speed = GPIO_Speed_40MHz;
 GPIO_InitStructure2.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure2.GPIO_PuPd = GPIO_PuPd_DOWN;
 GPIO_InitStructure2.GPIO_Pin = GPIO_Pin_NSS2;
 GPIO_Init(GPIOSPI2, &GPIO_InitStructure2);

 // Настраиваем ноги SPI2 для работы в режиме альтернативной функции
 GPIO_PinAFConfig(GPIOSPI2, GPIO_PinSourceSCK2, GPIO_AF_SPI2);
 GPIO_PinAFConfig(GPIOSPI2, GPIO_PinSourceMISO2, GPIO_AF_SPI2);
 GPIO_PinAFConfig(GPIOSPI2, GPIO_PinSourceMOSI2, GPIO_AF_SPI2);

 GPIO_SetBits(GPIOSPI2, GPIO_Pin_NSS2); 
}


// -- Инициализация SPI2 -------------------------------------------------------
void Init_SPI2()
{
 SPI_InitTypeDef   SPI_InitStructure;

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);   

 SPI_Cmd(SPI2, DISABLE); 
 SPI_I2S_DeInit(SPI2);

 init_GPIO_for_SPI2(); 

 // Настройки SPI2
 SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
 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_InitStructure.SPI_Mode=SPI_Mode_Master;
 SPI_InitStructure.SPI_CRCPolynomial=7;  

 SPI_Init(SPI2,&SPI_InitStructure);

 SPI_Cmd(SPI2,ENABLE);

 GPIO_SetBits(GPIOSPI2, GPIO_Pin_NSS2);
}

Чтение регистра датчика:

  uint8_t cmd = 0x4F;

   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET) {}
   GPIO_ResetBits(GPIOSPI2, GPIO_Pin_NSS2);

   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) {}
   SPI_I2S_SendData(SPI2, cmd);  

   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) {}
   uint8_t data = SPI_I2S_ReceiveData(SPI2);
   
   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) {}
   SPI_I2S_SendData(SPI2, 0x00);

   while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) {}
   data = SPI_I2S_ReceiveData(SPI2);

   GPIO_SetBits(GPIOSPI2, GPIO_Pin_NSS2);

по идее должен выдать свое имя

Такая схема у меня работала на другом SPI но там было MOSI И MISO разными проводами, а тут все в одном, что делать не знаю пробовал поставить в инициализации SPI_Direction_1Line_Tx, но тогда мы не можем считать, а насколько я понимаю мы должны сначала прислать адрес ячейки а потом считать инфу, и все по одному проводу. Объясните пожалуйста что не так, и как заставить работать.

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А SDA не наводит на мысль что интерфейс I2C? И как он соотносится с SPI?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А SDA не наводит на мысль что интерфейс I2C? И как он соотносится с SPI?

SDA/SDI/SDO это одна ножка датчика,

а ножкой CS мы определяем будем общаться по SPI или I2C

сори за не точнсть, так на схеме написано что мне дали

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте, есть проблема, надо подключить HTS221(датчик температуры и влажности) к STM32L100.

Схема соеденения:

HTS221 SCL --------- PB13(SCK2) STM32L100

................RDY---------PC6(RDY2)

................SDA---------PB15(MOSI2)

................CS------------PB12(CS2)

Схема соединения изменению не подлежит.

 

SPI у датчика "не SPI". Схема соединения подлежит не изменению, а доработке: вывод MOSI2 соединить с MISO2.

Тогда после отправки первого байта, программно придется переключать MOSI2 в режим GP_I и принимать байт ответа по MISO2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таки читайте внимательней рефренс-мануал на STM32L100, особенно раздел 28.3.4 Configuring the SPI for half-duplex communication :)

И не слушайте Обаму - схему менять не надо :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Таки читайте внимательней рефренс-мануал на STM32L100, особенно раздел 28.3.4 Configuring the SPI for half-duplex communication :)

И не слушайте Обаму - схему менять не надо :)

спасибо, сейчас гляну

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если есть half-duplex, то не слушайте, а если нет, то…

 

Кстати, ST всех вводят в заблуждение: этот интерфейс назывался 2Wire.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прочитал 28.3.4 Configuring the SPI for half-duplex communication

поискал в системных файлах халф дуплекс но нашел только такие конфигурации:

файл stm32l1xx_spi.h

/** @defgroup SPI_data_direction 
 * @{
 */

#define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000)
#define SPI_Direction_2Lines_RxOnly     ((uint16_t)0x0400)
#define SPI_Direction_1Line_Rx          ((uint16_t)0x8000)
#define SPI_Direction_1Line_Tx          ((uint16_t)0xC000)
#define IS_SPI_DIRECTION_MODE(MODE) (((MODE) == SPI_Direction_2Lines_FullDuplex) || \
                                    ((MODE) == SPI_Direction_2Lines_RxOnly) || \
                                    ((MODE) == SPI_Direction_1Line_Rx) || \
                                    ((MODE) == SPI_Direction_1Line_Tx))
/**

у меня не полу дуплекса или я что то не понял?

 

нашел ещё один сомнительный момент в коде

/*******************  Bit definition for SPI_CR1 register  ********************/
#define  SPI_CR1_CPHA                        ((uint16_t)0x0001)            /*!< Clock Phase */
#define  SPI_CR1_CPOL                        ((uint16_t)0x0002)            /*!< Clock Polarity */
#define  SPI_CR1_MSTR                        ((uint16_t)0x0004)            /*!< Master Selection */

#define  SPI_CR1_BR                          ((uint16_t)0x0038)            /*!< BR[2:0] bits (Baud Rate Control) */
#define  SPI_CR1_BR_0                        ((uint16_t)0x0008)            /*!< Bit 0 */
#define  SPI_CR1_BR_1                        ((uint16_t)0x0010)            /*!< Bit 1 */
#define  SPI_CR1_BR_2                        ((uint16_t)0x0020)            /*!< Bit 2 */

#define  SPI_CR1_SPE                         ((uint16_t)0x0040)            /*!< SPI Enable */
#define  SPI_CR1_LSBFIRST                    ((uint16_t)0x0080)            /*!< Frame Format */
#define  SPI_CR1_SSI                         ((uint16_t)0x0100)            /*!< Internal slave select */
#define  SPI_CR1_SSM                         ((uint16_t)0x0200)            /*!< Software slave management */
#define  SPI_CR1_RXONLY                      ((uint16_t)0x0400)            /*!< Receive only */
#define  SPI_CR1_DFF                         ((uint16_t)0x0800)            /*!< Data Frame Format */
#define  SPI_CR1_CRCNEXT                     ((uint16_t)0x1000)            /*!< Transmit CRC next */
#define  SPI_CR1_CRCEN                       ((uint16_t)0x2000)            /*!< Hardware CRC calculation enable */
#define  SPI_CR1_BIDIOE                      ((uint16_t)0x4000)            /*!< Output enable in bidirectional mode */
#define  SPI_CR1_BIDIMODE                    ((uint16_t)0x8000)            /*!< Bidirectional data mode enable */

/*******************  Bit definition for SPI_CR2 register  ********************/
#define  SPI_CR2_RXDMAEN                     ((uint8_t)0x01)               /*!< Rx Buffer DMA Enable */
#define  SPI_CR2_TXDMAEN                     ((uint8_t)0x02)               /*!< Tx Buffer DMA Enable */
#define  SPI_CR2_SSOE                        ((uint8_t)0x04)               /*!< SS Output Enable */
#define  SPI_CR2_FRF                         ((uint8_t)0x08)               /*!< Frame format */
#define  SPI_CR2_ERRIE                       ((uint8_t)0x20)               /*!< Error Interrupt Enable */
#define  SPI_CR2_RXNEIE                      ((uint8_t)0x40)               /*!< RX buffer Not Empty Interrupt Enable */
#define  SPI_CR2_TXEIE                       ((uint8_t)0x80)               /*!< Tx buffer Empty Interrupt Enable */

 

 

#define SPI_CR1_BIDIMODE ((uint16_t)0x8000) /*!< Bidirectional data mode enable */

в даташите написано 1 clock and 1 bidirectional data wire (BIDIMODE=1)

а на SPI2 нету BIDIMODE, только на SPI1 значит ли это что на SPI2 нуту полу дуплекса?

 

Полу дуплекса двунаправленного мне именно двунаправленность на одном проводе нужна

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SPI_CR1_BIDIMODE - CR1 - это номер регистра, а не номер модуля SPI.

 

Делее про полудуплекс. Вся соль в частичке "полу" :) То есть низзя одновременно передавать и принимать. Если Вы внимательно рассмотрите протокол SPI для датчика HTS221, то увидите, что мастер в начале обмена всегда передаёт один байт, а далее уже по обстоятельствам - либо передаёт, либо принимает, за направление овечает бит SPI_CR1_BIDIOE.

 

Ещё раз повторю: читайте документацию, там всё написано :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

SPI_CR1_BIDIMODE - CR1 - это номер регистра, а не номер модуля SPI.

 

Делее про полудуплекс. Вся соль в частичке "полу" :) То есть низзя одновременно передавать и принимать. Если Вы внимательно рассмотрите протокол SPI для датчика HTS221, то увидите, что мастер в начале обмена всегда передаёт один байт, а далее уже по обстоятельствам - либо передаёт, либо принимает, за направление овечает бит SPI_CR1_BIDIOE.

 

Ещё раз повторю: читайте документацию, там всё написано :)

 

"…The transfer direction (Input/Output) is selected by the BIDIOE bit in the

SPI_CR1 register. When this bit is 1, the data line is output otherwise it is input…"

Так что я был не далёк от истины, предлагая переводить MOSI во GP-вход у дуплексного SPI. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

уважаемые электроники, я так и не понял что мне надо сделать чтобы все заработало, надо:

установить бит BIDIOE = 1

отправить байт адреса откуда я хочу считать

установить бит BIDIOE = 0

считать байт от датчика

у меня правильный ход мыслей? или я опять запутался?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

уважаемые электроники, я так и не понял что мне надо сделать чтобы все заработало, надо:

установить бит BIDIOE = 1

отправить байт адреса откуда я хочу считать

установить бит BIDIOE = 0

считать байт от датчика

у меня правильный ход мыслей? или я опять запутался?

 

Да

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Теперь я применил этот код к моему датчику температуры HTS221, но не получил ничего от него, прошу вашей помощи в поиске ошибок

 

//Инициализация GPIO

void gpio_init()
{
 RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN; //Тактирование портов A, B


 //Линии SPI2 (Master)
 //PB15(MOSI), PB14(MISO), PB13(SCK), PB12(NSS) - AF, Push-Pull, AF5(SPI1)
 GPIOB->MODER |= GPIO_MODER_MODER15_1 | GPIO_MODER_MODER14_1 | GPIO_MODER_MODER13_1 | GPIO_MODER_MODER12_1; //Alternate function
 GPIOB->OTYPER &= ~(GPIO_OTYPER_OT_15 | GPIO_OTYPER_OT_14 | GPIO_OTYPER_OT_13 | GPIO_OTYPER_OT_11); //Push-Pull
 GPIOB->AFR[1] |= (5<<28 | 5<<24 | 5<<20 | 5<<16); //PB15, PB14, P13, PB12 = AF5 



 // настройка ноги управления
 GPIO_InitTypeDef GPIO_InitStructure;
 EXTI_InitTypeDef EXTI_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;

 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD, ENABLE); // Запуск необходимых GPIO


 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;                  
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_400KHz;
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 GPIO_ResetBits(GPIOB, GPIO_Pin_12);



}

 

//Инициализация SPI2

void spi_init()
{
 RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
 SPI2->CR1 |= SPI_CR1_BR; //Baud rate = Fpclk/256
 SPI2->CR1 &= ~SPI_CR1_CPOL; //Полярность тактового сигнала
 SPI2->CR1 &= ~SPI_CR1_CPHA; //Фаза тактового сигнала
 SPI2->CR1 &= ~SPI_CR1_DFF; //8 бит данных
 SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB передается первым
 SPI2->CR1 |= SPI_CR1_SSM; //Программный режим NSS
 SPI2->CR1 |= SPI_CR1_SSI; //Аналогично состоянию, когда на входе NSS высокий уровень
 SPI2->CR2 |= SPI_CR2_SSOE; //Вывод NSS - выход управления slave select
 SPI2->CR1 |= SPI_CR1_MSTR; //Режим Master

 SPI2->CR1 |= SPI_CR1_BIDIMODE; // двунаправленный режим по одной шине данных
 SPI2->CR1 |= SPI_CR1_BIDIOE;  //BIDIOE  передача

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



}

 

 

//Основной цикл программы

 

// MASTER SPI2

int main()
{
 gpio_init(); //Вызов функции инициализации портов
 spi_init(); //Вызов функции инициализации модулей SPI 
 //GPIOH->BSRRL |= GPIO_BSRR_BS_12;  // передача запрещена
 GPIO_SetBits(GPIOB, GPIO_Pin_12);//общение запрещено 
 while(1)
 {
  //GPIOB->BSRRH |= GPIO_BSRR_BS_12; // начинаем передачу 
  GPIO_ResetBits(GPIOB, GPIO_Pin_12);//начинаем общние 

 //передача данных.

 SPI2->CR1 |= SPI_CR1_BIDIOE;  //BIDIOE  передача
 SPI2->DR = 0x4F; //Пишем в буфер передатчика SPI1.
 while(!(SPI2->SR & SPI_SR_TXE));// Ожидаем окончания передачи данных
 SPI2->CR1 |= SPI_CR1_BIDIOE;  //BIDIOE  передача

 for(uint32_t i=0; i<0x000FFFFF; i++); 
   //Прием данных.

 SPI2->CR1 &= ~ SPI_CR1_BIDIOE;  //BIDIOE  прием
 while(!(SPI2->SR & SPI_SR_RXNE));//приняли данные
 bufPr1 = SPI2->DR;//Считываем данные из приемного буфера SPI1. При этой операции происходит очистка буфера и сброс флага RXNE
 SPI2->CR1 |= SPI_CR1_BIDIOE;  //BIDIOE  передача




//GPIOB->BSRRL |= GPIO_BSRR_BS_12;  // заканчиваем передачу
 GPIO_SetBits(GPIOB, GPIO_Pin_12);//общение запрещено

 //Временная задержка между вызовами функции обмена данными
 for(uint32_t i=0; i<0x000FFFFF; i++); 
 }
}

 

Этим кодом я спрашиваю его имя

http://www.farnell.com/datasheets/1836732.pdf

страница 16

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте,

Здравствуйте :)

 

//передача данных.

 

SPI2->CR1 |= SPI_CR1_BIDIOE; //BIDIOE передача

SPI2->DR = 0x4F; //Пишем в буфер передатчика SPI1.

while(!(SPI2->SR & SPI_SR_TXE));// Ожидаем окончания передачи данных

SPI2->CR1 |= SPI_CR1_BIDIOE; //BIDIOE передача

 

Точно Spi переведён на приём? Copy-paste погубит мир :)

 

А вообще, для подобных работ осциллограф наипервейшее средство. Есть?

 

PS:

for(uint32_t i=0; i<0x000FFFFF; i++);

//Прием данных.

 

SPI2->CR1 &= ~ SPI_CR1_BIDIOE; //BIDIOE прием

Ох, ё-моё, а ведь переведён…

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...