打印
[STM32F1]

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

[复制链接]
211|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
tpgf|  楼主 | 2024-2-22 17:28 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
前言
本文记录了如何用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 = 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+(MAXNUM/2-MAXNUM/2*Am);
                PWM_SetCompare1(temp);
        }
}       

三、波形效果


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



四、加电容滤波后的波形



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

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/m0_68747151/article/details/135140184

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1360

主题

13960

帖子

8

粉丝