您尚未登录。

#1 全志 SOC » F1C200S纯裸机的定时器中断问题求解 » 2026-04-03 18:40:36

435788A
回复: 0

F1C200S纯裸机的定时器中断调不出来。
定时器0作延时delay_us()、delay_ms()正常,但定时器1、定时器2中断无反映。
上传失败了,只好粘贴:

#ifndef __F1C100S_TIMER_H__
#define __F1C100S_TIMER_H__

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

//=============================================================================
// 定时器编号定义
//=============================================================================
#define TIMER0  0
#define TIMER1  1
#define TIMER2  2

//=============================================================================
// 延时函数接口(使用TIMER0)
//=============================================================================

/**
* @brief 初始化延时定时器(TIMER0)
* @note 需要在系统初始化时调用一次
*/
void delay_init(void);

/**
* @brief 微秒级延时
* @param us 延时的微秒数(0~178956970)
*/
void delay_us(uint32_t us);

/**
* @brief 毫秒级延时
* @param ms 延时的毫秒数
*/
void delay_ms(uint32_t ms);

/**
* @brief 高精度微秒级延时(循环延时)
* @param us 延时的微秒数(建议小于100)
*/
void delay_us_precise(uint32_t us);

/**
* @brief 低功耗毫秒级延时(使用32KHz时钟)
* @param ms 延时的毫秒数
*/
void delay_ms_lowpower(uint32_t ms);

/**
* @brief 获取定时器当前值
* @return 当前递减计数值
*/
uint32_t delay_get_current_value(void);

/**
* @brief 检查定时器状态
* @return 1-运行中,0-已停止
*/
int delay_is_running(void);

/**
* @brief 停止延时定时器
*/
void delay_stop(void);

//=============================================================================
// 定时器1接口(中断模式,1秒中断)
//=============================================================================

/**
* @brief 初始化定时器1,配置为1秒中断
* @param callback 可选的中断回调函数(为NULL则使用内部计数器)
* @note 中断号:F1C100S_IRQ_TIMER1 (14)
*/
void timer1_init(void (*callback)(void));

/**
* @brief 启动定时器1
*/
void timer1_start(void);

/**
* @brief 停止定时器1
*/
void timer1_stop(void);

/**
* @brief 获取定时器1中断计数(每秒加1)
* @return 中断触发次数
*/
uint32_t timer1_get_count(void);

/**
* @brief 清除定时器1计数
*/
void timer1_clear_count(void);

/**
* @brief 检查定时器1是否正在运行
* @return 1-运行中,0-已停止
*/
int timer1_is_running(void);

//=============================================================================
// 定时器2接口(中断模式,1秒中断)
//=============================================================================

/**
* @brief 初始化定时器2,配置为1秒中断
* @param callback 可选的中断回调函数(为NULL则使用内部计数器)
* @note 中断号:F1C100S_IRQ_TIMER2 (15)
*/
void timer2_init(void (*callback)(void));

/**
* @brief 启动定时器2
*/
void timer2_start(void);

/**
* @brief 停止定时器2
*/
void timer2_stop(void);

/**
* @brief 获取定时器2中断计数(每秒加1)
* @return 中断触发次数
*/
uint32_t timer2_get_count(void);

/**
* @brief 清除定时器2计数
*/
void timer2_clear_count(void);

/**
* @brief 检查定时器2是否正在运行
* @return 1-运行中,0-已停止
*/
int timer2_is_running(void);

//=============================================================================
// AVS计数器接口
//=============================================================================

/**
* @brief 初始化AVS计数器
* @param counter_id 计数器ID (0 或 1)
* @param divisor 分频系数(1~2047),计数时钟 = 24MHz / divisor
* @param initial_value 初始计数值(33位,低1位必须为0)
* @return 0-成功,-1-失败
*/
int avs_counter_init(uint32_t counter_id, uint16_t divisor, uint64_t initial_value);

/**
* @brief 启动AVS计数器
* @param counter_id 计数器ID (0 或 1)
*/
void avs_counter_start(uint32_t counter_id);

/**
* @brief 暂停AVS计数器
* @param counter_id 计数器ID (0 或 1)
*/
void avs_counter_pause(uint32_t counter_id);

/**
* @brief 停止AVS计数器
* @param counter_id 计数器ID (0 或 1)
*/
void avs_counter_stop(uint32_t counter_id);

/**
* @brief 读取AVS计数器当前值
* @param counter_id 计数器ID (0 或 1)
* @return 33位计数值
*/
uint64_t avs_counter_read(uint32_t counter_id);

/**
* @brief 设置AVS计数器值
* @param counter_id 计数器ID (0 或 1)
* @param value 33位计数值(必须为偶数)
* @return 0-成功,-1-失败
*/
int avs_counter_set(uint32_t counter_id, uint64_t value);

/**
* @brief 配置AVS计数器分频
* @param counter_id 计数器ID (0 或 1)
* @param divisor 分频系数(1~2047)
*/
void avs_counter_set_divisor(uint32_t counter_id, uint16_t divisor);

/**
* @brief 获取AVS计数器当前分频值
* @param counter_id 计数器ID (0 或 1)
* @return 分频系数
*/
uint16_t avs_counter_get_divisor(uint32_t counter_id);

/**
* @brief 复位AVS计数器
* @param counter_id 计数器ID (0 或 1)
*/
void avs_counter_reset(uint32_t counter_id);

/**
* @brief 初始化两个AVS计数器为默认配置
* @note 默认配置:1MHz计数频率(1us步进),从0开始计数
*/
void avs_counters_init_default(void);

/**
* @brief 获取AVS计数器计时的微秒数
* @param counter_id 计数器ID (0 或 1)
* @return 微秒数(基于当前分频设置)
*/
uint64_t avs_counter_get_us(uint32_t counter_id);

/**
* @brief 等待AVS计数器达到指定值
* @param counter_id 计数器ID (0 或 1)
* @param target 目标计数值
* @param timeout_us 超时微秒数(0表示无限等待)
* @return 0-达到目标,-1-超时
*/
int avs_counter_wait(uint32_t counter_id, uint64_t target, uint32_t timeout_us);

#ifdef __cplusplus
}
#endif

#endif // __F1C100S_TIMER_H__



====================================================================================================================================================================================================================================================================================================================================================================================================================================



C文件:

// F1C100S/F1C200s裸机定时器驱动
#include <stdint.h>
#include "io.h"
#include "f1c100s_timer.h"
#include "f1c100s-irq.h"
#include "f1c100s_timer.h"
#include "ftypes.h"

//=============================================================================
// 寄存器定义
//=============================================================================

// F1C100S/F1C200s Timer寄存器基地址
#define TIMER0_REG_BASE  (0x01C20C00UL)
#define TIMER1_REG_BASE  (0x01C20C20UL)
#define TIMER2_REG_BASE  (0x01C20C40UL)

// Timer寄存器偏移地址
#define TIMER_IRQ_EN_REG     0x00  // 定时器中断使能寄存器
#define TIMER_IRQ_STA_REG    0x04  // 定时器中断状态寄存器
#define TIMER_CTRL_REG       0x10  // 定时器控制寄存器
#define TIMER_INTV_VALUE_REG 0x14  // 定时器间隔值寄存器,32位
#define TIMER_CUR_VALUE_REG  0x18  // 定时器当前值寄存器
#define TIMER_AVS_CNT_CTRL   0x80  // AVS计数器控制寄存器
#define TIMER_AVS_CNT0       0x84  // AVS计数器0寄存器
#define TIMER_AVS_CNT1       0x88  // AVS计数器1寄存器
#define TIMER_AVS_CNT_DIV    0x8C  // AVS计数器分频寄存器

// 定时器控制位定义
#define TIMER_EN            (1 << 0)  // 定时器使能
#define TIMER_RELOAD        (1 << 1)  // 重新加载计数值
#define TIMER_SRC_CLK_32K   (0 << 2)  // 时钟源选择:32.768KHz (LOSC)
#define TIMER_SRC_CLK_24M   (1 << 2)  // 时钟源选择:24MHz
#define TIMER_SRC_CLK_1K    (2 << 2)  // 时钟源选择:1KHz (保留)
#define TIMER_SRC_CLK_PCLK  (3 << 2)  // 时钟源选择:PCLK (保留)
#define TIMER_MODE_CONTINUE (0 << 7)  // 连续模式
#define TIMER_MODE_SINGLE   (1 << 7)  // 单次模式
#define TIMER_PRESCALE_1    (0 << 4)  // 预分频:1
#define TIMER_PRESCALE_2    (1 << 4)  // 预分频:2
#define TIMER_PRESCALE_4    (2 << 4)  // 预分频:4
#define TIMER_PRESCALE_8    (3 << 4)  // 预分频:8
#define TIMER_PRESCALE_16   (4 << 4)  // 预分频:16
#define TIMER_PRESCALE_32   (5 << 4)  // 预分频:32
#define TIMER_PRESCALE_64   (6 << 4)  // 预分频:64
#define TIMER_PRESCALE_128  (7 << 4)  // 预分频:128

// AVS计数器控制位定义
#define AVS_CNT0_EN         (1 << 0)  // 计数器0使能
#define AVS_CNT1_EN         (1 << 1)  // 计数器1使能
#define AVS_CNT0_PAUSE      (1 << 8)  // 计数器0暂停
#define AVS_CNT1_PAUSE      (1 << 9)  // 计数器1暂停

// 系统时钟频率
#define SYSTEM_CLOCK_24M    24000000UL  // 24MHz
#define SYSTEM_CLOCK_32K    32768UL     // 32.768KHz

// 定时器最大值(32位)
#define TIMER_MAX_VALUE     0xFFFFFFFFUL

// AVS默认分频值(24MHz/24 = 1MHz,即1us计数一次)
#define AVS_DEFAULT_DIVISOR 24

// 1秒所需的计数值(24MHz时钟,预分频1)
#define TICK_PER_SECOND     24000000UL

//=============================================================================
// 调用外部
//=============================================================================
extern    int32_t    N1,H;

extern    void f1c100s_intc_set_isr(uint8_t nIRQ, void (*handle)(void));
extern    void f1c100s_intc_enable_irq(uint8_t nIRQ);

//=============================================================================
// 静态变量
//=============================================================================

// TIMER1 中断计数和回调
static volatile uint32_t timer1_counter = 0;
static void (*timer1_callback)(void) = NULL;

// TIMER2 中断计数和回调
static volatile uint32_t timer2_counter = 0;
static void (*timer2_callback)(void) = NULL;

//=============================================================================
// 内部函数声明
//=============================================================================

static void timer_set_interval(uint32_t base, uint32_t us, uint32_t clk_src, uint32_t prescale);
static void timer_enable_interrupt(uint32_t base, uint32_t timer_id);
static void timer_disable_interrupt(uint32_t base, uint32_t timer_id);
static void timer_clear_interrupt(uint32_t base, uint32_t timer_id);

//=============================================================================
// 定时器中断服务函数
//=============================================================================

/**
* @brief 定时器1中断服务函数
* @note 中断号:F1C100S_IRQ_TIMER1 (14)
*/
static void timer1_irq_handler(void)
{
    // 清除中断状态
    timer_clear_interrupt(TIMER1_REG_BASE, 1);
   
    // 增加计数
    timer1_counter++;
    N1++;
    // 调用回调函数(如果存在)
    if (timer1_callback) {
        timer1_callback();
    }
}

/**
* @brief 定时器2中断服务函数
* @note 中断号:F1C100S_IRQ_TIMER2 (15)
*/
static void timer2_irq_handler(void)
{
    // 清除中断状态
    timer_clear_interrupt(TIMER2_REG_BASE, 2);
   
    // 增加计数
    timer2_counter++;
    H++;
    // 调用回调函数(如果存在)
    if (timer2_callback) {
        timer2_callback();
    }
}

//=============================================================================
// 内部辅助函数
//=============================================================================

/**
* @brief 设置定时器间隔(微秒)
*/
static void timer_set_interval(uint32_t base, uint32_t us, uint32_t clk_src, uint32_t prescale)
{
    uint32_t timeout;
   
    // 计算需要的计数值
    // 实际时钟频率 = 24MHz / (prescale + 1)
    uint32_t freq = SYSTEM_CLOCK_24M / (1 << prescale);
    timeout = (us * freq) / 1000000UL;
   
    if (timeout > TIMER_MAX_VALUE) {
        timeout = TIMER_MAX_VALUE;
    }
   
    // 设置间隔值
    write32(base + TIMER_INTV_VALUE_REG, timeout);
}

