0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【试用报告】沁恒CH32V307评估板体验:定时器使用基础

电子发烧友论坛 来源:未知 2023-03-28 13:05 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

CH32V307系统提供了多个类型的定时器,具体可查看手册了解:



这次的分享,我们使用到的定时器为系统时基定时器和基本定时器TIM6。


闪烁使用的LED,为LED1,使用连接线将LED1和PA0连接即可;实际运行时,间隔1秒闪烁一次。



有的同学可能会说,使用Delay_Ms或Delay_Us做演示,也能实现LED闪烁呀!


但在Delay的时候,你的程序,需要在这个地方,等待Delay时间后,才会继续运行。


而使用中断,我们的程序,能够继续运行做其他的事情,等到定时中断到来的时候,才处理LED的闪烁。这样程序的处理效率将会更高。


一、系统时基定时器SysTick


现在,我们了解一下系统时基定时器SysTick。


系统时基定时器:这是内核控制器自带的一个 64 位可选递增或递减的计数器,用于产生 SYSTICK 异常(异常号:15),可专用于实时操作系统,为系统提供“心跳”节律,也可当成一个标准的 64 位计数器。具有自动重加 载功能及可编程时钟源。


通过查看提供的实例和资料,了解到如下的关键信息:


1、系统的运行频率可以工作在72MHz,也可以工作在144MHz,通过system_ch32v30x.h/system_ch32v30x.c来修改:

// #define SYSCLK_FREQ_72MHz 72000000
#define SYSCLK_FREQ_144MHz 144000000

(左右移动查看全部内容)


在我的实例中,设置工作在144MHz。


2、在设置SysTick的时候,通过SysTick->CMP来设置定时中断周期:SysTick->CMP = SystemCoreClock / 1000 * 1000; //后面的1000代表1000HZ(那就是1ms进一次中断),*1000 表示 1000ms进入一次


3、有人会遇到,中断只进入一次,经过请教沁恒的陶工,了解到如下处理方法:

// 中断只进入一次的问题解决方法:
// 1. 如果使用沁恒提供的工具链,则使用如下的声明:
// void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
// 2. 如果使用通用的risc-v工具链,如我在macOS下使用赛昉提供的工具链,则使用如下的声明:
void SysTick_Handler(void) __attribute__((interrupt()));

(左右移动查看全部内容)


最终,具体的代码如下:

/*
使用VTF IRQ中断控制LED闪烁
*/


#include "debug.h"
#include "board.h"


// 中断只进入一次的问题解决方法:
// 1. 如果使用沁恒提供的工具链,则使用如下的声明:
// void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
// 2. 如果使用通用的risc-v工具链,如我在macOS下使用赛昉提供的工具链,则使用如下的声明:
void SysTick_Handler(void) __attribute__((interrupt()));


// LED状态
volatile uint16_t LED_Status = 0; // 中断里使用的变量加 volatile 可当成全局变量


// 初始化 GPIO
void GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}


// 初始化 SysTick 定时器
void SysTick_init(void)
{
/*配置中断优先级*/
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = SysTicK_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占式优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应式优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能
NVIC_Init(&NVIC_InitStructure);


/*配置定时器*/
SysTick->CTLR= 0;
SysTick->SR = 0;
SysTick->CNT = 0;
SysTick->CMP = SystemCoreClock / 1000 * 1000; //后面的1000代表1000HZ(那就是1ms进一次中断),*1000 表示 1000ms进入一次
SysTick->CTLR= 0xf;
}


int main(void)
{
/* Initialize board components. */
BOARD_SystemClock_Config();
BOARD_IOMUX_Init();
BOARD_Peripheral_Init();


GPIO_INIT(); // 初始化 GPIO
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断控制器的优先级分组为 占优先级 2位 ,优先级2位。


USART_Printf_Init(115200);
printf("SystemClk:%drn", SystemCoreClock);
printf("Interrupt SysTick Testrn");


SysTick_init();
while (1)
{
}
}


// 中断服务处理
void SysTick_Handler(void)
{
SysTick->SR = 0;
LED_Status = !LED_Status; // 将 LED 状态值取反
GPIO_WriteBit(GPIOA, GPIO_Pin_0, LED_Status); // 配置 PA0 (即 LED1) 状态


printf("Toggle LED by SysTick: %drn", LED_Status);
}

(左右移动查看全部内容)


在上述代码中,关键部分如下:

  • GPIO_INIT:初始化GPIO,使用PA0;记得预先连接LED1和PA0

  • SysTick_init:SysTick初始化,主要设置中断周期

  • SysTick_Handler:中断服务处理,其内部的操作需要狠准快

除了板载的LED1(前提是连好了线)会间隔1秒闪烁一次,通过串口工具,我们也可以看到输出的调试信息:



二、基本定时器TIM6


然后,我们再来了解一下基本定时器。


基本定时器:基本定时器是一个 16 位自动装载计数器,支持 16 位可编程预分频器。可以位数模转换(DAC)提供时钟,触发 DAC 的同步电路。基本定时器之间是互相独立的,互不共享任何资源。


CH32V307提供了两个基本定时器TIM6和TIM7,用法是一样的,下面的实例中,使用TIM6。


通过官方提供的实例和资料了解到,基本定时器使用的过程中,有两个设置是最重要的:

  • TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器时钟。

  • TIM_Period:定时器周期,实际就是设定自动重载寄存器的值。


这两个参数结合就能实现实际所需要的定时。


根据定时器时钟的频率,比如时钟的频率是144MHz,可以理解为1秒钟MCU会自己数144M次,预分频系数就是将频率分割,比如分频系数是144,则该时钟的频率会变成144MHZ/144=1MHz,但是在设置的时候要注意,数值应该是144-1。


为了让 LED1间隔 1 秒闪烁一次,我们需要让定时器 1 秒溢出,要计数 144M * 1 = 144M 个时钟周期,而定时器只有16位,最大65535,所以这是不够的。因此,需要用到预分频器,设分频系数为 14400,可以得到 10KHz 的定时器时钟,这样设置计数值 10000 就可以做到 1s 定时。


最终具体的代码如下:

/*
使用基本定时器TIM6控制LED闪烁
*/


#include "debug.h" // 包含 CH32V307 的头文件,C 标准单元库和delay()函数
#include "board.h"


// 中断只进入一次的问题解决方法:
// 1. 如果使用沁恒提供的工具链,则使用如下的声明:
// void TIM6_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
// 2. 如果使用通用的risc-v工具链,如我在macOS下使用赛昉提供的工具链,则使用如下的声明:
void TIM6_IRQHandler(void) __attribute__((interrupt()));


// LED状态
volatile uint16_t LED_Status = 0; // 中断里使用的变量加 volatile 可当成全局变量


// 初始化 GPIO
void GPIO_INIT(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}


// 初始化定时器 TIM6
void TIM6_Init(u16 arr, u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;


RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);


TIM_TimeBaseInitStructure.TIM_Period = arr;
TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;
TIM_TimeBaseInit(TIM6, &TIM_TimeBaseInitStructure);


TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
TIM_ARRPreloadConfig(TIM6, ENABLE);
TIM_Cmd(TIM6, ENABLE);
}


// 初始化定时器中断
void Interrupt_Init(void)
{
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}


int main(void)
{
/* Initialize board components. */
BOARD_SystemClock_Config();
BOARD_IOMUX_Init();
BOARD_Peripheral_Init();


GPIO_INIT(); // 初始化 GPIO
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断控制器的优先级分组为 占优先级 2位 ,优先级2位。


USART_Printf_Init(115200);


TIM6_Init(10000 - 1, 14400 - 1); // 初始化定时器,让 LED 1 秒闪烁一次,我们需要让定时器 1 秒溢出,要计数 `144M * 1 = 144M` 个时钟周期,而定时器只有16位,这是不够的。需要用到预分频器,设分频系数为 14400,可以得到 10KHz 的定时器时钟,这样设置计数值 10000 就可以做到 1s 定时。
Interrupt_Init(); //初始化定时器中断


printf("SystemClk:%drn", SystemCoreClock);
printf("Interrupt TIM6 Testrn");


while (1)
{
}
}


// 中断服务处理
void TIM6_IRQHandler(void)
{
TIM_ClearFlag(TIM6, TIM_FLAG_Update); //清除标志位
LED_Status = !LED_Status; // 将 LED 状态值取反
GPIO_WriteBit(GPIOA, GPIO_Pin_0, LED_Status); // 配置 PE11 (即 LED1) 状态


printf("Toggle LED by TIM6: %drn", LED_Status);
}

(左右移动查看全部内容)


在上述代码中,关键部分如下:

  • GPIO_INIT:初始化GPIO,使用PA0;记得预先连接LED1和PA0

  • TIM6_init:TIM6初始化,主要设置分频和时间周期

  • Interrupt_Init:终端初始化

  • TIM6_IRQHandler中断服务处理,其内部的操作同样需要狠准快


除了板载的LED1(前提是连好了线)会间隔1秒闪烁一次,通过串口工具,我们也可以看到输出的调试信息:






声明本文由电子发烧友社区发布,转载请注明以上来源。如需社区合作及入群交流,请添加微信EEFans0806,或者发邮箱liuyong@huaqiu.com。


更多热点文章阅读

  • 龙芯架构首款面向嵌入式应用的开发板,2K500开发应用实例

  • ARM架构国产MCU移植!国民技术N32系列开源移植样例合集

  • RK3568!四核64位ARMv8.2A架构,汇聚编译源码及实战样例

  • OpenHarmony开源鸿蒙大赛作品集:基于RK2206开发板20+成熟应用案例!

  • 24Bit ADC高精度低功耗MCU 医疗级别设备参考设计(附上高精确算法+电路原理图)


原文标题:【试用报告】沁恒CH32V307评估板体验:定时器使用基础

文章出处:【微信公众号:电子发烧友论坛】欢迎添加关注!文章转载请注明出处。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 电子技术
    +关注

    关注

    19

    文章

    936

    浏览量

    60513
  • 电子发烧友论坛

    关注

    5

    文章

    198

    浏览量

    1959
  • ch32
    +关注

    关注

    0

    文章

    74

    浏览量

    1350

原文标题:【试用报告】沁恒CH32V307评估板体验:定时器使用基础

文章出处:【微信号:gh_9b9470648b3c,微信公众号:电子发烧友论坛】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    富瀚微FH8626V300L试用报告

    *附件:富瀚微FH8626V300L试用报告 -双路AOV智能检测.docx
    发表于 04-15 23:22

    国产100M以太网PHY:CH182H2性能测试应用看这篇就够了

    本文分享一款100M以太网PHY芯片,CH182H2。并分享基于官方的开发CH32V307V-EVT-R3来评估下这款芯片的应用,以及性能测试。具体的性能,参数,特点等可以参考数据手
    的头像 发表于 02-14 20:56 3.4w次阅读
    国产100M以太网PHY:<b class='flag-5'>沁</b><b class='flag-5'>恒</b><b class='flag-5'>CH</b>182H2性能测试应用看这篇就够了

    CH9347助力新国标充电宝全平台无感连接

    、HarmonyOS手机平板和Windows、macOS、Linux等桌面平台,全平台无感,连接无弹窗,不请求额外权限,不涉及隐私,即连即用,覆盖高性能到低成本多层级的终端应用需求。 U SB 透传,充电宝全平台无感连接 USB透传芯片CH9347系列是
    的头像 发表于 01-16 17:37 2138次阅读
    <b class='flag-5'>沁</b><b class='flag-5'>恒</b><b class='flag-5'>CH</b>9347助力新国标充电宝全平台无感连接

    智能电表方案MCU单片机CH32V307系列

    智能电表作为现代电网数据采集的关键设备,承担着电能计量、用电监测与远程管理的重要职能。其核心在于稳定、高效且功能丰富的控制单元。针对这一需求,英尚代理推出搭载MCU单片机CH32V307系列的智能电表解决方案,凭借其出色的互
    的头像 发表于 01-12 17:12 935次阅读
    智能电表方案MCU单片机<b class='flag-5'>CH32V307</b>系列

    RT-Thread Studio CH32V307工程,程序运行异常怎么解决?

    RT-Thread Studio CH32V307 工程历程程序运行异常,官方的EVT历程使用是OK的,没人维护吗?
    发表于 10-13 06:36

    【作品合集】微电子CH585开发测评

    (一)【CH585开发免费试用体验】CH585开发环境搭建(二)【
    发表于 09-08 10:38

    CH554评估资料包

    CH554评估说明及参考应用例程,包括USB设备、USB-Host、读写U盘文件、Touch-Key、Type-C、ADC、定时器、PWM、串口、SPI等例子。适用于:
    发表于 08-12 16:21 2次下载

    Texas Instruments TLC3555EVM定时器评估模块 (EVM)数据手册

    Texas Instruments TLC3555EVM定时器评估模块 (EVM) 设计用于帮助用户轻松评估和测试TLC3555器件的运行和功能。评估模块可按标准
    的头像 发表于 07-21 14:03 1014次阅读
    Texas Instruments TLC3555EVM<b class='flag-5'>定时器</b><b class='flag-5'>评估</b>模块 (EVM)数据手册

    CH585开发免费试用体验】定时器操作

    开发环境: IDE:MounRiver Studio MCU:CH585 1 定时器的工作原理 CH585定时器最基本功能是定时,可以设置不
    发表于 07-05 23:06

    CH585开发免费试用体验】1、开箱评测

    MounRiver_Studio_Setup_V220.zip是基于vscode, MounRiver_Studio_Setup_V192.zip是基于eclipse。 由于之前使用了
    发表于 07-03 12:57

    CH585开发免费试用体验】+品读老朋友的新产品

    。 图2 开发板正面 图3 开发背面 在CH585 评估上配有的资源有: 开关 S1 :供电开关,用于切断或连接外部 5V 供电或 U
    发表于 07-03 11:04

    CH585开发免费试用体验】+开箱点灯篇

    一、引言 上周末收到官方寄过来的CH585M-R1开发,今天来分享一下,完成开箱以及环境搭建,并进行点灯入门操作。 CH585是集成B
    发表于 07-02 20:26

    CH585开发免费试用体验】+开箱及开发环境准备

    首先感谢社区及厂家提供开发试用的机会,平时一直有关注的产品及RISC-V生态,虽然有尝试过使用青稞RISC-
    发表于 06-27 21:44

    微电子:从互连互通应用推动RISC-V落地发展

    微电子邀您共襄盛举微电子专注于连接技术和微处理器内核研究,基于多层次青稞RISC-V微处理器、多类型物理层收发器构建USB/蓝牙/以
    的头像 发表于 06-26 09:52 1862次阅读
    <b class='flag-5'>沁</b><b class='flag-5'>恒</b>微电子:从互连互通应用推动RISC-<b class='flag-5'>V</b>落地发展

    搭载RISC-V架构!CH585开发免费试用

    CH585是集成BLE无线通讯和高速USB及NFC的RISC-V MCU/SoC。片上集成了2Mbps低功耗蓝牙BLE通讯模块、USB全速控制器及收发器、USB高速控制器及收发器(480Mbps
    的头像 发表于 06-05 16:28 2426次阅读
    搭载RISC-<b class='flag-5'>V</b>架构!<b class='flag-5'>沁</b><b class='flag-5'>恒</b><b class='flag-5'>CH</b>585开发<b class='flag-5'>板</b>免费<b class='flag-5'>试用</b>