0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【試用報告】沁恒CH32V307評估板體驗:定時器使用基礎(chǔ)

電子發(fā)燒友論壇 ? 來源:未知 ? 2023-03-28 13:05 ? 次閱讀

CH32V307系統(tǒng)提供了多個類型的定時器,具體可查看手冊了解:



這次的分享,我們使用到的定時器為系統(tǒng)時基定時器和基本定時器TIM6。


閃爍使用的LED,為LED1,使用連接線將LED1和PA0連接即可;實際運行時,間隔1秒閃爍一次。



有的同學(xué)可能會說,使用Delay_Ms或Delay_Us做演示,也能實現(xiàn)LED閃爍呀!


但在Delay的時候,你的程序,需要在這個地方,等待Delay時間后,才會繼續(xù)運行。


而使用中斷,我們的程序,能夠繼續(xù)運行做其他的事情,等到定時中斷到來的時候,才處理LED的閃爍。這樣程序的處理效率將會更高。


一、系統(tǒng)時基定時器SysTick


現(xiàn)在,我們了解一下系統(tǒng)時基定時器SysTick。


系統(tǒng)時基定時器:這是內(nèi)核控制器自帶的一個 64 位可選遞增或遞減的計數(shù)器,用于產(chǎn)生 SYSTICK 異常(異常號:15),可專用于實時操作系統(tǒng),為系統(tǒng)提供“心跳”節(jié)律,也可當(dāng)成一個標(biāo)準(zhǔn)的 64 位計數(shù)器。具有自動重加 載功能及可編程時鐘源。


通過查看提供的實例和資料,了解到如下的關(guān)鍵信息


1、系統(tǒng)的運行頻率可以工作在72MHz,也可以工作在144MHz,通過system_ch32v30x.h/system_ch32v30x.c來修改:

// #define SYSCLK_FREQ_72MHz 72000000
#define SYSCLK_FREQ_144MHz 144000000

(左右移動查看全部內(nèi)容)


在我的實例中,設(shè)置工作在144MHz。


2、在設(shè)置SysTick的時候,通過SysTick->CMP來設(shè)置定時中斷周期:SysTick->CMP = SystemCoreClock / 1000 * 1000; //后面的1000代表1000HZ(那就是1ms進(jìn)一次中斷),*1000 表示 1000ms進(jìn)入一次


3、有人會遇到,中斷只進(jìn)入一次,經(jīng)過請教沁恒的陶工,了解到如下處理方法:

// 中斷只進(jìn)入一次的問題解決方法:
// 1. 如果使用沁恒提供的工具鏈,則使用如下的聲明:
// void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
// 2. 如果使用通用的risc-v工具鏈,如我在macOS下使用賽昉提供的工具鏈,則使用如下的聲明:
void SysTick_Handler(void) __attribute__((interrupt()));

(左右移動查看全部內(nèi)容)


最終,具體的代碼如下:

/*
使用VTF IRQ中斷控制LED閃爍
*/


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


// 中斷只進(jìn)入一次的問題解決方法:
// 1. 如果使用沁恒提供的工具鏈,則使用如下的聲明:
// void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
// 2. 如果使用通用的risc-v工具鏈,如我在macOS下使用賽昉提供的工具鏈,則使用如下的聲明:
void SysTick_Handler(void) __attribute__((interrupt()));


// LED狀態(tài)
volatile uint16_t LED_Status = 0; // 中斷里使用的變量加 volatile 可當(dāng)成全局變量


// 初始化 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)
{
/*配置中斷優(yōu)先級*/
NVIC_InitTypeDef NVIC_InitStructure = {0};
NVIC_InitStructure.NVIC_IRQChannel = SysTicK_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//搶占式優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//響應(yīng)式優(yōu)先級
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進(jìn)一次中斷),*1000 表示 1000ms進(jìn)入一次
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); //設(shè)置中斷控制器的優(yōu)先級分組為 占優(yōu)先級 2位 ,優(yōu)先級2位。


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


SysTick_init();
while (1)
{
}
}


