预装载功能探究一:比较/捕获寄存器预装载使能的意义

2023-11-02

以沁恒CH32V307VCT6芯片测试为基准,测试开发板:CH32V307V-R1-1V0

以下内容均为解析调用此句代码的意义

TIM_OC1PreloadConfig ( TIM1, TIM_OCPreload_Enable );

第一层:解析底层代码结构

void TIM_OC1PreloadConfig(TIM_TypeDef *TIMx, uint16_t TIM_OCPreload)

{

    uint16_t tmpccmr1 = 0;

    tmpccmr1 = TIMx->CHCTLR1;

    tmpccmr1 &= (uint16_t) ~((uint16_t)TIM_OC1PE);

    tmpccmr1 |= TIM_OCPreload;

    TIMx->CHCTLR1 = tmpccmr1;

}

#define  TIM_OC1PE        ((uint16_t)0x0008)    /* Output Compare 1 Preload enable */

解析:从代码中可以看出底层代码是对“输出比较寄存器1TIMx_CHCTLR1)”的

bit3位进行置位和初始化;

第二层:解析手册中关于此位的描述

手册中输出比较寄存器1TIMx_CHCTLR1

Bit3OC1PE-输出比较寄存器1预装载使能位”详细描述如下:

输出比较寄存器1预装载使能位

1开启输出比较寄存器1(TIMx_CH1CVR)的预装载功能,读写操作仅对预装载寄存器操作,输出比较寄存器1的预装载值在更新事件到来时被加载至当前影子寄存器中;

0禁止输出比较寄存器1的预装载功能,可随时写入输出比较寄存器1,并且新写入的数值立即起作用

首先我们所用的“输出比较寄存器1(TIMx_CH1CVR)”实际上均是由两个寄存器组成的:

Preload register(预装载寄存器)+ Shadow register(影子寄存器)

如果OC1PE=0,即不使能CH1CVR的预装载功能,则修改TIMx_CH1CVR寄存器的值就是操作影子寄存器,新的CH1CVR的值会立即生效。

如果OC1PE=1,即使能CH1CVR的预装载功能,则修改TIMx_CH1CVR 寄存器的值就是操作预装载寄存器,要等到发生更新事件后,TIMx_CH1CVR预装载寄存器的值才会拷贝到影子寄存器中,进而新的CH1CVR的值才会生效。

第三层:实验代码深度解析

实验代码:

设定系统时钟为SYSCLK_CLOCK=48MHz;

设定定时器1预分频系数PSC=48000-1,即定时器1ms记一个数;

设定定时器1自动重装载值ARR=100-1,即定时器计数到100更新一次,周期为100ms;

设定TIM1_CH1、TIM1_CH2、TIM1_CH3均为输出比较模式,且配置相同。

设定定时器1输出比较寄存器1、2、3的值为CH1CVR=CH2CVR=CH3CVR=CCP=30。

开启输出比较寄存器1(TIM1_CH1)的预装载功能

禁止输出比较寄存器2(TIM1_CH2)的预装载功能。

开启定时器1更新中断,设定进入5次中断后更改输出比较寄存器1和2的值

CH1CVR=CH2CVR=90;

三个通道波形如下所示:

波形图解析:

在输出5次正常的占空比30%的PWM波后,即定时器第5次进入定时器更新中断后

程序中将CH1CVR=CH2CVR=90,即将后续PWM输出的占空比更改为90%

        1.对于TIM1_CH1,开启输出比较寄存器1(TIM1_CH1)的预装载功能;

TIM1->CH1CVR=90;的操作相当于将值存入预装载寄存器,在等待发生更新事件(波形图B线处)后,会将值拷贝到影子寄存器,进而新的CH1CVR的值才会生效。

        2.对于TIM1_CH2,禁止输出比较寄存器2(TIM1_CH2)的预装载功能;

TIM1->CH2CVR=90;的操作相当于将值直接存入影子寄存器(波形图A线处),新的CH2CVR的值会立刻生效。

完整程序如下:

#include "debug.h"
void TIM1_UP_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
u16 i=0;

