STM32F401RE Nucleo board, cannot toggle user LED - c

I am trying to figure out how to toggle an LED on the Nucleo board and I just don't see the User LED toggle. Looking online it seems this is all you have to do. Has anyone else encountered this issue?
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
int main(void)
{
int counter = 0;
SystemInit();
GPIO_InitTypeDef temp;
temp.GPIO_Mode = GPIO_Mode_OUT;
temp.GPIO_OType = GPIO_OType_PP; // Push Pull
temp.GPIO_Pin = GPIO_Pin_5;
temp.GPIO_Speed = GPIO_Low_Speed;
temp.GPIO_PuPd = GPIO_PuPd_NOPULL;
RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_Init( GPIOA, &temp );
while( 1 )
{
if ( counter++ > 10000 )
{
GPIO_ToggleBits( GPIOA, GPIO_Pin_5 );
counter = 0;
}
}
}

You have to write
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
in order to enable GPIOA.

You cannot enable an AHB1 peripheral clock using the AHB2 clock control.
RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
^^^^ ^^^
"I just don't see the User LED toggle."
Even when you correctly enable the GPIO clock, you are toggling the output very fast (MHz order) and counter serves no obvious purpose. If a flashing LED was your aim, that will not do it; you'll just see an LED at somewhat less than full brightness - you need a delay between each toggle.

Clifford is absolutely right, the LED is "toggling" way to fast. The STM32F401RE supposedly is running at 168Mhz. Change your counter value from 10.000 to e.g. 50.000.000 to see the LED toggling at an appropriate rate.

Related

ATMEGA32U4 PWM issue

I am developing a simple program to run a buzzer in AVR on a Teensy 2.0 (ATMEGA32u4) and I am having great difficulty getting the PWM output to work. The PWM output is on PB6 and I can test it digitally so I am not worried about the hardware setup of the buzzer.
Eventually, the PWM will have a 50% duty cycle and the frequency will modulate, however, I am more concerned I am not getting any output at this point.
I have tried several different PWM setups and even have a second timer running to complete other tasks.
Here is my setup and program skeleton:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void button_handler(void);
void setup(void)
{
cli(); // Disable interrupts
// Set sysclk to 16 MHz
CLKPR = (1<<CLKPCE); // Prescaler change enable
CLKPR = 0x00; // Set prescaler to zero
DDRB = (1<<DDB6); // configure PORT B6 (buzzer) as output
// initliase timer1
// Fast PWM, TOP = OCR1A, Update OCR1B at TOP, TOV1 flag set on TOP
// Clear OC1B on compare match, set OC1B at TOP
// clkI/O/1 (No prescaling)
TCCR1A = (1<<COM1B1)|(1<<WGM11)|(1<<WGM10);
TCCR1B = (1<<WGM13)|(1<<WGM12)|(1<<CS10);
OCR1A = 1023; // Setup PWM Registers
OCR1B = 511; // 50% duty cycle
sei(); // Enable interrupts
}
int main(void)
{
setup(); // initialise device
for (;;)
{
// runs led blinking on PORTD, removed for simplicity
}
}
Really struggling to see where I am going wrong so any help would be much appreciated!
Finally managed a fix coming back after a few months, a simple clean fixed the issue.

I'm having trouble with buttons and IRQ handler in keil uVision(STM32F103RBT6)

