cancel
Showing results for 
Search instead for 
Did you mean: 

No response from TIM2 and SPI2

JKing.8
Associate III

Hello all,

I have been working on an STM32F0, with an external ADC. I used PA5 as an SCK with SPI1_SCK, PA6 as an SDO with SPI1_MISO, and PA8 as a CNV with TIM1_CH1. With one external ADC, it all worked as intended. I used an oscilloscope to confirm that it is giving accurate waves. My next task is to implement a second external ADC. I am trying to implement it by itself before combining them, but I am running into issues. This time I plan to use PB13 as an SCK with SPI2_SCK, PB14 as an SDO with SPI2_MISO, and PB11 as a CNV with TIM2_CH4. With these, I cannot get any wave readings. I use the libopencm3 library.

This is my original working code:

#ifndef STM32F0

#define STM32F0

#endif

#include "spi_eadc.h"

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

static void clock_setup(void)

{

/* Enable clock at 48mhz */

rcc_clock_setup_in_hsi_out_48mhz();

/* Enables clocks for all needed peripherals */

rcc_periph_clock_enable(RCC_GPIOA | RCC_GPIOB | RCC_GPIOC);

rcc_periph_clock_enable(RCC_SPI1);

rcc_periph_clock_enable(RCC_USART1);

rcc_periph_clock_enable(RCC_TIM1);

}

static void gpio_setup(void)

{

/** LED GPIO SETUP **/

gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8 | GPIO9);

/** SPI GPIO SETUP **/

/* Configure CNV GPIO as PA8 (TIM1_CH1) */

gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO8);

gpio_set_af(GPIOA, GPIO_AF2, GPIO8);

gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO8);

/* Configure SCK GPIO as PA5 */

gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5);

gpio_set_af(GPIOA, GPIO_AF0, GPIO5);

gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO5);

/* Configure MISO GPIO as PA6 */

gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6);

gpio_set_af(GPIOA, GPIO_AF0, GPIO6);

gpio_set_output_options(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO6);

/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */

gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);

gpio_set_af(GPIOA, GPIO_AF1, GPIO9);

}

static void spi_setup(void)

{

spi_reset(SPI1);

spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_4, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,

SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_MSBFIRST);

spi_set_data_size(SPI1, 16);

spi_enable_software_slave_management(SPI1);

spi_set_nss_high(SPI1);

spi_enable(SPI1);

}

static void uart_setup(void)

{

nvic_enable_irq(NVIC_USART1_IRQ);

usart_set_baudrate(USART1, 115200);

usart_set_databits(USART1, 8);

usart_set_stopbits(USART1, 1);

usart_set_mode(USART1, USART_MODE_TX);

usart_set_parity(USART1, USART_PARITY_NONE);

usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);

usart_set_mode(USART1, USART_MODE_TX_RX);

usart_enable(USART1);

}

static void timer_setup(void)

{

timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_TOGGLE);

timer_enable_oc_output(TIM1, TIM_OC1);

timer_enable_break_main_output(TIM1);

timer_set_oc_value(TIM1, TIM_OC1, 24000);

timer_set_prescaler(TIM1, 480 - 1);

timer_set_period(TIM1, 48000 - 1);

timer_generate_event(TIM1, TIM_EGR_CC1G | TIM_EGR_TG);

nvic_enable_irq(NVIC_TIM1_CC_IRQ);

timer_enable_irq(TIM1, TIM_DIER_CC1IE);

TIM_CR1(TIM1) |= TIM_CR1_CEN;

}

void tim1_cc_isr(void)

{

gpio_toggle(GPIOC, GPIO9);

SPI1_DR = 0x1;

while (!(SPI1_SR & SPI_SR_RXNE))

; /* wait for SPI transfer complete */

// I do calculations here but remove them for simplicity

TIM1_CCMR1 = TIM_CCMR1_OC1M_FORCE_HIGH; // (assumes all other bits are zero)

TIM1_CCMR1 = TIM_CCMR1_OC1M_TOGGLE;

TIM1_SR = ~TIM_SR_CC1IF; // clear interrupt

}

int main(void)

{

clock_setup();

gpio_setup();

spi_setup();

uart_setup();

timer_setup();

while (1)

;

}

This is the code for the second ADC, that is not getting a response:

#ifndef STM32F0

#define STM32F0

#endif

#include "spi_eadc.h"

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

static void clock_setup(void)

{

/* Enable clock at 48mhz */

rcc_clock_setup_in_hsi_out_48mhz();

/* Enables clocks for all needed peripherals */

rcc_periph_clock_enable(RCC_GPIOA | RCC_GPIOB | RCC_GPIOC);

rcc_periph_clock_enable(RCC_SPI2);

rcc_periph_clock_enable(RCC_USART1);

rcc_periph_clock_enable(RCC_TIM2);

}

static void gpio_setup(void)

{

/** LED GPIO SETUP **/

gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8 | GPIO9);

/** SPI GPIO SETUP **/

/* Configure CNV GPIO as PB11 (TIM2_CH4) */

gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11);

gpio_set_af(GPIOB, GPIO_AF2, GPIO11);

gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO11);

/* Configure SCK GPIO as PB13 */

gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO13);

gpio_set_af(GPIOB, GPIO_AF0, GPIO13);

gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO13);

/* Configure MISO GPIO as PB14 */

gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO14);

gpio_set_af(GPIOB, GPIO_AF0, GPIO14);

gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO14);

/* Setup GPIO pin GPIO_USART1_TX/GPIO9 on GPIO port A for transmit. */

gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9);

gpio_set_af(GPIOA, GPIO_AF1, GPIO9);

}

static void spi_setup(void)

{

spi_reset(SPI2);

spi_init_master(SPI2, SPI_CR1_BAUDRATE_FPCLK_DIV_4, SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,

SPI_CR1_CPHA_CLK_TRANSITION_1, SPI_CR1_MSBFIRST);

spi_set_data_size(SPI2, 16);

spi_enable_software_slave_management(SPI2);

spi_set_nss_high(SPI2);

spi_enable(SPI2);

}

static void uart_setup(void)

{

nvic_enable_irq(NVIC_USART1_IRQ);

usart_set_baudrate(USART1, 115200);

usart_set_databits(USART1, 8);

usart_set_stopbits(USART1, 1);

usart_set_mode(USART1, USART_MODE_TX);

usart_set_parity(USART1, USART_PARITY_NONE);

usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE);

usart_set_mode(USART1, USART_MODE_TX_RX);

usart_enable(USART1);

}

static void timer_setup(void)

{

timer_set_oc_mode(TIM2, TIM_OC4, TIM_OCM_TOGGLE);

timer_enable_oc_output(TIM2, TIM_OC4);

timer_enable_break_main_output(TIM2);

timer_set_oc_value(TIM2, TIM_OC4, 24000);

timer_set_prescaler(TIM2, 480 - 1);

timer_set_period(TIM2, 48000 - 1);

timer_generate_event(TIM2, TIM_EGR_CC4G | TIM_EGR_TG);

nvic_enable_irq(NVIC_TIM2_IRQ);

timer_enable_irq(TIM2, TIM_DIER_CC4IE);

TIM_CR1(TIM2) |= TIM_CR1_CEN;

}

void tim2_isr(void)

{

gpio_toggle(GPIOC, GPIO9);

SPI2_DR = 0x1;

while (!(SPI2_SR & SPI_SR_RXNE))

; /* wait for SPI transfer complete */

// I do calculations here but remove them for simplicity

TIM2_CCMR2 = TIM_CCMR2_OC4M_FORCE_HIGH; // (assumes all other bits are zero)

TIM2_CCMR2 = TIM_CCMR2_OC4M_TOGGLE;

TIM2_SR = ~TIM_SR_CC4IF; // clear interrupt

}

int main(void)

{

clock_setup();

gpio_setup();

spi_setup();

uart_setup();

timer_setup();

while (1)

;

}

Any tips, insight, or solutions would be greatly appreciated. Thanks in advance!

5 REPLIES 5

That you use some unusual environment, does not help here, problem may be hidden in that environment too. Generally, read out and check/compare-to-working/post content of SPI, TIM and relevant GPIO registers.​

> With these, I cannot get any wave readings

What is on the TIM and SPI pins?

​Divide and conquer - get timer working separately, then get the interrupt working, then get polled SPI working, then put things together.

JW​

JKing.8
Associate III

Thank you for the response JW,

As for the environment, I forgot to mention that in my initial post I am using the libopencm3 library. I have worked to simplify the setup and focus on the CNV. I removed the external ADC entirely and have the scope tied directly to PB11. This narrows my focus in the code to timer_setup() and tim2_isr(). I am confident that I am reaching the interrupt function as I get the LED flash. That would lead me to believe that the problem lies in timer_setup(), yet everything that I try shows no life on the scope.

Thank you for the response JW,

As for the environment, I forgot to mention that in my initial post I am using the libopencm3 library. I have worked to simplify the setup and focus on the CNV. I removed the external ADC entirely and have the scope tied directly to PB11. This narrows my focus in the code to timer_setup() and tim2_isr(). I am confident that I am reaching the interrupt function as I get the LED flash. That would lead me to believe that the problem lies in timer_setup(), yet everything that I try shows no life on the scope.

Which F0, exactly?

Set PB11 as GPIO Output, toggle and observe (i.e. isn't there a bad solder joint or similar hw problem).

I don't quite understand, what do you do in the ISR with the TIMx_CCMR register, and why do you do it. Start without that, just output plain PWM.

Read out (in debugger; or in code, transmitting through suitable means e.g. UART) content of TIMx and relevant GPIO registers.

JW

STM32F051R8T6

This is the datasheet: https://www.st.com/resource/en/datasheet/stm32f051r8.pdf

I will attempt to read out the content of TIM

Thanks again 🙂