用stm32f103c8t6生成互补的带死区的spwm波

文章详细介绍了如何使用STM32F103C8T6的高级定时器TIM1和TIM3生成互补SPWM波,并配置死区,最终通过20kHz信号滤波得到50Hz正弦波。示例代码包括定时器初始化、PWM设置、正弦波生成以及主函数和定时中断处理。
摘要由CSDN通过智能技术生成

前言

本文记录了如何用stm32f103c8t6的高级定时器来生成互补的spwm波且带死区。频率为20khz,经过10uf电容滤波得到50hz正弦波。废话不多说直接上代码。

一、代码

1.1 高级定时器TIM1

PWM.c

#include "stm32f10x.h"
#include "PWM.h"
#include "spwm.h"
void PWM_Init(void)
{

	GPIO_InitTypeDef GPIOInitStruct;	

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);	/*使能GPIOA,GPIOB时钟*/
	
	GPIOInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIOInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIOInitStruct.GPIO_Pin = GPIO_Pin_8;											/*PA8:CH1*/
	GPIO_Init(GPIOA, &GPIOInitStruct);
	
	GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;											/*PB13:CH1N*/
	GPIO_Init(GPIOB, &GPIOInitStruct);
	
	GPIOInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;				
	GPIOInitStruct.GPIO_Pin = GPIO_Pin_12;											/*PB12:BKIN*/
	GPIO_Init(GPIOB, &GPIOInitStruct);

	GPIO_SetBits(GPIOB, GPIO_Pin_12);												/*设置PB12*/
	
		TIM_TimeBaseInitTypeDef		TIMTimeBaseStruct;
	TIM_OCInitTypeDef			TIMOCInitStruct;
	TIM_BDTRInitTypeDef			TIMBDTRInitStruct;
 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 							/*使能TIM1时钟*/
 
	/*时基结构体配置*/
	TIMTimeBaseStruct.TIM_Period = MAXNUM - 1;										/*从0开始 一个信号周期计数400次*/ 
	TIMTimeBaseStruct.TIM_Prescaler = 9 - 1;										
	TIMTimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1; 							/*时钟分频因子 = 1,tDTS=tCKINT*/
	TIMTimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up; 						/*向上计数*/
	TIMTimeBaseStruct.TIM_RepetitionCounter = 0; 									/*禁用重复计数器*/
	TIM_TimeBaseInit(TIM1, &TIMTimeBaseStruct); 
 
	/*输出比较结构体配置*/
	TIMOCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;									/*PWM1模式*/
	TIMOCInitStruct.TIM_OutputState = TIM_OutputState_Enable;						/*输出使能*/
	TIMOCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;						/*互补输出使能*/
	TIMOCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;							/*输出有效电平为高电平*/
	TIMOCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;							/*互补输出有效电平为高电平*/
	TIMOCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set;							/*输出空闲时为高电平*/
	TIMOCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;						/*互补输出空闲时为低电平*/
 
	/*初始化TIM1的通道1*/
	TIMOCInitStruct.TIM_Pulse = 25- 1; 											/*占空比 = 250 / 1000 = 25%*/
	TIM_OC1Init(TIM1,&TIMOCInitStruct);
	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);								/*开启预装载,在更新时间后才会重新装载数值*/		
 
	/*刹车和死区结构体配置*/
	TIMBDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Enable;							/*运行模式下“关闭模式”选择 = 1*/
	TIMBDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Enable;							/*空闲模式下“关闭模式”选择 = 1*/
	TIMBDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_1;								/*锁定级别1,见参考手册*/
	TIMBDTRInitStruct.TIM_DeadTime = 0x40;											/*死区时间:0x40大概为0.9us*/
	TIMBDTRInitStruct.TIM_Break = TIM_Break_Enable;									/*开启刹车功能*/
	TIMBDTRInitStruct.TIM_BreakPolarity = TIM_BreakPolarity_Low;					/*刹车输入低电平有效,如果引脚检测到高电平则会停止PWM的输出,不会产生任何波形*/
	TIMBDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;				/*开启自动输出*/
	TIM_BDTRConfig(TIM1, &TIMBDTRInitStruct);
 
	TIM_Cmd(TIM1, ENABLE);  														/*使能定时器,计数器开始计数*/
	
	TIM_CtrlPWMOutputs(TIM1, ENABLE);												/*开启主输出*/
}

void PWM_SetCompare1(uint16_t Compare1)//通道一
{
	TIM_SetCompare1(TIM1,Compare1);//0~ARR
}

 

1.2生成正弦波表格

spwm.c

#include "stm32f10x.h" 
#include "spwm.h"
#include "math.h"

uint16_t sinData[400];
float Am=0.85;//调制深度

//point 一个周期内的点数
//maxnum 最大值
void get_sin_tab1( uint16_t point, uint16_t maxnum )
{
    uint16_t i = 0, j = 0, k = 0;
    float hd = 0.0;        	//弧度
    float fz = 0.0;       	//峰值
    uint16_t tem = 0;
    j = point / 2;			//水平线位置 单片机没有负电压
    hd = PI / j;        	// π/2 内每一个点对应的弧度值
    k = maxnum / 2;      	//最大值一半
    for( i = 0; i < point; i++ )
    {     
		fz = k * sin( hd * i )+200;					
        tem = ( uint16_t )fz ;						
        sinData[i] = tem;
    }
}

spwm.h

#ifndef _SPWM_H
#define _SPWM_H

#define PI 3.1415926f
#define MAXNUM 400//占空比最大值

extern float Am;

extern uint16_t sinData[400];
void get_sin_tab1(uint16_t point,uint16_t maxnum);

#endif

 

1.3定时中断

50us一次定时中断

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	//定时器定时中断和外部时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//第一步使能APB1外设,因为TIM2在APB1
	
	TIM_InternalClockConfig(TIM3);//第二步使用内部时钟
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//第三步时基单元初始化
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseInitStruct.TIM_Period=100-1;//周期,ARR重装计数器的值,取值0~65535
	TIM_TimeBaseInitStruct.TIM_Prescaler=36-1;//PSC预分频器的值,因为预分频器和计数器都有一个数的偏差,所以-1
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;//重复计数器的值,高级计数器才有
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	TIM_ClearFlag(TIM3,TIM_FLAG_Update);//手动清除中断标志位,因为库函数会自动更新事件
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//第四步使能中断,TIM_IT_Update更新中断通道
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//第五步配置NVIC//分组
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;//设置中断通道
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;//配置中断优先级
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_Cmd(TIM3,ENABLE);//第六步启动定时器
	
}

二、主函数部分

#include "stm32f10x.h"                  
#include "PWM.h"
#include "spwm.h"
#include "Timer.h"
int main(void)
{
	PWM_Init();
	Timer_Init();
	get_sin_tab1(400,MAXNUM);
	while(1)
	{
		
	}	
} 


void TIM3_IRQHandler(void)
{
	static unsigned int i=0;
	uint16_t temp=0;
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
	{
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
		i++;
		if(i==MAXNUM){i=0;}
		temp=Am*sinData[i]+(MAXNUM/2-MAXNUM/2*Am);
		PWM_SetCompare1(temp);
	}
}	

三、波形效果

913feae2b0954dfc9f5621aac9fda56d.jpeg

通过测量得到死区时间为0.9us,图中Xa-Xb为900ns。

a53b2f75b4934858a1fb1199a8f688ba.jpeg 

四、加电容滤波后的波形

12361773956248b2ae82be2b6220c1fb.jpeg

可以看到是相位差180°的两个50hz正弦波。

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

le26

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值