|
|
  |
SPI1 в STM32F429 считывает 0 в младший бит |
|
|
|
Jun 19 2016, 16:42
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Вроде нашел в чем дело. Я поначалу не знал, что хардвер чип селект не доделан и его нужно только вручную ставить. Ну и выбрал хардвер, где-то нашел, что для его снятия надо вызывать DISABLE_SPI(). Вроде обмен происходит, а поскольку проблема не возникла сразу, а SPI это мизерная часть моего проекта, то я не стал вникать в детали тогда. Что происходит. При каждой транзакции разрешается интерфейс и одновременно сигнал клока идет в единицу (клок инвертирован), чип селект в ноль. Если на клоке есть емкость, то он немного запаздывает и видимо воспринимается как первый фронт клока. Будет время переделаю на софтвер чипселект и расскажу. Цитата(ViKo @ Jun 18 2016, 00:12)  И де вы такое прочитали?  На ноль омов резисторов не бывает.  Бывают. Цитата(ViKo @ Jun 18 2016, 17:01)  С первого же сообщения (slave устройство...) и до последнего от топикстартера. Поскольку есть устройство, то гарантии, что оно выдает мощную единицу всегда - нет. Топикстартер мог даже и не разглядеть кратковременного провала в цепи, в зависимости от качества осциллографа и квалификации "наблюдателя". Ну осциллографом я пользоваться умею и никакого другого значения кроме единицы там не видел.
|
|
|
|
|
Jun 19 2016, 18:13
|

Универсальный солдатик
     
Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362

|
Цитата(Tarbal @ Jun 19 2016, 19:42)  Бывают. Пе-ре-мыч-ки. Цитата Ну осциллографом я пользоваться умею и никакого другого значения кроме единицы там не видел. Назовите модель осциллографа, полосу частот, частоту дискретизации.
|
|
|
|
|
Jun 19 2016, 18:21
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(ViKo @ Jun 19 2016, 18:28)  У меня есть STM32F429I-Disco. Если выложите код, похожий на нерабочий, могу посмотреть. Но с нуля писать лень. Вдруг не не заработает.  Короче, пытаюсь воспроизвести ошибку - не получается. Перепробовал SPI1, SPI4, SPI5. Точные номер SPI и номера пинов не помню. Хотел же тогда на электроникс запостить, но поленился описывать глюк. Итого: ошибку воспроизвести не могу; если кто сообщит номер SPI и номера пинов (и каналов DMA опционально), то могу попробовать на макете.
|
|
|
|
|
Jun 19 2016, 19:16
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(adnega @ Jun 19 2016, 21:21)  ошибку воспроизвести не могу Короче, проверил все с SPI1 по SPI5. Ошибка, увы, не воспроизводится. Читаю-пишу так Код BYTE spi_send_byte(const BYTE data) { BYTE spib; while((SPI3->SR & (1 << SPI_SR_TXE)) == 0); SPI3->DR = data; while((SPI3->SR & (1 << SPI_SR_RXNE)) == 0); spib = SPI3->DR; return spib; } Цитата(ViKo @ Jun 19 2016, 21:13)  Пе-ре-мыч-ки. Вопрос определений. Под "резистором 0 Ом" можно понимать: перемычку, резистор, кусок провода, печатную дорожку и т.п. Я покупаю такие; в счете написано "резисторы".
Эскизы прикрепленных изображений
|
|
|
|
|
Jun 19 2016, 22:23
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
Цитата(ViKo @ Jun 20 2016, 01:14)  Ага, нашел, jumper. Он еще и точность имеет, и мощность рассеивания.  Я буду называть перемычками, как принято.  Цитата(ViKo @ Jun 19 2016, 19:28)  У меня есть STM32F429I-Disco. Если выложите код, похожий на нерабочий, могу посмотреть. Но с нуля писать лень. Вдруг не не заработает.  Вот такой код. Только теперь вместо нуля всегда читает единицу и только в первом интерфейсе. CODE HAL_StatusTypeDef SPI_WaitOnFlagTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus Status, uint32_t Timeout) { uint32_t start = jiffies; while(__HAL_SPI_GET_FLAG(hspi, Flag) == Status){ if(jiffies - start >= Timeout){ return -HAL_TIMEOUT; } } return HAL_OK; } #if 0 /* This funtion is used to transmit and receive data * with SPI1 * data --> data to be transmitted * returns received value */ uint8_t SPI1_send(uint8_t data){
SPI1->DR = data; // write data to be transmitted to the SPI data register while( !(SPI1->SR & SPI_I2S_FLAG_TXE) ); // wait until transmit complete while( !(SPI1->SR & SPI_I2S_FLAG_RXNE) ); // wait until receive complete while( SPI1->SR & SPI_I2S_FLAG_BSY ); // wait until SPI is not busy anymore return SPI1->DR; // return received data from SPI data register } #endif
int SPI_Transmit1(SPI_HandleTypeDef *hspi, uint8_t* val, uint32_t timeout) { FlagStatus Status; __HAL_SPI_ENABLE(hspi); hspi->Instance->DR = *val; Status = SPI_WaitOnFlagTimeout(hspi, SPI_FLAG_TXE, RESET, timeout); if(HAL_OK != Status){ return Status; } Status = SPI_WaitOnFlagTimeout(hspi, SPI_FLAG_RXNE, RESET, timeout); if(HAL_OK != Status){ return Status; } Status = SPI_WaitOnFlagTimeout(hspi, SPI_FLAG_BSY, SET, timeout); *val = hspi->Instance->DR; return Status; }
int write_spi_reg(uint8_t chip_id, uint8_t reg_addr, uint8_t val) { SPI_HandleTypeDef* hspi; uint8_t buf[SPI_WRITE_LEN]; uint8_t i; uint8_t id; GPIO_TypeDef* port; uint16_t pin;
HAL_StatusTypeDef ret;
if(CHIPS_AMOUNT <= chip_id){ return -WRONG_PARAMETER; }
hspi = hspi1; id = 0 port = GPIOA; pin = GPIO_PIN_4;
buf[0] = WR_SPI_CMD(id); buf[1] = reg_addr; buf[2] = val;
for(i = 0; i < SPI_WRITE_LEN; i++){ HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[i], SPI_TIMEOUT); HAL_GPIO_WritePin(port, pin, 1); short_delay(7);
if(HAL_OK != ret){ responce_handle(ret); return -ret; } } return NO_ERROR; }
int read_spi_reg(uint8_t chip_id, uint8_t reg_addr) { SPI_HandleTypeDef* hspi; uint8_t buf[2]; uint8_t id; HAL_StatusTypeDef ret; GPIO_TypeDef* port; uint16_t pin; chip_interface_t* chip_if;
if(CHIPS_AMOUNT <= chip_id){ return; } hspi = hspi1; id = 0 port = GPIOA; pin = GPIO_PIN_4;
buf[0] = RD_SPI_CMD(id); buf[1] = reg_addr;
HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[0], SPI_TIMEOUT);
HAL_GPIO_WritePin(port, pin, 1); short_delay(7); HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[1], SPI_TIMEOUT); HAL_GPIO_WritePin(port, pin, 1); short_delay(7);
if(HAL_OK != ret){ responce_handle(ret); return (uint16_t) -1; }
HAL_GPIO_WritePin(port, pin, 0); short_delay(7); ret = SPI_Transmit1(hspi, &buf[0], SPI_TIMEOUT); HAL_GPIO_WritePin(port, pin, 1); short_delay(7);
if(HAL_OK != ret){ responce_handle(ret); }
return (uint32_t)buf[0]; }
Конфигурация: Registers SPI_CR1 = 0x0000015F SPI_CR2 = 0x00000004
|
|
|
|
|
Jun 20 2016, 00:02
|
Профессионал
    
