Пишу с опозданием надобыло кое какие проекты сдавать и платы делать.
Во первых я не заявлял что нашел глюк, тема четко говорит "проблемы с СПИ", а проблемы могут быть по разым причинам, в том числе и по причине моей ошибки.
Сделал вот что:
1) После того как убедился что на новой голой плате проект СПИ заработал, я переписал старый проект по новому, и прогнал его тоже на новой плате - Заработало.
2) Старую платуполностью отсоеденил от всего что было соеденено, прогнал тот же епределанный проект - Заработало.
3) Начал присоеденять по очереди остальную перферию - Заработало с присоединенной всей периферией (Uart,PWM,I2C)
4) После того как СПИ проект с подсоединенной но не активизированной программно периферией заработал, я ее начал по очереди активизировать, в итоге проект был доведен до "оригиального" состояния, и тоже заработал
под "заработал" я имею ввиду что сразу при включении не надо долго ждать и я вижу свои байты на осциллографе.
Единственное что я заметил в результате всего этого это задержка SCK на примерно 1500нс когда все нижеприведенные функции не заккоментированны.
Когда закомментированны две последние функции включения i2c и usart3 то задержка подтянутого SCK не более 400нс
Когда закомментирован только usart3 то задержка SCk перед его переключением и посылкой байта 900нс
Когда все нижеприведенные функции включены (не закомментированны) то задержка SCK перед его переключением и посылкой байта 1500нс
При этом: Если включить всеэти функции (не комментировать их) и включить цикл задержки длинной после включения платы, а потом подать через тот же Usart3 команду на посылку байта по SPI, то байт отсылается сразу и SCK не задерживается (сразу начинает пиерелючатся)
Вот моя последовательность включения программно периферии:
Код
config_gpio_all(); // configure all GPIOs
config_pwm_io(); // configure Input and Output PWM channels
config_spi_all(); // config all peripherals using SPI
config_i2c_all(); // config all peripherals using I2C
config_usart3(); // configure USART3
А вот код каждой функции:
CODE
uint32_t config_gpio_all(void)
{
//=============================================================================
// GPIOB configuration
//=============================================================================
// enable GPIOB clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
// Alternate Function
GPIOB->MODER = 0; // clear moder register
GPIOB->MODER |=
(
GPIO_MODER_MODER12_1 | // Alternate Function, SPI2 NSS
GPIO_MODER_MODER13_1 | // Alternate Function, SPI2 SCK
GPIO_MODER_MODER14_1 | // Alternate Function, SPI2 MISO
GPIO_MODER_MODER15_1 | // Alternate Function, SPI2 MOSI
GPIO_MODER_MODER9_1 | // Alternate Function, I2C1, SDA
GPIO_MODER_MODER8_1 | // Alternate Function, I2C1, SCL
GPIO_MODER_MODER4_1 | // AF, PWM_OUT1, TIM3_CH1
GPIO_MODER_MODER5_1 | // AF, PWM_OUT2, TIM3_CH2
GPIO_MODER_MODER0_1 | // AF, PWM_OUT3, TIM3_CH3
GPIO_MODER_MODER1_1 | // AF, PWM_OUT4, TIM3_CH4
GPIO_MODER_MODER6_1 | // AF, PWM_IN5, TIM4_CH1
GPIO_MODER_MODER7_1 // AF, PWM_IN6, TIM4_CH2
);
// Output type
GPIOB->OTYPER = 0; // clear otype register
GPIOB->OTYPER |= // push-pull if 0
(
GPIO_OTYPER_OT_8 | // Open-Drain, I2C1, SCL
GPIO_OTYPER_OT_9 // OPen-Drain, I2C1, SDA
);
// Speed type
GPIOB->OSPEEDR = 0; // clear ospeedr register
GPIOB->OSPEEDR |=
(
GPIO_OSPEEDER_OSPEEDR12_1 | // SPI2 NSS 50MH
GPIO_OSPEEDER_OSPEEDR13_1 | // SPI2 SCK, 50MHz
GPIO_OSPEEDER_OSPEEDR14_1 | // SPI2 MISO 50MH
GPIO_OSPEEDER_OSPEEDR15_1 | // SPI2 MOSI 50MH
GPIO_OSPEEDER_OSPEEDR4_1 | // PWM_OUT1, TIM3_CH1, 50MHz
GPIO_OSPEEDER_OSPEEDR5_1 | // PWM_OUT2, TIM3_CH2, 50MHz
GPIO_OSPEEDER_OSPEEDR0_1 | // PWM_OUT3, TIM3_CH3, 50MHz
GPIO_OSPEEDER_OSPEEDR1_1 | // PWM_OUT4, TIM3_CH4, 50MHz
GPIO_OSPEEDER_OSPEEDR6_1 | // PWM_IN5, TIM4_CH1, 50MHz
GPIO_OSPEEDER_OSPEEDR7_1 // PWM_IN6, TIM4_CH2, 50MHz
);
// Push/Pull
GPIOB->PUPDR = 0; // clear pupdr register
GPIOB->PUPDR |=
(
GPIO_PUPDR_PUPDR8_0 | // Pull-Up, I2C1, SCL
GPIO_PUPDR_PUPDR9_0 | // Pull-Up, I2C1, SDA
GPIO_PUPDR_PUPDR4_0 | // Pull-Up, PWM_OUT1, TIM3_CH1
GPIO_PUPDR_PUPDR5_0 | // Pull-Up, PWM_OUT2, TIM3_CH2
GPIO_PUPDR_PUPDR0_0 | // Pull-Up, PWM_OUT3, TIM3_CH3
GPIO_PUPDR_PUPDR1_0 | // Pull-Up, PWM_OUT4, TIM3_CH4
GPIO_PUPDR_PUPDR6_0 | // Pull-Up, PWM_IN5, TIM4_CH1
GPIO_PUPDR_PUPDR7_0 // Pull-Up, PWM_IN6, TIM4_CH2
);
// Alternate Function pins
GPIOB->AFR[1] = 0; // clear AFR_H register
GPIOB->AFR[1] |=
(
(4 << ((8 - 8) << 2)) | // I2C1 SCL, AF4
(4 << ((9 - 8) << 2)) | // I2C1 SDA, AF4
(5 << ((12 - 8) << 2)) | // SPI2 NSS, AF5
(5 << ((13 - 8) << 2)) | // SPI2 SCK, AF5
(5 << ((14 - 8) << 2)) | // SPI2 MISO, AF5
(5 << ((15 - 8) << 2)) // SPI2 MOSI, AF5
);
GPIOB->AFR[0] = 0; // clear AFR_L register
GPIOB->AFR[0] |=
(
(2 << ((4 - 0) << 2)) | // PWM_OUT1, TIM3_CH1, AF2
(2 << ((5 - 0) << 2)) | // PWM_OUT2, TIM3_CH2, AF2
(2 << ((0 - 0) << 2)) | // PWM_OUT3, TIM3_CH3, AF2
(2 << ((1 - 0) << 2)) | // PWM_OUT4, TIM3_CH4, AF2
(2 << ((6 - 0) << 2)) | // TIM4_CH1, AF2
(2 << ((7 - 0) << 2)) // TIM4_CH2, AF2
);
//=============================================================================
// GPIOD configuration
//=============================================================================
// enable GPIOD clock
((RCC_TypeDef *)(RCC_BASE))->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
// Alternate Function
((GPIO_TypeDef *)(GPIOD_BASE))->MODER |=
(GPIO_MODER_MODER9_1 | // Alternate Function, USART3_RX
GPIO_MODER_MODER8_1 ); // Alternate Function, USART3_TX
// Output type
((GPIO_TypeDef *)(GPIOD_BASE))->OTYPER |= 0;// push-pull if 0
//(GPIO_OTYPER_OT_8 | // Open-Drain, I2C1, SCL
//GPIO_OTYPER_OT_9); // OPen-Drain, I2C1, SDA
// Speed type
((GPIO_TypeDef *)(GPIOD))->OSPEEDR |=
(GPIO_OSPEEDER_OSPEEDR8_1 | // USART3 TX 50 MHz
GPIO_OSPEEDER_OSPEEDR9_1); // USART3 RX 50 MHz
// Push/Pull for USART3
((GPIO_TypeDef *)(GPIOD_BASE))->PUPDR |=
(
GPIO_PUPDR_PUPDR8_0 | // Pull-Up, USART3 TX
GPIO_PUPDR_PUPDR9_0 // Pull-Up, USART3 RX
);
((GPIO_TypeDef *)(GPIOD_BASE))->AFR[1] |= (
(7 << ((8 - 8) << 2)) | // USART3 TX, AF7
(7 << ((9 - 8) << 2)) ); // USART3 RX, AF7
return 0;
}
CODE
uint32_t config_pwm_io(void)
{
//=============================================================================
// set up PWM Output on TIM3 channels
//=============================================================================
// enable TIM3 clock
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
// set the prescaler for 2MHz clock count
// fpclk = 42MHz, TIM3_clk = 2*fpclk = 84MHz
// CK_CNT = TIM3_clk / (PSC + 1)
// PSC = TIM3_clk / CK_CNT - 1
TIM3->PSC = 41; // 84MHz/2MHz - 1 = 41
// set the Auto Reload Register
// Needed period = (1/CK_CNT) * ARR
TIM3->ARR = 30000; // PWM_period = 15ms / (1/2MHz)
// clear CR2
TIM3->CR2 = 0;
TIM3->CCR1 = 3000; // 10% duty cycle, for CH1
TIM3->CCR2 = 3000; // 10% duty cycle, for CH2
TIM3->CCR3 = 3000; // 10% duty cycle, for CH3
TIM3->CCR4 = 3000; // 10% duty cycle, for CH4
// set output compare mode 1.
TIM3->CCMR1 |=
TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | // CH1
TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // CH2
TIM3->CCMR2 |=
TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | // CH3
TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1; // CH4
// enable Output compare
TIM3->CCER |= TIM_CCER_CC1E; //CH1
TIM3->CCER |= TIM_CCER_CC2E; //CH2
TIM3->CCER |= TIM_CCER_CC3E; //CH3
TIM3->CCER |= TIM_CCER_CC4E; //CH4
// enable TIM3
TIM3->CR1 |= TIM_CR1_CEN;
return 0;
}
CODE
uint32_t config_spi_all(void)
{
//=============================================================================
// SPI1 Related configuration
//=============================================================================
// enable SPI2 clock
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
// configure SPI2
SPI2 -> CR1 |= (SPI_CR1_SPE | SPI_CR1_CPOL |
SPI_CR1_CPHA | SPI_CR1_MSTR |
SPI_CR1_BR_1 | SPI_CR1_SSM | SPI_CR1_SSI);
//SPI2->CR2 |= (SPI_CR2_SSOE);
return 0;
}
CODE
uint32_t config_i2c_all(void)
{
//=============================================================================
// I2C1 Related configuration
//=============================================================================
// enable I2C1 clock
((RCC_TypeDef *) (RCC_BASE))->APB1ENR |= RCC_APB1ENR_I2C1EN;
// 1) configure I2C_CR2
I2C1 -> CR2 |= (I2C_CR2_FREQ_5 | I2C_CR2_FREQ_3 |
I2C_CR2_FREQ_1); // APB1 clock is 42MHz
// 2) Configure Clock Control Register, I2C_CCR
// For 100KHz, APB1clk=42MHz, T_high = T_low = (1/42MHz)*210 = 5us
// For Fast mode, T_high = 9*(1/42MHz)*CCR = 0.8us,
// T_low = 16*(1/42MHz)*CCR = 1.5us,
// CCR = 4, F/S = 1, DUTY = 1, I2C_CCR = 0xc004
I2C1 -> CCR = 0xc004; // 0xd2, d210 for 100KHz,
// 3) Configure I2C_TRISE, Rise Time register
I2C1 -> TRISE = 0x2b; // 0x2b, d42 (42 + 1)
// 4) enable I2C1 peripheral
I2C1 -> CR1 |= (I2C_CR1_PE);
return 0;
}
CODE
uint32_t config_usart3(void)
{
//=============================================================================
// USART3 Related configuration
//=============================================================================
// enable I2C1 clock
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
// 1) Setting UE, amd M bits
USART3-> CR1 |= 0x2000; // UE = 1
// 2) Programming number of stop bits if needed
// 3) Enable DMA if needed
// 4) set the Baud Rate
// BAUD = fck / ( 8 * (2 - OVER8) * USARTDIV )
// fck = 42MHz,
// OVER8 = 0
// Choose BAUD = 115200
// then: USARTDIV = fck / ( 8 * (2 -OVER8) * BAUD = 22.75
// BRR = (22 << 4) | ( 0.75 * 16) = 364,
// or: BRR = fck / BAUD = 42MHz / 115200 = 364
USART3->BRR = 364;
// enable transmitter
USART3->CR1 |= USART_CR1_TE;
// enable receiver
USART3->CR1 |= USART_CR1_RE;
return 0;
}
Короче вывод такой что если сразу после включения всей периферии в приведенном коде посылать байт по SPI то буден задержкав 1500нс, но байт по любому отсылается.
p.s. задача поднятия пина SS после передачи байта тоже решена программным путем. Никакие эксперименты с битами SSOE SSI SSM ни следование мануалу не привело к тому чтобыstm32 сам поднимал пин SS вверх после успешной отправки байта. (как я уже написал...после отправки читаю прием а потом уже BSY и вручную поднимаю его сам)
(почти тоже самое что в теме приведенной Viko)
а так вобщем работает все.