[单片机芯片]

CH32L103免表中断和SysTick应用

[复制链接]
683|9
手机看帖
扫描二维码
随时随地手机跟帖
L-MCU|  楼主 | 2024-6-28 17:21 | 显示全部楼层 |阅读模式
本帖最后由 L-MCU 于 2024-6-28 17:21 编辑

1、VTF与SysTick介绍
CH32L103内置可编程快速中断控制器(PFIC–Programmable Fast Interrupt Controller),特有免表VTF(Vector Table Free)中断响应机制,4路可编程直达中断向量地址。关于免表中断,可不经过中断向量表的查表过程,直达中断函数入口。关于免表中断的具体介绍,可看QingKeV4微处理器手册。
CH32L103内核自带了一个64位加减计数器(SysTick),支持HCLK或者HCLK/8作为时基,具有较高优先级,校准后可用于时间基准。

2、VTF与SysTick应用
开启免表中断(VTF)后,可以缩短中断延迟时间。关于中断延迟(响应)时间,即从中断触发条件产生到中断函数执行的时间。通过SysTick中断可以验证开启VTF后会缩短中断延迟时间。
CH32L103的SysTick进入中断的条件为:当计数寄存器的值与比较寄存器的值相同时,触发中断。测试程序配置SysTick计数模式为向上计数,选择HCLK作为时基,当计数器值与比较寄存器值相同时,会触发中断,此时SysTick计数器会重新从0开始计数,在中断第一时间读取计数器的值。通过对开启VTF和不开启VTF计数器值的比较,当开启VTF后计数器值变小,说明中断延迟时间被缩短。
具体测试程序如下:
/********************************** (C) COPYRIGHT *******************************
* File Name          : main.c
* Author             : WCH
* Version            : V1.0.0
* Date               : 2023/07/08
* Description        : Main program body.
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/

/*
*@Note
*VTF IRQ interrupt routine:
*This example is used to demonstrate VTF IRQ
*/
#include "debug.h"

/* Global define */


/* Global Variable */
uint32_t time=0;

void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

/*********************************************************************
* @fn      Systick_Init
*
* [url=home.php?mod=space&uid=247401]@brief[/url]   Initializes Systick.
*
* [url=home.php?mod=space&uid=266161]@return[/url]  none
*/
void SYSTICK_Init_Config(u64 ticks)
{
    SysTick->SR = 0;
    SysTick->CNT = 0;
    SysTick->CMP = ticks;
    SysTick->CTLR =0x0F;

    NVIC_SetPriority(SysTicK_IRQn, 0);
    NVIC_EnableIRQ(SysTicK_IRQn);
    SetVTFIRQ((u32)SysTick_Handler,SysTicK_IRQn,0,ENABLE);
}

/*********************************************************************
* @fn      main
*
* [url=home.php?mod=space&uid=247401]@brief[/url]   Main program.
*
* [url=home.php?mod=space&uid=266161]@return[/url]  none
*/
int main(void)
{
    SystemCoreClockUpdate();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n",SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
    printf("Interrupt VTF Test\r\n");

    SYSTICK_Init_Config(SystemCoreClock-1);

    while(1)
    {
    }
}

/*********************************************************************
* @fn      SysTick_Handler
*
* @brief   This function handles SysTick exception.
*
* @return  none
*/
void SysTick_Handler(void)
{
    printf("CNT:%d\r\n",(u32)SysTick->CNT);
    SysTick->CTLR=0;
    SysTick->SR=0;
}
关于SysTick的配置,程序中:
(1)首先对系统计数状态寄存器(STK_SR)以及系统计数寄存器(STK_CNT)置0,清除对应标志位,以及将计数器值置0,从0开始向上计数。
(2)其次对系统计数比较寄存器寄存器(STK_CMP)进行赋值,此处赋值为SystemCoreClock-1,SystemCoreClock的大小为96M,则需要计数96M次,即96000000次。
(3)最后对系统计数控制寄存器(STK_CTLR)进行配置并进行中断使能以及开启免表中断。系统计数控制寄存器(STK_CTLR)赋值为0x0F,即配置启动系统计数器STK,使能计数器中断,选择HCLK做时基,向上计数到比较值后重新从0开始计数。
关于SysTick时基,可选择HCLK或HCLK/8作为时基。以测试例程为例,选择HCLK作为时基,HCLK大小一般为系统主频大小,具体看配置,此处为系统主频大小96MHz,则SysTick计数一次的时间为1/96MHz。比较寄存器值设置为96M-1,从0开始计数,则计数96M次。因此进一次SysTick中断的时间为1s进一次中断。
关于系统计数控制寄存器(STK_CTLR),具体如下:
7862667e5d3b78fb6.png
根据例程:
当不开启免表中断时,进入中断后,打印计数器的值为22,如下图
93193667e5d508f184.png
当开启免表中断时,进入中断后,打印计数器的值为20,如下图  
40959667e5d60170c6.png
由结果可知,开启免表中断后,中断延迟时间还是缩短一些的。

3、软件中断
通过配置系统计数控制寄存器(STK_CTLR)的位31置1,可以配置触发软件中断,如下图
83457667e5d8ed01c7.png
关于软件中断的触发以及对应标志位的清除函数如下:
/*********************************************************************
* @fn      main
*
* @brief   Main program.
*
* @return  none
*/
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
    printf("This is printf example\r\n");

    NVIC_EnableIRQ(Software_IRQn);

    while(1)
    {
        SysTick->CTLR |= (1<<31);
        Delay_Ms(1000);
    }
}

void SW_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void SW_Handler(void)
{
    SysTick->CTLR &= ~(1<<31);
    printf("Enter INT\r\n");

}
程序中,首先使能开启软件中断,然后在while循环中每隔1s将位31置1进入软件中断,软件中断中将该位清0。

附件为测试所用例程,有需要可以下载看一下。


CH32L103 SysTick和软件中断.zip

1.32 MB

使用特权

评论回复
tpgf| | 2024-7-1 12:13 | 显示全部楼层
在什么情况下需要开启免表中断呢

使用特权

评论回复
heimaojingzhang| | 2024-7-1 12:51 | 显示全部楼层
请问楼主能不能详细的解释一下什么叫做免表中断呢

使用特权

评论回复
keaibukelian| | 2024-7-1 13:32 | 显示全部楼层
为什么要关闭软件的中断使能呢

使用特权

评论回复
wakayi| | 2024-7-1 14:12 | 显示全部楼层
免表中断响应机制是无需查看中断表吗

使用特权

评论回复
评论
L-MCU 2024-7-1 16:23 回复TA
是的,不经过查表过程,直达中断函数入口 
L-MCU|  楼主 | 2024-7-1 16:22 | 显示全部楼层
tpgf 发表于 2024-7-1 12:13
在什么情况下需要开启免表中断呢

免表中断可以直达中断函数入口,当你对中断延迟响应时间有要求可以开启

使用特权

评论回复
L-MCU|  楼主 | 2024-7-1 16:23 | 显示全部楼层
heimaojingzhang 发表于 2024-7-1 12:51
请问楼主能不能详细的解释一下什么叫做免表中断呢

可以看青稞手册的介绍

使用特权

评论回复
renzheshengui| | 2024-7-1 21:50 | 显示全部楼层
中断延迟时间的时长 可以配置吗

使用特权

评论回复
paotangsan| | 2024-7-1 22:21 | 显示全部楼层
系统时钟最长可以多长时间进入一次中断啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

17

帖子

0

粉丝