/**
* @brief 使能定时器中断
*/
static void timer_enable_interrupt(uint32_t base, uint32_t timer_id)
{
    uint32_t reg = read32(base + TIMER_IRQ_EN_REG);
    reg |= (1 << timer_id);
    write32(base + TIMER_IRQ_EN_REG, reg);
}

/**
* @brief 禁用定时器中断
*/
static void timer_disable_interrupt(uint32_t base, uint32_t timer_id)
{
    uint32_t reg = read32(base + TIMER_IRQ_EN_REG);
    reg &= ~(1 << timer_id);
    write32(base + TIMER_IRQ_EN_REG, reg);
}

/**
* @brief 清除定时器中断状态
*/
static void timer_clear_interrupt(uint32_t base, uint32_t timer_id)
{
    write32(base + TIMER_IRQ_STA_REG, (1 << timer_id));
}

//=============================================================================
// 延时函数 (TIMER0)
//=============================================================================

/**
* @brief 初始化延时函数使用的定时器
*/
void delay_init(void)
{
    // 1. 禁用定时器
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, 0);
   
    // 2. 清除中断状态
    write32(TIMER0_REG_BASE + TIMER_IRQ_STA_REG, 0x07);
   
    // 3. 禁用中断
    timer_disable_interrupt(TIMER0_REG_BASE, 0);
   
    // 4. 配置定时器:24MHz时钟源,预分频1,连续模式
    uint32_t ctrl_value = TIMER_SRC_CLK_24M | TIMER_MODE_CONTINUE | TIMER_PRESCALE_1;
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, ctrl_value);
}

/**
* @brief 微秒级延时
*/
void delay_us(uint32_t us)
{
    uint32_t timeout;
    uint32_t ctrl_val;
   
    if (us == 0) return;
   
    // 计算需要的计数值(24MHz时钟,1us = 24个时钟周期)
    timeout = us * 24;
   
    if (timeout > TIMER_MAX_VALUE) {
        timeout = TIMER_MAX_VALUE;
    }
   
    // 设置定时器间隔值
    write32(TIMER0_REG_BASE + TIMER_INTV_VALUE_REG, timeout);
   
    // 读取当前控制值
    ctrl_val = read32(TIMER0_REG_BASE + TIMER_CTRL_REG);
   
    // 启动定时器
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, ctrl_val | TIMER_RELOAD | TIMER_EN);
   
    // 等待RELOAD位自动清零
    while (read32(TIMER0_REG_BASE + TIMER_CTRL_REG) & TIMER_RELOAD);
   
    // 等待定时器计数到0
    while (read32(TIMER0_REG_BASE + TIMER_CUR_VALUE_REG) != 0);
   
    // 停止定时器
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, read32(TIMER0_REG_BASE + TIMER_CTRL_REG) & ~TIMER_EN);
}

/**
* @brief 毫秒级延时
*/
void delay_ms(uint32_t ms)
{
    const uint32_t MAX_MS_PER_CALL = 1000;
   
    while (ms > MAX_MS_PER_CALL) {
        delay_us(MAX_MS_PER_CALL * 1000);
        ms -= MAX_MS_PER_CALL;
    }
   
    if (ms > 0) {
        delay_us(ms * 1000);
    }
}

/**
* @brief 高精度微秒级延时(使用循环)
*/
void delay_us_precise(uint32_t us)
{
    volatile uint32_t count = us * 12;
    while (count--) {
        __asm__ volatile ("nop");
    }
}

/**
* @brief 使用32KHz时钟源的延时(低功耗)
*/
void delay_ms_lowpower(uint32_t ms)
{
    uint32_t timeout;
    uint32_t ctrl_val;
   
    if (ms == 0) return;
   
    uint32_t ctrl_backup = read32(TIMER0_REG_BASE + TIMER_CTRL_REG);
   
    uint32_t ctrl_value = (ctrl_backup & ~(0xFC)) | TIMER_SRC_CLK_32K | TIMER_PRESCALE_1;
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, ctrl_value);
   
    timeout = (ms * SYSTEM_CLOCK_32K) / 1000;
    if (timeout > TIMER_MAX_VALUE) {
        timeout = TIMER_MAX_VALUE;
    }
   
    write32(TIMER0_REG_BASE + TIMER_INTV_VALUE_REG, timeout);
    ctrl_val = read32(TIMER0_REG_BASE + TIMER_CTRL_REG);
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, ctrl_val | TIMER_RELOAD | TIMER_EN);
   
    while (read32(TIMER0_REG_BASE + TIMER_CTRL_REG) & TIMER_RELOAD);
    while (read32(TIMER0_REG_BASE + TIMER_CUR_VALUE_REG) != 0);
   
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, read32(TIMER0_REG_BASE + TIMER_CTRL_REG) & ~TIMER_EN);
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, ctrl_backup);
}

/**
* @brief 获取定时器当前计数值
*/
uint32_t delay_get_current_value(void)
{
    return read32(TIMER0_REG_BASE + TIMER_CUR_VALUE_REG);
}

/**
* @brief 检查定时器是否正在运行
*/
int delay_is_running(void)
{
    return (read32(TIMER0_REG_BASE + TIMER_CTRL_REG) & TIMER_EN) ? 1 : 0;
}

/**
* @brief 停止延时定时器
*/
void delay_stop(void)
{
    write32(TIMER0_REG_BASE + TIMER_CTRL_REG, read32(TIMER0_REG_BASE + TIMER_CTRL_REG) & ~TIMER_EN);
}

//=============================================================================
// 定时器1接口(中断模式,1秒中断)
//=============================================================================

