当前位置: 首页 > news >正文

利用STC15输出两路互补SPWM波形

利用STC15输出两路互补SPWM波形


  • 🎞逻辑分析仪信号采集演示:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 🔖本案例使用的是IAP15W4K61S4验证。

  • 📍相关篇《STC15系列PWM相关功能寄存器介绍》

  • 📌相关开源PCB《【PCB开源分享】STC/IAP15W4K61S4开发板》

  • 🎈相关参考来源于STC官方资料。

📋STC15W4K32S4系列新增6通道高精度PWM (带死区控制的增强型PWM波形发生器)简介

STC15W4K32S4系列的单片机集成了一组(各自独立6路)增强型的PWM波形发生器。PWM波形发生器内部有一个15位的PWM计数器供6路PWM使用,用户可以设置每路PWM的初始电平。另外,PWM波形发生器为每路PWM又设计了两个用于控制波形翻转的计数器T1/T2,可以非常灵活的每路PWM的高低电平宽度,从而达到对PWM的占空比以及PWM的输出延迟进行控制的目的。由于6路PWM是各自独立的,且每路PWM的初始状态可以进行设定,所以用户可以将其中的任意两路配合起来使用,即可实现互补对称输出以及死区控制等特殊应用。

📑SPWM实现原理介绍

SPWM是使用PWM来获得正弦波输出效果的一种技术。像STCI5W4KxS4系列MCU内带6通道15位PWM,各路PWM周期 (频率) 相同,输出的占空比独立可调,并且输出始终保持同步,输出相位可设置。这些特性使得设计SPWM成为可能并且可方便设置死区时间,对于驱动桥式电路,死区时间至关重要。不过本MCU没有专门的死区控制寄存器,通讨查表法设置PWM占空比参数来达到。

在这里插入图片描述

内部15位的PWM计数器一旦运行,就会从0开始在每个PWM时钟到来时加1,其值线性上升,当计数到与15位的周期设置寄存器[PWMCHPWMCL]相等时(图中斜线A到B),内部PWM计数器归0,并产生中断,称为“归0中断”。本例周期设置为2400,内部计数器计到2400就归0,即2399,下一个时钟就归0.

STC15W4K32S4 PWM输出端口定义和切换

STC15W4K32S4系列增强型PWM输出端口定义如下:[PWM2:P3.7, PWM3:P2.1, PWM4:P2.2, PWM5:P2.3, PWM6:P1.6, PWM7:P1.7],每路PWM的输出端口都可使用特殊功能寄存器位CnPINSEL分别独立的切换到第二组:[PWM2_2:P2.7, PWM3_2:P4.5, PWM4_2:P4.4, PWM5_2:P4.2, PWM6_2:P0.7, PWM7_2:P0.6]。
所有与PWM相关的端口,在上电后均为高阻输入态,必须在程序中将这些口设置为双向口或强推挽模式才可正常输出波形。

🌼双路PWM产生互补或同相的SPWM示例程序代码

  • 🎉本示例程序来源于STC15实验箱中的案例。
  • ✨使用的是PWM3(P21)和PWM4(P22)两路。
  • 📢在使用STC-ISP烧录时,注意选择24MHz,不然波形频率就不对了。

当内部计数器的值与某个翻转寄存器的值相等时,就对对应的输出IO取反,本例中,PWM3从P2.1输出
并且PWM3输出的P2.1初始电平为0,PWM4输出的P2.2初始电平为1,则,当内部PWM计数器计到等于PWM4T1=53时,P2.2 由高输出低,计到等于PWM3T1=65时,P2.1由低输出高,计到等于PWM3T2-800时,P2.1由高输出低,计到等于PWM4T2-812时,P22由低输出高
两路输出是互补的,用于驱动一些MOSFET的半桥式驱动IC。可以看到这两路PWM的翻转时刻有一点差别,相差12个时钟,为什么要这样设计呢?这就是传说中的死区。为了方便说明,把这两路PWM放大如图2:

