CH32V103C8T6的时钟操作

CH32V103C8T6引脚和STM32F103C8T6完全兼容,市场上销售的最小系统板采用公版设计,价格不到10元。但CH32V103需要WCH-Link开发,好在便宜,还自带一个串口,性价比还是不错的。

电路图如下:

仍以点灯为例:

MounRiver Studio+WCH-Link调通CH32V103C-CSDN博客

由于其LED所接的引脚为PC13,需要进行适当调整,完整代码如下:

复制代码
#include "debug.h"
void GPIO_Toggle_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}
int main(void)
{
    u8 i = 0;
    SystemCoreClockUpdate();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    Delay_Init();
    USART_Printf_Init(115200);
    printf("SystemClk:%d\r\n", SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );
    printf("GPIO Toggle TEST\r\n");
    GPIO_Toggle_INIT();
    while(1)
    {
        Delay_Ms(1000);
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
    }
}

打开User->system_ch32v10x.c文件,找到以下部分,根据提示进行修改

复制代码
#define SYSCLK_FREQ_HSE    HSE_VALUE   //使用外部时钟,默认是8M
//#define SYSCLK_FREQ_48MHz_HSE  48000000 //使用外部时钟,经锁相环PLL倍频成48M
//#define SYSCLK_FREQ_56MHz_HSE  56000000 //使用外部时钟,经锁相环PLL倍频成56M
//#define SYSCLK_FREQ_72MHz_HSE  72000000 //使用外部时钟,经锁相环PLL倍频成72M
//#define SYSCLK_FREQ_HSI    HSI_VALUE    //使用内部时钟,默认是8M
//#define SYSCLK_FREQ_48MHz_HSI  48000000 //使用内部时钟,经锁相环PLL倍频成48M
//#define SYSCLK_FREQ_56MHz_HSI  56000000 //使用内部时钟,经锁相环PLL倍频成56M
//#define SYSCLK_FREQ_72MHz_HSI  72000000 //使用内部时钟,经锁相环PLL倍频成72M

其中,HSE_VALUE和HSI_VALUE都可以在

Peripheral->inc->ch32v10x.h文件内进行修改

选用12.288M外部晶振,常用的uart通信速率并经测试成功,充分利用WCH-Link的自带串口,将其上的RX接开发板的A9引脚,参考如下:

38400,19200,9600

define SYSCLK_FREQ_48MHz_HSE 48000000后面的48000000,改为73728000,此时选用73.728M时钟,常用的uart通信速率并测试成功,参考如下:

921600(*),460800(*),230400,115200,57600,38400,19200,9600

*921600和460800会出现乱码,是因为受制于WCH-Link串口的硬件限制,改为FT232或CH340等将工作正常。

输出一个2.048M的方波以及8KHz的正脉冲,其脉冲宽度在1us左右,全部代码(AI辅助完成)如下:

复制代码
#include "debug.h"
#include "ch32v10x_tim.h"

/* ================= 引脚定义 ================= */
// 2.048MHz 方波输出 (TIM2_CH1, PA0)
#define PIN_2M_GPIO        GPIOA
#define PIN_2M_PIN         GPIO_Pin_0
#define PIN_2M_TIM         TIM2
#define PIN_2M_CHANNEL     1

// 8kHz 976ns 正脉冲输出 (TIM4_CH1, PB6)
#define PIN_8K_GPIO        GPIOB
#define PIN_8K_PIN         GPIO_Pin_6
#define PIN_8K_TIM         TIM4
#define PIN_8K_CHANNEL     1

/* ================= 时钟参数 ================= */
#define SYSCLK_HZ          73728000UL      // 系统时钟 73.728 MHz
#define T_SYSCLK_NS        13.56f          // 单个系统时钟周期 ≈ 13.56 ns

/* ================= 2.048MHz 方波参数 ================= */
// 2.048MHz 周期 = 73.728MHz / 2.048MHz = 36 个系统时钟
#define ARR_2M             35              // 自动重载值 = 36 - 1
#define CCR_2M             17              // 比较值 = 17 → 高电平持续 18 个时钟 (占空比 50%)

/* ================= 8kHz 976ns 脉冲参数 ================= */
// 8kHz 周期 = 125 μs = 73.728MHz / 8000 = 9216 个系统时钟
#define ARR_8K             9215            // 自动重载值 = 9216 - 1
// 976ns 脉宽 = 976ns / 13.56ns ≈ 72 个系统时钟 → 比较值设为 71 (高电平持续 72 个时钟)
#define CCR_8K             71              // 高电平持续 72 个时钟 → 实际脉宽 = 72 × 13.56ns = 976.3ns

/* ================= 函数声明 ================= */
void PWM_2M_Init(void);
void PWM_8K_Init(void);
void GPIO_Toggle_INIT(void);

/* 初始化 2.048MHz 方波 (PA0, TIM2_CH1) */
void PWM_2M_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    // 配置 PA0 为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = PIN_2M_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(PIN_2M_GPIO, &GPIO_InitStructure);

    // 定时器 TIM2 时基配置
    TIM_TimeBaseStructure.TIM_Period = ARR_2M;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(PIN_2M_TIM, &TIM_TimeBaseStructure);

    // PWM1 模式,高电平有效
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR_2M;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(PIN_2M_TIM, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(PIN_2M_TIM, TIM_OCPreload_Enable);

    // 使能自动重装载和定时器
    TIM_ARRPreloadConfig(PIN_2M_TIM, ENABLE);
    TIM_Cmd(PIN_2M_TIM, ENABLE);
}

/* 初始化 8kHz 976ns 正脉冲 (PB6, TIM4_CH1) */
void PWM_8K_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    // 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   // 使能 TIM4 时钟

    // 配置 PB6 为复用推挽输出
    GPIO_InitStructure.GPIO_Pin = PIN_8K_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(PIN_8K_GPIO, &GPIO_InitStructure);

    // 定时器 TIM4 时基配置:周期 8kHz
    TIM_TimeBaseStructure.TIM_Period = ARR_8K;
    TIM_TimeBaseStructure.TIM_Prescaler = 0;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(PIN_8K_TIM, &TIM_TimeBaseStructure);

    // PWM1 模式,高电平有效,脉宽 = (CCR_8K+1) 个系统时钟
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = CCR_8K;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init(PIN_8K_TIM, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(PIN_8K_TIM, TIM_OCPreload_Enable);

    // 使能自动重装载和定时器
    TIM_ARRPreloadConfig(PIN_8K_TIM, ENABLE);
    TIM_Cmd(PIN_8K_TIM, ENABLE);
}

/* 初始化 PC13 翻转(用于指示程序运行状态) */
void GPIO_Toggle_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}

int main(void)
{
    u8 i = 0;
    SystemCoreClockUpdate();
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    Delay_Init();
    USART_Printf_Init(115200);

    // 打印系统信息
    printf("SystemClk: %d Hz\r\n", SystemCoreClock);
    printf("ChipID: %08x\r\n", DBGMCU_GetCHIPID());
    printf("GPIO Toggle TEST\r\n");

    // 初始化 PA0 输出 2.048MHz 方波
    PWM_2M_Init();
    printf("2.048MHz square wave output on PA0 (TIM2_CH1)\r\n");

    // 初始化 PB6 输出 8kHz 976ns 正脉冲
    PWM_8K_Init();
    printf("8kHz positive pulse (width 976ns) output on PB6 (TIM4_CH1)\r\n");
    printf("  -> Pulse width = 976ns (2 BCLK cycles @ 2.048MHz)\r\n");
    printf("  -> Compatible with TP3057 Short-Frame mode (1-2 BCLK cycles)\r\n");

    // 初始化 PC13 翻转
    GPIO_Toggle_INIT();
    printf("PC13 toggles every 1 second (period 2s)\r\n");

    while(1)
    {
        Delay_Ms(1000);
        // 每秒钟翻转一次 PC13
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
    }
}

以上代码,用作TIM1、TIM3输出可能失败。

相关推荐
不做无法实现的梦~1 小时前
SBUS 接收机到 STM32:为什么要做硬件反相、如何解析数据、如何接线与实现代码
stm32·单片机·嵌入式硬件
一路往蓝-Anbo2 小时前
第二章:隔离硬件 —— 利用 CMock 伪造 GPIO 与定时器
stm32·单片机·嵌入式硬件·软件工程·信息与通信·tdd
刘延林.3 小时前
esp32 s3+micpython快速验证ML307R 是否能正常连接4G
单片机·嵌入式硬件
不做无法实现的梦~8 小时前
86步进电机和DM860H驱动器的使用方法和记录
单片机·嵌入式硬件
Aaron15889 小时前
RFSOC+VU13P/VU9P+GPU多通道同步一体化解决方案
人工智能·嵌入式硬件·算法·matlab·fpga开发·硬件架构·基带工程
所见即所得111119 小时前
stm32烧录过程中串口问题(串口被占用无法使用)
stm32·单片机·嵌入式硬件
Freak嵌入式9 小时前
WIZnet-EVB-Pico2开始,用MicroPython玩转以太网开发
arm开发·人工智能·python·嵌入式硬件·机器人·嵌入式·micropython
Ligocious10 小时前
stm32---1.两种开发方式点亮LED
stm32·单片机
黑白园10 小时前
STM32F103C8TC使用ST-Link下载
stm32·单片机·嵌入式硬件