void TIM1_OutCompare_Init( u16 arr, u16 psc, u16 ccp )
{
    GPIO_InitTypeDef GPIO_InitStructure={0};
    TIM_OCInitTypeDef TIM_OCInitStructure={0};
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure={0};
    NVIC_InitTypeDef  NVIC_InitStructure = {0};

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    TIM_TimeBaseInitStructure.TIM_Period = arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ccp;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC1Init( TIM1, &TIM_OCInitStructure );
    TIM_OC2Init( TIM1, &TIM_OCInitStructure );
    TIM_OC3Init( TIM1, &TIM_OCInitStructure );

    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    TIM_CtrlPWMOutputs(TIM1, ENABLE );
    TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Enable );
    TIM_OC2PreloadConfig( TIM1, TIM_OCPreload_Disable );
    TIM_OC3PreloadConfig( TIM1, TIM_OCPreload_Disable );
    TIM_ARRPreloadConfig( TIM1, ENABLE );
    TIM_ClearITPendingBit(TIM1,TIM_IT_Update);
    TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
    TIM_Cmd( TIM1, ENABLE );
}

void TIM1_UP_IRQHandler(void)
{

    if(TIM_GetITStatus(TIM1,TIM_IT_Update) == SET)
    {
        i++;
        if(i==5)
        {
            TIM1->CH1CVR=90;
            TIM1->CH2CVR=90;
        }
        TIM_ClearFlag(TIM1,TIM_IT_Update);
    }

}

int main(void)
{
    TIM1_OutCompare_Init( 100-1, 48000-1, 30 );//1ms记一个数
    while(1);
}

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

预装载功能探究一:比较/捕获寄存器预装载使能的意义 的相关文章

  • 硬件基础元器件【1.电阻篇】

    文章目录 1 电阻 1 1 电阻的作用 1 2 电阻选型要点 1 3 电阻的主要使用场景 1 3 1 上 下拉电阻 上下拉电阻作用 阻值选择原则 1 3 2 MOS管栅极驱动电阻 1 3 3 电源反馈电阻 1 3 4 晶振并联电阻 1 3
  • 算法(C++):加一

    算法 C 加一 题目难度 简单 题目描述 给定一个由 整数 组成的 非空 数组所表示的非负整数 在该数的基础上加一 最高位数字存放在数组的首位 数组中每个元素只存储单个数字 你可以假设除了整数 0 之外 这个整数不会以零开头 示例1 输入

