中颖51芯片学习9. PWM(12bit脉冲宽度调制)

中颖51芯片学习9. PWM(12bit脉冲宽度调制)

  • 一、资源简介
  • 二、PWM工作流程
  • 三、寄存器介绍
    • 1. PWMx控制寄存器PWMxCON
    • 2. PWM0周期寄存器PWM0PH/L
    • 3. PWM1周期寄存器PWM1PH/L
    • 4. PWM0占空比控制寄存器PWM0DH/L
    • 5. PWM1占空比控制寄存器 PWM1DH/L
    • 6. 占空比寄存器与周期关系
  • 四、代码实现示例
    • 1. 基本功能
    • 2. 封装PWM函数
      • (1)pwm_utils.c
      • (2)main.c

本文使用的芯片型号为 SH79F9476

一、资源简介

前面介绍了使用 SH79F9476 的可编程计数器阵列 PCA0 生成PWM波,其支持8位、16位脉宽调制。
主要特性如下:

  1. 两路12位PWM模块:SH79F9476提供了两个PWM模块,每个模块可以生成具有可调周期和占空比的脉宽调制波形。

  2. 周期溢出中断:每个PWM周期都提供了溢出中断功能,可以在周期结束时触发中断处理程序。

  3. 输出极性可选择:可以通过设置PWM控制寄存器来选择PWM输出的极性,从而决定占空比期间输出的电平。

  4. PWM模块控制:使用PWM控制寄存器(PWMxCON)可以配置PWM模块的时钟源、输出极性、周期中断等参数。

  5. 周期设置:使用PWM周期寄存器(PWMxPH/L)可以设置PWM输出波形的周期,以控制脉冲的频率。

  6. 占空比设置:使用PWM占空比寄存器(PWMxDH/L)可以设置PWM输出波形的占空比,以控制脉冲的宽度。

二、PWM工作流程

SH79F9476的PWM工作流程如下:

  1. 选择PWM模块时钟源
    在开始配置PWM模块之前,首先需要选择PWM模块的时钟源。可以通过设置PWM控制寄存器(PWMxCON)中的PWMxCK[2:0]位来选择时钟源,以确定PWM模块的工作时钟频率。

  2. 设置PWM周期
    使用PWM周期寄存器(PWMxPH/L)设置PWM输出波形的周期。这些寄存器用于控制PWM脉冲的频率。在设置周期之前,需要确定所需的PWM输出频率,并根据所选的时钟源来计算周期寄存器的值。

  3. 设置PWM占空比
    使用PWM占空比寄存器(PWMxDH/L)设置PWM输出波形的占空比。这些寄存器用于控制PWM脉冲的宽度。在设置占空比之前,需要确定所需的PWM输出占空比,并根据所选的周期来计算占空比寄存器的值。

  4. 选择PWM输出模式
    使用PWM控制寄存器(PWMxCON)中的PWMxS位选择PWM输出模式。可以选择PWM占空比期间输出高电平还是低电平。

  5. 使能PWM模块
    设置PWM使能位(PWMxEN)来启用所需的PWM模块。这将启动PWM输出并使其按照设置的周期和占空比工作。

  6. 修改周期和占空比(可选)
    在PWM输出允许期间,可以根据需要修改周期和占空比寄存器的值。修改后的值将在下一个PWM周期开始生效。

  7. 处理PWM周期中断(可选)
    如果启用了PWM周期中断,当PWM周期结束时,将触发中断处理程序。可以在中断处理程序中执行相应的操作,例如更新周期和占空比等。

  8. 调整PWM输出(可选)
    根据实际需求,可以根据系统的运行情况调整PWM输出的周期和占空比。可以根据外部输入信号或系统状态来动态调整PWM输出。

三、寄存器介绍

1. PWMx控制寄存器PWMxCON

在这里插入图片描述
位功能说明:
在这里插入图片描述
下面示例:

PWM0CON = 0x81;
  • 允许 PWM0模块
  • PWM0占空比期间输出高电平,占空比溢出后输出低电平
  • PWM0使用系统时钟,不分频
  • 禁止PWM0周期中断
  • PWM0输出允许