/**
* @brief 初始化定时器1,配置为1秒中断
*/
void timer1_init(void (*callback)(void))
{
    // 保存回调函数
    timer1_callback = callback;
    timer1_counter = 0;
   
    // 禁用定时器
    write32(TIMER1_REG_BASE + TIMER_CTRL_REG, 0);
   
    // 清除中断状态
    timer_clear_interrupt(TIMER1_REG_BASE, 1);
   
    // 禁用中断
    timer_disable_interrupt(TIMER1_REG_BASE, 1);
   
    // 设置1秒间隔(24MHz时钟,预分频1)
//    write32(TIMER1_REG_BASE + TIMER_INTV_VALUE_REG, TICK_PER_SECOND);
    write32(TIMER1_REG_BASE + TIMER_INTV_VALUE_REG, 750000);//预分频32,24MHz/32=750000
    // 配置定时器:24MHz时钟源,预分频1,连续模式
    uint32_t ctrl_value = TIMER_SRC_CLK_24M | TIMER_MODE_CONTINUE | TIMER_PRESCALE_32;
    write32(TIMER1_REG_BASE + TIMER_CTRL_REG, ctrl_value);
       
    // 注册中断处理函数
    f1c100s_intc_set_isr(F1C100S_IRQ_TIMER1, timer1_irq_handler);
   
    // 使能中断控制器中的定时器1中断
    f1c100s_intc_enable_irq(F1C100S_IRQ_TIMER1);
   
    // 使能中断
    timer_enable_interrupt(TIMER1_REG_BASE, 1);
}

/**
* @brief 启动定时器1
*/
void timer1_start(void)
{
    uint32_t ctrl_val = read32(TIMER1_REG_BASE + TIMER_CTRL_REG);
    write32(TIMER1_REG_BASE + TIMER_CTRL_REG, ctrl_val | TIMER_RELOAD | TIMER_EN);
}

/**
* @brief 停止定时器1
*/
void timer1_stop(void)
{
    uint32_t ctrl_val = read32(TIMER1_REG_BASE + TIMER_CTRL_REG);
    write32(TIMER1_REG_BASE + TIMER_CTRL_REG, ctrl_val & ~TIMER_EN);
}

/**
* @brief 获取定时器1中断计数
*/
uint32_t timer1_get_count(void)
{
    return timer1_counter;
}

/**
* @brief 清除定时器1计数
*/
void timer1_clear_count(void)
{
    timer1_counter = 0;
}

/**
* @brief 检查定时器1是否正在运行
*/
int timer1_is_running(void)
{
    return (read32(TIMER1_REG_BASE + TIMER_CTRL_REG) & TIMER_EN) ? 1 : 0;
}

//=============================================================================
// 定时器2接口(中断模式,1秒中断)
//=============================================================================

/**
* @brief 初始化定时器2,配置为1秒中断
*/
void timer2_init(void (*callback)(void))
{
    // 保存回调函数
    timer2_callback = callback;
    timer2_counter = 0;
   
    // 禁用定时器
    write32(TIMER2_REG_BASE + TIMER_CTRL_REG, 0);
   
    // 清除中断状态
    timer_clear_interrupt(TIMER2_REG_BASE, 2);
   
    // 禁用中断
    timer_disable_interrupt(TIMER2_REG_BASE, 2);
   
    // 设置1秒间隔(24MHz时钟,预分频1)
    write32(TIMER2_REG_BASE + TIMER_INTV_VALUE_REG, TICK_PER_SECOND);
   
    // 配置定时器:24MHz时钟源,预分频1,连续模式
    uint32_t ctrl_value = TIMER_SRC_CLK_24M | TIMER_MODE_CONTINUE | TIMER_PRESCALE_1;
    write32(TIMER2_REG_BASE + TIMER_CTRL_REG, ctrl_value);
   
    // 使能中断
    timer_enable_interrupt(TIMER2_REG_BASE, 2);
   
    // 注册中断处理函数
    f1c100s_intc_set_isr(F1C100S_IRQ_TIMER2, timer2_irq_handler);
   
    // 使能中断控制器中的定时器2中断
    f1c100s_intc_enable_irq(F1C100S_IRQ_TIMER2);
}

/**
* @brief 启动定时器2
*/
void timer2_start(void)
{
    uint32_t ctrl_val = read32(TIMER2_REG_BASE + TIMER_CTRL_REG);
    write32(TIMER2_REG_BASE + TIMER_CTRL_REG, ctrl_val | TIMER_RELOAD | TIMER_EN);
}

/**
* @brief 停止定时器2
*/
void timer2_stop(void)
{
    uint32_t ctrl_val = read32(TIMER2_REG_BASE + TIMER_CTRL_REG);
    write32(TIMER2_REG_BASE + TIMER_CTRL_REG, ctrl_val & ~TIMER_EN);
}

/**
* @brief 获取定时器2中断计数
*/
uint32_t timer2_get_count(void)
{
    return timer2_counter;
}

/**
* @brief 清除定时器2计数
*/
void timer2_clear_count(void)
{
    timer2_counter = 0;
}

/**
* @brief 检查定时器2是否正在运行
*/
int timer2_is_running(void)
{
    return (read32(TIMER2_REG_BASE + TIMER_CTRL_REG) & TIMER_EN) ? 1 : 0;
}

//=============================================================================
// AVS计数器函数
//=============================================================================

/**
* @brief 初始化AVS计数器
*/
int avs_counter_init(uint32_t counter_id, uint16_t divisor, uint64_t initial_value)
{
    uint32_t reg_val;
    uint32_t ctrl_reg;
   
    if (counter_id > 1) return -1;
    if (divisor == 0 || divisor > 2047) return -1;
   
    if (initial_value & 0x1) {
        initial_value &= ~0x1ULL;
    }
   
    ctrl_reg = TIMER0_REG_BASE + TIMER_AVS_CNT_CTRL;
   
    reg_val = read32(ctrl_reg);
    if (counter_id == 0) {
        reg_val |= AVS_CNT0_PAUSE;
    } else {
        reg_val |= AVS_CNT1_PAUSE;
    }
    write32(ctrl_reg, reg_val);
   
    uint32_t div_reg = read32(TIMER0_REG_BASE + TIMER_AVS_CNT_DIV);
   
    if (counter_id == 0) {
        div_reg &= 0xFFFFF000;
        div_reg |= (divisor - 1) & 0xFFF;
    } else {
        div_reg &= ~(0xFFF << 16);
        div_reg |= ((divisor - 1) & 0xFFF) << 16;
    }
    write32(TIMER0_REG_BASE + TIMER_AVS_CNT_DIV, div_reg);
   
    if (counter_id == 0) {
        write32(TIMER0_REG_BASE + TIMER_AVS_CNT0, (uint32_t)(initial_value >> 1));
    } else {
        write32(TIMER0_REG_BASE + TIMER_AVS_CNT1, (uint32_t)(initial_value >> 1));
    }
   
    return 0;
}

/**
* @brief 启动AVS计数器
*/
void avs_counter_start(uint32_t counter_id)
{
    uint32_t reg_val;
    uint32_t ctrl_reg = TIMER0_REG_BASE + TIMER_AVS_CNT_CTRL;
   
    reg_val = read32(ctrl_reg);
   
    if (counter_id == 0) {
        reg_val &= ~AVS_CNT0_PAUSE;
        reg_val |= AVS_CNT0_EN;
    } else {
        reg_val &= ~AVS_CNT1_PAUSE;
        reg_val |= AVS_CNT1_EN;
    }
   
    write32(ctrl_reg, reg_val);
}

/**
* @brief 暂停AVS计数器
*/
void avs_counter_pause(uint32_t counter_id)
{
    uint32_t reg_val;
    uint32_t ctrl_reg = TIMER0_REG_BASE + TIMER_AVS_CNT_CTRL;
   
    reg_val = read32(ctrl_reg);
   
    if (counter_id == 0) {
        reg_val |= AVS_CNT0_PAUSE;
    } else {
        reg_val |= AVS_CNT1_PAUSE;
    }
   
    write32(ctrl_reg, reg_val);
}

/**
* @brief 停止AVS计数器
*/
void avs_counter_stop(uint32_t counter_id)
{
    uint32_t reg_val;
    uint32_t ctrl_reg = TIMER0_REG_BASE + TIMER_AVS_CNT_CTRL;
   
    reg_val = read32(ctrl_reg);
   
    if (counter_id == 0) {
        reg_val &= ~AVS_CNT0_EN;
        reg_val |= AVS_CNT0_PAUSE;
    } else {
        reg_val &= ~AVS_CNT1_EN;
        reg_val |= AVS_CNT1_PAUSE;
    }
   
    write32(ctrl_reg, reg_val);
}

/**
* @brief 读取AVS计数器当前值
*/
uint64_t avs_counter_read(uint32_t counter_id)
{
    uint32_t high;
   
    if (counter_id == 0) {
        high = read32(TIMER0_REG_BASE + TIMER_AVS_CNT0);
    } else {
        high = read32(TIMER0_REG_BASE + TIMER_AVS_CNT1);
    }
   
    return ((uint64_t)high) << 1;
}

/**
* @brief 设置AVS计数器值
*/
int avs_counter_set(uint32_t counter_id, uint64_t value)
{
    if (value & 0x1) {
        return -1;
    }
   
    avs_counter_pause(counter_id);
   
    if (counter_id == 0) {
        write32(TIMER0_REG_BASE + TIMER_AVS_CNT0, (uint32_t)(value >> 1));
    } else {
        write32(TIMER0_REG_BASE + TIMER_AVS_CNT1, (uint32_t)(value >> 1));
    }
   
    return 0;
}

/**
* @brief 配置AVS计数器分频
*/
void avs_counter_set_divisor(uint32_t counter_id, uint16_t divisor)
{
    uint32_t div_reg;
   
    if (divisor == 0) divisor = 1;
    if (divisor > 2047) divisor = 2047;
   
    div_reg = read32(TIMER0_REG_BASE + TIMER_AVS_CNT_DIV);
   
    if (counter_id == 0) {
        div_reg &= 0xFFFFF000;
        div_reg |= (divisor - 1) & 0xFFF;
    } else {
        div_reg &= ~(0xFFF << 16);
        div_reg |= ((divisor - 1) & 0xFFF) << 16;
    }
   
    write32(TIMER0_REG_BASE + TIMER_AVS_CNT_DIV, div_reg);
}

/**
* @brief 获取AVS计数器当前分频值
*/
uint16_t avs_counter_get_divisor(uint32_t counter_id)
{
    uint32_t div_reg = read32(TIMER0_REG_BASE + TIMER_AVS_CNT_DIV);
   
    if (counter_id == 0) {
        return (div_reg & 0xFFF) + 1;
    } else {
        return ((div_reg >> 16) & 0xFFF) + 1;
    }
}

/**
* @brief 复位AVS计数器
*/
void avs_counter_reset(uint32_t counter_id)
{
    avs_counter_stop(counter_id);
   
    if (counter_id == 0) {
        write32(TIMER0_REG_BASE + TIMER_AVS_CNT0, 0);
    } else {
        write32(TIMER0_REG_BASE + TIMER_AVS_CNT1, 0);
    }
}

/**
* @brief 初始化两个AVS计数器为默认配置
*/
void avs_counters_init_default(void)
{
    write32(TIMER0_REG_BASE + TIMER_AVS_CNT_CTRL, AVS_CNT0_PAUSE | AVS_CNT1_PAUSE);
   
    uint32_t div_val = ((AVS_DEFAULT_DIVISOR - 1) & 0xFFF) |
                      (((AVS_DEFAULT_DIVISOR - 1) & 0xFFF) << 16);
    write32(TIMER0_REG_BASE + TIMER_AVS_CNT_DIV, div_val);
   
    write32(TIMER0_REG_BASE + TIMER_AVS_CNT0, 0);
    write32(TIMER0_REG_BASE + TIMER_AVS_CNT1, 0);
}

/**
* @brief 获取AVS计数器计时的微秒数
*/
uint64_t avs_counter_get_us(uint32_t counter_id)
{
    uint64_t ticks = avs_counter_read(counter_id);
    uint16_t divisor = avs_counter_get_divisor(counter_id);
   
    return (ticks * divisor) / 24;
}

/**
* @brief 等待AVS计数器达到指定值
*/
int avs_counter_wait(uint32_t counter_id, uint64_t target, uint32_t timeout_us)
{
    uint64_t start, current;
    uint32_t elapsed = 0;
   
    start = avs_counter_read(counter_id);
   
    while (1) {
        current = avs_counter_read(counter_id);
       
        if (current >= target) {
            return 0;
        }
       
        if (timeout_us > 0) {
            elapsed = (uint32_t)((current - start) * avs_counter_get_divisor(counter_id) / 24);
            if (elapsed >= timeout_us) {
                return -1;
            }
        }
    }
}
/*-----------------------------------------------------------*/
/*-----------------------------------------------------------*/

/*
使用示例:
#include "f1c100s_timer.h"
#include "f1c100s-intc.h"

// 自定义回调函数示例
void my_timer1_callback(void)
{
    // 每秒执行一次
    // 注意:中断中不要执行耗时操作
}

void my_timer2_callback(void)
{
    // 每秒执行一次
}

void main(void)
{
    // 1. 初始化中断控制器
    f1c100s_intc_init();
   
    // 2. 初始化延时定时器(TIMER0)
    delay_init();
   
    // 3. 初始化定时器1(1秒中断)
    timer1_init(my_timer1_callback);
    timer1_start();
   
    // 4. 初始化定时器2(1秒中断)
    timer2_init(my_timer2_callback);
    timer2_start();
   
    // 5. 初始化AVS计数器
    avs_counters_init_default();
    avs_counter_start(0);
   
    // 6. 主循环
    while (1) {
        // 获取定时器计数
        uint32_t t1 = timer1_get_count();
        uint32_t t2 = timer2_get_count();
       
        // 使用延时函数
        delay_ms(100);
       
        // 获取AVS计时(微秒)
        uint64_t us = avs_counter_get_us(0);
    }
}

*/

#2 Re: 全志 SOC » F1C200S SPI NAND FLASH启动遇到问题 » 2026-02-21 22:42:26

我花了很长的时间,把 F1C100s_with_Keil_RTX4_emWin 搞成了纯洁裸机,去掉RTX。
又把STM32的LCD弄了进去,SD、I2C、触摸都调通了

裸机应该是不行的,在STM32上出现过这样的情况:在测试时一切正常!但是上机后运行一段时间后出现 main()内的跑飞了!表现为屏幕显示乱了或卡死、按键无反映!不可操作。但是定时器中断函数内的运行一切正常!一直运行到程序结束!所执行的操作也是正确的

#3 Re: 全志 SOC » F1C100s_Keil_纯裸机_触摸屏SD卡驱动_当作STM32了 » 2025-08-07 16:51:18

506826164@qq.com 说:

892857误差是3%,看log基本问题不大,我没遇到乱码



感谢。
分频: 7:892857bps
换个USB串口行了。WCH-LINK-V1.1的不行,全是乱码,WCH-LINKE的可以,CH32V305的,换CH340USB串口收发也正常

#4 Re: 全志 SOC » F1C100s_Keil_纯裸机_触摸屏SD卡驱动_当作STM32了 » 2025-08-06 23:21:56

506826164@qq.com 说:

这不是极限,把54改成7就是921600,我看log常用这个

54改成7后  892857.1 bps,测试结果出现乱码!

考虑到与F1C200S连接芯片的速度取整值:
为 10, = 625000 bps,为 5时, = 1250000bps
25, = 250000 bps

#5 全志 SOC » F1C100s_Keil_纯裸机_触摸屏SD卡驱动_当作STM32了 » 2025-08-06 13:40:09

435788A
回复: 7

终于把F1C100s的Keil_纯裸机_触摸屏SD卡驱动都凑齐,可以当作STM32把玩了。在此分享的同时顺便问问F1C100s串口波特率的问题:
/* 配置UART参数115200-8-1-0 */
  addr = UART0_REG_BASE;
  write32(addr + UART_IER_REG, 0x0);
  write32(addr + UART_FCR_REG, 0xf7);
  write32(addr + UART_MCR_REG, 0x0);
  val = read32(addr + UART_LCR_REG);
  val |= (1 << 7);
  write32(addr + UART_LCR_REG, val);
  write32(addr + UART_DLL_REG, (54 & 0xff));        // APB=100Mhz时div=54,则baud=115200
  write32(addr + UART_DLH_REG, ((54 >> 8) & 0xff));
  val = read32(addr + UART_LCR_REG);
  val &= ~(1 << 7);
  write32(addr + UART_LCR_REG, val);
  val = read32(addr + UART_LCR_REG);
  val &= ~0x3f;
  val |= ((0x3 << 0) | (0 << 2) | (0x0 << 3));
  write32(addr + UART_LCR_REG, val)

中的
write32(addr + UART_DLL_REG, (54 & 0xff));        // APB=100Mhz时div=54,则baud=115200
  write32(addr + UART_DLH_REG, ((54 >> 8) & 0xff));

把数值54改为27时为 230400 波特率,为了和RS485连接,这是F1C100s串口波特率极限了吗?波特率如果有大误差是通信不了的

F1C100s_Keil_纯裸机_TP_sd.zip

#6 Re: 全志 SOC » F1C100S的io初始化求助 » 2024-05-08 14:02:37

jiaowoxiaolu 说:

你确定是0x01c208b4+0xB4而不是0x01c20800+0xB4 吗,一般基地址都是0结尾的

感谢
   write32((0x01c20800+0xB4), 0x22222);可以读出TF卡的容量了!似乎还有要设置的地方,在  等待数据完成或自动命令完成时,超时了。
SDint_1.jpg

其中  PF Multi-Driving Register 0 这个寄存器不知道它的作用和设置方法
PF_Multi-Driving_Register_0.jpg

#7 全志 SOC » F1C100S的io初始化求助 » 2024-05-07 17:39:24

435788A
回复: 2

F1C100S的Keil 工程中,SD io 初始化参考用户手册的129页,设置为SD接口,但不能读写SD卡。

/*SD IO 初始化*/
void SD_IO_Init()
{   
    write32((0x01c208b4+0xB4), 0x22222);   
}
这个0x22222是用手机上的 十六进制转换器  转换出来的
除了设置 0xB4 寄存器,还要设置其他寄存器吗?
F1C_sd_io.jpg

#8 Re: 全志 SOC » F1C100S裸机移植LVGL卡屏 » 2024-04-03 22:43:53

根据 https://whycan.com/t_8611.html  的帖子,我移植了LVGL8.35版本,我的是F1C100S的,帖子的是F1C200S,用在F1C100S上会白屏。移植时是正常的,22%~24%CPU左右,同一个程序,第二晚上再测试时发现99%CPU。触摸不动了。
IMG20240402233606.jpg
到第二天再烧录测试又正常了。

我个人猜测,是不是LVGL8.35版本不稳定,GUI-Guider-1.6.1-GA版本图形开发软件对应的是LVGL_V8.35 版本
GUI-Guider-1.7.0-GA又退回到LVGL_V8.31 版本
要么是我的硬件有问题,不然就是玄学了。

#9 Re: 全志 SOC » F1C100S裸机移植LVGL卡屏 » 2024-03-30 09:35:09

定时器不工作,定时器没有进入中断,测试了串口也没有进入中断。
驱动程序是复制过来拼合的,没有调通

#10 全志 SOC » F1C100S裸机移植LVGL卡屏 » 2024-03-28 10:40:25

435788A
回复: 9

F1C100S裸机移植LVGL_V8.35和V8.31版卡屏,
GUI-Guider-1.6.1-GA对应的是LVGL_V8.35
GUI-Guider-1.7.0-GA对应的是LVGL_V8.31

裸机移植LVGL均卡屏,上电出现画面后卡死不动了,求助
IMG20240327213405.jpg
F1C100s_NS2009_LVGL835_SD-FATFS-4.3寸.zip

#11 Re: 全志 SOC » 哇酷网友都乐于分享:为大家制作了F1C100s的RTX4+emWin5稳定项目! » 2024-03-01 17:41:12

acom2024 说:
koeijam 说:

1、插个眼,方便继续学些
2、用keil5打开工程
3、荔枝nano+800X600可点亮,需修改fb-f1c100s.c和LCDConf.c分辨率
4、烧录: sunxi-fel.exe -p spiflash-write 0 Blinky.bin


烧录后重新上电,有界面出来吗? 我这边是白屏?

spl-separated分支:该分支把SPL代码分离出来,编译为f1c100s-spl_uart0.bin和f1c100s-spl_uart1.bin;在生成spl-separated.bin时自动合并SPL。
该分支只能用在F1C200S,用在我的F1C100S上就是白屏!

fb-write-through:该分支在我的F1C100S上只能烧录进25Q64上运行,不能烧进DRAM上运行

#13 全志 SOC » GT911触摸屏不能正常使用 » 2023-07-04 21:03:20

435788A
回复: 2

一年前买的GT911触摸屏,买回来后一直放着,没有上机通电测试,现在拿出来上机发现触摸分成三段,左边的触摸接近触摸点,左中的触摸不了;中右的触摸点向右边偏离!越往右边触摸出的点越向右边偏!触摸右边时,点不在屏幕上了。

芯片丝印有GT911字样,为什么我买到的GT911触摸屏是这样的呢

IMG20230702150631.jpg

#14 全志 SOC » F1C100S串口中断接收不了长字符串 » 2023-06-11 22:10:58

435788A
回复: 1

F1C100S串口中断接收不了长字符串,用 “小淘气科技” 的裸机 串口中断 程序测试,发100个字符串只接收到四十来个字符串
不知道是芯片内部坏了还是程序问题

2中断.jpg

.png
F1C100S_UART0_1_2_中断收发.7z

#15 Nuvoton N32905/N32926/NUC972/N9H20/N9H26/N9H30 » NUC972串口实验 串口助手发送后无响应 » 2022-01-16 14:53:38

435788A
回复: 1

NUC972串口实验,串口助手发送后无响应,按照程序应该是串口助手发送数据后,NUC972会把数据转发回给串口助手的
串口接线:GND、TX、RX。
源码:15.串口实验.rar

//主函数
int main (void)
{
    int  retval, len;
      //系统初始化
    sysDisableCache();
    sysFlushCache(I_D_CACHE);
    sysEnableCache(CACHE_WRITE_BACK);
    sysInitializeUART();
    //配置串口1相关的IO口
    outpw(REG_SYS_GPE_MFPL, (inpw(REG_SYS_GPE_MFPL) & 0xff0000ff) | (0x9999 << 8));// GPE2, 3, 4, 5 //TX, RX, RTS, CTS

        sysprintf("\r\n-------------串口通讯实验----------------\r\n");
      sysprintf("------------青岛千亿电子科技有限公司---------\r\n");
      sysprintf("--------------------------------------------\r\n");   

      sysprintf("串口1测试例程,程序开始会打印“你好 酷客 !!”信息,之后向开发板串口发送数据,开发板会返回所发送的数据.\r\n");

    /* 配置串口1 */
    param.uFreq = 12000000;
    param.uBaudRate = 115200;
    param.ucUartNo = UART1;
    param.ucDataBits = DATA_BITS_8;
    param.ucStopBits = STOP_BITS_1;
    param.ucParity = PARITY_NONE;
    param.ucRxTriggerLevel = UART_FCR_RFITL_1BYTE;
    retval = uartOpen(&param);
       
    if(retval != 0) {
        uartprintf("串口打开失败!\n");
    }

    retval = uartIoctl(param.ucUartNo, UART_IOC_SETTXMODE, UARTINTMODE, 0);
    if (retval != 0) {
        uartprintf("设置发送中断模式失败!\n");
    }

    retval = uartIoctl(param.ucUartNo, UART_IOC_SETRXMODE, UARTINTMODE, 0);
    if (retval != 0) {
        uartprintf("设置接收中断模式失败!\n");
    }


     //串口发送数据 “你好 酷客!!”
         len = strlen((PINT8) TX_Test);
         uartWrite(param.ucUartNo, TX_Test, len);
       
         uartprintf("\r\n 通过串口1向开发板发送数据,开发板会返回所发送的数据.\r\n");
         while(1)
      {
                    retval = uartRead(param.ucUartNo, RX_Test, 1);
                    if(retval==1)
                    uartWrite(param.ucUartNo, RX_Test, 1);
        }
}

#16 Re: 全志 SOC » [记录]f1c200s运行RT-thread » 2022-01-15 13:27:37

@LinjieGuo
下载了,还是出错误。
rtt错误1.jpg
用惯了Keil这种界面,有错误直接跳到出错代码处
这个rtt一时难以上手

#17 Re: 全志 SOC » [记录]f1c200s运行RT-thread » 2022-01-14 22:49:48

我也来学习,初次接触RTT,文件在那里也不知道,给我来了个错误了
RTT.png

#18 Re: 全志 SOC » 不雷同开源送两片,可选 D1/ D1s/ V3x/XR806/XR829/XR32/R11【长期有效】, F1C200s/V3s暂停 » 2022-01-12 14:12:55

435788A 说:

刚画出来,还没打样验证。https://whycan.com/files/members/7570/F133.jpg
F133未验证.rar

上传的文件有错误复位无电容,晶振也不对。
把改过的立创EDA被份文件分享在此
由于没有240欧姆电阻,用250欧姆电阻替代运行不了

EDA_全志F133A_.zip
_20220112140015.png
IMG20220112140731.jpg

#21 Re: 全志 SOC » 初玩F1C100S » 2021-12-22 22:54:29