// 中斷服務(wù)處理
void SysTick_Handler(void)
{
SysTick->SR = 0;
LED_Status = !LED_Status; // 將 LED 狀態(tài)值取反
GPIO_WriteBit(GPIOA, GPIO_Pin_0, LED_Status); // 配置 PA0 (即 LED1) 狀態(tài)


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

(左右移動查看全部內(nèi)容)


在上述代碼中,關(guān)鍵部分如下:

  • GPIO_INIT:初始化GPIO,使用PA0;記得預(yù)先連接LED1和PA0

  • SysTick_init:SysTick初始化,主要設(shè)置中斷周期

  • SysTick_Handler:中斷服務(wù)處理,其內(nèi)部的操作需要狠準(zhǔn)快

除了板載的LED1(前提是連好了線)會間隔1秒閃爍一次,通過串口工具,我們也可以看到輸出的調(diào)試信息:



二、基本定時器TIM6


然后,我們再來了解一下基本定時器。


基本定時器:基本定時器是一個 16 位自動裝載計數(shù)器,支持 16 位可編程預(yù)分頻器??梢晕粩?shù)模轉(zhuǎn)換(DAC)提供時鐘,觸發(fā) DAC 的同步電路?;径〞r器之間是互相獨立的,互不共享任何資源。


CH32V307提供了兩個基本定時器TIM6和TIM7,用法是一樣的,下面的實例中,使用TIM6。


通過官方提供的實例和資料了解到,基本定時器使用的過程中,有兩個設(shè)置是最重要的:

  • TIM_Prescaler:定時器預(yù)分頻器設(shè)置,時鐘源經(jīng)該預(yù)分頻器才是定時器時鐘。

  • TIM_Period:定時器周期,實際就是設(shè)定自動重載寄存器的值。


這兩個參數(shù)結(jié)合就能實現(xiàn)實際所需要的定時。


根據(jù)定時器時鐘的頻率,比如時鐘的頻率是144MHz,可以理解為1秒鐘MCU會自己數(shù)144M次,預(yù)分頻系數(shù)就是將頻率分割,比如分頻系數(shù)是144,則該時鐘的頻率會變成144MHZ/144=1MHz,但是在設(shè)置的時候要注意,數(shù)值應(yīng)該是144-1。


為了讓 LED1間隔 1 秒閃爍一次,我們需要讓定時器 1 秒溢出,要計數(shù) 144M * 1 = 144M 個時鐘周期,而定時器只有16位,最大65535,所以這是不夠的。因此,需要用到預(yù)分頻器,設(shè)分頻系數(shù)為 14400,可以得到 10KHz 的定時器時鐘,這樣設(shè)置計數(shù)值 10000 就可以做到 1s 定時。


最終具體的代碼如下:

/*
使用基本定時器TIM6控制LED閃爍
*/


#include "debug.h" // 包含 CH32V307 的頭文件,C 標(biāo)準(zhǔn)單元庫和delay()函數(shù)
#include "board.h"


// 中斷只進(jìn)入一次的問題解決方法:
// 1. 如果使用沁恒提供的工具鏈,則使用如下的聲明:
// void TIM6_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
// 2. 如果使用通用的risc-v工具鏈,如我在macOS下使用賽昉提供的工具鏈,則使用如下的聲明:
void TIM6_IRQHandler(void) __attribute__((interrupt()));


// LED狀態(tài)
volatile uint16_t LED_Status = 0; // 中斷里使用的變量加 volatile 可當(dāng)成全局變量


// 初始化 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; //搶占優(yōu)先級
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子優(yōu)先級
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); //設(shè)置中斷控制器的優(yōu)先級分組為 占優(yōu)先級 2位 ,優(yōu)先級2位。


USART_Printf_Init(115200);


TIM6_Init(10000 - 1, 14400 - 1); // 初始化定時器,讓 LED 1 秒閃爍一次,我們需要讓定時器 1 秒溢出,要計數(shù) `144M * 1 = 144M` 個時鐘周期,而定時器只有16位,這是不夠的。需要用到預(yù)分頻器,設(shè)分頻系數(shù)為 14400,可以得到 10KHz 的定時器時鐘,這樣設(shè)置計數(shù)值 10000 就可以做到 1s 定時。
Interrupt_Init(); //初始化定時器中斷


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


while (1)
{
}
}


// 中斷服務(wù)處理
void TIM6_IRQHandler(void)
{
TIM_ClearFlag(TIM6, TIM_FLAG_Update); //清除標(biāo)志位
LED_Status = !LED_Status; // 將 LED 狀態(tài)值取反
GPIO_WriteBit(GPIOA, GPIO_Pin_0, LED_Status); // 配置 PE11 (即 LED1) 狀態(tài)


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

(左右移動查看全部內(nèi)容)


在上述代碼中,關(guān)鍵部分如下:

  • GPIO_INIT:初始化GPIO,使用PA0;記得預(yù)先連接LED1和PA0

  • TIM6_init:TIM6初始化,主要設(shè)置分頻和時間周期

  • Interrupt_Init:終端初始化

  • TIM6_IRQHandler中斷服務(wù)處理,其內(nèi)部的操作同樣需要狠準(zhǔn)快


除了板載的LED1(前提是連好了線)會間隔1秒閃爍一次,通過串口工具,我們也可以看到輸出的調(diào)試信息:






聲明本文由電子發(fā)燒友社區(qū)發(fā)布,轉(zhuǎn)載請注明以上來源。如需社區(qū)合作及入群交流,請?zhí)砑游⑿臙EFans0806,或者發(fā)郵箱liuyong@huaqiu.com。


更多熱點文章閱讀

  • 龍芯架構(gòu)首款面向嵌入式應(yīng)用的開發(fā)板,2K500開發(fā)應(yīng)用實例

  • ARM架構(gòu)國產(chǎn)MCU移植!國民技術(shù)N32系列開源移植樣例合集

  • RK3568!四核64位ARMv8.2A架構(gòu),匯聚編譯源碼及實戰(zhàn)樣例

  • OpenHarmony開源鴻蒙大賽作品集:基于RK2206開發(fā)板20+成熟應(yīng)用案例!

  • 24Bit ADC高精度低功耗MCU 醫(yī)療級別設(shè)備參考設(shè)計(附上高精確算法+電路原理圖)


原文標(biāo)題:【試用報告】沁恒CH32V307評估板體驗:定時器使用基礎(chǔ)

文章出處:【微信公眾號:電子發(fā)燒友論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 電子技術(shù)
    +關(guān)注

    關(guān)注

    18

    文章

    853

    瀏覽量

    55510
  • 電子發(fā)燒友論壇

    關(guān)注

    4

    文章

    197

    瀏覽量

    990
  • ch32
    +關(guān)注

    關(guān)注

    0

    文章

    73

    瀏覽量

    589

原文標(biāo)題:【試用報告】沁恒CH32V307評估板體驗:定時器使用基礎(chǔ)