在这里插入图片描述

  • P22输出低电平后,再过12个时钟在24MHZ时,对应0.Sus),P2.1输出高电平。

  • P2.1输出低电平后,再过12个时钟在24MHZ时,对应0.5us),P2.2输出高电平。
    这个12个时钟就是死区时间,本例PWM时钟为IT模式,对应0.5ws。假设P2.1驱动的是半桥的下臂,P22驱动的是上臂,则P2.2输出低电平后,上臂开始关闭,经过05us,上臂关闭完毕,P2.1输出高电平,下臂打开。P2.1输出低电平后,下臂开始关闭,经过0.5us,下臂关闭完毕,P2.2输出高电平,上臂打开。这样,死区时间的设置,可以避免上下臂同时打开造成烧毁MOSFET。
    有人会说,一路输出关闭的同时,另一路大开,不会烧管子啊?
    错啦,MOSFET打开快,关闭慢相关知识请翻翻书),所以需要一段时间关闭
    P2.1或P2.2如果直接用示波器观察,会看到比我们的思绪还凌乱的波形,因为PWM一直在变化,但
    是通过RC (1K+1uF) 低通滤波再观察的话,就会看到两个反相的正弦波,神奇吧,呵呵!

  • RC低通滤波器,截止频率计算公式:
    在这里插入图片描述
    在这里插入图片描述

  • 经过RC低通滤波器后,使用示波器采集的2路波形:
    在这里插入图片描述
    在这里插入图片描述

本例伸用24MHz时钟,PWM时钟为1T模式,PWM周期2400,正收表幅度为2300,往上偏移60
个时钟方便过0中断重装数据)。正弦采样为200点,则输出正弦波频率 =240000002400/200=50HZ。


/*------------------------------------------------------------------*/
/* --- STC MCU International Limited -------------------------------*/
/* --- STC 1T Series MCU RC Demo -----------------------------------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ---------------------*/
/* --- Web: www.GXWMCU.com -----------------------------------------*/
/* --- QQ:  800003751 ----------------------------------------------*/
/* If you want to use the program or the program referenced in the  */
/* article, please specify in which data and procedures from STC    */
/*------------------------------------------------------------------*/


#include	"config.h"
#include	"PWM.h"


/*************	功能说明	**************

演示使用2路PWM产生互补或同相的SPWM.

主时钟选择24MHZ, PWM时钟选择1T, PWM周期2400, 死区12个时钟(0.5us).正弦波表用200点. 

输出正弦波频率 = 24000000 / 2400 / 200 = 50 HZ.

本程序仅仅是一个SPWM的演示程序, 用户可以通过上面的计算方法修改PWM周期和正弦波的点数和幅度.

本程序输出频率固定, 如果需要变频, 请用户自己设计变频方案.

本程序从P2.1(PWM3)输出正相脉冲, 从P2.2(PWM4)输出反相脉冲(互补).

如果需要P2.2输出同相的, 请在初始化配置中"Start_IO_Level"项选择0(设置PWM输出端口的初始电平, 0或1).


工程文件:
delay.c
pwm.c
main.c

******************************************/

/*************	本地常量声明	**************/


/*************	本地变量声明	**************/


/*************	本地函数声明	**************/



/*************  外部函数和变量声明 *****************/



