Understanding code for LED light for stm32f334R8? - c

#include "stm32f30x_conf.h"
uint16_t read_pos(void);
void PC_Conf(void);
uint8_t get_bit(uint8_t, uint8_t);
// PROCESSORTACT = 64 MHz
// AHB Prescaler = 1
// APB1 Prescaler = 2
// APB2 Prescaler = 1
long pin = 1;
long dir = 1;
char recvd;
int main(void){
/*
*/
//Definitions
GPIO_InitTypeDef GPIO_Initstructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_NVICInitStructure;
//ENABLE CLOCK
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//GPIO
GPIO_Initstructure.GPIO_Mode=GPIO_Mode_OUT;
GPIO_Initstructure.GPIO_OType=GPIO_OType_PP;
GPIO_Initstructure.GPIO_Pin=GPIO_Pin_All;
GPIO_Initstructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_Initstructure);
//TIMER
TIM_TimeBaseInitStructure.TIM_Prescaler = (64000-1); //TIM2 cycle to 1kHz
TIM_TimeBaseInitStructure.TIM_Period = 500; //Every 500ms
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
//NVIC
NVIC_NVICInitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_NVICInitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_NVICInitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_NVICInitStructure.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_NVICInitStructure);
//Enable everything
TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
/* Infinite loop */
while (1)
{
}
}
void TIM2_IRQHandler(void)
{
GPIOB->ODR &= 0;
GPIOB->ODR ^=1<<pin;
//Pin to new value
if(dir == 1)
{
if(pin == 5)
pin=11;
else if(pin == 15)
{ pin-=1;
dir = 0;
}
else
pin+=1;
}
else
{
if(pin == 11)
pin = 5;
else if(pin == 1)
{
pin+=1;
dir = 1;
}
else
pin-=1;
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
I have trouble understanding this code. First part is okay, but I don't understand the last function.
Can someone explain me simply what is going on in the last part of this code in TIM2_IRQHandler(void)?
I am new in this, any help would be welcome.

In many interrupts you need to clear the interrupt pending flag. If you don't when you exit from the handler, the interrupt will be called again. Every interrupt is described in the Reference manual of your micro. For example SPI interrupt pending flag is cleared by writing or reading from the DR register. Another one requires that bit to be cleared by the programmer.
The rule of thumb: clear the flag as soon as you enter the interrupt.
If the interrupt can be triggered by more than one event, the programmer should check which one was the source of the exception.

Related

smt32 interrupts. why my diode is not blinking?

I have smt32l1xx board and this code below is not working. Debugger shows pinA5 is set, but diode connected to this pin is still not lightening. I dont know why. Even i add delay after setting bit it is not working. diode is connected to PA5 and GND on board.
#include <stm32l1xx.h>
#define ENABLE 1
#define DISABLE 0
void TIM2_IRQHandler() //interrupt
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_5))
GPIO_ResetBits(GPIOA, GPIO_Pin_5); //LED OFF
else
GPIO_SetBits(GPIOA, GPIO_Pin_5); //LED ON <- im here and still nothing
}
}
int main(void)
{
/* gpio init struct */
GPIO_InitTypeDef gpio;
TIM_TimeBaseInitTypeDef tim;
NVIC_InitTypeDef nvic;
/* reset rcc */
RCC_DeInit();
RCC_APB2PeriphClockCmd(RCC_AHBENR_GPIOAEN, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
GPIO_StructInit(&gpio);
/* use pin 0 */
gpio.GPIO_Pin = GPIO_Pin_5;
/* mode: output */
gpio.GPIO_Mode = GPIO_Mode_OUT;
/* apply configuration */
GPIO_Init(GPIOA, &gpio);
TIM_TimeBaseStructInit(&tim); //timer
tim.TIM_CounterMode = TIM_CounterMode_Up;
tim.TIM_Prescaler = 64000 - 1;
tim.TIM_Period = 1000 - 1;
TIM_TimeBaseInit(TIM2, &tim);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
nvic.NVIC_IRQChannel = TIM2_IRQn; //interrupt
nvic.NVIC_IRQChannelPreemptionPriority = 0;
nvic.NVIC_IRQChannelSubPriority = 0;
nvic.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic);
while (1)
{
}
/* never reached */
return 0;
}
To make sure that your hardware is properly initialized, you should use STM32CubeMX.
It seems that the GPIOA clock is on the AHB bus, however you call RCC_APB2PeriphClockCmd which is for APB2. So try to use the equivalent for AHB something like RCC_AHBPeriphClockCmd

Minimizing Interrupt Time, Maximizing Compiler Processing Speed, Reaching STM32F3 Operator Speed

I am currently working on STM32F3 Discovery Board. I wrote a basic program in C to see if it works at 72 MHz which is about 14 ns in time. Hopefully it worked at this frequency, but when I want to toggle just one random pin on the device, turning it ON or OFF takes 660 ns in an infinite while loop. Then I checked with an oscilloscope, how much each command takes. Values might not be exact, Here is what I found;
a while loop(only for checking) = 120 ns, a "for" loop(only for checking) = 160 ns
One turn of a while loop = 280 ns, one turn of a for loop = 320 ns, which means each turn takes 160 ns.
asm("NOP") = 14 ns(which must be equal to operator frequency(72 MHz, as expected), an empty function call = 225 ns
I don't think these values are same for other compilers, or other computers, but I am not even close to 72 MHz. Minimum interrupt I got was 2 microsecond. Is there any way to minimize these values? Is there anyway to increase the gcc compiler speed?
#include "stm32f30x.h"
#include <common.h>
void InitializeTimer(void) ;
void EnableTimerInterrupt(void);
void TIM2_IRQHandler(void);
GPIO_InitTypeDef configuration;
void dly(int dly_nmbr);
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//NVIC_InitTypeDef NVIC_InitStructure;
RCC_ClocksTypeDef RCC_ClockFreq;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* Configure PA10 in output pushpull mode */
/*****I called init_pin function from common.c because it was easier
but I guess it takes some time too*********/
init_pin(GPIOA,GPIO_Pin_10,GPIO_Mode_OUT,GPIO_Speed_50MHz,GPIO_OType_PP,GPIO_PuPd_NOPULL);
/****I tried usual way to configure the pins too****/
//configuration.GPIO_Pin = GPIO_Pin_10;
//configuration.GPIO_Mode = GPIO_Mode_OUT;
//configuration.GPIO_OType = GPIO_OType_PP;
//configuration.GPIO_Speed = GPIO_Speed_50MHz;
//configuration.GPIO_PuPd = GPIO_PuPd_NOPULL;
//GPIO_Init(GPIOA, &configuration);
//InitializeTimer();
/*** This function fills the RCC_ClockFreq structure with the current
frequencies of different on chip clocks (for debug purpose) **************/
RCC_GetClocksFreq(&RCC_ClockFreq);
/* Enable Clock Security System(CSS): this will generate an NMI exception
when HSE clock fails *****************************************************/
RCC_ClockSecuritySystemCmd(ENABLE);
/* Enable and configure RCC global IRQ channel, will be used to manage HSE ready
and PLL ready interrupts.
These interrupts are enabled in stm32f0xx_it.c file **********************/
/* I disabled the interrupts for the purpose of maximizing the program speed*/
// NVIC_InitStructure.NVIC_IRQChannel = RCC_IRQn;
// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// NVIC_Init(&NVIC_InitStructure);
/************* Output HSE clock on MCO1 pin(PA8) ************/
/****************** Enable the GPIOA Clock ******************/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* MCO pin configuration: PA8 */
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_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Output System Clock on MCO pin */
RCC_MCOConfig(RCC_MCOSource_SYSCLK);
/************** This is the toggling part. I tried each command here ***************/
while(1)
{
// volatile int i = 0;
// dly(0);
/*I called an empty function called dly before and after the toggle
to see function call time*/
GPIO_Toggle(GPIOA,GPIO_Pin_10);
// dly(0);
// while(i<=0)
// {
// i++;
// }
// for(i=0;i<=0;i++);
}
}
/*Empty Function*/
void dly(int dly_nmbr)
{
}
/************** Interrupt Functions **************/
// void TIM2_IRQHandler()
// {
// if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
// {
// TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// }
// }
// void InitializeTimer()
// {
// RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
//
// TIM_TimeBaseInitTypeDef timerInitStructure;
// timerInitStructure.TIM_Prescaler = 0;
// timerInitStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2;
// timerInitStructure.TIM_Period = 2;
// timerInitStructure.TIM_ClockDivision = 0x0000;
// timerInitStructure.TIM_RepetitionCounter = 100;
// TIM_TimeBaseInit(TIM2, &timerInitStructure);
//
// TIM_Cmd(TIM2, ENABLE);
// TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
// EnableTimerInterrupt();
// }
// void EnableTimerInterrupt()
// {
// NVIC_InitTypeDef nvicStructure;
// nvicStructure.NVIC_IRQChannel = TIM2_IRQn;
// nvicStructure.NVIC_IRQChannelCmd = ENABLE;
// // TIM2->ARR = 1;
// // TIM2->PSC = 1;
// NVIC_Init(&nvicStructure);
//
// }
/****************** EOF ********************/

Interrupt handling with 8051 C using Keil uVision

I've been doing a project about home automation in which I have to use timer interrupts with 8051 microcontroller. I've constructed the following code, however I couldn't manage to get interrupt working. It seems that the program does not go into timer ISR at all. I use a buton to simulate PIR input, therefore lampControl is triggered, no worries there. I use as a library.
Any ideas or help will be greately appreciated:
void timer0_isr(void) interrupt 1 //Timer 0 Interrupt
{
TH0 = 0xDC;
TL0 = 0x00;
TR0 = 1;
if (++lamp_interrupt_count == 6000)
{
sendCharacterShowAsHex(0x8F);
lamp_interrupt_count = 0;
TR0 = 0;
}
}
void main()
{
unsigned char chr;
IE = 0x93;
while(1)
{
serialInput();
if (getPIRInput() == 0x00)
{
lampControl(0x80);
}
....
....
....
}
void lampControl(unsigned char serial_data_in)
{
if (serial_data_in == 0x80)
{
sendCharacterShowAsHex(0x80);
//enable interrupts
IE = 0x93;
device_interrupt = 2; //Lamp
TMOD = 0x21; // Timer0 Gate=0, Mode 1, 16bit timer
TH0 = 0xDC;
TL0 = 0x00;
TR0 = 1;
}
else if(serial_data_in == 0x8F)
{
sendCharacterShowAsHex(0x8F);
}
}
You need to configure the timer and interrupts before you can use them.
In main() you need at least the following configuration bits set in order to be able to turn
the timer on with "TR0 = 1;" :
Set those bits first thing in main() and this should do the trick:
TMOD = 0x01; // 16-bit no auto reload
TH0 = 0xDC; //Set high and low bits to count 0xFFFF - 0xDC00 = 0x23FF counts
TL0 = 0x00;
ET0 = 1; // Enable timer0 interrupt
EA = 1; // Enable all interrupts
//TR0 = 1; //Enable Timer0 immediately
The rest of your code should run fine.
Note: you could change your interrupt function definition to:
"void timer0_isr(void) interrupt 1 using 1" to force it to use register bank 1 for the interrupt function operation.

Why isn't Timer2 Interrupt firing up?

I am trying to enable timer2 interrupt to use it for PWM purposes. In this case, I just turn on an LED and when timer 2 interrupt occurs I turn it off but the timer interrupt never occurs. Everything looks good to me so I don't understand why Timer2 is not firing up. I am using PIC18F87J11, here is the datasheet.
/*
File: main.c
Date: 2011-SEP-4
Target: PIC18F87J11
IDE: MPLAB 8.76
Compiler: C18 3.40
*/
#include <p18cxxx.h>
#include<usart.h>
#include <pwm.h>
#include <delays.h>
#pragma config FOSC = INTOSC, WDTEN = OFF, XINST = OFF
#pragma interrupt HighISR
void main(void) {
unsigned int i;
/* set FOSC clock to 8MHZ */
OSCCON = 0b01110000;
/* turn off 4x PLL */
OSCTUNE = 0x00;
/* make all ADC inputs digital I/O */
ANCON0 = 0xFF;
ANCON1 = 0xFF;
PR2 = 124; // Period
TMR2=0;
// 1/16 prescalar
T2CONbits.T2CKPS0 = 1;
T2CONbits.T2CKPS1 = 0;
PIE1bits.TMR2IE == 1; // Enables the TMR2 to PR2 match interrupt
// Enable Timer 2
T2CONbits.TMR2ON = 1;
INTCONbits.PEIE = 1; // Enable Perpherial Interrupt
INTCONbits.GIE = 1; // Enable Global Interrupt
TRISDbits.TRISD6 = 0; // Turn on LED
LATDbits.LATD6 = 1;
while (1);
}
#pragma code highVector=0x08
void HighVector(void) {
_asm goto HighISR _endasm
}
#pragma code /* return to default code section */
// Timer Interrupt
void HighISR(void) {
if (PIR1bits.TMR2IF == 1) {
LATDbits.LATD6 = 0; // Turn off LED to indicate it came thru
PIR1bits.TMR2IF = 0;
}
}
Thanks!
Found my mistake
PIE1bits.TMR2IE == 1;
It should be PIE1bits.TMR2IE = 1;

How to use the timer 6 or timer 7 in stm32f100RB?

I'm learning to use the MCU STM32f100RB, which is based on the arm cortex m3.
To test the timer 6, I wrote a bit of codes as following.It's supposed to make the led blink. But it does not work.Anyone can give me a hand telling me what's problem? Is the timer initialized correctly?
Thx
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
void delay_millisec(register unsigned short n);
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB1Periph_TIM6, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //enable the pin 8 and pin 9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
while(1)
{
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_RESET);
delay_millisec(1000);
GPIO_WriteBit(GPIOC, GPIO_Pin_8, Bit_SET);
delay_millisec(1000);
}
return 0;
}
void delay_millisec(register unsigned short n)
{
if (n > 1) n--;
TIM6->PSC = 23999; // Set prescaler to 24,000 (PSC + 1)
TIM6->ARR = n; // n = 1 gives 2msec delay rest are ok
TIM6->CNT = 0;
TIM6->EGR = TIM_EGR_UG; // copy values into actual registers!
// Enable timer in one pulse mode
TIM6->CR1 |= (TIM_CR1_OPM | TIM_CR1_CEN);
while (TIM6->CR1 & TIM_CR1_CEN); // wait for it to switch off
}
You are not enabling the timer peripheral's clock, from what I can see.
Note that your code does this:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB1Periph_TIM6, ENABLE);
^ ^ ^
| | |
APB2 APB2 APB1?!!
but this can't be right; you're using constants for peripheral clock 1 and 2 in the same call, to clock 2. That won't fly.
You need to have:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
You really should be using the Standard Peripheral Library for the timer initialization too, no point in poking registers directly.

Resources