文章出處:【微信號:gh_9b9470648b3c,微信公眾號:電子發(fā)燒友論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    龍芯2K0300蜂鳥試用報告

    龍芯2K0300蜂鳥試用報告 一、試用環(huán)境 操作系統(tǒng)和框架:Linux+QT5.15 交叉編譯工具鏈
    發(fā)表于 09-13 18:00

    【龍芯2K0300蜂鳥試用】龍芯2K0300蜂鳥試用報告

    龍芯2K0300蜂鳥試用報告 1.拆箱、上電開機(jī) 2.自帶CH340串口通訊芯片,不需要再用串口工具,已經(jīng)板載了 3.主要由JW5079A、SW34201B、FORESEE
    發(fā)表于 08-09 11:58

    ch32v307_RTT】1、使用RT-Thread studio新建工程

    【前言】 ch32v307有成熟的RT-Thread 支持,使用RT-Thread studio可以快速的建立工程,我將分享系列文章,這一篇是如何快速建立工程。 【前題】 安裝好RT-Thread
    發(fā)表于 06-29 18:25

    WCH32V307體驗tcpserver

    的端口,然后發(fā)送一段內(nèi)容,可以接收到發(fā)送的內(nèi)容: 【總結(jié)】 這個塊ch32V307拿到好久了,這次重新體驗了一下tcpserver的示例,下次再體驗mqtt示例。
    發(fā)表于 04-30 17:24

    CH32V307V評估】之HarmonyOS運行

    我們知道CH32V307是基于32位RISC-V內(nèi)核設(shè)計的大容量通用微控制器,搭載V4F內(nèi)核,支持單精度浮點指令集,具有更高的運算性能。支持內(nèi)置PHY收發(fā)器的USB2.0高速接口(480Mbps
    發(fā)表于 04-28 23:38

    國產(chǎn)RISC-V MCU推薦

    這顆芯片,眾望所歸 眾多網(wǎng)友都推薦了微(WCH)的CH32V307。29447945表示最近正好在用RISC-V架構(gòu)的芯片(CH32V307
    發(fā)表于 04-17 11:00

    分享CH32X035評估說明及參考應(yīng)用例程

    定時器等豐富外設(shè)資源,可輕松構(gòu)建電機(jī)方案;同時廣泛應(yīng)用于光伏、儲能電源等相關(guān)領(lǐng)域。 CH32X035評估說明及參考應(yīng)用例程: /elecplay.php?action=show&am
    發(fā)表于 03-18 11:04

    CH32X035可以運行RTT操作系統(tǒng)嗎?

    CH32X035支持USB通訊+PD電源雙功能,集成PIOC、I2C、多組運放/比較器/定時器等豐富片上資源,助您推開Type-C的大門,開啟PDUSB特色應(yīng)用創(chuàng)意之旅。 不知道他
    發(fā)表于 03-18 10:59

    CH32V303_305_307 數(shù)據(jù)手冊

    電子發(fā)燒友網(wǎng)站提供《CH32V303_305_307 數(shù)據(jù)手冊.rar》資料免費下載
    發(fā)表于 01-25 09:08 ?1次下載

    CH32V307 flash操作注意事項

    之前的帖子,我實現(xiàn)了在CH32X035的SD卡IAP升級,想把這個功能在CH32V307上也實現(xiàn)了,但在移植過程中發(fā)現(xiàn)個問題,在應(yīng)用區(qū)程序都是運行在144M的,我的升級方案中會涉及到升級標(biāo)志的寫入
    發(fā)表于 11-30 22:50

    CH32V208 開發(fā)免費試用+ U盤/ SD NAND讀寫與多功能數(shù)碼相框

    CH32V208繼承了恆產(chǎn)品一貫的傳統(tǒng),即U盤的讀寫功能。這使得盡管CH32V208的閃存要比CH32V307的小一倍,但有了U盤讀寫功能的支持就可有效地緩解用戶對存儲空間的需求。它
    的頭像 發(fā)表于 11-10 11:44 ?673次閱讀
    <b class='flag-5'>沁</b><b class='flag-5'>恒</b> <b class='flag-5'>CH32V</b>208 開發(fā)<b class='flag-5'>板</b>免費<b class='flag-5'>試用</b>+ U盤/ SD NAND讀寫與多功能數(shù)碼相框

    CH32V307_DAC輸出正弦波

    CH32V307 DAC輸出正弦波 本文介紹使用CH32V307的DAC功能,從輸出管腳輸出正弦波。 使用到的硬件 CH32V307芯片模塊包含2個可配置8/12位數(shù)模轉(zhuǎn)換器,其引腳分別位PA4
    發(fā)表于 11-09 21:27

    踩坑記錄—RT-Thread Studio燒錄ch32v307

    用RT-Thread Studio向ch32v307vct6燒錄程序,有個前置條件要完成。
    的頭像 發(fā)表于 10-13 15:28 ?3329次閱讀
    踩坑記錄—RT-Thread Studio燒錄<b class='flag-5'>ch32v307</b>

    Linux驅(qū)動定時器使用示例

    定時器使用示例 使用步驟: 1、調(diào)用 init_timer 初始化一個定時器,給 struct timer_list 各成員賦值。 2、調(diào)用 add_timer 將定時器添加到內(nèi)核定時器
    的頭像 發(fā)表于 10-04 15:47 ?572次閱讀

    CH58X系列藍(lán)牙MCU如何實現(xiàn)低功耗觸摸喚醒?

    CH58X系列藍(lán)牙MCU如何實現(xiàn)低功耗觸摸喚醒?
    的頭像 發(fā)表于 09-26 16:27 ?1835次閱讀
    <b class='flag-5'>沁</b><b class='flag-5'>恒</b><b class='flag-5'>CH</b>58X系列藍(lán)牙MCU如何實現(xiàn)低功耗觸摸喚醒?