|
|
  |
STM32L100 + HTS221 |
|
|
|
Jun 11 2015, 05:52
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
Здравствуйте, есть проблема, надо подключить HTS221(датчик температуры и влажности) к STM32L100. Схема соеденения: HTS221 SCL --------- PB13(SCK2) STM32L100 ................RDY---------PC6(RDY2) ................SDA---------PB15(MOSI2) ................CS------------PB12(CS2) Схема соединения изменению не подлежит. Инициализация SPI 2: CODE #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 - Jun 11 2015, 05:59
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Jun 11 2015, 06:12
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
Цитата(SasaVitebsk @ Jun 11 2015, 06:06)  А SDA не наводит на мысль что интерфейс I2C? И как он соотносится с SPI? SDA/SDI/SDO это одна ножка датчика, а ножкой CS мы определяем будем общаться по SPI или I2C сори за не точнсть, так на схеме написано что мне дали
|
|
|
|
|
Jun 11 2015, 06:23
|

Знающий
   
Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663

|
Цитата(BooSooV @ Jun 11 2015, 09:52)  Здравствуйте, есть проблема, надо подключить HTS221(датчик температуры и влажности) к STM32L100. Схема соеденения: HTS221 SCL --------- PB13(SCK2) STM32L100 ................RDY---------PC6(RDY2) ................SDA---------PB15(MOSI2) ................CS------------PB12(CS2) Схема соединения изменению не подлежит. SPI у датчика "не SPI". Схема соединения подлежит не изменению, а доработке: вывод MOSI2 соединить с MISO2. Тогда после отправки первого байта, программно придется переключать MOSI2 в режим GP_I и принимать байт ответа по MISO2.
--------------------
Пролетарий умственного труда.
|
|
|
|
|
Jun 11 2015, 06:27
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
Цитата(RabidRabbit @ Jun 11 2015, 06:24)  Таки читайте внимательней рефренс-мануал на STM32L100, особенно раздел 28.3.4 Configuring the SPI for half-duplex communication  И не слушайте Обаму - схему менять не надо  спасибо, сейчас гляну
|
|
|
|
|
Jun 11 2015, 07:14
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
прочитал 28.3.4 Configuring the SPI for half-duplex communication поискал в системных файлах халф дуплекс но нашел только такие конфигурации: файл stm32l1xx_spi.h CODE /** @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)) /** у меня не полу дуплекса или я что то не понял? нашел ещё один сомнительный момент в коде CODE /******************* 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 нуту полу дуплекса? Полу дуплекса двунаправленного мне именно двунаправленность на одном проводе нужна
|
|
|
|
|
Jun 11 2015, 07:41
|

Знающий
   
Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663

|
Цитата(RabidRabbit @ Jun 11 2015, 11:24)  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.
--------------------
Пролетарий умственного труда.
|
|
|
|
|
Jun 11 2015, 08:12
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
уважаемые электроники, я так и не понял что мне надо сделать чтобы все заработало, надо: установить бит BIDIOE = 1 отправить байт адреса откуда я хочу считать установить бит BIDIOE = 0 считать байт от датчика у меня правильный ход мыслей? или я опять запутался?
|
|
|
|
|
Jun 11 2015, 08:36
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
Цитата(Obam @ Jun 11 2015, 08:23)  Да спасибо, буду пробовать, потом отпишусь о успехах
|
|
|
|
|
Jun 24 2015, 05:57
|
Участник

Группа: Участник
Сообщений: 35
Регистрация: 10-06-15
Пользователь №: 87 107

|
Здравствуйте, я опять с вопросами, написал код который худо бедно передает по одному проводу данные, от мастера слейву и обратно, правда передает только один раз а не в цикле, где то накосячил. Теперь я применил этот код к моему датчику температуры HTS221, но не получил ничего от него, прошу вашей помощи в поиске ошибок //Инициализация GPIO CODE 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 CODE 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 CODE 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
|
|
|
|
|
Jun 24 2015, 06:33
|

Знающий
   
Группа: Участник
Сообщений: 756
Регистрация: 14-11-14
Пользователь №: 83 663

|
Цитата(BooSooV @ Jun 24 2015, 09:57)  Здравствуйте, Здравствуйте  Цитата //передача данных. 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 - Jun 24 2015, 06:41
--------------------
Пролетарий умственного труда.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|