画了个简单的板,没有使用到TV接口,直接留空了相关引脚。加入6P触摸屏接口,但是没有和F1C100相连接。
25Q64的片选使用了电子开关BL1551,作为下载烧录按钮用
50P上翻的FPC座。元件随便摆摆,把线连上,能否工作期待样板回来。
Schematic_F1C100S__2021-12-22.pdf
Gerber_PCB_F1C100S_1.zip
F1C100S.jpg
F1C100S2.jpg

#22 Re: 全志 SOC » 不雷同开源送两片,可选 D1/ D1s/ V3x/XR806/XR829/XR32/R11【长期有效】, F1C200s/V3s暂停 » 2021-12-19 23:27:22

有这好事?F1C100S正在进行中,布放可能有点难看。
D1S还没有参考图,以LVDS接口为主

#23 Re: 全志 SOC » 关于F1C100S屏幕RGB » 2021-12-10 22:47:09

tam2907 说:

long tmp32 =read32(0x01C0C000+0x40);
tmp32|=0x00800000;
write32(0x01C0C000+0x40,tmp32);
产即生效



非常感谢

在 xuyao2020-F1C100s_with_Keil_RTX4_emWin5 工程模板里,把这段代码加到LCDConf.C文件里
面的static void _InitController(void)函数的尾末,成功了。不再是红底色了
IMG20211210221733.jpg

IMG20211210221808.jpgIMG20211210222154.jpg

#24 Re: 全志 SOC » 网站需要改革,放开文件下载权限(不需要与积分挂钩) » 2021-12-10 21:35:06

无法下载,可能文件已经删除或者不存在了,对于下载不到文件的,是否可以退回积分

#25 Re: 全志 SOC » 用了论坛大神的开源图纸做块f133谁知道DDR供电电压超高。。。。。。有哪位大神可以指点下吗? » 2021-12-10 21:07:20

焊接顺序,先得把供电整正常了才能上主芯片。不差钱的也可以先上主芯片,因为主芯片难焊接,焊好了主芯片再焊其他

#26 Re: 全志 SOC » 关于F1C100S屏幕RGB » 2021-12-10 12:55:58

看到了,意思是寄存器TCON0 地址为 0x040,第23位=1时R色和B色的数据交换了
例程模板为 F1C100s_with_Keil_RTX4_emWin546e-master
应该在fb-f1c100s.c文件,还不知道修改那里。

#27 全志 SOC » 关于F1C100S屏幕RGB » 2021-12-09 22:13:05

435788A
回复: 6

商品板RGB是顺着屏幕接口排列的,荔枝挀和tiny200图纸的不是,有交叉线。
MS_CK700.jpg
MS-CK700.1.jpg
画板时参考tiny200v1图纸,发现布线交叉,不知道程序上什么可以调节的参数。
.jpg
手册文档中只有串口输出RGB数据时,调节可以RGB输出的顺序,没有说明并口RGB可调节RGB排列
tiny200v1.pdf
F1C200s_UM_V1_1.pdf6.jpg

#28 Re: 全志 SOC » 网站需要改革,放开文件下载权限(不需要与积分挂钩) » 2021-12-09 18:44:27

发帖得积分,积分下载,是合理的,初来这里我也花了钱,但是已经把LED点亮了,是真的!

#30 全志 SOC » 初玩F1C100S » 2021-12-07 22:23:59

435788A
回复: 1

STM32价格没有降多少,看到了F1C100S,搜集F1C100S的资料,找到了Keil的工程,一时兴起买了块板和屏幕
先是lvgl的F1C200s_V1_0工程,烧进板上后什么反映也没有,可能是DRAM不一样吧。又换xuyao2020-F1C100s_with_Keil_RTX4_emWin5工程,终于看到屏幕接口有波形出现,成功运行起来了!

1.2V供电实测为1.29V,断开1.2V线路串入万用表,测得73mA电流,在这里做个记录。剩下两路2.49V、3.0V为DH-M6C,DK-06L稳压IC,就三组电压。
F1C100S没有I2C接口

测试了IO的翻转速度,程序:
gpio_f1c100s_set_dir(&GPIO_PE, 0, GPIO_DIRECTION_OUTPUT);
     while(1)
     {
     gpio_f1c100s_set_value(&GPIO_PE, 0, 1);
        gpio_f1c100s_set_value(&GPIO_PE, 0, 0);
     }
测得 2.174MHz
IO翻转速度_20211207-2222.jpgxuyao2020-F1C100s_with_Keil_RTX4_emWin5.zip

#31 Re: 全志 SOC » 哇酷网友都乐于分享:为大家制作了F1C100s的RTX4+emWin5稳定项目! » 2021-11-25 19:43:47

我的为F1C100S,https://github.com/hongxuyao/F1C100s_with_Keil_RTX4_emWin5这个程序烧录后运行不起来,白屏。

#32 Re: 全志 SOC » FreeRTOS移植到F1C100S, 含GCC和keil版本 » 2021-11-20 13:38:56

到目前我找到可以在我的F1C100S板上运行起来的,只有荔枝派群里的xuyao2020-F1C100s_with_Keil_RTX4_emWin5-master
其他的能够烧录,烧录完成后重新上电无反映。

想用到双串口、TF卡、USB读写U盘,新手的我无从着手

#33 Re: 全志 SOC » F1C100S的Keil裸机USB模拟U盘工程,USB2.0高速模式 » 2021-11-18 11:39:58

努力翻帖,望早日玩转F1Cxx

代码已下载,编译出现错误:

*** Error: Failed to execute 'arm-none-eabi-gcc'

#34 Re: 全志 SOC » DKTool F1C100s/F1C200s专用工具 哇酷网特别版,20201221正式发布!!!! » 2021-11-17 18:50:47

我的可以是看戏板的板子,F1C100S,没有屏幕,烧完程序后重新上电F1C100S不再有温升,对应串口无输出,屏幕接口所有引脚无波形(无输出)
第一次玩F1Cxx.jpg

#35 Re: 全志 SOC » 自制f1c100s/f1c200s板子电源部分的电阻电容电感的封装问题 » 2021-11-14 12:38:34

手工焊的话,个人觉得0402不好焊接,能用0603就用0603,0402封装的可以焊到0603焊盘位上

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn


太原小智科技有限责任公司 - 东莞哇酷科技有限公司联合开发