随机推荐

  • centos7下docker中mysql大小写敏感相关问题解决方案

    因为linux下的mysql默认区分大小写 而windows下的mysql默认不区分 所以关联的时候 有时候会出问题 所以我们要取消linux小的区分大小写 目录 一 mysql大小写解决方案 1 启动docker 2 运行mysql容器
  • zabbix监控TCP连接状态

    一 zabbix监控TCP连接状态 1 取到TCP连接状态的值 root web01 netstat antp awk NR gt 2 print 6 grep TIME WAIT wc l 可以取到TIME WAIT的个数 依次类推 可以
  • linux安装mysql-8.0.11出现错误

    linux安装mysql 8 0 11出现 2020 04 16T11 47 06 723455Z 0 Warning MY 011070 Server Disabling symbolic links using skip symboli
  • java基础经典题——猴子吃桃

    作为学java循环的经典问题 猴子第一天摘了若干个桃子 当即吃了一半 还不解馋 又多吃了一个 第二天 吃剩下的桃子的一半 还不过瘾 又多吃了一个 以后每天都吃前一天剩下的一半多一个 到第10天想再吃时 只剩下一个桃子了 问第一天共摘了多少个
  • Ubuntu系统中如何删除一个用户

    1 打开终端命令行 运用userdel命令删除指定的用户 注意要加sudo权限指令 如下图 sudo userdel ascend 2 在删除的时候一定注意是在管理员目录下的 普通的用户是没有这个权限的 3 删除指令执行完了以后怎么判断是否
  • linux桌面小程序开发日记4(pyqt5+yolov5)

    linux桌面小程序开发日记4 修改detect py文件 让yolov5连接摄像头 同时输出识别出来的内容 最后一篇博客地址 https blog csdn net Liuchengzhizhi article details 12369
  • 论穷举法破解0到6位数登录密码的可行性

    0到6位数密码含数字 字母大小写 英文符号有537412247190种可能性 千亿数量级 3998 410GB 在局域网网速 个人台式电脑情况下 java代码 httpclient 访问路由器网址一次要414ms 如果只访问头信息的话会快1
  • ROI pooling 和 ROI Align详解

    ROI Align 是在Mask RCNN这篇论文里提出的一种区域特征聚集方式 很好地解决了ROI Pooling操作中两次量化造成的区域不匹配 mis alignment 的问题 实验显示 在检测测任务中将 ROI Pooling 替换为
  • 华为OD机试(Java,JS,Python,C++)-Excel单元格数值统计

    Excel单元格数值统计 时间限制 2s 空间限制 256MB 限定语言 不限 题目描述 Excel工作表中对选定区域的数值进行统计的功能非常实用 仿照Excel的这个功能 请对给定表格中选中区域中的单元格进行求和统计 并输出统计结果 为简
  • innodb事务实现

    事务的特性 ACID 事务的类别 事务实现 redo redoLog buffer 的格式 undo 更新主键 purge group commit 因为上层的binlog和底层的redolog要保持一致 所以 事务控制语句 事务隔离级别
  • C++11标准模板(STL)- 算法(std::rotate)

    定义于头文件
  • logistics回归之sklearn中的LogisticRegressionCV

    一 Logistic回归的认知与应用场景 Logistic回归为概率型非线性回归模型 是研究二分类观察结果与一些影响因素之间关系的 一种多变量分析方法 通常的问题是 研究某些因素条件下某个结果是否发生 比如医学中根据病人的一些症状 来判断它
  • Android-打包AAR步骤以及最为关键的注意事项

    转自 https www jianshu com p f391d0a6691e 简介 最近因为项目的要求 需要把开发的模块打包成aar 供其他项目调用 在搞了一段时间后 发现这里还是有很多需要注意的地方 所以记录一下 帮助大家不要走弯路 首
  • 调试for循环的技巧

    今天用IDEA调试for循环时 断点打在了for的左边 不小心按了F9 跳到下一个断点 意外发现原来可以通过这种方式对for循环的每次循环进行调试 不必自己手动一行行调试才到下一次for循环 这对于一种场景特别适用 假设你需要查看第 5 次
  • 并发编程系列之重入锁VS读写锁

    前言 上节我们介绍了Java中的锁基础篇 也算是对锁有了个基本的认识 对锁底层的一些原理有所掌握 那么今天我们就来看看2个最常见的锁的实例应用 重入锁和读写锁 这是今天旅途最美的两大景点 是不是有点迫不及待了 OK 那就让我们一起开启今天的
  • 电磁式继电器使用注意事项

    电磁继电器的使用 1 触点通断时线圈两端会感应出较大的电动势 如果不加隔离 便很容易通过地电势将干扰引入板上其它电路 导致单片机复位 线圈控制端加光耦隔离 线圈的电源与板子的电源隔离 另外线圈两端要加续流二极管 见后说明 可选常用的1N40
  • 【计算机组成原理】16-定点数与浮点数

    一 定点数的表示方法 1 纯小数 乘以比例因子以满足定点数保存格式 2 纯整数 小数点在后面 二 浮点数的表示方法 计算机处理的很大程度上不是纯小数或纯整数 数据范围很大 定点数难以表达 1 浮点数的表示格式 科学计数法 j S 尾数 r
  • 华为人才在线--华为认证进阶路径

    华为人才在线 华为认证进阶路径网址 网址 https e huawei com cn talent cert roadmap 在这个网址可以学习华为的各类技术方向 能下载到培训教程和实验手册 以及在线学习 如学习路由交换的HCIA点击红色的
  • Numpy数组

    NumPy 最重要的一个特点是其 N 维数组对象 ndarray 它是一系列同类型数据的集合 以 0 下标为开始进行集合中元素的索引 ndarray 对象是用于存放同类型元素的多维数组 ndarray 中的每个元素在内存中都有相同存储大小的
  • 预装载功能探究一:比较/捕获寄存器预装载使能的意义

    以沁恒CH32V307VCT6芯片测试为基准 测试开发板 CH32V307V R1 1V0 以下内容均为解析调用此句代码的意义 TIM OC1PreloadConfig TIM1 TIM OCPreload Enable 第一层 解析底层代