BooSooV 0 11 июня, 2015 Опубликовано 11 июня, 2015 (изменено) · Жалоба Здравствуйте, есть проблема, надо подключить 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, но тогда мы не можем считать, а насколько я понимаю мы должны сначала прислать адрес ячейки а потом считать инфу, и все по одному проводу. Объясните пожалуйста что не так, и как заставить работать. Изменено 11 июня, 2015 пользователем IgorKossak [codebox] для длинного кода, [code] - для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SapegoAL 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба А SDA не наводит на мысль что интерфейс I2C? И как он соотносится с SPI? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BooSooV 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба А SDA не наводит на мысль что интерфейс I2C? И как он соотносится с SPI? SDA/SDI/SDO это одна ножка датчика, а ножкой CS мы определяем будем общаться по SPI или I2C сори за не точнсть, так на схеме написано что мне дали Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба Здравствуйте, есть проблема, надо подключить HTS221(датчик температуры и влажности) к STM32L100. Схема соеденения: HTS221 SCL --------- PB13(SCK2) STM32L100 ................RDY---------PC6(RDY2) ................SDA---------PB15(MOSI2) ................CS------------PB12(CS2) Схема соединения изменению не подлежит. SPI у датчика "не SPI". Схема соединения подлежит не изменению, а доработке: вывод MOSI2 соединить с MISO2. Тогда после отправки первого байта, программно придется переключать MOSI2 в режим GP_I и принимать байт ответа по MISO2. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба Таки читайте внимательней рефренс-мануал на STM32L100, особенно раздел 28.3.4 Configuring the SPI for half-duplex communication :) И не слушайте Обаму - схему менять не надо :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BooSooV 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба Таки читайте внимательней рефренс-мануал на STM32L100, особенно раздел 28.3.4 Configuring the SPI for half-duplex communication :) И не слушайте Обаму - схему менять не надо :) спасибо, сейчас гляну Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба Если есть half-duplex, то не слушайте, а если нет, то… Кстати, ST всех вводят в заблуждение: этот интерфейс назывался 2Wire. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BooSooV 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба прочитал 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 нуту полу дуплекса? Полу дуплекса двунаправленного мне именно двунаправленность на одном проводе нужна Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба SPI_CR1_BIDIMODE - CR1 - это номер регистра, а не номер модуля SPI. Делее про полудуплекс. Вся соль в частичке "полу" :) То есть низзя одновременно передавать и принимать. Если Вы внимательно рассмотрите протокол SPI для датчика HTS221, то увидите, что мастер в начале обмена всегда передаёт один байт, а далее уже по обстоятельствам - либо передаёт, либо принимает, за направление овечает бит SPI_CR1_BIDIOE. Ещё раз повторю: читайте документацию, там всё написано :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба 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. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BooSooV 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба уважаемые электроники, я так и не понял что мне надо сделать чтобы все заработало, надо: установить бит BIDIOE = 1 отправить байт адреса откуда я хочу считать установить бит BIDIOE = 0 считать байт от датчика у меня правильный ход мыслей? или я опять запутался? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба уважаемые электроники, я так и не понял что мне надо сделать чтобы все заработало, надо: установить бит BIDIOE = 1 отправить байт адреса откуда я хочу считать установить бит BIDIOE = 0 считать байт от датчика у меня правильный ход мыслей? или я опять запутался? Да Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BooSooV 0 11 июня, 2015 Опубликовано 11 июня, 2015 · Жалоба Да спасибо, буду пробовать, потом отпишусь о успехах Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
BooSooV 0 24 июня, 2015 Опубликовано 24 июня, 2015 · Жалоба Здравствуйте, я опять с вопросами, написал код который худо бедно передает по одному проводу данные, от мастера слейву и обратно, правда передает только один раз а не в цикле, где то накосячил. Теперь я применил этот код к моему датчику температуры 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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 24 июня, 2015 Опубликовано 24 июня, 2015 (изменено) · Жалоба Здравствуйте, Здравствуйте :) //передача данных. 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 прием Ох, ё-моё, а ведь переведён… Изменено 24 июня, 2015 пользователем Obam Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться