alexf 0 3 октября, 2016 Опубликовано 3 октября, 2016 · Жалоба Проблемы с HAL уже обсуждались, но у меня немного другая, так что открыл новую тему. Имеется STM32F070 и делаю SPI на HAL. (Нахально?) Задача вроде не хитрая. Обмен с чипом SI4432 всегда по 2 байта. В режиме 8 бит NSS дергался между байтами, так что сделал управление по GPIO. Так проще. И все бы ничего, по осциллографу картинка идеальная. А дальше вылезла проблема. Когда чтение происходило из (внешнего) прерывания, по осциллографу картинка все так же хороша, а читаются нули. Отладчик показал, что в DRA лежит правельный байт и уровень FIFO выше 0. uint8_t extIntSpiReadReg (U8 reg){ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); spi_buf_out[0] = reg & 0x7f; // MSB first spi_buf_out[1] = 0; // ignored HAL_SPI_TransmitReceive(&hspi1, (uint8_t *)&spi_buf_out,(uint8_t *) &spi_buf_in, 2,10); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); return spi_buf_in[1]; } После долгих мучений попробовал по простому (в 16 битном режиме): uint16_t ReadSPI(uint8_t addr){ uint16_t val; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SPI active while((SPI1->SR & SPI_SR_TXE) == 0); // wait for TX empty SPI1->DR = (uint16_t)(addr << 8); while(SPI1->SR & SPI_SR_BSY); // wait for TX empty while((SPI1->SR & SPI_SR_RXNE) == 0); // wait for RX HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // SPI not active val = SPI1->DR; return val; } Вопрос к знатокам: почему HAL так странно себя ведет? Что не так делаю? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
serglg 0 4 октября, 2016 Опубликовано 4 октября, 2016 · Жалоба Да, я тоже так и не понял с чтением по SPI. Просто тупо читаю одно и то же 3 раза подряд (в STM32L476). И тогда получаю правильный байт. На осциллографе тоже всегда всё хорошо и при однократном чтении. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 4 октября, 2016 Опубликовано 4 октября, 2016 · Жалоба . . . . . Когда чтение происходило из (внешнего) прерывания, по осциллографу картинка все так же хороша, а читаются нули. .... После долгих мучений попробовал по простому (в 16 битном режиме): .... Имел дело с HAL другого процессора, MSP HAL может использовать прерывания. Соотв-но, это надо соотносить откуда (из основной программы или из вектора какого либо прерывания) происходит вызов HAL. Исходя из "Когда чтение происходило из (внешнего) прерывания", вызов HAL в векторе аппаратного прерывания ? Если так, для проверки выведите вызов в основную программу и проверьте будет ли глючить там. "После долгих мучений" - посмотрите исходник HAL на эти вызовы. Отладчиком тоже можно посмотреть ктоестьху. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexf 0 4 октября, 2016 Опубликовано 4 октября, 2016 (изменено) · Жалоба Если так, для проверки выведите вызов в основную программу и проверьте будет ли глючить там. В том то и дело, что пара вызовов из основной программы вроде работала как надо. А в коде HAL прерываний не заметил. Это первое, что пришло в голову. Я слегка соврал, что всегда по 2 байта. Забыл что есть чтение/запись Si4432 FIFO с произвольным, не обязательно четным числом байт. Поэкспериментировал с переключением с 8 на 16 бит и обратно, и тоже глючит. В результате скатился на всегда по 8 бит и даже 8 битное обращение к регистру. Скорость мне не важна - пока идет обмен, процессор все равно ждет. После отказа от вызовов HAL SPI, размер кода на 2 К уменьшился. Хоть памяти и много, все равно приятно. Код получился корявый, но вроде работает как надо. Пришлось, возможно в лишних местах, делать чтениа SDR для очистки RX FIFO. void SPI1_init(){ __HAL_RCC_SPI1_CLK_ENABLE(); SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_BR_0 | SPI_CR1_SSM | SPI_CR1_SSI; SPI1->CR2 = SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0; // 8 bit SPI1->CR2 |= SPI_CR2_FRXTH; // fifo treshold for 8 bits SPI1->CR1 |= (1 << 6); // enable } #define SPI1_DR_8_bit (*(__IO uint8_t *)((uint32_t) & (SPI1->DR))) void WriteSPI(uint8_t addr, uint8_t data){ uint8_t val; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SPI active val = SPI1->DR; // clear just in case while((SPI1->SR & SPI_SR_TXE) == 0); // wait for TX empty SPI1_DR_8_bit = addr; while((SPI1->SR & SPI_SR_RXNE) == 0); // wait for RX val = SPI1_DR_8_bit; // discarded while((SPI1->SR & SPI_SR_TXE) == 0); // wait for TX empty SPI1_DR_8_bit = data; while(SPI1->SR & SPI_SR_BSY); while((SPI1->SR & SPI_SR_RXNE) == 0); // wait for RX val = SPI1_DR_8_bit; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // SPI not active } uint8_t ReadSPI(uint8_t addr){ uint8_t val; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SPI active val = SPI1->DR; // clear just in case while((SPI1->SR & SPI_SR_TXE) == 0); // wait for TX empty SPI1_DR_8_bit = addr; while((SPI1->SR & SPI_SR_RXNE) == 0); // wait for RX val = SPI1_DR_8_bit; // discarded while((SPI1->SR & SPI_SR_TXE) == 0); // wait for TX empty SPI1_DR_8_bit = 0xff; while(SPI1->SR & SPI_SR_BSY); while((SPI1->SR & SPI_SR_RXNE) == 0); // wait for RX val = SPI1_DR_8_bit; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // SPI not active return val; } Изменено 4 октября, 2016 пользователем IgorKossak [codebox] для длинного кода. [code]-для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
k155la3 27 4 октября, 2016 Опубликовано 4 октября, 2016 (изменено) · Жалоба HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // SPI active . . . . . HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // SPI not active } если это в смысле CS, лучше, на мой взгляд, совместить функции Wr + Rd для работы с SPI. Я пользую нечто вроде SET_SELECT_SPI_FLASH; in_dat[0] = SPI_WrRd( out_dat[0] ); in_dat[1] = SPI_WrRd( out_dat[1] ); . . . . CLEAR_SELECT_SPI_ALL; так как выбор CS открывает "сессию" SPI, которая имеет свойство "одновременности" RD WR. И что сделает slave с приемным регистром при "переоткрытии" по CS - зависит от реализации slave. Ну, например, очистит приемный регистр передачи :) Изменено 4 октября, 2016 пользователем k155la3 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться