CH32V203C8T6 定时器TIM2 无法使用

V203C8T6?TIM2模块按照正常初始化不能使用,?由于无法进入调试,?无法得知具体信息,?按照一样的代码,驱动TIM3,?TIM4都是能正常使用的。在TIM2定时器更新中断里翻转IO管脚,用逻辑分析仪是无法看到波形的。TIM3要和TIM4一起启动才能正常使用,单独使用TIM3也是不行。TIM4单独使用是可以的。附件是我的测试代码,使用的VSCode +?CMake编译, OpenOCD下载。编译目标是test_tim.elf

icon_rar.gifwch_ch32v203_TeensyStepC.zip


test_tim.c?代码如下:

/*
?*?@Author:?xiaosenluo?个人信息保护,已隐藏
?*?@Date:?2023-02-06?00:32:59
?*?@LastEditors:?xiaosenluo?个人信息保护,已隐藏
?*?@LastEditTime:?2023-02-12?20:01:54
?*?@FilePath:?\wch_ch32v203_TeensyStepC\User\Test\test_tim.c
?*?@Description:?
?*?
?*?Copyright?(c)?2023?by?${git_name_email},?All?Rights?Reserved.?
?*/
/**********************************?(C)?COPYRIGHT?*******************************
?*?File?Name??????????:?main.c
?*?Author?????????????:?WCH
?*?Version????????????:?V1.0.0
?*?Date???????????????:?2021/06/06
?*?Description????????:?Main?program?body.
?*?Copyright?(c)?2021?Nanjing?Qinheng?Microelectronics?Co.,?Ltd.
?*?SPDX-License-Identifier:?Apache-2.0
?*******************************************************************************/


#include?"debug.h"
#include?"IQmath_RV32.h"
#include?"string.h"
#include?"ch32v20x_it.h"

/*?Global?define?*/

/*?Global?Variable?*/
/*********************************************************************
?*?@fn??????NMI_Handler
?*
?*?@brief???This?function?handles?NMI?exception.
?*
?*?@return??none
?*/
void?NMI_Handler(void)
{
}

/*********************************************************************
?*?@fn??????HardFault_Handler
?*
?*?@brief???This?function?handles?Hard?Fault?exception.
?*
?*?@return??none
?*/
void?HardFault_Handler(void)
{
??while?(1)
??{
??}
}


/*********************************************************************
?*?@fn??????GPIO_Toggle_INIT
?*
?*?@brief???Initializes?GPIOA.0
?*
?*?@return??none
?*/
void?GPIO_Toggle_INIT(void)
{
????GPIO_InitTypeDef?GPIO_InitStructure?=?{0};

????RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,?ENABLE);
????GPIO_InitStructure.GPIO_Pin?=?GPIO_Pin_0?|?GPIO_Pin_14?|?GPIO_Pin_12;
????GPIO_InitStructure.GPIO_Mode?=?GPIO_Mode_Out_PP;
????GPIO_InitStructure.GPIO_Speed?=?GPIO_Speed_50MHz;
????GPIO_Init(GPIOA,?&GPIO_InitStructure);

????RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,?ENABLE);
????GPIO_InitStructure.GPIO_Pin?=?GPIO_Pin_7?|?GPIO_Pin_5?|?GPIO_Pin_3?|?GPIO_Pin_1?|?GPIO_Pin_10?|?GPIO_Pin_12;
????GPIO_InitStructure.GPIO_Mode?=?GPIO_Mode_Out_PP;
????GPIO_InitStructure.GPIO_Speed?=?GPIO_Speed_50MHz;
????GPIO_Init(GPIOB,?&GPIO_InitStructure);
}

void?GPIO_Toggle(GPIO_TypeDef?*GPIOx,?uint16_t?Pinx){
????uint32_t?state?=?GPIOx->OUTDR;

????if(state?&?Pinx){???///?high
????????GPIOx->BCR?=?Pinx;
????}else{
????????GPIOx->BSHR?=?Pinx;
????}
}

void?TIM2_IRQHandler(void){
????if(TIM_GetFlagStatus(TIM2,?TIM_FLAG_Update)?==?SET){
????????TIM_ClearFlag(TIM2,?TIM_FLAG_Update);
????????GPIO_Toggle(GPIOB,?GPIO_Pin_1);
????}
}
void?TIM3_IRQHandler(void){
????if(TIM_GetFlagStatus(TIM3,?TIM_FLAG_Update)?==?SET){
????????TIM_ClearFlag(TIM3,?TIM_FLAG_Update);
????????GPIO_Toggle(GPIOB,?GPIO_Pin_10);
????}
}

void?TIM4_IRQHandler(void){
????if(TIM_GetFlagStatus(TIM4,?TIM_FLAG_Update)?==?SET){
????????TIM_ClearFlag(TIM4,?TIM_FLAG_Update);
????????GPIO_Toggle(GPIOB,?GPIO_Pin_3);
????}
????if(TIM_GetFlagStatus(TIM4,?TIM_FLAG_CC1)?==?SET){
????????TIM_ClearFlag(TIM4,?TIM_FLAG_CC1);
????????GPIO_Toggle(GPIOB,?GPIO_Pin_12);
????}
}

#define?TIM_CLK_PSC??????36000000
#define?STEP_TIM_CLK?????9000000
#define?ACC_TIM_CLK??????1000000

#define?TIMERFIELD_START(tim)??do{?\
????TIM_ARRPreloadConfig(tim,?ENABLE);?\
????TIM_ClearFlag(tim,?TIM_FLAG_Update);?\
????TIM_ITConfig(tim,?TIM_IT_Update,?ENABLE);?\
????TIM_Cmd(tim,?ENABLE);?\
}while(0)

#define?TIMERFIELD_STOP(tim)??do{?\
????TIM_Cmd(tim,?DISABLE);?\
????TIM_ClearFlag(tim,?TIM_FLAG_Update);?\
????TIM_ITConfig(tim,?TIM_IT_Update,?DISABLE);?\
}while(0)


/*********************************************************************
?*?@fn??????main
?*
?*?@brief???Main?program.
?*
?*?@return??none
?*/
int?main(void)
{
????SystemCoreClockUpdate();
????NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
????Delay_Init();
????USART_Printf_Init(115200);
????GPIO_Toggle_INIT();
????printf("SystemClk:%ld\r\n",?SystemCoreClock);


????TIM_TimeBaseInitTypeDef?TIM_TimeBaseInitStructure?=?{?0?};
????TIM_OCInitTypeDef?TIM_OCInitStructure={?0?};
????RCC_ClocksTypeDef?RCC_Clocks?=?{?0?};
???
????uint32_t?tim_clk?=?144000000,?priod?=?144,?presc?=?1;

????RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,?ENABLE);
????RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,?ENABLE);
????RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,?ENABLE);
???
????RCC_GetClocksFreq(&RCC_Clocks);
????tim_clk?=?RCC_Clocks.PCLK1_Frequency;
????if(!(RCC->CFGR0?&?RCC_PPRE1_DIV1)){
????????tim_clk?<<=?1;
????}

????tim_clk?/=?4;
????presc?=?(tim_clk?/?STEP_TIM_CLK)?-?1;
????priod?=?27;???///?默认间隔?3US

????TIM_TimeBaseInitStructure.TIM_ClockDivision?=?TIM_CKD_DIV4;
????TIM_TimeBaseInitStructure.TIM_CounterMode?=?TIM_CounterMode_Up;
????TIM_TimeBaseInitStructure.TIM_Period?=?1000;
????TIM_TimeBaseInitStructure.TIM_Prescaler?=?16;

????TIM_TimeBaseInit(TIM2,?&TIM_TimeBaseInitStructure);
????TIM_ARRPreloadConfig(TIM2,?ENABLE);
????TIM_Cmd(TIM2,?DISABLE?);
????TIM_ClearFlag(TIM2,?TIM_FLAG_Update);


????///?计数频率?9MHz,?用于输出?Step?脉冲
????TIM_TimeBaseInitStructure.TIM_Period?=?1800;
????TIM_TimeBaseInit(TIM4,?&TIM_TimeBaseInitStructure);
????TIM_ARRPreloadConfig(TIM4,?ENABLE);
????TIM_Cmd(TIM4,?DISABLE?);
????TIM_ClearFlag(TIM4,?TIM_FLAG_Update);


????///?用于设置加速间隔
????//?TIM_TimeBaseInitStructure.TIM_Prescaler?=?16;
????TIM_TimeBaseInitStructure.TIM_Period?=?800;
????TIM_TimeBaseInit(TIM3,?&TIM_TimeBaseInitStructure);
????TIM_ARRPreloadConfig(TIM3,?ENABLE);
????TIM_Cmd(TIM3,?DISABLE?);
????TIM_ClearFlag(TIM3,?TIM_FLAG_Update);

????//?TIM_OCInitStructure.TIM_OCMode?=?TIM_OCMode_Timing;
????//?TIM_OCInitStructure.TIM_OutputState?=?TIM_OutputState_Disable;
????//?TIM_OCInitStructure.TIM_Pulse?=?100;???///?默认宽度?2US
????//?TIM_OCInitStructure.TIM_OCPolarity?=?TIM_OCPolarity_Low;

????//?TIM_OC1Init(?TIM4,?&TIM_OCInitStructure?);
????//?TIM_OC1PreloadConfig(TIM4,?TIM_OCPreload_Disable);
????//?TIM_ClearFlag(TIM4,?TIM_FLAG_CC1);
????//?TIM_ITConfig(TIM4,?TIM_IT_CC1,?ENABLE);
???
????NVIC_SetPriority(TIM2_IRQn,?2);
????NVIC_SetPriority(TIM3_IRQn,?2);
????NVIC_SetPriority(TIM4_IRQn,?2);
???
????NVIC_EnableIRQ(TIM2_IRQn);
????NVIC_EnableIRQ(TIM3_IRQn);
????NVIC_EnableIRQ(TIM4_IRQn);
???
????TIMERFIELD_START(TIM2);
????//?TIMERFIELD_START(TIM3);
????TIMERFIELD_START(TIM4);


????while(1)
????{
????????Delay_Ms(250);
????????GPIO_Toggle(GPIOA,?GPIO_Pin_0);
????}
}


CMakeLists.txt内容如下:

cmake_minimum_required(VERSION?3.15)

set(CMAKE_SYSTEM_NAME?Generic)
set(CMAKE_SYSTEM_PROCESSOR?riscv)

set(CMAKE_C_COMPILER?riscv-none-embed-gcc)
set(CMAKE_CXX_COMPILER?riscv-none-embed-g++)
set(CMAKE_ASM_COMPILER?riscv-none-embed-gcc)
set(CMAKE_LINKER?riscv-none-embed-ld)
set(CMAKE_AR?riscv-none-embed-ar)
set(CMAKE_OBJCOPY?riscv-none-embed-objcopy)
set(CMAKE_OBJDUMP?riscv-none-embed-objdump)
set(SIZE?riscv-none-embed-size)
set(GDB?riscv-none-embed-gdb)

set(CMAKE_TRY_COMPILE_TARGET_TYPE?STATIC_LIBRARY)

#?set(CMAKE_EXECUTABLE_SUFFIX_C?".elf")

set(CMAKE_C_STANDARD?11)
set(CMAKE_CXX_STANDARD?17)


#?设置编译目标变量
#?set(PRJ_TARGET?"wch_template")
#?设置项目名称
project(wch_ch32v203_TeensyStepC?LANGUAGES?C?CXX?ASM)
#?设置项目根目录路径变量
#?set(PRJ_DIR?"C:/UserTemp/wch_cmake_template")

#?add_executable(${PRJ_TARGET})
#?set_target_properties(${PRJ_TARGET}?PROPERTIES?LINKER_LANGUAGE?C)

#?target_sources(${PRJ_TARGET}?PUBLIC
#?????????"${PRJ_DIR}/User/main.c")

#?MCU设置
add_compile_options(-march=rv32imac?-mabi=ilp32?-msmall-data-limit=8?-mno-save-restore)

#?优化设置
#?add_compile_options(-Os?-g3)

#?标准设置
#?add_compile_options(-std=gnu99)

#?编译设置
add_compile_options(
????????-Os
????????-Wall
????????-Wfatal-errors
????????-Wunused
????????-Wuninitialized
????????-fmessage-length=0
????????-ffunction-sections
????????-fdata-sections
????????-fsigned-char)

#?处理ASM文件
add_compile_options($)

if?("${CMAKE_BUILD_TYPE}"?STREQUAL?"Release")
????message(STATUS?"Maximum?optimization?for?speed")
????add_compile_options(-Ofast)
elseif?("${CMAKE_BUILD_TYPE}"?STREQUAL?"RelWithDebInfo")
????message(STATUS?"Maximum?optimization?for?speed,?debug?info?included")
????add_compile_options(-Ofast?-g)
elseif?("${CMAKE_BUILD_TYPE}"?STREQUAL?"MinSizeRel")
????message(STATUS?"Maximum?optimization?for?size")
????add_compile_options(-Os)
else?()
????message(STATUS?"Minimal?optimization,?debug?info?included")
????add_compile_options(-Og?-g)
endif?()


include_directories(
????????"C:/wch/tools/wch_riscv_gcc_8_2_0/riscv-none-embed/include"
????????"C:/wch/tools/wch_riscv_gcc_8_2_0/lib/gcc/riscv-none-embed/8.2.0/include"
????????"C:/wch/tools/wch_riscv_gcc_8_2_0/lib/gcc/riscv-none-embed/8.2.0/include-fixed"
????????"Peripheral/inc"
????????"Core"
????????"Debug"
)

file(GLOB_RECURSE?COMMENT_SOURCE_FILE
????????"Startup/startup_ch32v20x_D6.S"
????????"Core/core_riscv.c"
????????"Debug/debug.c"
????????"Peripheral/src/ch32v20x_adc.c"
????????"Peripheral/src/ch32v20x_bkp.c"
????????"Peripheral/src/ch32v20x_can.c"
????????"Peripheral/src/ch32v20x_crc.c"
????????"Peripheral/src/ch32v20x_dac.c"
????????"Peripheral/src/ch32v20x_dbgmcu.c"
????????"Peripheral/src/ch32v20x_dma.c"
????????"Peripheral/src/ch32v20x_exti.c"
????????"Peripheral/src/ch32v20x_flash.c"
????????"Peripheral/src/ch32v20x_gpio.c"
????????"Peripheral/src/ch32v20x_i2c.c"
????????"Peripheral/src/ch32v20x_iwdg.c"
????????"Peripheral/src/ch32v20x_misc.c"
????????"Peripheral/src/ch32v20x_opa.c"
????????"Peripheral/src/ch32v20x_pwr.c"
????????"Peripheral/src/ch32v20x_rcc.c"
????????"Peripheral/src/ch32v20x_rng.c"
????????"Peripheral/src/ch32v20x_rtc.c"
????????"Peripheral/src/ch32v20x_spi.c"
????????"Peripheral/src/ch32v20x_tim.c"
????????"Peripheral/src/ch32v20x_usart.c"
????????"Peripheral/src/ch32v20x_wwdg.c"
????????"User/uart_printf.c"
)



add_compile_definitions(PRINTF_ALIAS_STANDARD_FUNCTION_NAMES=1)
add_subdirectory(Components/printf)
link_libraries(printf)

link_directories("C:/wch/tools/wch_riscv_gcc_8_2_0/riscv-none-embed/lib/rv32imac/ilp32")

#?添加?IQmath
add_compile_definitions(MATH_TYPE=IQ_MATH?GLOBAL_Q=6)
#?include_directories(Components/IQmath_RV32)
link_libraries(IQmath_RV32)
link_libraries(m)

