|
STM32 SPI, не запускается |
|
|
|
Jan 23 2012, 11:43
|

Частый гость
 
Группа: Свой
Сообщений: 161
Регистрация: 17-08-04
Из: Караганда
Пользователь №: 516

|
Второй день пытаюсь вызвать к жизни SPI1 или 2 на STM32VLDISCOVERY. Перерыл интернет и даташит до тошноты. Не пойму что не так: CODE RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // Разрешить тактирование порта B. RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций GPIO. //Настройки GPIO GPIOB->CRH |= GPIO_CRH_MODE15_1; // Выход MOSI PB.15 GPIOB->CRH &= ~GPIO_CRH_MODE15_0; // 2MHz GPIOB->CRH &= ~GPIO_CRH_CNF15; // Push-Pull GPIOB->CRH &= ~GPIO_CRH_MODE14; // Вход MISO PB.14 GPIOB->CRH &= ~GPIO_CRH_CNF14_0; // GPIOB->CRH |= GPIO_CRH_CNF14_1; // Pull-Up GPIOB->ODR |= GPIO_ODR_ODR14; // GPIOB->CRH |= GPIO_CRH_MODE13_1; // Выход SCK PB.13 GPIOB->CRH &= ~GPIO_CRH_MODE13_0; // 2MHz GPIOB->CRH &= ~GPIO_CRH_CNF13; // Push-Pull
GPIOB->CRH &= ~GPIO_CRH_MODE12; // Вход NSS PB.12 GPIOB->CRH &= ~GPIO_CRH_CNF12_0; // GPIOB->CRH |= GPIO_CRH_CNF12_1; // Pull-Up GPIOB->ODR |= GPIO_ODR_ODR12; //Настройки SPI2 RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; //Разрешаем тактирование SPI2
SPI2->CR1 &= ~SPI_CR1_SPE; //Отключаем SPI перед изменением настроек SPI2->CR1 |= SPI_CR1_BR_0; //Задаем скорость SPI2->CR1 |= SPI_CR1_BR_1; // SPI2->CR1 |= SPI_CR1_CPOL; //Задаем режим SPI2->CR1 |= SPI_CR1_CPHA; // SPI2->CR1 &= ~SPI_CR1_DFF; //Формат данных 8 бит SPI2->CR1 &= ~SPI_CR1_CRCEN; //Запрет CRC SPI2->CR1 &= ~SPI_CR1_CRCNEXT; //Отключение передачи CRC SPI2->CR1 &= ~SPI_CR1_RXONLY; //и прочих не fullduplex настроек SPI2->CR1 &= ~SPI_CR1_SSM; //на всякий случай.. SPI2->CR1 &= ~SPI_CR1_SSI; // SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB вперед SPI2->CR1 |= SPI_CR1_MSTR; //В режиме Мастер SPI2->CR1 &= ~SPI_CR1_BIDIMODE;// SPI2->CR1 &= ~SPI_CR1_BIDIOE; //
SPI2->CR2 &= ~SPI_CR2_SSOE; // Запретить выход SS // (на входе задан высокий уровень) SPI2->CR1 |= SPI_CR1_SPE; // Включаем SPI ..... //Пробная прием-передача u8 temp; while (SPI2->SR & SPI_SR_BSY); while (!(SPI2->SR & SPI_SR_TXE)); SPI2->DR = 0x55; // Передача данных while (SPI2->SR & SPI_SR_BSY); while (!(SPI2->SR & SPI_SR_RXNE)); temp = SPI2->DR; // Чтение принятых данных ....... При отладке видно, что все настройки устанавливаются как прописано в коде, а в регистр DR данные 0x55 так и не записывается. На ногах процессора молчок. Тоже самое делал и для SPI1 с учетом бита альтернативной распиновки. Наверное, если взять библиотеку с функциями инициализации все бы заработало, но хочу вот так через "stm32f10x.h". Помогите пожалуйста разобраться.
Сообщение отредактировал IgorKossak - Jun 18 2012, 17:20
Причина редактирования: [codebox]
|
|
|
|
|
Jan 23 2012, 12:07
|

Участник

Группа: Участник
Сообщений: 31
Регистрация: 26-12-11
Пользователь №: 69 097

|
зачем же так "долбить" SPI2->CR1 ? ... все можно уместить в пару строк Код // включим тактирование - порт A, SPI1 RCC->APB2ENR = RCC_APB2ENR_IOPAEN |RCC_APB2ENR_AFIOEN | RCC_APB2ENR_SPI1EN; // set SPI1 AFIO->MAPR &= 0xFFFFFFFE; // clear AFIO_MAPR->SPI1_REMAP bit SPI1->CR1 = (1<<2)|(5<<3)|(1<<6)|(1<<8)|(1<<9); SPI1->CR2 = 0x0000; // set pin GPIOA->BSRR = 0x00000010; GPIOA->CRL = 0xB8B34444;
|
|
|
|
|
Jan 23 2012, 12:46
|
Знающий
   
Группа: Участник
Сообщений: 998
Регистрация: 27-08-08
Пользователь №: 39 850

|
Делал так (под новуб библиотеку периферии). Для работы с AD9832 CODE void SPI1_Init(void) {
// PA4 - NSS софтовый PA5 - SPI1 SCK PA7 - SPI1 MOSI
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // NSS: выход push-pull GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1);
// SCK: выход push-pull GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
// MOSI: выход push-pull GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; //? SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE);
GPIOA->ODR |= GPIO_OTYPER_ODR_4;
} Запускается без проблем. Но по ходу вопрос. Как переназначить GPIO SPI1 на другие ноги? В новой библиотеке (в предыдущей вроде были) исчезли функции ремапинга. Куда они подевались?
Сообщение отредактировал Acvarif - Jan 23 2012, 12:47
|
|
|
|
|
Jan 23 2012, 16:29
|

Участник

Группа: Участник
Сообщений: 31
Регистрация: 26-12-11
Пользователь №: 69 097

|
Цитата("Alhen") Это от безисходности и злобы ... ... надеюсь все теперь все ОК ... код из рабочего примера Цитата("Acvarif") Как переназначить GPIO SPI1 на другие ноги? 1 - посмотреть в datasheet  .. на других ногах "висит" JTAG, так что помимо установки AFIO_MAPR->SPI1_REMAP нужно позаботиться о JTAG
Сообщение отредактировал ChipKiller - Jan 23 2012, 16:31
|
|
|
|
|
Jan 24 2012, 04:26
|

Частый гость
 
Группа: Свой
Сообщений: 161
Регистрация: 17-08-04
Из: Караганда
Пользователь №: 516

|
Цитата(ChipKiller @ Jan 23 2012, 20:29)  ... надеюсь все теперь все ОК ... код из рабочего примера Благодарю за рабочий код, действительно все заработало, с меня пиво Я разобрался в чем была промашка, надо было назначить выходы в режиме альтернативной функции. Код GPIOA->CRL |= GPIO_CRL_MODE7; // Выход MOSI PA.7 (50 MHz) GPIOA->CRL &= ~GPIO_CRL_CNF7_0; // Push-Pull GPIOA->CRL |= GPIO_CRL_CNF7_1; // с альтернативной функцией !!!!!! Позволю себе выложить весь код тестовой программы в том же стиле. Такой "долбеж" по регистрам неизбежен на начальном этапе освоения камня, есть ощущение проникновения в сакральный смысл регистров CODE #include "stm32f10x.h" u8 temp;
void main() { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // Разрешить тактирование порта A. RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций GPIO. GPIOA->CRL |= GPIO_CRL_MODE7; // Выход MOSI PA.7 (50 MHz) GPIOA->CRL &= ~GPIO_CRL_CNF7_0; // Push-Pull GPIOA->CRL |= GPIO_CRL_CNF7_1; // с альтернативной функцией !!!!!! GPIOA->CRL &= ~GPIO_CRL_MODE6; // Вход MISO PA.6 GPIOA->CRL &= ~GPIO_CRL_CNF6_0; // GPIOA->CRL |= GPIO_CRL_CNF6_1; // with Pull-Up GPIOA->CRL |= GPIO_CRL_MODE5; // Выход SCK PA.5 (50 MHz) GPIOA->CRL &= ~GPIO_CRL_CNF5_0; // Push-Pull GPIOA->CRL |= GPIO_CRL_CNF5_1; // с альтернативной функцией !!!!
GPIOA->CRL |= GPIO_CRL_MODE4; // Выход NSS PA.4 (50 MHz) GPIOA->CRL &= ~GPIO_CRL_CNF4; // Push-Pull General Purpose GPIOA->BSRR = GPIO_BSRR_BS4; // AFIO->MAPR &= ~AFIO_MAPR_SPI1_REMAP; //Сбрасываем REMAP для SPI на PA4-7 RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
SPI1->CR1 &= ~SPI_CR1_SPE; //Запрещаем SPI перед изменениями настроек SPI1->CR1 |= SPI_CR1_BR_0; //Задаем скорость SPI1->CR1 |= SPI_CR1_BR_1; SPI1->CR1 |= SPI_CR1_CPOL; //Задаем режим SPI1->CR1 |= SPI_CR1_CPHA; // SPI1->CR1 &= ~SPI_CR1_DFF; //Формат данных 8 бит SPI1->CR1 &= ~SPI_CR1_CRCEN; //Запрет CRC SPI1->CR1 &= ~SPI_CR1_CRCNEXT; //Отключение передачи CRC SPI1->CR1 &= ~SPI_CR1_RXONLY; //и прочих не fullduplex настроек SPI1->CR1 &= ~SPI_CR1_SSM; //на всякий случай.. SPI1->CR1 &= ~SPI_CR1_SSI; SPI1->CR1 &= ~SPI_CR1_LSBFIRST; //MSB вперед SPI1->CR1 |= SPI_CR1_MSTR; //В режиме Мастер SPI1->CR1 &= ~SPI_CR1_BIDIMODE; SPI1->CR1 &= ~SPI_CR1_BIDIOE;
SPI1->CR1 |= SPI_CR1_SPE; // Включаем SPI while(1) { while (SPI1->SR & SPI_SR_BSY); while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0x55; // Передача данных while (SPI1->SR & SPI_SR_BSY); while (!(SPI1->SR & SPI_SR_RXNE)); temp = SPI1->DR; // Чтение принятых данных } } Кстати, пошагово в отладчике программа не проходит проверку на RXNE и попадает в бесконечный цикл. Видать, где-то, RXNE успевает сброситься. Сам кусок кода с записью и чтением я взял на форуме ST здесьАвтор утверждает, что у него код работает только в этом порядке, хотя в мануале RM0041 не рекомендуют проверять BSY при каждой посылке и приеме. Цитата Note: Do not use the BSY flag to handle each data transmission or reception. It is better to use the TXE and RXNE flags instead.
Сообщение отредактировал IgorKossak - Jan 24 2012, 09:50
Причина редактирования: [codebox]
|
|
|
|
|
Jun 13 2012, 13:15
|
Группа: Участник
Сообщений: 13
Регистрация: 10-01-11
Пользователь №: 62 132

|
Добрый вечер. Тоже разбираюсь с SPI. Вроде все делаю как в рабочем примере, но почему то не работает. Припаял SPI флешку, но при отправлении данных при отладке программы в регистр ODR записывается 00FF, и так и остается. Уже два дня мучаюсь, что может быть не так? CODE //////////=================SPI=============== void SPI_INIT(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); /* Deinitialize SPI3 peripheral */ SPI_I2S_DeInit(SPI3);
// SCK: выход push-pull PC10 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SCK; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, PIN_SCK , GPIO_AF_SPI3); // MOSI: выход push-pull PC12 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MOSI; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, PIN_MOSI , GPIO_AF_SPI3); // MISO: выход push-pull PC11 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MISO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, PIN_MISO , GPIO_AF_SPI3); //NSS: выход push-pull - use general GPIO for CS A4 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SPI_CS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); //SPI3 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_8; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI3, &SPI_InitStructure); SPI_Cmd(SPI3, ENABLE); } Отсылаю так CODE //////////================FOR READ_WRITE SPI=================//////////// void EEPROMSend(char byte){ SPI_I2S_SendData(SPI3, byte); while (SPI_GetFlagStatus(SPI3, SPI_FLAG_TXE) == RESET); }
void EEPROMSendByte(char byte){ GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); SPI_I2S_SendData(SPI3, byte); while (SPI_GetFlagStatus(SPI3, SPI_FLAG_RXNE) == RESET); GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); }
char EEPROMReceive(){ char byte; byte = SPI_I2S_ReceiveData(SPI3); while (SPI_GetFlagStatus(SPI3, SPI_FLAG_RXNE) == RESET); return byte; }
volatile static uint8_t data=0;
int main() { int i= 10; __enable_irq(); //Включаем прерывания LedInit(); SPI_INIT(); NVIC_SetPriority(SPI3_IRQn, 2); //Устанавливаем приоритет прерываний от SPI1 NVIC_EnableIRQ(SPI3_IRQn); //Включаем прерывания от SPI1
//Write Status Register (WRSR) Instruction Sequence i++; EEPROMSendByte(0x06); //command for write sequence EEPROM
//for i //Write to EEPROM GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROMSend(0x02); //00000010 - write command EEPROMSend(0x00); //address EEPROMSend(0x00); //address EEPROMSend(0x00); //address EEPROMSend(0x00); //data GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); delay(120*5000); ///
//Read from EEPROM GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROMSend(0x03); //read command EEPROMSend(0x00); //address EEPROMSend(0x00); //address EEPROMSend(0x00); //address data = EEPROMReceive(); //fake read data = EEPROMReceive(); //read GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); data++;
Сообщение отредактировал IgorKossak - Jun 13 2012, 13:23
Причина редактирования: [codebox] для длинного кода!!!
|
|
|
|
|
Jun 13 2012, 19:55
|

Профессионал
    
Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634

|
Цитата // MISO: выход push-pull PC11 Master Input Slave Output Оно?
|
|
|
|
|
Jun 14 2012, 08:54
|
Группа: Участник
Сообщений: 13
Регистрация: 10-01-11
Пользователь №: 62 132

|
Обновил библиотеки - заработало MOSI, CS и SCLK Сейчас посмотрел на осциллографе, MISO кстати и не работает. Сразу после записи команды чтения CS уходит в 1, то есть строчки Код data = EEPROMReceive(); //fake read data = EEPROMReceive(); //read Вообще пропускаются. MISO стабильно выдает 1,7 на всем протяжении) Может я что то не понимаю, но при отладке в строчках Код void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data) { /* Check the parameters */ assert_param(IS_SPI_ALL_PERIPH(SPIx)); /* Write in the DR register the data to be sent */ SPIx->DR = Data; } DR приравнивается 0xFE, хотя Data=0x06?
Сообщение отредактировал dfyz.s - Jun 14 2012, 08:30
|
|
|
|
|
Jun 14 2012, 10:03
|
Группа: Участник
Сообщений: 13
Регистрация: 10-01-11
Пользователь №: 62 132

|
На отладчик забил Понял, в чем был косяк. Код uint8_t EEPROMSend(uint8_t byte){ while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI3, byte); while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI3); }
void EEPROMSendByte(uint8_t byte){ GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROMSend(byte); GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); }
uint8_t EEPROMReceive(void) { return (EEPROMSend(DUMMY_BYTE)); } Необходимо просто отправлять байт и читать одновременно. Но на осциле MISO все равно не работает. Что то дергается, но невысокий уровень. Может Open Drain попробовать? Цитата в приведённом коде miso программировался на вывод. Должен быть входом. Код // MISO: выход push-pull PC11 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MISO; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; /// Сконфигурирован как MISO. Надо как IN Сделать? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /// ???? или здесь Open Drain поставить? GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure);
|
|
|
|
|
Jun 14 2012, 19:18
|
Частый гость
 
Группа: Участник
Сообщений: 76
Регистрация: 11-06-10
Пользователь №: 57 871

|
Цитата(Genadi Zawidowski @ Jun 14 2012, 21:48)  Нет, именно входом. А как это делается на NXP я понятия не имею... как и на STM32. Но знаю точно, что долго искать не пришлось бы, будь я за Вашим компютером. Где то так. Для SPI2. Код GPIOB->CRH &= ~(GPIO_CRH_CNF15 | GPIO_CRH_MODE15); GPIOB->CRH |= GPIO_CRH_CNF15_1 | GPIO_CRH_MODE15; //mosi GPIOB->CRH &= ~(GPIO_CRH_CNF14 | GPIO_CRH_MODE14); GPIOB->CRH |= GPIO_CRH_CNF14_0; //miso GPIOB->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13); GPIOB->CRH |= GPIO_CRH_CNF13_1 | GPIO_CRH_MODE13; //sck GPIOB->CRH &= ~(GPIO_CRH_CNF12 | GPIO_CRH_MODE12); GPIOB->CRH |= GPIO_CRH_MODE12; //cs
|
|
|
|
|
Jun 18 2012, 15:12
|
Группа: Участник
Сообщений: 13
Регистрация: 10-01-11
Пользователь №: 62 132

|
Цитата Код GPIOB->CRH &= ~(GPIO_CRH_CNF15 | GPIO_CRH_MODE15); GPIOB->CRH |= GPIO_CRH_CNF15_1 | GPIO_CRH_MODE15; //mosi GPIOB->CRH &= ~(GPIO_CRH_CNF14 | GPIO_CRH_MODE14); GPIOB->CRH |= GPIO_CRH_CNF14_0; //miso GPIOB->CRH &= ~(GPIO_CRH_CNF13 | GPIO_CRH_MODE13); GPIOB->CRH |= GPIO_CRH_CNF13_1 | GPIO_CRH_MODE13; //sck GPIOB->CRH &= ~(GPIO_CRH_CNF12 | GPIO_CRH_MODE12); GPIOB->CRH |= GPIO_CRH_MODE12; //cs Это для серии stm32f1xx. У меня же stm32f207. Спасибо за советы, но у меня уже было настроено на вход как видно по моим примерам. В итоге разобрался. Дело было в том, что ядро контроллера работает на частоте 120 МГц и порт не успевает выводить значения, которые задаешь подряд. Приходиться делать задержку. Итоговый код программы. Может кому-то пригодиться CODE #include <stm32f2xx_conf.h> #include <stdio.h>
//HSE 25 MHz //HSI 16 MHz // PLL configure 120 MHz signal // PCLK1 - HSE/4 - 30 MHz(APB1); PCLK2 - HSE/2 - 60 MHz(APB2)
#define DUMMY_BYTE 0xA5 #define PIN_EEPROM_SPI_CS GPIO_Pin_4 #define PIN_TAMPER GPIO_Pin_13 #define PIN_EEPROM_MOSI GPIO_Pin_12 #define PIN_EEPROM_MISO GPIO_Pin_11 #define PIN_EEPROM_SCK GPIO_Pin_10 #define PIN_SPI_CS 0x0010 #define PIN_SCK GPIO_PinSource10 #define PIN_MISO GPIO_PinSource11 #define PIN_MOSI GPIO_PinSource12
void delay(volatile uint32_t time) { for (; time != 0; time --); }
void Led_Init(void) { RCC -> AHB1ENR |= RCC_AHB1ENR_GPIOFEN; GPIOF -> MODER |= GPIO_MODER_MODER6_0 | GPIO_MODER_MODER7_0 | GPIO_MODER_MODER8_0 ; GPIOF -> OTYPER &= ~(GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7 | GPIO_OTYPER_OT_8); GPIOF -> OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7 | GPIO_OSPEEDER_OSPEEDR8 ; }
//////////=================SPI=============== void SPI_INIT(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); /* Deinitialize SPI3 peripheral */ SPI_I2S_DeInit(SPI3);
GPIO_PinAFConfig(GPIOC, PIN_SCK , GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOC, PIN_MOSI , GPIO_AF_SPI3); GPIO_PinAFConfig(GPIOC, PIN_MISO , GPIO_AF_SPI3);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // SCK: выход push-pull PC10 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SCK; GPIO_Init(GPIOC, &GPIO_InitStructure);
// MISO: выход push-pull PC11 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MISO; GPIO_Init(GPIOC, &GPIO_InitStructure);
// MOSI: выход push-pull PC12 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_MOSI; GPIO_Init(GPIOC, &GPIO_InitStructure);
//NSS: выход push-pull - use general GPIO for CS A4 GPIO_InitStructure.GPIO_Pin = PIN_EEPROM_SPI_CS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOA, &GPIO_InitStructure); //SPI3 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_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_Init(SPI3, &SPI_InitStructure); SPI_Cmd(SPI3, ENABLE); } //////////////============================================================
//////////================FOR READ_WRITE SPI=================////////////
uint8_t EEPROM_Send(uint8_t byte){ while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI3, byte); while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI3); }
void EEPROM_SendByte(uint8_t byte){ GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROM_Send(byte); GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); delay(2000); }
uint8_t EEPROM_Receive(void) { return (EEPROM_Send(DUMMY_BYTE)); }
uint8_t EEPROM_ReadStatReg(void) { uint8_t byte; GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROM_Send(0x05); byte=EEPROM_Receive(); GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); delay(2000); return (byte); }
void EEPROM_BulkErase(void) { EEPROM_SendByte(0xC7); while(EEPROM_ReadStatReg() & 1); } /////=========================================================
volatile static uint8_t data=0; volatile static uint8_t RegStat=0;
//////===================MAIN int main() { __enable_irq(); //Включаем прерывания Led_Init(); SPI_INIT();
EEPROM_BulkErase(); //Write enable (WREN) Instruction Sequence EEPROM_SendByte(0x06); //command for write sequence EEPROM //Write to EEPROM GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROM_Send(0x02); //00000010 - write command EEPROM_Send(0x00); //address EEPROM_Send(0x00); //address EEPROM_Send(0x00); //address EEPROM_Send(0xAA); //data EEPROM_Send(0xBB); //data EEPROM_Send(0xCC); //data while (SPI1->SR & SPI_SR_BSY); GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); delay(2000); while (SPI1->SR & SPI_SR_BSY); while(EEPROM_ReadStatReg() & 1); /// GPIOF->ODR |= GPIO_OTYPER_ODR_6;
//Read from EEPROM GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_RESET); EEPROM_Send(0x03); //read command EEPROM_Send(0x00); //address EEPROM_Send(0x00); //address EEPROM_Send(0x00); //address data = EEPROM_Receive(); //read data = EEPROM_Receive(); //read data = EEPROM_Receive(); //read data = EEPROM_Receive(); //read data = EEPROM_Receive(); //read GPIO_WriteBit(GPIOA, PIN_SPI_CS, Bit_SET); delay(2000);
/// GPIOF->ODR |= GPIO_OTYPER_ODR_8; delay(8000000); GPIOF->ODR &= ~GPIO_OTYPER_ODR_8; delay(8000000); GPIOF->ODR |= GPIO_OTYPER_ODR_8; GPIOF->ODR &= ~GPIO_OTYPER_ODR_6; delay(8000000); while(1){}; }
Думал, что это как то просчитанно. А так в общем все в проге было ОК :=)
Сообщение отредактировал IgorKossak - Jun 18 2012, 17:17
Причина редактирования: форматирование (лишние табы)
|
|
|
|
|
Oct 21 2012, 06:14
|
Участник