Sorry for asking such a basic question, I am a beginner to ARM programming. I'm currently struggling with a lab exercise.
I was supposed to: Use the on-board button (PC13) to switch on and off the on-board LED (PA5). When the button is pressed, the LED is on. When the button is released, the LED is off.
The code below can be built, but it doesn't produce the result I wanted. In fact, nothing happens when I push the button.
#include "stm32f10x.h" // Device header
#include "stdbool.h" // For Boolean data type
#define BUTTON_RCC_GPIO RCC_APB2Periph_GPIOC
#define BUTTON_GPIO GPIOC
#define BUTTON_GPIO_PIN GPIO_Pin_13
int main(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(BUTTON_RCC_GPIO, ENABLE);
//GPIO set up for PA5 (on board LED)
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//Timer 2 set up
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 0;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0;
timerInitStructure.TIM_ClockDivision = 0;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2, &timerInitStructure);
TIM_Cmd(TIM2, ENABLE);
TIM_TIxExternalClockConfig(TIM2, TIM_TIxExternalCLK1Source_TI2, TIM_ICPolarity_Rising, 0);
//Enable update event for Timer2
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
NVIC_EnableIRQ(TIM2_IRQn);
while(1);
static char state = 0;
}
static char state = 0;
void TIM2_IRQHandler(void) {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
GPIO_ResetBits(GPIOA, GPIO_Pin_5);
state = 1;
} else {
GPIO_SetBits(GPIOA, GPIO_Pin_5);
state = 0;
}
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
Edit: I have modified my code heavily, I decided not to use timers at all.
#include "stm32f10x.h" // Device header
#include "stdbool.h"
//TI2 PA1 Tim2 Ch2
#define BUTTON_RCC_GPIO RCC_APB2Periph_GPIOA
#define BUTTON_GPIO GPIOA
#define BUTTON_GPIO_PIN GPIO_Pin_13
#define L3_RCC_GPIO RCC_APB2Periph_GPIOA
#define L3_GPIO GPIOA
#define L3_PIN GPIO_Pin_5
static bool wait = true;
int main(void) {
GPIO_InitTypeDef GPIO_InitStruct;
// GPIO clock for I/O
RCC_APB2PeriphClockCmd(BUTTON_RCC_GPIO, ENABLE);
RCC_APB2PeriphClockCmd(L3_RCC_GPIO, ENABLE);
// Configure I/O for L3
GPIO_InitStruct.GPIO_Pin = L3_PIN;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(L3_GPIO, &GPIO_InitStruct);
while(1) {
if(BUTTON_GPIO_PIN==true)
{
GPIO_SetBits(L3_GPIO, L3_PIN);
}else
{
GPIO_ResetBits(L3_GPIO, L3_PIN);
}
}
}
You didn't write this explicitly, but I assume your lab exercise is using the
NUCLEO-F103RB, where you find the
STM32F103RBTx controller equipped with a user push button at PC13 and a user LED at PA5 - I hardly think another brand creats a PCB with the very same properties... :-)
As KIIV already pointed out in the comment, the reason you aren't seeing the LED change when the button is pressed, is that the controller input pin the button is connected to (PC13) isn't even checked.
Instead, the output state (PA5) for the LED is toggled in an ISR triggered by the interrupt of a timer (TIM2).
The timer configuration (which may be incomplete, I can't tell from reading your code snippet alone) is triggered by rising edges at an external clock source at event TI2, which is tied to channel TIM2_CH2 (available for pins PA1 and PB3, for which I don't see any init code, however).
Some lines are redundant (the invocations to RCC_APB2PeriphClockCmd() and the definitions of state, which will shadow each other...).
I have the impression that this code is not yet near to completion, but it may be helpful for you to first study what you want to achieve with the program, and what you are going to achieve by which section of your code. Then, finding the right solution for each detail is more a matter of studiousness and looking up the right datasheets (see links above).

Measure duration of the signal

I have old programmable timer/ counter (PD71054 - count rate is set to 3Mhz), and now I would like to program a timer in STM32 (STM32F103RET6) to replace PD71054. I need to measure the duration of the square wave (PA0 pin), I found information about on of timer function - capture, but I do not know how to use it. And unfortunately I did't find good examples how to use it (SPL library). I tried to checking the edges of the signal. If a rising edge is detected, TIM5 will be started, if a falling edge is detected TIM5 will be stopped and the counted value will be saved. But I don’t know if this solution is good and how to set an interrupt for both edges of signal and have two different functions to handle for each of the slopes. signal example
int main(void)
{
TIM5_Config();
NVIC_Config ();
//IWDG_ReloadCounter();
RCC_Config();
RCC_APB1PeriphClockCmd(RCC_APB1PeriphClockCmd, ENABLE);
while(1){
}
}
RCC_Config()
{
BKP_DeInit();
// Reset RCC
RCC_DeInit ();
// HSI ON
RCC_HSICmd(ENABLE);
// Wait for HSI
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET){};
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div1);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
void IWDG_Config (void) {
// watchdoga IWGD
IWDG_WriteAccessCmd (IWDG_WriteAccess_Enable);
IWDG_SetPrescaler(IWDG_Prescaler_4); // 40kHz/4 = 10kHz
IWDG_SetReload(0x28A); // 65ms
IWDG_Enable(); // Start IWDG oraz LSI
}
void TIM5_IRQHandler(void)
{
TIM_Cmd(TIM5, ENABLE);
}
void TIM5_Config (void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
// Ustawienia podstawy czasu TIM5
TIM_TimeBaseStructure.TIM_Period= 0xFFFF; //65535
TIM_TimeBaseStructure.TIM_Prescaler = 23; // fclk = 72MHz/24 =okolo 3MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
// Zrodlo przerwania kanal 1
TIM_ITConfig(TIM5,TIM_IT_Update|TIM_IT_CC1,ENABLE);
TIM_Cmd(TIM5,ENABLE);
// TIM5_CH1, Rising edge, no filter
TIM_TIxExternalClockConfig(TIM5, TIM_TIxExternalCLK1Source_TI1, TIM_ICPolarity_Rising, 0x00);
TIM5_ICInitStructure.TIM_Channel=TIM_Channel_1;
TIM5_ICInitStructure.TIM_ICFilter=0;
TIM5_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
TIM5_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;
TIM5_ICInitStructure.TIM_ICSelection=TIM_ICSelection_DirectTI;
TIM_ICInit(TIM5, &TIM5_ICInitStructure);
}
void NVIC_Config (void)
{
NVIC_InitStructure.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
Sorry I dont have time to go into details about TIMER capture methods.I can offer easer way to do this, at least you can try. Set PA0 pin as EXTI on rising, falling edges. So IRQ will be generated on rising and falling edges. Also setup TIM1 or TIM2 , basically 32bit timer with needed precision, just start timer and its counter. So at rising edge, you can easily reset timer TIM1->CNT = 0 it will be your start time when SIGNAL rise. And then when falling edge appear fetch TIM->CNT . Thats all. Just don't forget to control extra flags (own created variables) wich will help to separate rising and falling edges. Also you could even count those pulses in those events, but its not reliable way.
This is only a snippet, abstract, it should help to understand an idea.
void enable_timer(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseInitTypeDef timerInitStructure;
timerInitStructure.TIM_Prescaler = 48;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0xFFFFFFFF; //32 bit timer , precision 1us
timerInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM1, &timerInitStructure);
TIM_Cmd(TIM1, ENABLE);
}
EXTI handler:
void EXTI0_1_IRQHandler (void)
{
if (EXTI_GetITStatus(EXTI_LINE0) != RESET){
EXTI_ClearITPendingBit(EXTI_LINE0); //clear the irq flag
if(rising_edge)
TIM1->CNT = 0;
if(falling_edge)
fetcher = TIM1->CNT; // here you get your pulse duration time in us
}
}

using a timer to count pulses on STM32F7

I have a question about using a timer to count pulses form a encoder (only one pin) I don't care about the direction.
I'm tryning to use Timer 3, but I'm not sure how to set it up in CubeMx.
picture and text
I start it with:
HAL_TIM_Base_Start( mpEncoderTim );
And read with:
count = mpEncoderTim->Instance->CNT;
Hope anyone of you, have done this before, so you can give me a hint
thanks in advance and best regards
panduro..
Thanks.
I found the error, the timer period was set to 0, so the timer would never count higher than 0 :-(
best regards..
I'v had some kind of similar issue with stepper motor. I'v made a stepper driver code for (DRV8825, A4899 chips) , code is iRQ based and with maths for motor acceleration, speed and etc. But I had to test if it is accurate, so I had to count steps.
For testing case I configured concrete pin as ETR(external trigger input) - it is input pin,my stepper output pin goes to that input,(as for sure goes to motor too). And each rising or lowering edge(depends on configuration) generates an irq, so at irq I can set counter of steps, in your case pulses.
I am not familiar with cubeMX stuff, most of the time I write directly to register or using old SPL(standard peripherial drivers). I will show how it works with SPL as it should be more readable for cubeMX users.
Anyway I just try to show basic idea how to do it.This concrete code works on STM32f030
Firstly configure input pin (read datasheet just few pins can work as external triggers and with concrete timers)
void digital_input_config (void){
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_2);
}
Now you need a timer configuration, each timer has different pins with ETR, so it depends on your STM32 MCU.You have to read data sheet accurately.
void enable_capture_TIM1(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_ETRClockMode2Config(TIM1,TIM_ExtTRGPSC_DIV_NONE,TIM_ExtTRGPolarity_NonInverted,0x00);
TIM_SelectInputTrigger(TIM1,TIM_TS_ETRF);
TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Trigger);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM1_BRK_UP_TRG_COM_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPriority = 0;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM1, ENABLE);
TIM_ITConfig(TIM1, TIM_IT_Trigger, ENABLE);
}
And at the IRQ you can do pulse counting.
void TIM1_BRK_UP_TRG_COM_IRQHandler(void){
if(TIM_GetITStatus(TIM1, TIM_IT_Trigger) != RESET) {
TIM_ClearITPendingBit(TIM1, TIM_IT_Trigger);
PulseCNT++;
}
}
I'v tested this code with pulse generator and it's really accurate, it can be used for pulse count, or frequency measuring.

8051 c programming, interrupt progblem

I'm programming an Intel 8051 (C8051F312) microcontroller. I just want to make a blinking led program by using interrupts. It compiles, but the led does not blink. Any ideas I would appreciate. Thank you!
My code is:
#include <C8051F310.H>
#include <stdio.h>
sbit led = P2^7; //LED connected to D7 of Port2
void timer(void) interrupt 1 //interrupt no. 1 for Timer 0
{
led=~led; // toggle LED on interrupt
TH0=0xFC; // initial values loaded to timer
TL0=0x66;
}
void main(void)
{
TMOD = 0x01; // mode1 of Timer0
TH0 = 0xFC; // initial values loaded to timer
TL0 = 0x66;
EA = 1; // global interrupt enable
ET0 = 1; // enables Timer 0 interrupt
TR0 = 1; // start timer
while(1); // do nothing
}
Like Mike Jablonski above said, you need to knock down your interrupt rate. Your original code is interrupting at 3.0625MHz / 12 / 922 ~= 277Hz. Part of your CKCON addition disables scaling to the timer (by setting T0M), so now you're interrupting at ~3.3kHz. You won't be able to see that.
Seeing anything presumes that you have a functional circuit. You're not configuring your output pin. You said your LED is on "now", but hopefully not meaning that it wasn't before. That wouldn't make a lot of sense since you didn't change anything about what the pin is doing.
Get rid of your CKCON line to keep the /12 scaling, and reload TH0 and TL0 with 0x00 on interrupt. That will get you interrupting at a little less than 4Hz, much more visible.
Make that pin push-pull:
P2MDOUT = 0x80;
XBR1 = 0x40;
Start reading the datasheet to your micro.

Resources