Skip to main content
johnjohn9104
Associate II
July 19, 2012
Question

Problems with interupt-configuration

  • July 19, 2012
  • 6 replies
  • 1622 views
Posted on July 19, 2012 at 15:50

Hello,

in my Application I have got a LED which is toggled by Timer2. When only this timer is running, the output level of the I/O pin is 3V when high. When I additionaly activate the USART interrupt, the output level goes only up to 2,5V.

// Enable interrupt TIM2
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// Enable interrupt USART1
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

Can anybody explain this? Next, when I alter the USART-code to

NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;

the LED stops blinking and it seems, that the timer is no more running. This should only disable the USART-interrupt, why does it impact the timer-interrupt? Regards Tom
    This topic has been closed for replies.

    6 replies

    jpeacock2399
    Associate III
    July 19, 2012
    Posted on July 19, 2012 at 16:02

    What processor and which pins are you using?  Chances are it's a conflict with alternate functions.

      Jack Peacock

    johnjohn9104
    Associate II
    July 19, 2012
    Posted on July 19, 2012 at 19:54

    The controller is a STM32L15... (sorry, can't have a look at the moment).

    The USART1 is on Pins PA9/10, the Leds are on PB6/7.

    As far as i know there are no alternate functions of USART1 on the Port B.

    What I don't understand is why the timer is no longer working when disabling the USART1 .... ?

    Regards

    Tom

    Andrew Neil
    Super User
    July 19, 2012
    Posted on July 19, 2012 at 20:15

    ''When only this timer is running, the output level of the I/O pin is 3V when high.

     

    When I additionaly activate the USART interrupt, the output level goes only up to 2,5V''

     

    How are you measuring those voltages?

    Have you checked with an oscilloscope to see if there is anything ''high frequency'' going on...?

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    johnjohn9104
    Associate II
    July 20, 2012
    Posted on July 20, 2012 at 07:43

    Tesla DeLorean
    Guru
    July 20, 2012
    Posted on July 20, 2012 at 09:28

    The biggest issue is USART_FLAG_TXE != USART_IT_TXE, etc

    Then again, you also don't initialize the pins correctly. The timer period and prescaler are N-1, ie for N cycles [0 .. N-1] The NUL marking and buffer limits were a problem. Using 8-bit indexes is very inefficient, the registers are 32-bit and work more effectively even with ranges <256 A more considered solution might look like this :

    #include ''stm32l1xx.h''
    /* function prototypes */
    void RCC_Configuration(void);
    void GPIO_Configuration(void);
    void NVIC_Configuration(void);
    void USART1_Configuration(void);
    void TIM2_Configuration(void);
    void SysTick_Handler(void);
    void TIM2_IRQHandler(void);
    void USART1_Send(char cData);
    void USART1_IRQHandler(void);
    int iTick = 0;
    int main(void)
    {
    RCC_Configuration();
    NVIC_Configuration();
    GPIO_Configuration();
    USART1_Configuration();
    TIM2_Configuration();
    // Init SysTick Timer
    SysTick_Config(1000000);
    while(1)
    {
    // Just for debugging
    if (iTick != 0)
    {
    iTick = 0;
    }
    }
    }
    void USART1_Send(char cData)
    {
    // Wait for buffer empty
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    // Send first byte
    USART_SendData(USART1, cData);
    // Enable Tx interrupt after sending first byte
    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
    }
    void RCC_Configuration(void)
    {
    // Enable GPIOA, GPIOB clock
    RCC_AHBPeriphClockCmd (RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, ENABLE);
    // Enable TIM2 clock
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    // Enable USART1 clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    // Set sysclock to output PA8
    RCC_MCOConfig(RCC_MCOSource_SYSCLK, RCC_MCODiv_1);
    }
    void NVIC_Configuration(void)
    {
    NVIC_InitTypeDef NVIC_InitStructure;
    // Enable interrupt TIM2
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    // Enable interrupt USART1
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    }
    void SysTick_Handler(void)
    {
    iTick = 1;
    }
    void GPIO_Configuration(void)
    {
    // Initialize Leds mounted on STM32L board
    GPIO_InitTypeDef GPIO_InitStructure;
    // Configure the GPIO_LED pin
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    // Configure USART1 Tx (PA9) and Rx (PA10) as alternate function
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // Configure MCO (PA8) as alternate function
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_MCO);
    }
    void USART1_Configuration(void)
    {
    USART_InitTypeDef USART_InitStructure;
    /* USART1 configured as follow:
    - BaudRate = 115200 baud
    - Word Length = 8 Bits
    - One Stop Bit
    - No parity
    - Hardware flow control disabled (RTS and CTS signals)
    - Receive and transmit enabled
    */
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
    //Disable Transmit Data Register empty interrupt
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    //Enable Receive Data register not empty interrupt
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    }
    void TIM2_Configuration(void)
    {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    //setting timer 2 interrupt to ??hz ((??/1000)*1000)s
    TIM_TimeBaseStructure.TIM_Prescaler = 1000 - 1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period = 10000 - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    /* TIM IT enable */
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    /* TIM2 enable counter */
    TIM_Cmd(TIM2, ENABLE);
    }
    void TIM2_IRQHandler(void)
    {
    //If interrupt happens the do this
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
    //Clear interrupt and start counting again to get precise freq
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    //Toggle led to see some chance in port B pin 6
    if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_6) == RESET)
    GPIO_WriteBit(GPIOB,GPIO_Pin_6,SET);
    else
    GPIO_WriteBit(GPIOB,GPIO_Pin_6,RESET);
    }
    }
    void USART1_IRQHandler(void)
    {
    static char cReceiveData[100];
    static char cSendData[100];
    static int iReceiveIndex = 0;
    static int iSendIndex = 0;
    int a;
    if (USART_GetITStatus(USART1, USART_IT_RXNE)!= RESET)
    {
    GPIOB->ODR ^= GPIO_Pin_7;
    cReceiveData[iReceiveIndex++]=(uint8_t)USART_ReceiveData(USART1);
    if ((cReceiveData[iReceiveIndex-1] == 0x0D) || (iReceiveIndex >= 99))
    {
    for (a = 0; a < iReceiveIndex;a++)
    {
    cSendData[a] = cReceiveData[a];
    cReceiveData[a] = 0;
    }
    cSendData[a] = 0; // NUL terminate
    
    iReceiveIndex = 0;
    iSendIndex = 0;
    USART1_Send(cSendData[iSendIndex++]); //echo
    }
    }
    if (USART_GetITStatus(USART1, USART_IT_TXE)!= RESET)
    {
    if ((cSendData[iSendIndex] != 0) && (iSendIndex < 100))
    USART_SendData(USART1, cSendData[iSendIndex++]);
    else
    {
    // Disable Tx interrupt after sending last byte
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    for (a = 0; a < iSendIndex;a++)
    {
    cSendData[a] = 0;
    }
    }
    }
    // Clear all flags
    USART_ClearITPendingBit(USART1, (USART_IT_CTS | USART_IT_LBD | USART_IT_TC | USART_IT_RXNE));
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    johnjohn9104
    Associate II
    July 20, 2012
    Posted on July 20, 2012 at 11:39

    Thanks for your support!

    Just before I read your answer I found that by adding this line:

    GPIO_StructInit(&GPIO_InitStructure);

    before each new GPIO configuration the output level was correct. You are right thatUSART_FLAG_TXE != USART_IT_TXE but in the SR theUSART_FLAG_TXE id at position 0x80 and in the CR1 the USART_IT_TXE is also at position 0x So this piece of my code worked as expected. I know that my code is not perfect (for example the missing receive- and send-length check) because it is not intended to be ''productional'' code, it is at some points just quick and dirty functional ''play'' code to get used to the device. I promise to improve the quality I will post here in the future ;) Regards Tom