hd44780 0 18 июля, 2018 Опубликовано 18 июля, 2018 · Жалоба Привет всем. Попал тут в руки проц STM32H743 в виде платы NUCLEO-H743I. Разобрался, как запустить его на все 400 МГц, Systick завёл, светодиодиками помигал - все это заработало. Частоту систика проверил осциллом. Перешёл к SPI (маленький дисплейчик ILI9163). Сам дисп рабочий, работал на Ф103. Драйвер диспа собственно оттуда же. Драйвер разделён на 2 части - низкоуровневая (работа с SPI и ногами) и т.н. высокоуровневая (пуляние в дисп команд, отрисовка точек, знакогенератор и пр). Соответственно в адаптации нуждается только низкоуровневая часть, т.к. высокоуровневая напрямую в ноги и SPI не лезет. С ногами nCS, nRESET и пр. ногодрыгом я управился, они работают нормально, а с SPI затык - синхра идёт исправно, а из ноги MOSI упорно прёт ноль. Нога MISO в данном случае не нужна вообще, т.к. у дисплея её нет. Пишу на помеси из регистров и кубового хала. М.б. это и нехорошо, но с ходу писать на регистрах на проце, которого раньше в глаза не видел как-то нехорошо. Инит пинов: // Configure PA5 - SPI1 SCK GPIO_InitStruct.Pin = GPIO_PIN_5; // SCK GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* // Configure PA7 - SPI1 MOSI // Configure PB5 - SPI1 MOSI // Configure PD7 - SPI1 MOSI GPIO_InitStruct.Pin = GPIO_PIN_7; // MOSI // GPIO_InitStruct.Pin = GPIO_PIN_5; // MOSI GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_PULLUP; // GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; // HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); */ // PA7 - SPI1 MOSI // MODER - AF = 10 GPIOA->MODER |= GPIO_MODER_MODER5_1; // 10 // TYPER - PP = 0 - Push-pull GPIOA->OTYPER |= GPIO_OTYPER_IDR_7; // 0 // SPEEDR - OSPEEDRy = 11 GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7; // 11 // PUPD_R = 10 - Pull-down GPIOA->PUPDR |= GPIO_PUPDR_PUPDR7_1; // 10 Нога PA5 (SCK) работает как угодно - хоть халом её инитить, хоть чем. PA7 (MOSI) - не работает никак. Инитил по-разному. Инит SPI (в основном хал): /*** Configure the SPI peripheral ***/ SPI_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SPI123; SPI_PeriphClkInit.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL; HAL_RCCEx_PeriphCLKConfig(&SPI_PeriphClkInit); /* Enable SPI clock */ // __HAL_RCC_SPI1_CLK_ENABLE(); // SET_BIT (RCC->APB2ENR, RCC_APB2ENR_SPI1EN); RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // SPI Config hnucleo_Spi.Instance = SPI_PORT; // hnucleo_Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; hnucleo_Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hnucleo_Spi.Init.Direction = SPI_DIRECTION_2LINES; // hnucleo_Spi.Init.Direction = SPI_DIRECTION_2LINES_TXONLY; hnucleo_Spi.Init.CLKPhase = SPI_PHASE_2EDGE; hnucleo_Spi.Init.CLKPolarity = SPI_POLARITY_HIGH; hnucleo_Spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hnucleo_Spi.Init.CRCPolynomial = 7; hnucleo_Spi.Init.DataSize = SPI_DATASIZE_8BIT; hnucleo_Spi.Init.FirstBit = SPI_FIRSTBIT_MSB; hnucleo_Spi.Init.NSS = SPI_NSS_SOFT; hnucleo_Spi.Init.TIMode = SPI_TIMODE_DISABLE; hnucleo_Spi.Init.Mode = SPI_MODE_MASTER; hnucleo_Spi.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* Recommended setting to avoid glitches */ hnucleo_Spi.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; hnucleo_Spi.Init.CRCLength = SPI_CRC_LENGTH_8BIT; hnucleo_Spi.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; hnucleo_Spi.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN; hnucleo_Spi.Init.NSSPolarity = SPI_NSS_POLARITY_LOW; hnucleo_Spi.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; hnucleo_Spi.Init.MasterSSIdleness = 0x00000000; hnucleo_Spi.Init.MasterInterDataIdleness = 0x00000000; hnucleo_Spi.Init.MasterReceiverAutoSusp = 0x00000000; HAL_SPI_Init(&hnucleo_Spi); // Enable SPI peripheral SET_BIT( SPI_PORT->CR1 , SPI_CR1_SPE); SPI_PORT === SPI1. Отправка байта в SPI1 (хал): // Чтение/запись байта SPI void ili9162_sendByte ( uint8_t data ) { /* // Длина передаваемых байт - 1 MODIFY_REG (SPI1->CR2, SPI_CR2_TSIZE, 1); // Старт передачи SET_BIT(SPI1->CR1, SPI_CR1_CSTART); while ( !( SPI1 -> SR & SPI_SR_TXP ) ); SPI1 ->TXDR = data; // Ждать завершения передачи // while ( ! ( SPI1 -> SR & SPI_SR_TXC ) ); */ uint8_t data_in; HAL_StatusTypeDef status = HAL_OK; status = HAL_SPI_TransmitReceive(&hnucleo_Spi, &data_in, &data, 1, 1000); } // SPI_sendByte Моя поделка на регистрах не пашет вообще, я пока бросил, оставил хал. Проверяю всё это вызовом в вечном цикле ili9162_sendByte ( 0xAA ); В чём может быть дело? Если надо, выложу весь проект на 9 атоллике. Спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 18 июля, 2018 Опубликовано 18 июля, 2018 (изменено) · Жалоба Как ни странным может показаться, при передаче 8-bit как проверкуосвобождения передатчика делю так: while ((SPI1->SR & SPI_SR_RXP) == 0) ; (void) * (volatile uint8_t *) & SPI1->RXDR; /* clear SPI_SR_RXP in status register */ А вот так передача: * (volatile uint8_t *) & (SPI1)->TXDR = v; // prevent data packing feature Естественно, первая передача без ожидания перед ней. Как обычно, проект тут: https://188.134.5.254/browser/hfreceiver/trunk/hardware.c - функция hardware_spi_master_setfreq и hardware_spi_connect Изменено 18 июля, 2018 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 18 июля, 2018 Опубликовано 18 июля, 2018 · Жалоба Судя по осциллу SPI и его ноги ожили. Долбаный хал с его callback-ами. Как обычно, проект тут: https://188.134.5.254/browser/hfreceiver/trunk/hardware.c - функция hardware_spi_master_setfreq и hardware_spi_connect Угу, гляну, может там надо как-то ждать реального ухода байта в дисп, иначе он его не воспринимает. Там сразу после отправки CS поднимается в 1. Если поднимется раньше реального ухода байта из всех этих очередей проца, то дисп его не воспримет ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 18 июля, 2018 Опубликовано 18 июля, 2018 · Жалоба Разумеется, всегда надо (если иное не сказано). А процессор шустрый, модет и не выдать ничего. C/D тоже надо не ранее передачи перключать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 18 июля, 2018 Опубликовано 18 июля, 2018 · Жалоба С C/D и nCS всё в порядке: void ILI9163writecommand(uint8_t c) { res_rs ( ); //low res_cs ( ); //low ili9162_sendByte ( c ); set_cs ( ); //hi } void ILI9163writedata(uint8_t c) { set_rs ( ); //hi res_cs ( ); //low ili9162_sendByte ( c ); set_cs ( ); //hi } Вопрос только в отправке байта .. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 19 июля, 2018 Опубликовано 19 июля, 2018 · Жалоба Если просто писать в TXDR данные пишуться в буфер, который настроить нужно (когда флаги будут выставляться и формат данных). А старт передачи так SPI1->CR1 |= SPI_CR1_CSTART; только начал тоже разбираться пока передал 4 байта, NSS красиво управляет сам с нужными задержками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 20 июля, 2018 Опубликовано 20 июля, 2018 · Жалоба Что-то я совсем запутался :( Некий прогресс есть, хоть и неполный. 1. Переписал инициализацию на регистрах: CLEAR_BIT( SPI_PORT->CR1, SPI_CR1_SPE); // Disable SPI SPI_PORT -> CR1 = SPI_CR1_SSI; // SSI := 1 SPI_PORT -> CR2 = 0x0; SPI_PORT -> CFG1 = SPI_CFG1_MBR | SPI_CFG1_DSIZE_2 | SPI_CFG1_DSIZE_1 | SPI_CFG1_DSIZE_0; // MBR = 7 - clock/256; DSIZE = 0111 - 8 bit/frame SPI_PORT -> CFG2 = SPI_CFG2_AFCNTR | SPI_CFG2_SSM | SPI_CFG2_CPOL | SPI_CFG2_CPHA | SPI_CFG2_MASTER; // Enable SPI peripheral SET_BIT( SPI_PORT->CR1, SPI_CR1_SPE); работает, проблем пока вроде не заметил, если так можно выразиться в свете нижеследующих пунктов.... от хала оставил только вот это hnucleo_Spi.Instance = SPI_PORT; hnucleo_Spi.State = HAL_SPI_STATE_READY; потому что без него отправка байтов халовской функцией подыхает на взлёте. Инит пинов SPI оставил пока на хале, дабы резать колбасу по кусочкам: // SPI pins GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 2. Дисплей пока отключил, убрал в сторонку, не дорос я до него :biggrin: . Замкнул MISO-MOSI проводком, т.е. просто эхо. Пытаюсь передать байт: хал: // Чтение/запись байта SPI uint8_t ili9162_sendByte ( uint8_t data_out ) { uint8_t data_in; HAL_StatusTypeDef status = HAL_SPI_TransmitReceive(&hnucleo_Spi, &data_out, &data_in, 1, 1000); return data_in; Байт по кольцу гоняет, т.е. возвращает то, что я и отправляю. Типа нормально. закомментариваю хал, пишу на регистрах: // Чтение/запись байта SPI uint8_t ili9162_sendByte ( uint8_t data_out ) { uint8_t data_in; MODIFY_REG(SPI_PORT->CR2, SPI_CR2_TSIZE, 1); // Передача while ( !( SPI_PORT -> SR & SPI_SR_TXP ) ); *((__IO uint8_t *)&SPI1->TXDR) = data_out; SET_BIT ( SPI_PORT->CR1, SPI_CR1_CSTART ); // Приём while ((SPI1->SR & (SPI_SR_RXWNE | SPI_SR_RXPLVL)) == 0); data_in = *((__IO uint8_t *)&SPI_PORT->RXDR); return data_in; 2 байта передаёт-принимает нормально, на третьем виснет на условии приёма. Единственное отличие здесь от хала это то, что HAL_SPI_TransmitReceive постоянно включает/выключает SPI и MODIFY_REG(SPI1->CR2, SPI_CR2_TSIZE, Size); делает при выключенном SPI. Неужели это необходимо? Попробовал включать-выключать SPI - стало ещё хуже - один байт передал и завис .. 3. К слову о периферийных SPI-девайсах. Тут вообще всё плачевно. Вышеупоминавшийся дисплей вообще не инитится, пробовал подключать датчик BME280 (SPI интерфейс) - вместо ID (который равен 60h) читает одни нули, хотя на всяких там F1/F4 как положено 60h и датчик работает с песнями. Эта хрень даже с халовской HAL_SPI_TransmitReceive, которая эхо исправно делает. Помогите разобраться плиз. Такое чувство, что я где-то на одни и те же грабли наступаю ... Рабочий драйвер для BME280 (SPI) могу выложить если кому интересно. По I2C я его ни разу нигде не запускал, пока не нужно. Код уважаемого Genadi Zawidowski смотрел, но, видимо, чего-то недопонял, т.к. тоже повис на приёме байта если правильно помню :( . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 20 июля, 2018 Опубликовано 20 июля, 2018 · Жалоба Как разберусь сам помогу) делаю для NRF24. К коду которму месяц так и не возвращался, сегодня продолжу копания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 20 июля, 2018 Опубликовано 20 июля, 2018 · Жалоба Как разберусь сам помогу) делаю для NRF24. К коду которму месяц так и не возвращался, сегодня продолжу копания. Угу, спасибо. Я тоже буду отписываться, если что-то новое появится. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 20 июля, 2018 Опубликовано 20 июля, 2018 · Жалоба Пару лет назад я делал проект на похожем процессоре для Боинга. Там с SPI была проблема. Он (не помню на прием или передачу) младший бит иногда портил. В этом форуме есть моя тема про это. В конце я сделал програмный SPI. Через несколько месяцев вышла errata с описанием этой проблемы. https://electronix.ru/forum/index.php?showtopic=135946 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 21 июля, 2018 Опубликовано 21 июля, 2018 · Жалоба hd44780 Вроде бы все получилось. Особое внимание нужно уделить системе тактирования. Пока что сделал на прерываниях, нужно еще исследовать как более оптимально работать с буфером. Проверялось без железок только на анализатор. /** * @brief This function handles Debug Monitor exception. * @param None * @retval None */ void SPI1_IRQHandler(void) { uint16_t tCTSIZE = (SPI_NRF->SPI->SR >> 16); if(SPI_NRF->SPI->SR & SPI_SR_RXP) { while(SPI_NRF->SPI->SR & SPI_SR_RXP) { if(SPI_NRF->RxBuffPos < SPI_NRF->TransLength) { SPI_NRF->RxBuff[SPI_NRF->RxBuffPos++] = *(volatile uint8_t *) &(SPI_NRF->SPI)->RXDR; } else break; } } if(SPI_NRF->SPI->SR & SPI_SR_TXP) {// while(SPI_NRF->SPI->SR & SPI_SR_TXP) { if(SPI_NRF->TxBuffPos < SPI_NRF->TransLength) { *(volatile uint8_t *) &(SPI_NRF->SPI)->TXDR = SPI_NRF->TxBuff[SPI_NRF->TxBuffPos++]; } else break; } } } настройка RCC->D2CCIP1R = RCC_D2CCIP1R_SPI123SEL_2; // kernel clock выбираем per_ck RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN; // разрешили тактирование GPIO на котором висит SPI RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // включаем тактирование модуля // конфигурируем SPI1 SPI_NRF->SPI->CFG1 = SPI_CFG1_MBR_0 | SPI_CFG1_MBR_2 | SPI_CFG1_FTHLV_0 | SPI_CFG1_FTHLV_1 | SPI_CFG1_DSIZE_0 | SPI_CFG1_DSIZE_1 | SPI_CFG1_DSIZE_2; SPI_NRF->SPI->CFG2 = SPI_CFG2_SSOE | SPI_CFG2_MASTER | SPI_CFG2_AFCNTR; void TSPI::SendBuff(uint8_t *aTxBuff, uint8_t *aRxBuff, uint16_t aCnt) { RxBuffPos = 0; TxBuffPos = 0; RxBuff = aRxBuff; TxBuff = aTxBuff; TransLength = aCnt; SPI->CR2 = aCnt; SPI->CR1 |= SPI_CR1_SPE; SPI->CR1 |= SPI_CR1_CSTART; SPI->IER |= SPI_IER_RXPIE | SPI_IER_TXPIE; } нужно еще углубиться в настройки... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 21 июля, 2018 Опубликовано 21 июля, 2018 · Жалоба поправочка : SPI_NRF->SPI->CFG1 = SPI_CFG1_MBR_0 | SPI_CFG1_MBR_2 | SPI_CFG1_DSIZE_0 | SPI_CFG1_DSIZE_1 | SPI_CFG1_DSIZE_2; для работы с буфером побайтно FTHVL нужно в 0 установить P.S. редактировать сообщения не могу. Текущая проблема не могу передать второй и последующие пакеты. Первый нормально. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
hd44780 0 21 июля, 2018 Опубликовано 21 июля, 2018 · Жалоба Текущая проблема не могу передать второй и последующие пакеты. Первый нормально. У меня тож самое пока :crying: . Первый байт проходит в песнями, потом виснет на опросе флагов SR. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MasterElectric 0 21 июля, 2018 Опубликовано 21 июля, 2018 (изменено) · Жалоба Заработало!!! Причем особо ничего не менял. Обращение к буферу пока что побайтно. Потом поэкспериментирую при разных фреймах. Работает от HSI (64 МГц) инициализация: // RCC->D2CCIP1R = RCC_D2CCIP1R_SPI123SEL_2; // kernel clock выбираем per_ck RCC->AHB4ENR |= RCC_AHB4ENR_GPIOAEN; // разрешили тактирование GPIO на котором висит SPI RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; // включаем тактирование модуля // конфигурируем SPI1 SPI_NRF->SPI->CFG1 = SPI_CFG1_MBR_0 | SPI_CFG1_MBR_2 | SPI_CFG1_DSIZE_0 | SPI_CFG1_DSIZE_1 | SPI_CFG1_DSIZE_2; SPI_NRF->SPI->CFG2 = SPI_CFG2_SSOE | SPI_CFG2_MASTER | SPI_CFG2_AFCNTR; SPI_NRF->SPI->CR1 |= SPI_CR1_SPE; NVIC_EnableIRQ(SPI1_IRQn); отправка пакетов в мейне a = 19; SPI_NRF->SendBuff(SPI1_TxBuff, SPI1_RxBuff, a); while(SPI_NRF->SPI->CR1 & SPI_CR1_CSTART); SPI_NRF->SendBuff(SPI1_TxBuff, SPI1_RxBuff, 20); while(SPI_NRF->SPI->CR1 & SPI_CR1_CSTART); SPI_NRF->SendBuff(SPI1_TxBuff, SPI1_RxBuff, 5); while(SPI_NRF->SPI->CR1 & SPI_CR1_CSTART); SPI_NRF->SendBuff(SPI1_TxBuff, SPI1_RxBuff, 7); /* Infinite loop */ while(1); функция отправки: void TSPI::SendBuff(uint8_t *aTxBuff, uint8_t *aRxBuff, uint16_t aCnt) { RxBuffPos = 0; TxBuffPos = 0; RxBuff = aRxBuff; TxBuff = aTxBuff; TransLength = aCnt; SPI->CR2 = aCnt; SPI->CR1 |= SPI_CR1_CSTART; SPI->IER |= SPI_IER_RXPIE | SPI_IER_TXPIE | SPI_IER_EOTIE; } обработчик прерывания: void SPI1_IRQHandler(void) { uint16_t tCTSIZE = (SPI_NRF->SPI->SR >> 16); if((SPI_NRF->SPI->SR & SPI_SR_RXP) && (SPI_NRF->SPI->IER & SPI_IER_RXPIE)) { while(SPI_NRF->SPI->SR & SPI_SR_RXP) { if(SPI_NRF->RxBuffPos < SPI_NRF->TransLength) { SPI_NRF->RxBuff[SPI_NRF->RxBuffPos++] = *(volatile uint8_t *) &(SPI_NRF->SPI)->RXDR; } else break; } } if((SPI_NRF->SPI->SR & SPI_SR_EOT) && (SPI_NRF->SPI->IER & SPI_IER_EOTIE)) {// закончили передавать SPI_NRF->SPI->IER &= ~(SPI_IER_RXPIE | SPI_IER_TXPIE); SPI_NRF->SPI->IFCR = SPI_IFCR_EOTC; } if((SPI_NRF->SPI->SR & SPI_SR_TXP) && (SPI_NRF->SPI->IER & SPI_IER_TXPIE)) {// while(SPI_NRF->SPI->SR & SPI_SR_TXP) { if(SPI_NRF->TxBuffPos < SPI_NRF->TransLength) { *(volatile uint8_t *) &(SPI_NRF->SPI)->TXDR = SPI_NRF->TxBuff[SPI_NRF->TxBuffPos++]; } else {// все отправили в буфер SPI_NRF->SPI->IER &= ~(SPI_IER_TXPIE); break; } } } } Изменено 21 июля, 2018 пользователем MasterElectric Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 21 июля, 2018 Опубликовано 21 июля, 2018 (изменено) · Жалоба Че-то вы тут поникли все. Надо свою поделку допаять и присоединиться к коллективным похоронам ковыряниям SPI на STM32H753 :biggrin: Это плата от графической части кое-какого пульта управления. Решил под конец только для себя сделать один макет - но не на F4 уже а на F7, благо они pin-to-pin совместимы на этом корпусе :rolleyes: Завтра запаяю все остальное и экран поставлю, если лень не одолеет. P.S. MasterElectric, пожалуйста, поменьше картинку сделайте... Изменено 21 июля, 2018 пользователем Arlleex Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться