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输出可能失败。

相关推荐
HAPPY酷11 分钟前
单片机OLED进阶:打造赛博朋克风“碎片化消散”文字特效
单片机·嵌入式硬件·microsoft
czhaii14 分钟前
GB2312简体中文编码表
单片机·算法
玩转单片机与嵌入式16 分钟前
AI 推理会不会堵住实时任务?MCU 上跑模型时,RTOS 和 DMA 该怎么配合?
人工智能·单片机·嵌入式硬件
清风66666643 分钟前
基于单片机的超声波人体感应PWM自动调光灯设计与实现
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
fffzd43 分钟前
STM32:IIC与温湿度传感器(轮询模式)
stm32·单片机·嵌入式硬件·iic·通信·嵌入式软件·i2c
项目題供诗1 小时前
STM32-编码器接口测速(十七)
stm32·单片机·嵌入式硬件
嵌入式小站1 小时前
STM32 零基础可移植教程 19:I2C 读写寄存器,先读一个设备 ID
stm32·单片机·嵌入式硬件
minglie11 小时前
zynq用普通网口在局域网同步
单片机
weixin_467182281 小时前
Arduino进阶二|自定义类库保姆级教程(从零手写属于自己的传感器类库+完整源码)
c语言·c++·单片机·嵌入式硬件·arduino·c++面向对象·diy库文件
清风6666662 小时前
基于单片机的64位多模式流水灯控制系统设计
单片机·毕业设计·课程设计·期末大作业