set(LINKER_SCRIPT?${CMAKE_SOURCE_DIR}/Ld/Link.ld)
#?链接设置
add_link_options(-march=rv32imac?-mabi=ilp32)
add_link_options(-ffunction-sections?-fdata-sections?-fmessage-length=0?-fstack-usage)

#add_link_options(-std=gnu11)
add_link_options(-Wall?-Wfatal-errors)
add_link_options(-Wl,-check-sections?-Wl,-fatal-warnings?-Wl,--gc-sections?-Wl,--print-memory-usage)
add_link_options(-T?${LINKER_SCRIPT})
add_link_options(-nostartfiles?-Xlinker?--gc-sections)
add_link_options("-Wl,-Map,${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map"?-Wl,--cref)
add_link_options(--specs=nano.specs?--specs=nosys.specs)
add_link_options(-lm)

add_executable(${PROJECT_NAME}.elf?${COMMENT_SOURCE_FILE}?User/main.c)
if?("${CMAKE_BUILD_TYPE}"?STREQUAL?"Release")
????message(STATUS?"Maximum?optimization?for?speed")
????target_compile_options(${PROJECT_NAME}.elf?PRIVATE?-Ofast)
elseif?("${CMAKE_BUILD_TYPE}"?STREQUAL?"RelWithDebInfo")
????message(STATUS?"Maximum?optimization?for?speed,?debug?info?included")
????target_compile_options(${PROJECT_NAME}.elf?PRIVATE?-Og)
elseif?("${CMAKE_BUILD_TYPE}"?STREQUAL?"MinSizeRel")
????message(STATUS?"Maximum?optimization?for?size")
????target_compile_options(${PROJECT_NAME}.elf?PRIVATE?-Os)
else?()
????message(STATUS?"Minimal?optimization,?debug?info?included")
????target_compile_options(${PROJECT_NAME}.elf?PRIVATE?-Og?-g)
endif?()

target_include_directories(${PROJECT_NAME}.elf?PRIVATE?User)

target_sources(${PROJECT_NAME}.elf?PRIVATE?
????"User/ch32v20x_it.c"
????"User/system_ch32v20x.c"
????"User/tim.c"
)

target_include_directories(${PROJECT_NAME}.elf?PRIVATE?Components/TeensyStepC/src)
target_sources(${PROJECT_NAME}.elf?PRIVATE?
????"Components/TeensyStepC/src/Stepper.c"
????"Components/TeensyStepC/src/StepControlBase.c"
????"Components/TeensyStepC/src/RotateControlBase.c"
????"Components/TeensyStepC/src/MotorControlBase.c"
????"Components/TeensyStepC/src/ErrorHandler.c"
????"Components/TeensyStepC/src/accelerators/LinStepAccelerator.c"
????"Components/TeensyStepC/src/accelerators/LinRotAccelerator.c"
????"Components/TeensyStepC/src/accelerators/SinRotAccelerator.c"
????"Components/TeensyStepC/src/port/timer/wch/TimerField.c"
)

target_include_directories(${PROJECT_NAME}.elf?PRIVATE?Components/bget)
target_sources(${PROJECT_NAME}.elf?PRIVATE?
????"Components/bget/bget.c"
)

include(User/Test/test_tim.cmake)


