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

server/2024/9/24 6:22:28/

中颖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.ppmy.cn/server/9809.html

相关文章

esp32的idf开发框架的目录结构

1、创建工程mytest&#xff0c;生成如下的目录结构。 idf.py create-project mytest 2、在mytest.c中添加如下代码&#xff0c;该代码功能是控制GPIO_2引脚上的LED闪烁 #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h&q…

tomcat更换应用目录

有时候要更换tomcat的应用目录&#xff0c;使之不在webapps下面。经过实验&#xff0c;有两种方法可行&#xff1a; 1. 修改server.xml中的<Host>标签 <Host name"localhost" appBase"../apps/haha" 红色字体部分修改为应用的路径&#xff0c;…

C++中的queue(容器适配器)

目录 一、成员函数 一、构造函数 二、入栈 push 三、出栈 pop 四、判空 empty 五、队列大小 size 六、取队头元素 front 七、取队尾元素 back 八、入栈 emplace 九、交换函数 swap 二、非成员函数重载 一、关系运算符重载 二、交换函数 swap C中的queue不再是容…

旅游陪同翻译难吗, 旅游翻译英译中哪家好?

近来&#xff0c;随着中国旅游业的蓬勃发展&#xff0c;旅游陪同翻译的需求也水涨船高&#xff0c;这些专业的翻译服务者为中外游客搭建起友谊的桥梁&#xff0c;引领他们共同探索中国这片古老而神秘的土地 。那么&#xff0c;旅游陪同翻译英译中难吗&#xff1f;我们如何在众多…

【Ansible】04

【Ansible】03 任务块 block任务块 使用 block 可以将多个任务合并为一个组可以将整个 block任务组 , 一起控制是否要执行 # 如果webservers组中的主机系统发行版是Rocky&#xff0c;则安装并启动nginx [rootpubserver ansible]# vim block1.yml --- - name: block tasksho…

Linux0.11 源码中的内存分页机制

学习Linux的源码&#xff0c;《深入linux 内核架构》这本书看起来就让人害怕&#xff0c;然后就想着看看早期的linux版本的源码&#xff0c;从网上查看资料发现linux0.11 这个版本有很多人拿来当成教学版本&#xff0c;而且也有很多的参考书以这个版本作为基础来讲解&#xff0…

docker-MySQL 8 主从搭建

一.目录结构&#xff1a; 我是在/home目录下&#xff0c;建立个sql文件夹&#xff1a; 二、配置文件 1.mysql配置 mysql-master下.conf文件配置 ###### [mysqld] server-id1 # 启用二进制日志 log-binmaster-bin # 指定需要复制的数据库 binlog-do-dbtest_db # 指定二进制日…

自然语言处理(NLP)技术

自然语言处理&#xff08;NLP&#xff09;技术是一种处理和分析人类语言的技术&#xff0c;它可以帮助计算机理解、解释和生成自然语言。 以下是一些常见的使用NLP技术的例子&#xff1a; 1. 机器翻译&#xff1a;NLP技术可以将一种语言翻译成另一种语言&#xff0c;比如将英…