//========================================================================
// 函数: void	PWM_config(void)
// 描述: PWM配置函数。
// 参数: none.
// 返回: none.
// 版本: VER1.0
// 日期: 2014-8-15
// 备注: 
//========================================================================
void	PWM_config(void)
{
	PWMx_InitDefine		PWMx_InitStructure;					//结构定义
	
	PWMx_InitStructure.PWMx_IO_Select       = PWM3_P21;		//PWM输出IO选择. PWM2_P37,PWM2_P27,PWM3_P21,PWM3_P45,PWM4_P22,PWM4_P44,PWM5_P23,PWM5_P42,PWM6_P16,PWM6_P07,PWM7_P17,PWM7_P06
	PWMx_InitStructure.Start_IO_Level       = 0;			//设置PWM输出端口的初始电平, 0或1
	PWMx_InitStructure.PWMx_Interrupt       = DISABLE;		//中断允许,   			ENABLE或DISABLE
	PWMx_InitStructure.FirstEdge_Interrupt  = DISABLE;		//第一个翻转中断允许,   ENABLE或DISABLE
	PWMx_InitStructure.SecondEdge_Interrupt = DISABLE;		//第二个翻转中断允许,   ENABLE或DISABLE
	PWMx_InitStructure.FirstEdge            = 65;			//第一个翻转计数, 1~32767
	PWMx_InitStructure.SecondEdge           = 1220;			//第二个翻转计数, 1~32767
	PWMx_Configuration(PWM3_ID, &PWMx_InitStructure);		//初始化PWM, 	PWM2_ID,PWM3_ID,PWM4_ID,PWM5_ID,PWM6_ID,PWM7_ID
	P21 = 0;
	P2n_push_pull(1<<1);									//IO初始化, 上电时为高阻

	PWMx_InitStructure.PWMx_IO_Select       = PWM4_P22;		//PWM输出IO选择. PWM2_P37,PWM2_P27,PWM3_P21,PWM3_P45,PWM4_P22,PWM4_P44,PWM5_P23,PWM5_P42,PWM6_P16,PWM6_P07,PWM7_P17,PWM7_P06
	PWMx_InitStructure.Start_IO_Level       = 1;			//设置PWM输出端口的初始电平, 0或1
	PWMx_InitStructure.PWMx_Interrupt       = DISABLE;		//中断允许,   			ENABLE或DISABLE
	PWMx_InitStructure.FirstEdge_Interrupt  = DISABLE;		//第一个翻转中断允许,   ENABLE或DISABLE
	PWMx_InitStructure.SecondEdge_Interrupt = DISABLE;		//第二个翻转中断允许,   ENABLE或DISABLE
	PWMx_InitStructure.FirstEdge            = 65-PWM_DeadZone;	//第一个翻转计数, 1~32767
	PWMx_InitStructure.SecondEdge           = 1220+PWM_DeadZone;//第二个翻转计数, 1~32767
	PWMx_Configuration(PWM4_ID, &PWMx_InitStructure);		//初始化PWM, 	PWM2_ID,PWM3_ID,PWM4_ID,PWM5_ID,PWM6_ID,PWM7_ID
	P22 = 1;
	P2n_push_pull(1<<2);									//IO初始化, 上电时为高阻

	PWM_SourceClk_Duty(PwmClk_1T, 2400);	//时钟源: PwmClk_1T,PwmClk_2T, ... PwmClk_16T, PwmClk_Timer2,   PWM周期: 1~32767
	
	PWMCR |= ENPWM;		// 使能PWM波形发生器,PWM计数器开始计数
//	PWMCR &= ~ECBI;		//禁止PWM计数器归零中断
	PWMCR |=  ECBI;		//允许PWM计数器归零中断

//	PWMFDCR = ENFD | FLTFLIO | FDIO;	//PWM失效中断控制,  ENFD | FLTFLIO | EFDI | FDCMP | FDIO
}


/**********************************************/
void main(void)
{
	
	PWM_config();	//初始化PWM

	EA = 1;			//允许全局中断

	while (1)
	{
		
	}
}


📚完整工程代码

链接: https://pan.baidu.com/s/1PlF8HmJgXOgMTSa48lodcg
提取码: 8h6k

相关文章:

  • 我发现买不起自己出版的书了,这到底是咋回事?
  • 「自定义类型」C语言中的构造数据类型如结构,联合,枚举
  • 【C++修炼之路】C++入门(下)
  • 【C++】C++11语法 ~ 可变参数模板
  • 初识计算机网络
  • 无痕埋点在Android中的实现
  • 全网最详细地介绍mybatis-plus框架
  • C语言及算法设计课程实验五:循环结构程序设计
  • Java 定时任务详解
  • h5实现相机
  • 字节跳动青训营--前端day6
  • 浅谈估值模型:PB指标与剩余收益估值
  • 深度解读 python 实现 dbscan算法
  • 2023年“华数杯”国际大学生数学建模A题完整思路
  • C++ 入门
  • ECMAScript6(0):ES6简明参考手册
  • Java,console输出实时的转向GUI textbox
  • java8-模拟hadoop
  • JS笔记四:作用域、变量(函数)提升
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • node-glob通配符
  • Promise面试题,控制异步流程
  • Python - 闭包Closure
  • Python学习之路13-记分
  • vue 配置sass、scss全局变量
  • vuex 学习笔记 01
  • 高程读书笔记 第六章 面向对象程序设计
  • 前嗅ForeSpider中数据浏览界面介绍
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • 专访Pony.ai 楼天城:自动驾驶已经走过了“从0到1”,“规模”是行业的分水岭| 自动驾驶这十年 ...
  • ​2021半年盘点,不想你错过的重磅新书
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • #QT(一种朴素的计算器实现方法)
  • $().each和$.each的区别
  • (C++20) consteval立即函数
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (论文阅读22/100)Learning a Deep Compact Image Representation for Visual Tracking
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • (转)socket Aio demo
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .net Signalr 使用笔记
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .net 无限分类
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET序列化 serializable,反序列化
  • @EnableWebMvc介绍和使用详细demo
  • @Transactional 详解
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • [ACL2022] Text Smoothing: 一种在文本分类任务上的数据增强方法
  • [Angularjs]asp.net mvc+angularjs+web api单页应用之CRUD操作
  • [C#] 如何调用Python脚本程序
  • [C++] Windows中字符串函数的种类
  • [C++] 如何使用Visual Studio 2022 + QT6创建桌面应用