页次: 1
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);
}
}
*/
终于把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串口波特率极限了吗?波特率如果有大误差是通信不了的
根据 https://whycan.com/t_8611.html 的帖子,我移植了LVGL8.35版本,我的是F1C100S的,帖子的是F1C200S,用在F1C100S上会白屏。移植时是正常的,22%~24%CPU左右,同一个程序,第二晚上再测试时发现99%CPU。触摸不动了。
到第二天再烧录测试又正常了。
我个人猜测,是不是LVGL8.35版本不稳定,GUI-Guider-1.6.1-GA版本图形开发软件对应的是LVGL_V8.35 版本
GUI-Guider-1.7.0-GA又退回到LVGL_V8.31 版本
要么是我的硬件有问题,不然就是玄学了。
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均卡屏,上电出现画面后卡死不动了,求助
F1C100s_NS2009_LVGL835_SD-FATFS-4.3寸.zip
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上运行
F1C100S串口中断接收不了长字符串,用 “小淘气科技” 的裸机 串口中断 程序测试,发100个字符串只接收到四十来个字符串
不知道是芯片内部坏了还是程序问题

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(¶m);
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);
}
}
刚画出来,还没打样验证。https://whycan.com/files/members/7570/F133.jpg
F133未验证.rar
上传的文件有错误复位无电容,晶振也不对。
把改过的立创EDA被份文件分享在此
由于没有240欧姆电阻,用250欧姆电阻替代运行不了
刚画出来,还没打样验证。
F133未验证.rar
画了个简单的板,没有使用到TV接口,直接留空了相关引脚。加入6P触摸屏接口,但是没有和F1C100相连接。
25Q64的片选使用了电子开关BL1551,作为下载烧录按钮用
50P上翻的FPC座。元件随便摆摆,把线连上,能否工作期待样板回来。
Schematic_F1C100S__2021-12-22.pdf
Gerber_PCB_F1C100S_1.zip

看到了,意思是寄存器TCON0 地址为 0x040,第23位=1时R色和B色的数据交换了
例程模板为 F1C100s_with_Keil_RTX4_emWin546e-master
应该在fb-f1c100s.c文件,还不知道修改那里。
商品板RGB是顺着屏幕接口排列的,荔枝挀和tiny200图纸的不是,有交叉线。

画板时参考tiny200v1图纸,发现布线交叉,不知道程序上什么可以调节的参数。
手册文档中只有串口输出RGB数据时,调节可以RGB输出的顺序,没有说明并口RGB可调节RGB排列
tiny200v1.pdf
F1C200s_UM_V1_1.pdf
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
xuyao2020-F1C100s_with_Keil_RTX4_emWin5.zip
页次: 1