sgrig 0 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба Пытаюсь подключить AD7793 к STM32F103 через SPI. В регистры АЦП все пишется без проблем, но читается из них что попало. Самое удивительное, что AD7793 выдает то, что надо - смотрю осциллоскопом на MISO процессора. Может, кто сталкивался? А то уже крыша едет... Буду признателен за любые идеи. Инициализация такая: void init_spi(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; /* GPIOA, GPIOB and SPI1 clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); /* Configure SPI1 pins: NSS, SCK, MISO and MOSI ----------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* SPI1 configuration ------------------------------------------------------*/ SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); /* Enable SPI1 NSS output for master mode */ SPI_SSOutputCmd(SPI1, ENABLE); /* Enable SPI1 */ SPI_Cmd(SPI1, ENABLE); } 8-ми битные регистры читаю так: char AD7793_read(char Reg) { char result; char reg = ((Reg&7)<<3) | 0x40; /* write to Communication Register AD7793 */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, reg); /* read byte with dummy write */ while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, 0x00); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); result = SPI_I2S_ReceiveData(SPI1); return result; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 24 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба Возможно, причина в том, что управлении линией ChipSelect происходит аппаратно, т.е. дергается на каждом байте. SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; Попробуйте программно дергать этим выводом согласно даташита на АЦП. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sgrig 0 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба Возможно, причина в том, что управлении линией ChipSelect происходит аппаратно, т.е. дергается на каждом байте. SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; Попробуйте программно дергать этим выводом согласно даташита на АЦП. 1) Линия не дергается - стоит в нуле. 2) АЦП выдает то, что нужно (см. пост выше). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба /* Configure SPI1 pins: NSS, SCK, MISO and MOSI ----------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); Так вы все ноги на выход настроили. Включите MISO на вход (Input Floating или Input Pulled), и будет вам счастье. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sgrig 0 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба Так вы все ноги на выход настроили. Включите MISO на вход (Input Floating или Input Pulled), и будет вам счастье. Почему? С чего вы взяли? Здесь все ноги настроены на альтернативные функции, насколько я понимаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба Из своего собственного опыта. GPIO_Mode_AF_PP - Альтернативный режим, Пушпульный Выход. А MISO должен быть настроен как вход. Специального альтернативного режима на вход нет, поэтому используйте GPIO_Mode_IN_FLOATING, GPIO_Mode_IPU или GPIO_Mode_IPD - на свой вкус. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Flexz 0 5 октября, 2009 Опубликовано 5 октября, 2009 · Жалоба В юзермануале есть для этого даже раздел специальный есть "8.1.11 Peripherals’ GPIO configurations", где все настройки портов для периферии расписаны Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sgrig 0 6 октября, 2009 Опубликовано 6 октября, 2009 · Жалоба Вы абсолютно правы, этот момент я упустил. Но беда в том, что все осталось на месте, хотя в процедуру инициализации GPIO внес изменения: /* Configure SPI1 pins: NSS, SCK and MOSI as alternate functions -----------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure SPI1 pin: MISO as pull-up input -------------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_UPD; GPIO_Init(GPIOA, &GPIO_InitStructure); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 6 октября, 2009 Опубликовано 6 октября, 2009 · Жалоба Тогда остаётся перебрать другие комбинации CPOL и CPHA, понизить скорость, и таки попробовать поуправлять NSS вручную. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sgrig 0 6 октября, 2009 Опубликовано 6 октября, 2009 · Жалоба Победил так: цикл обращения к SPI вынес в отдельную функцию, в которой первым делом чищу приемный буфер: u8 send_spi(u8 byte) { /* Flush away any rogue data in rx buffer */ if (SPI_I2S_GetFlagStatus(AD7793_SPI, SPI_I2S_FLAG_RXNE) == SET) SPI_I2S_ReceiveData(AD7793_SPI); /* Loop while DR register in not empty */ while(SPI_I2S_GetFlagStatus(AD7793_SPI, SPI_I2S_FLAG_TXE) == RESET); /* Send byte through the AD7793_SPI peripheral */ SPI_I2S_SendData(AD7793_SPI, byte); /* Wait to receive a byte */ while(SPI_I2S_GetFlagStatus(AD7793_SPI, SPI_I2S_FLAG_RXNE) == RESET); /* Return the byte read from the SPI bus */ return SPI_I2S_ReceiveData(AD7793_SPI); } Все заработало как часы. Самое смешное, что вернул MISO в состояние GPIO_Mode_AF_PP, что противоречит документации. А все работает! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
baralgin 0 10 декабря, 2009 Опубликовано 10 декабря, 2009 · Жалоба В исходниках этой папки: \STM32F10x_StdPeriph_Lib_V3.1.2\Project\STM32F10x_StdPeriph_Examples\SPI\M25P64_FLASH SCK, MISO и MOSI - настроены как GPIO_Mode_AF_PP. ... Не могу связать stm32 с FM25L04. Пациент практически живёт, но что-то не так. В общем статусный регистр нормально читается и пишется (там фактически два бита защиты только). Но вот заставить писать и читать нормально ячейки памяти не могу. Тайминги просматриваю логическим анализатором. При записи ничего криминального нет и всё проходит в соответствии с диаграммами даташита на FM25. А вот чтение работает не верно: на линии MISO просто повторяется DUMMY-байт и при этом чтение SPI_I2S_ReceiveData возвращает 0. Настройка MISO на плавающий вход ничего не меняет. CS управляется программно (отрабатывает адекватно). Вот кусок кода: void spi_init(void) { SPI_FLASH_CS_HIGH(); SPI_InitTypeDef SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 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_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; /* ïî õîäó íå íóæåí */ SPI_Init(SPI_FM25, &SPI_InitStructure); } static uint8_t sendByte(uint8_t byte) { WAIT_TXE(); SPI_I2S_SendData( SPI_FM25, byte ); WAIT_RXNE(); return SPI_I2S_ReceiveData(SPI_FM25); } void spi_readBuf(uint16_t addr, uint8_t* buff, uint16_t buff_size) { uint_fast16_t i; if( ( addr > FM25_MAX_ADDR ) || ( buff_size > FM25_MAX_ADDR ) || ( !buff ) ) return; SPI_FLASH_CS_LOW(); { sendByte(FM25_READ_ADDR_HI( addr )); sendByte(FM25_READ_ADDR_LO( addr )); for( i = 0; i < buff_size; i++ ) { buff[i] = sendByte(FM25_CMD_DUMMY); } } SPI_FLASH_CS_HIGH(); } void spi_writeBuf(uint16_t addr, uint8_t* buff, uint16_t buff_size) { uint_fast16_t i; if( ( addr > FM25_MAX_ADDR ) || ( buff_size > FM25_MAX_ADDR ) || ( !buff ) ) return; SPI_FLASH_WriteEnable(); SPI_FLASH_CS_LOW(); { sendByte( FM25_WRITE_ADDR_HI( addr ) ); sendByte( FM25_WRITE_ADDR_LO( addr ) ); for( i = 0; i < buff_size; i++ ) { sendByte(buff[i]); } } SPI_FLASH_CS_HIGH(); } void spi_test(void) { static uint8_t buff[1]; buff[0] = 0x22; spi_writeBuf(0x0000, buff, 1 ); spi_readBuf(0x0000, buff, 1); } Функции FM25_READ_ADDR_HI/LO и FM25_WRITE_ADDR_HI/LO - дают нужный опкод на чтение и запись + нужный адрес. Работают корректно. В функции sendByte пробовал делать предварительную проверку приёмного буффера - ничего не меняет. Уже второй день бьюсь :( . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
baralgin 0 10 декабря, 2009 Опубликовано 10 декабря, 2009 (изменено) · Жалоба Модифицировал функцию чтения до непрерывности: static uint8_t readOneByte(uint16_t addr) { uint8_t ret; SPI_FLASH_CS_LOW(); WAIT_TXE(); SPI_I2S_SendData(SPI_FM25, FM25_READ_ADDR_HI( addr )); WAIT_TXE(); SPI_I2S_SendData(SPI_FM25, FM25_READ_ADDR_LO( addr )); WAIT_RXNE(); SPI_I2S_ReceiveData(SPI_FM25); WAIT_TXE(); SPI_I2S_SendData(SPI_FM25, FM25_CMD_DUMMY ); WAIT_RXNE(); SPI_I2S_ReceiveData(SPI_FM25); WAIT_RXNE(); ret = SPI_I2S_ReceiveData(SPI_FM25); SPI_FLASH_CS_HIGH(); return ret; } Шесть последовательных вызовов с адресом от 0 до 5. Все вызовы возвращают 0. При этом, что происходит на выводах в приложенной картинке(всё как в даташите..). На ней снизу вверх: CS, SCK, MOSI, MISO . DUMMY равен 0x71. На MISO иногда проскакивают значения но они не ловятся приёмником... ps: картинка gif - нужно кликнуть. Изменено 10 декабря, 2009 пользователем baralgin Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
baralgin 0 11 декабря, 2009 Опубликовано 11 декабря, 2009 · Жалоба Отбой... впаяли более плотную микросхему, в которой адрес двухбайтный, вследствии чего она ничего не передавала после первого байта адреса... Удосужиться прочитать реальную маркировку пришло в голову только на третий день мучений :) . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться