I'm trying to setup a timer that executes every 1ms, in order to estimate the execution time of a function. I attach the code at the end of the post. I'm pretty sure about the configuration of the timer, since I have done only very little modification to a working demo (iNemo_AHRS_continous demo, even the function for prvFindFactors is taken by such a demo).
Unfortunately, in this case my ISR is never executed, any idea of the reason? Thanks
void iNemoProfilerConfig(void)
{
unsigned short a;
unsigned short b;
unsigned long n;
/* This value is the frequency interrupts in Hz */
unsigned short frequency = 1000;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable timer clocks */
RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM4, ENABLE );
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
TIM_TimeBaseStructInit( &TIM_TimeBaseStructure );
/* Time base configuration for timer 2 - which generates the interrupts. */
n = SystemCoreClock/frequency;
prvFindFactors( n, &a, &b );
TIM_TimeBaseStructure.TIM_Period = b - 1;
TIM_TimeBaseStructure.TIM_Prescaler = a - 1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit( TIM4, &TIM_TimeBaseStructure );
TIM_ARRPreloadConfig( TIM4, ENABLE );
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 13;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
}
void Enable_Timer4(FunctionalState command) {
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
TIM_ITConfig( TIM4, TIM_IT_Update, command );
}
void TIM4_IRQHandler(void)
{
USART1_Printf("INTERRUPT = %i \r\n", counter);
if(TIM_GetITStatus(TIM4, TIM_IT_Update))
{
//xTim2Raised=SET;
counter++;
/* Clear the IRQ bit */
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
//main chunk
int main(void)
{
SystemInit();
/* At this stage the microcontroller clock setting is already configured,
this is done through SystemInit() function which is called from startup
file (startup_stm32f10x_xx.s) before to branch to application main.
To reconfigure the default setting of SystemInit() function, refer to
system_stm32f10x.c file
*/
USART1_Init();
for(uint32_t i=0; i<0xFFFFF;i++);
iNemoTimerConfig();
iNemoProfilerConfig();
iNEMO_AHRS_Start();
LSM_Start();
L3G_Start();
/* Wait some seconds in order to ensure the user opens the VCOM terminal */
for(uint32_t i=0;i<0x1FFFFFF;i++);
Enable_Timer(ENABLE);
Enable_Timer4(ENABLE);
while(1)
{
counter = 0;
iNEMO_AHRS_Attitude();
USART1_Printf("counter = %i \r\n", counter);
Related
I am facing a strange issue while programming PIC18f45k22. I am initiating system modules and then I write a blocking delay for 3 seconds to wait for a touch screen to start (because I need to send some information to this screen). But when I do this I discovered that when I initiate timer before writing the delay, I discover that the system freezes.
This is the code that I used
NOTE: all the functions work fine without any problem.
void main(void) {
Sys_Init();
__delay_ms(3000);
while(1){
//Code
}
System initiation code
void Sys_Init(void) {
Delay_XTAL();
OSCILLATOR_Init();
DIGITAL_PIN_STATE();
ANALOG_PIN_STATE();
ADC_INIT(); //change clock select pins when oscillator changes
Spi_Init();
DHT22_init();
Uart_Init(9600); //initiate UART (change baud values when oscillator value changed)
Timer1_Init(); //initiate timer one (change prescaler and counter value if oscillator value changes)
}
Timer code
void Timer1_Init(void){ //for interrupt program use this function
//Prescaler 1:1; TMR1 Preload = 61536; Actual Interrupt Time : 1 ms
T1CON = 0x01;
TMR1IF = 0;
TMR1H = 0xF0;
TMR1L = 0x60;
TMR1IE = 1;
INTCON = 0xC0;
}
Interrupt code
void __interrupt() ISR (void){
Timer1();
}
void Timer1(void){ //for interrupt program
if (TMR1IF){
cnt1++;
TMR1H = 0xF0; //overflow every 1 ms
TMR1L = 0x60;
TMR1IF = 0;
}
}
I'm using Timer to make the LED on/off for every 1 second (instead of using delay function). However, when I execute this code on IAR IDE, the LED on/off at about 2.5-3 second, not 1 second like I want. I wonder if there is any mistake in the code, or do I have to modify somewhere for the correct clock speed?
I'm using standard peripheral library, and the IDE I'm using is IAR.
#include "stm32f4xx.h"
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_BaseStruct;
void GPIO_Configuration(void);
void TIM_Configuration(void);
void Delay(__IO uint32_t nCount);
int main(void)
{
GPIO_Configuration();
TIM_Configuration();
while(1)
{
if(TIM_GetFlagStatus(TIM2,TIM_FLAG_Update) != RESET)
{
TIM_ClearFlag(TIM2,TIM_IT_Update);
GPIO_ToggleBits(GPIOD,GPIO_Pin_14);
}
}
}
void GPIO_Configuration(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* Configure PB0 PB1 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void TIM_Configuration(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_BaseStruct.TIM_Prescaler = 42000-1;
TIM_BaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseStruct.TIM_Period = 2000-1;
TIM_BaseStruct.TIM_ClockDivision = 0;
TIM_BaseStruct.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_BaseStruct);
TIM_Cmd(TIM2,ENABLE);
}
void Delay(__IO uint32_t nCount)
{
while(nCount--)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
I'm going to assume your clock frequency is 168Mhz. With your current prescaler and period values, this would put your timer at 2s.
(CLK_FREQ / (PRESCALER * PERIOD)) = (168MHZ / (42000 * 2000)) = 2 seconds
Try changing the period to 1000 to make it run at 1s. This, again, is assuming your clock frequency is 168Mhz. If your clock frequency is different, you can easily calculate the PRESCALER and PERIOD values (shown above) to get to 1s.
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 ********************/
Good afternoon,
I've configured my RX interrupt using the following simple function.
char c;
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt( void )
{
IFS0bits.U1RXIF = 0; // Clear RX Interrupt flag
c = U1RXREG;
}
The problem is, UART transmits fine, but the interrupt service routine is never entered when it gets sent a character. I can trace with a scope that the character is actually sent without issues, but the interrupt does not get triggered.
The device used for communication is TTL-232R-3v3. The device is running at 3.3V
The actual model number of the dspic33 is p33FJ128MC802
The programming environment is Mplab 8 and the compiled is XC16
Is there a missing setting to perhaps enable the interrupt? What could be missing?
Thanks,
Here is the UART initialization code.
U1MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
U1MODEbits.USIDL = 0; // Bit13 Continue in Idle
U1MODEbits.IREN = 0; // Bit12 No IR translation
U1MODEbits.RTSMD = 0; // Bit11 Simplex Mode
U1MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
U1MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here)
U1MODEbits.LPBACK = 0; // Bit6 No Loop Back
U1MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
U1MODEbits.URXINV = 0; // Bit4 IdleState = 1 (for dsPIC)
U1MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
U1MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
U1MODEbits.STSEL = 0; // Bit0 One Stop Bit
// U1BRG = (Fcy / (16 * BaudRate)) - 1
// U1BRG = (36850000 / (16 * 9600)) - 1
// U1BRG = 238.908854 //Round to 239
U1BRG = 239;
U1STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
U1STAbits.UTXINV = 0; //Bit14 N/A, IRDA config
U1STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
U1STAbits.UTXBRK = 0; //Bit11 Disabled
U1STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
U1STAbits.UTXBF = 0; //Bit9 *Read Only Bit*
U1STAbits.TRMT = 0; //Bit8 *Read Only bit*
U1STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
U1STAbits.ADDEN = 0; //Bit5 Address Detect Disabled
U1STAbits.RIDLE = 0; //Bit4 *Read Only Bit*
U1STAbits.PERR = 0; //Bit3 *Read Only Bit*
U1STAbits.FERR = 0; //Bit2 *Read Only Bit*
U1STAbits.OERR = 0; //Bit1 *Read Only Bit*
U1STAbits.URXDA = 0; //Bit0 *Read Only Bit*
RPINR18bits.U1RXR = 0b00010;//7; //RX is Pin RP2
RPOR1bits.RP3R = 0b00011; //TX is pin RP3
U1MODEbits.UARTEN = 1; // And turn the peripheral on
U1STAbits.UTXEN = 1;
Check if the pin has additional functionality. Typically this is AD (analog pin). Make sure you turn off all analog, via the ADP or ANSEL registers (type and number varies depending on exact chip) E.g. I have this routine (I use both 33F and 33E and a high and low pincount one of both, hence the ifdefs)
void analogoff(void){
#if defined(__dsPIC33F__)
ADPCFG =0xFFFF;
AD1PCFGH=0xFFFF;
AD1PCFGL=0xFFFF;
#endif
#if defined(__dsPIC33E__)
#if !defined(__dsPIC33EP256MU806__)
ANSELA=0;
#endif
ANSELB=0;
ANSELC=0;
ANSELD=0;
ANSELE=0;
ANSELG=0;
#endif
}
Also, make absolutely sure the oscillator and thus the part's speed is correct, though if TX has the correct baudrate (scope!) that is probably ok.
My uart1 init:
U1BRG = brgval;
U1MODE = 0x8000; // Reset UART to 8-n-1, alt pins, and enable lowspeed (=bit 3)
U1MODEbits.USIDL =0; // disable module when device is idle.
U1MODEbits.IREN =0; // IRDA disable
U1MODEbits.RTSMD =0; // flow control mode (1= simplex mode)
U1MODEbits.UEN =0; // RTS en CTS controlled by PORTlatches
U1MODEbits.WAKE =0; // no wakeup enabled;
U1MODEbits.LPBACK=0; // loopback disabled
U1MODEbits.ABAUD =0; // no autobaud
#if !defined(__PIC24F__)
U1MODEbits.URXINV =0; // RXINV inversion RX. (0= idle = '1')
#endif
U1MODEbits.BRGH =1; // high speed.
U1MODEbits.PDSEL =0; // 8 bit no parity
U1MODEbits.STSEL =0; // 1 stopbit.
U1STA = 0x0440;
U1STAbits.URXISEL0=0;// Reset status register and enable TX & RX.
U1STAbits.URXISEL1=0; // rx interrupt on a char.
_U1RXIF=0; // Clear UART RX Interrupt Flag
_U1RXIE = 1; // Interruption active pour la reception
_U1RXIP=2;
_U1TXIP=2;
_U1TXIF=0;
_U1TXIE=0; // only enabled when actually sending
U1MODEbits.UARTEN=1;
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;