set(HEX_FILE?${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE?${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
set(LIST_FILE?${PROJECT_BINARY_DIR}/${PROJECT_NAME}.list)

add_custom_command(TARGET?${PROJECT_NAME}.elf?POST_BUILD
????????COMMAND?${SIZE}?--format=berkeley?$????????COMMAND?${CMAKE_OBJDUMP}?--all-headers?--demangle?--disassemble?$?>?${LIST_FILE}
????????COMMAND?${CMAKE_OBJCOPY}?-O?ihex?$?${HEX_FILE}
????????COMMAND?${CMAKE_OBJCOPY}?-O?binary?$?${BIN_FILE}
????????COMMENT?"Building?${HEX_FILE}
Building?${BIN_FILE}")


test_tim.cmake?内容如下:

add_executable(test_tim.elf?${COMMENT_SOURCE_FILE}?${COMMENT_SOURCE_FILE}?User/Test/test_tim.c)
target_include_directories(test_tim.elf?PRIVATE?User)
target_compile_options(test_tim.elf?PRIVATE?-Os)
target_sources(test_tim.elf?PRIVATE?
????"User/system_ch32v20x.c"
????"User/tim.c"
)

set(HEX_FILE?${PROJECT_BINARY_DIR}/test_tim.hex)
set(BIN_FILE?${PROJECT_BINARY_DIR}/test_tim.bin)
set(LIST_FILE?${PROJECT_BINARY_DIR}/test_tim.list)

add_custom_command(TARGET?test_tim.elf?POST_BUILD
????????COMMAND?${SIZE}?--format=berkeley?$????????COMMAND?${CMAKE_OBJDUMP}?--all-headers?--demangle?--disassemble?$?>?${LIST_FILE}
????????COMMAND?${CMAKE_OBJCOPY}?-O?ihex?$?${HEX_FILE}
????????COMMAND?${CMAKE_OBJCOPY}?-O?binary?$?${BIN_FILE}
????????COMMENT?"Building?${HEX_FILE}
Building?${BIN_FILE}")


麻烦看看是定时器Bug还是代码有问题,?麻烦给一个TIM2,3,4测试代码,?邮箱? 个人信息保护,已隐藏

邮箱: 个人信息保护,已隐藏


您好,附件为CH32V203C8T6 TIM2、3、4同时使用的一个例程,在定时器更新中断中进行IO翻转,可以参考一下,如下图。后续若有问题,可通过邮箱进行沟通(lzs@wch.cn)

icon_rar.gifCH32V203 C8T6-TIM2、3、4中断.zip

image.png


请问动态修改ARR寄存器的值需要注意什么, 还有中断设置需要注意什么, 我测试的时候发现,TIM4在正常工作后, TIM3计数完成一个周期触发Update中断, 然后TIM4莫名其妙不工作了, 但是TIM3是可以继续工作的, TIM3中断里会计算TIM4新的输出频率, 然后更新TIM4的ARR寄存器, 我觉得问题在于动态修改ARR, 数据手册说了ARR在何时加载到CNT, 却没说更新ARR需要什么事项, 按照一般来说是可以随时更新ARR的。


您好,可参考下图,设置好ARR之后再调用TIM_ARRPreloadConfig函数使能一下

image.png


XSL2023-02-13_22-00-12.jpgg.jpg

终于搞懂了。非常感谢!但还是有以下小问题,希望解答:

  1.  中断频率非常高时,定时器也会停止工作,设定计数频率为9MHz时,ARR=10会导致定时器停止工作。我测试过主频144MHz,中断内部执行过程会小于900nS,加上压栈出栈开销,时间应该大于1US,按照中断响应逻辑,同级别的无法抢占,所以第二次Update需要等待第一次的响应完成才会响应,这个造成后果应该是一直在响应Update,不应该造成定时器停止工作。


您好,可将中断函数设置为不同的优先级测试一下是否会有该问题,后续若有问题,可将工程发至我的邮箱(lzs@wch.cn)具体看一下,后续问题也可通过邮箱进行沟通交流。



楼主找到问题了吗,我和你一样,TIM2和TIM1一样的配置,但是就是无法显示波形


楼主找到问题了吗,我和你一样,TIM2和TIM1一样的配置,但是就是无法显示波形


您好,附件为CH32V203 TIM2 PWM输出例程,可以参考一下。使能开始对应定时器通道PWM输出,要注意程序配置,如下图。

icon_rar.gifCH32V203C8T6 TIM2 PWM.zip

image.png




image.png


image.png



注意管脚复用功能, 我的使用场景用不到PWM, 仅仅用到输出比较中断




有定时器5使用PWM输出的吗,我用的定时器234例程改的没有PWM输出





您好,CH32V203C8T6没有TIM5,只有高级定时器TIM1和通用定时器TIM2、3、4,没有TIM5


只有登录才能回复,可以选择微信账号登录