Группа: Участник
Сообщений: 29
Регистрация: 13-09-12
Пользователь №: 73 529

|
хочу подключить к STM32F4 DISCOVERY дисплей LCD NOKIA 5110 использую CooCoxв софт SPI подключение проходит (так я проверил строку инициализации дисплея) для хардварного SPI сначала вызываю инициализацию SPI2 используемые ноги: - PB13 CLK - PB15 MOSI - NSS и MISO не использую так как нужно только записывать данные и SPI2 всегда в режиме мастера Код // Инициализация SPI2 void SPI2_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // включили SPI2 SPI_DeInit(SPI2); // сбрасываем настройки SPI2 на первоначальные
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // включили GPIOB
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); // SPI2_CLK GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // SPI2_MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(GPIOB, &GPIO_InitStructure);
// сюда задание альтернативных функций 13 и 15 пина тоже переносил. результата нет // GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); // SPI2_CLK // GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // SPI2_MOSI
// SPI2 SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; 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_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE); } частота камня 168 мгц поэтому взял максимальный делитель для SPI2 = 256 далее инициализирую GPIO для других линий дисплея Код // Инициализация LCD NOKIA 5110 c помощью SPI2 void lcd5110_init(void) { GPIO_InitTypeDef GPIO_InitStructure; unsigned char y, x;
// RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // такт GPIOB, для софт SPI, для хард - делается при ините SPI2
// конфигурируем пины порта B как выход // для soft spi // GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
// для хардварного SPI GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10 | GPIO_Pin_14;
// общие строки инициализации GPIO_InitStructure.GPIO_Mode =GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd =GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); далее работаю с дисплеем, этот код используется и в софт и хард работе SPI c дисплеем Код // Линии управления LCD в неактивное состояние LCD_CS1; // CS=1 LCD_RST1; // RST=1 delay_ms(10); // пауза 0.2 сек.
// сброс дисплея LCD_CS0; // CS=0 LCD_RST0; // RST=0 delay_ms(10); // пауза 0.2 сек. LCD_RST1; // RST=1 LCD_CS1; // CS=1 delay_ms(10); // пауза 0.2 сек.
// последовательность инициализации дисплея LCD_DC0; // передача команды LCD_SendData(0x21); LCD_SendData(0xC6); LCD_SendData(0x06); LCD_SendData(0x13); LCD_SendData(0x20); LCD_SendData(0x0C);
LCD_DC0; // передача команд LCD_SendData(0x40); LCD_SendData(0x80);
LCD_DC1; // передача данных for (y=0;y<6;y++) for (x=0;x<84;x++) LCD_SendData(0x88);
LCD_DC0; // передача команд LCD_SendData(0x0C); } и собственно, сама процедура передачи данных на дисплей Код void LCD_SendData(unsigned char data) { // unsigned char i; // для программного SPI
LCD_CS0; // включаем выбор дисплея // хардварный SPI SPI_I2S_SendData(SPI2, data); while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
/* // это реализация программного SPI работает! // программный SPI for(i=0;i<8;i++) { if (data & 0x80) LCD_MOSI1; else LCD_MOSI0; data = data<<1; LCD_SCK0; LCD_SCK0; LCD_SCK0; LCD_SCK1; LCD_SCK1; LCD_SCK1; } */ LCD_CS1; } процедуры вызываю из main() Код SPI2_Config(); // конфигурация SPI2
lcd5110_init(); // конфигурация LCD почему не работает аппаратный SPI2?
Сообщение отредактировал ВитГо - Oct 21 2012, 06:23
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|