Группа: Свой
Сообщений: 1 351
Регистрация: 21-05-10
Пользователь №: 57 439

|
А замена на такую функцию (без аппаратной поддержки SPI) прекрасно работает. CODE #define PIN(PORT, PIN) GPIO##PORT, GPIO_PIN_##PIN
#define SPI1_CLK_PIN PIN(B, 3) #define SPI1_MOSI_PIN PIN(A,7) #define SPI1_MISO_PIN PIN(A, 6) #define SPI1_SS_PIN PIN(A, 4)
#define SET_CLK1() HAL_GPIO_WritePin(SPI1_CLK_PIN, 1) #define CLR_CLK1() HAL_GPIO_WritePin(SPI1_CLK_PIN, 0)
#define SET_MOSI1() HAL_GPIO_WritePin(SPI1_MOSI_PIN, 1) #define CLR_MOSI1() HAL_GPIO_WritePin(SPI1_MOSI_PIN, 0)
#define GET_MISO1() HAL_GPIO_ReadPin(SPI1_MISO_PIN)
int SPI_Transmit1(SPI_HandleTypeDef *hspi, uint8_t* val, uint32_t timeout) { int i; uint8_t res= 0, tmp = *val; if(&hspi1 == hspi){ for(i = 0; i < 8; i++){ res <<= 1; CLR_CLK1(); if(tmp & 0x80){ SET_MOSI1(); } else { CLR_MOSI1(); } res |= GET_MISO1(); SET_CLK1(); tmp <<= 1; } } else { return SPI_Transmit1_hw(hspi, val, timeout); } *val = res; return 0; }
В принципе если ожидать в цикле флагов, аппаратное исполнение не дает выигрыша, ну разве только на выскоких частотах обмена. Программное исполнение дает клок 1 мегагерц, что довольно сносно.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|