PWM1CON=0xC1; //11000001
  • 允许PWM1模块
  • PWM1占空比期间输出低电平,占空比溢出后输出高电平
  • PWM1使用系统时钟
  • 禁止PWM1周期中断
  • PWM1输出允许

2. PWM0周期寄存器PWM0PH/L

在这里插入图片描述
输出周期为 [PWM0PH,PWM0PL] * PWM时钟周期 。
PWM0的计数器计数至PWM0PH/L值后归0,这时如果PWM0S=0,则PWM0输出低电平 ;如果PWM0S=1,则PWM0输出高电平。

示例:

	PWM0PL = 0xff;PWM0PH = 0x0f;

周期为 0xfff*系统时钟周期,假设系统时钟为12MHz,则PWM0周期为 0xfff/12MHz=0.34125ms

3. PWM1周期寄存器PWM1PH/L

在这里插入图片描述

4. PWM0占空比控制寄存器PWM0DH/L

在这里插入图片描述
位功能说明:
在这里插入图片描述

5. PWM1占空比控制寄存器 PWM1DH/L

在这里插入图片描述
位功能说明:
在这里插入图片描述
修改占空比要注意的是:

  • 修改寄存器 PWMxDH 将使得 PWMx 的输出在下一个周期生效。
  • 用户需先修改 PWMxDL ,再修改 PWMxDH 以修改 PWM占空比。
  • 无论 PWMxDH 是否被修改,都需要将 PWMxDH 再写一次。否则,低位的修改无效。

6. 占空比寄存器与周期关系

下图示例可以比较清楚看出PWMP和PWMD所指的时间:
在这里插入图片描述
即PWMP为PWM周期 ,
PWMD为PWM输出高/低电平时间,具体输出高还是低取决于PWMS的值。

四、代码实现示例

1. 基本功能

下面实例实现PWM输出的基本代码:

void init_pwm0()
{_push_(INSCON);Select_Bank0();PWM0PL = 0xff;PWM0PH = 0x0f;PWM0DL = 0xff;PWM0DH = 0x07;PWM0CON = 0x81;_pop_(INSCON);
}void init_pwm1()
{_push_(INSCON);Select_Bank1();PWM1PL = 0xff;PWM1PH = 0x0f;PWM1DL = 0xff;PWM1DH = 0x07;PWM1CON = 0xc1;_pop_(INSCON);
}

代码选项设置,时钟使用128K:
在这里插入图片描述

2路PWM波形对比: (2路垂直偏移设置不同以方便观察)
在这里插入图片描述

2. 封装PWM函数

(1)pwm_utils.c

#include "pwm_utils.h"/*** @param frequency 频率* @param duty 占空比,单位是百分比* @param polar 极性* @brief 初始化PWM0*/
void Pwm0_Init(volatile U16 frequency, volatile U16 duty, volatile U16 polar) {// 周期,单位是msvolatile U16 period = 1000 / frequency;volatile U16 PWM0P = period * 128;volatile U16 PWM0D = (PWM0P / 100) * duty;_push_(INSCON);Select_Bank0();// 周期寄存器, 0x0fff=4095,周期=4095/128K=32ms// 通过周期计算PWM0Px的值,PWM0Px=period*128K/1000PWM0PL = PWM0P & 0xff;PWM0PH = PWM0P >> 8;// 占空比寄存器,0x07ff=2047// 计算占空比寄存器的值,PWM0Dx=周期寄存器值*duty/100PWM0DL = PWM0D & 0xff;PWM0DH = PWM0D >> 8;if (polar == 1) {PWM0CON |= 0x40;} else {PWM0CON &= 0xbf;}// PWM0控制寄存器 1000_0001, 使能、输出允许PWM0CON |= 0x81;_pop_(INSCON);
}/*** @param frequency 频率* @param duty 占空比,单位是百分比* @param polar 极性* @brief 初始化PWM1*/
void Pwm1_Init(volatile U16 frequency, volatile U16 duty, volatile U16 polar) {// 周期,单位是msvolatile U16 period = 1000 / frequency;volatile U16 PWM1P = period * 128;volatile U16 PWM1D = (PWM1P / 100) * duty;_push_(INSCON);Select_Bank1();// 周期寄存器PWM1PL = PWM1P & 0xff;PWM1PH = PWM1P >> 8;// 占空比寄存器PWM1DL = PWM1D & 0xff;PWM1DH = PWM1D >> 8;if (polar == 1) {PWM1CON |= 0x40;} else {PWM1CON &= 0xbf;}// PWM1控制寄存器 1100_0001,使能、占空比期间输出低电平、占空比溢出后输出高电平、输出允许PWM1CON |= 0x81;_pop_(INSCON);
}

(2)main.c

#include "SH79F9476.h"
#include "clk_utils.h"
#include "pwm_utils.h"void main() {// 选择低速时钟lowFrequenceClk();Pwm0_Init(32, 50, 0);Pwm1_Init(32, 80, 1);while (1) {}
}

输出频率32Hz、占空比80、极性相反的波形运行示例:
在这里插入图片描述

本文参考资源来自中颖官网。
本文代码开源地址: https://gitee.com/xundh/learn-sinowealth-51

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跨语言指令调优深度探索

目录 I. 介绍II. 方法与数据III. 结果与讨论1. 跨语言迁移能力2. 问题的识别3. 提高跨语言表现的可能方向 IV. 结论V. 参考文献 I. 介绍 在大型语言模型的领域,英文数据由于其广泛的可用性和普遍性,经常被用作训练模型的主要语料。尽管这些模型可能在英…

ESLlint重大更新后,使用旧版ESLint搭配Prettier的配置方式

概要 就在前几天,ESLint迎来了一次重大更新,9.0.0版本,根据官方文档介绍,使用新版的先决条件是Node.js版本必须是18.18.0、20.9.0,或者是>21.1.0的版本,新版ESLint将不再直接支持以下旧版配置(非扁平化…

二、OSPF协议基础

基于SPF算法(Dijkstra算法)的链路状态路由协议OSPF(Open Shortest Path First,开放式最短路径优先) 目录 1.RIP在大型网络中部署所面临的问题 2.Router ID 3.OSPF的报文 4.OSPF邻居建立过程 5.OSPF报文的确认机制…

SAP的生成式AI

这是一篇openSAP中关于SAP生成式AI课程的笔记,原地址https://open.sap.com/courses/genai1/ 文章目录 Unit 1: Approaches to artificial intelligence概念三种范式监督学习非监督学习强化学习Unit 2: Introduction to generative AI生成式AI基础模型关系基础模型有哪些能力呢…

怎么通过isinstance(Obj,Class)验证?【isinstance】

最近有这样一个项目,这个项目可以用一个成熟的项目的构造树,读取树,再检索的过程,现在有新的需求,另一个逻辑构造同样节点结构的树,pickle序列化保存,再使用原来项目的读取、检索函数&#xff0…

一年期免费SSL证书申请方法

免费SSL证书的申请已经成为当今互联网安全实践中的重要环节,它不仅有助于保护网站数据传输的隐私性和完整性,还能提升用户信任度,因为现代浏览器会明确标识出未使用HTTPS(即未部署SSL证书)的网站为“不安全”。以下是一…

互联网安全面临的全新挑战

前言 当前移动互联网安全形势严峻,移动智能终端漏洞居高不下、修复缓慢,移动互联网恶意程序持续增长,同时影响个人和企业安全。与此同时,根据政策形势移动互联网安全监管重心从事前向事中事后转移,需加强网络安全态势感…

玩转必应bing国内广告投放,正确的攻略方式!

搜索引擎广告作为精准触达潜在客户的重要渠道,一直是众多企业营销策略中的关键一环,在国内市场,虽然百度占据主导地位,但必应Bing凭借其独特的用户群体、高质量的搜索体验以及与微软生态的紧密集成,为广告主提供了不可…

相关运算及实现

本文介绍相关运算及实现。 相关运算在相关检测及数字锁相放大中经常用到,其与卷积运算又有一定的联系,本文简要介绍其基本运算及与卷积运算的联系,并给出实现。 1.定义 这里以长度为N的离散时间序列x(n),y(n)为例,相关运算定义如…

nvm管理多个node版本,快速来回切换node版本

前言 文章基于 windows环境 使用nvm安装多版本nodejs。 最近公司有的项目比较老需要降低node版本才能运行,由于来回进行卸载不同版本的node比较麻烦;所以需要使用node工程多版本管理,后面自己就简单捯饬了一下nvm来管理node,顺便…

VTK----VTK数据结构详解2(计算机篇)

在VTK中,属性数据和点都用数据数组(data arrays)表示。某些属性数据(例如法线、张量)需要具有与其定义一致的元组(在计算机编程中,元组(tuple)用来表示存储多种数据类型的…

vue下载文件时显示进度条

1.单个下载&#xff08;开始是导出按钮 下载显示进度条&#xff09; html <el-button click.stop"exportReport(scope.row, scope.index)" v-if"!scope.row.schedule" icon"el-icon-download"size"small" type"text"styl…

cocos-lua资源管理

本文介绍cocos-lua项目的资源管理和工作流&#xff0c;适用人群包括初学者和有经验开发者&#xff0c;故读者可根据自己的需要有选择性的查阅自己需要的内容 一.简单案例解析 下文通过介绍一个简单demo&#xff0c;介绍合图和资源目录结构 1.1 运行效果 1.2 ccs结构 1.3 目录…

【Python-Spark(大规模数据)】

Python-Spark&#xff08;大规模数据&#xff09; ■ Spark■ PySparl编程模型■ 基础准备■ 数据输入■ RDD的map成员方法的使用■ RDD的flatMap成员方法的使用■ RDD的reduceByKey成员方法的使用■ 单词计数统计■ RDD的filter成员方法的使用■ RDD的distinct成员方法的使用■…

LANGUAGE-DRIVEN SEMANTIC SEGMENTATION

环境不易满足&#xff0c;不建议复现

详解js中的console对象

对于前端开发而言&#xff0c;console对象大家肯定都很熟悉&#xff0c;最常用的 console.log() 是开发调试必用的 但是对于console对象的其他方法&#xff0c;相对而言使用的就比较少了。下面详细介绍一下&#xff1a; 谷歌浏览器输出console对象&#xff1a; 值得一提的是不…

JAVA MQTT 发布主题请求,订阅主题接收,订阅主题回复,发布主题再接收回复,三步走

先看效果 一、准备工作 1.官网下载emqx压缩包放到自己的盘符下&#xff0c;不要带中文路径 下载 EMQX 2.在路径的bin中&#xff0c;cmd&#xff0c;启动emqx服务 emqx start 3.访问服务&#xff0c;能打开就证明启动成功&#xff0c;登录的话官网默认的密码账号&#xff08;…

【C#】Stopwatch计时器

使用Stopwatch检查C#中代码块的执行时间&#xff0c;比如歌曲&#xff0c;图片的下载时间问题 首先&#xff0c;我们可看到Stopwatch 类内部的函数。 根据需求&#xff0c;我们具体可使用到 Start() 开始计时&#xff0c;Stop() 停止计时等 //创建 Stopwatch 实例 Stopwatch …

STM32单片机C语言模块化编程实战:LED控制详解与示例

一、开发环境 硬件&#xff1a;正点原子探索者 V3 STM32F407 开发板 单片机&#xff1a;STM32F407ZGT6 Keil版本&#xff1a;5.32 STM32CubeMX版本&#xff1a;6.9.2 STM32Cube MCU Packges版本&#xff1a;STM32F4 V1.27.1 之前介绍了很多关于点灯的方法&#xff0c;比如…

ARM DMIPS算力说明

ARM DMIPS算力说明 ARM算力参考官网地址 https://en.wikipedia.org/wiki/List_of_ARM_processors Product familyARM architectureProcessorFeatureCache (I / D), MMUTypical MIPS MHzReferenceARM1ARMv1ARM1First implementationNoneARM2ARMv2ARM2ARMv2 added the MUL (mu…