首页 > 其他分享 >TMS320F28377D学习日志:day4基于ePWM的呼吸灯

TMS320F28377D学习日志:day4基于ePWM的呼吸灯

时间:2024-07-06 15:57:18浏览次数:18  
标签:CC TMS320F28377D day4 AQ 模块 ePWM EPwm1Regs bit PWM

文章目录


前言

28377D具有24路PWM输出引脚,14路高分辨率的HRPWM。ePWM是对PWM的加强型。其中一个ePWM通道有2个PWM输出引脚EPWMxA、EPWMxB,可以用于配置两路独立单边沿PWM、两路对称双边沿PWM和一路双边沿PWM。每个ePWM具有1个16位的时基计数器,用于控制周期和频率。
该通过对ePWM0进行配置,复用GPIO0和GPIO1为epwm,输出两路周期相同,占空比不同的PWM波形。在引脚接上LED,通过循环语句改变PWM的占空比,从而实现LED由亮到灭再到亮。


一、TMS320F28377D的ePWM介绍

1.1 PWM的复用引脚

PWM模块的输出引脚见下表,其中每组EPWM都有2组不同的引脚,在实际应用中复用其中一组引脚即可。

EPWMGPIO
EPWM1A/BGPIO0/1或GPIO145/146
EPWM2A/BGPIO2/3或GPIO147/148
EPWM3A/BGPIO4/5或GPIO149/150
EPWM4A/BGPIO6/7或GPIO151/152
EPWM5A/BGPIO8/9或GPIO153/154
EPWM6A/BGPIO10/11或GPIO155/156
EPWM7A/BGPIO12/13或GPIO157/158
EPWM8A/BGPIO14/15或GPIO159/160
EPWM9A/BGPIO16/17或GPIO161/162
EPWM10A/BGPIO18/19或GPIO163/164
EPWM11A/BGPIO20/21或GPIO165/166
EPWM12A/BGPIO22/23或GPIO167/168

1.2 PWM模块的组成

一个ePWM模块由8个小模块组成,如下图。分别为时基模块(TB)、比较计数模块(CC)、动作模块(AQ)、死区模块(DB)、PWM斩波模块(PC)、时间触发模块(ET)、防联模块(TZ)和数字比较模块(DC)。
在这里插入图片描述
其中,配置PWM波形常用的是TB、CC、AQ、DB和ET等模块。接下来介绍TB、CC和AQ模块。

1.3 TB模块

在这里插入图片描述
在这里插入图片描述
TB模块可以用于设计PWM的周期大小。其中有三种计数方式:向上计数、向下计数和向上-向下计数。其中配置PWM的周期/频率与TBPRD和TBCTRL这两个寄存器有关。TBPRD为时基周期寄存器值,用于储存计数的最大值。TBCTRL为时基计数器的计数模式,其中可以设置以上的三种计数模式。
对于设置为向上-向下计数模式的情况
在这里插入图片描述
其中PWM周期等于2倍的TBPRD乘以单个计数的时间。
对于对于设置为向上计数模式或者向下计数模式的情况
在这里插入图片描述
其中PWM周期等于TBPRD加一的和,再乘以单个计数的时间。
其中上面两图中T(TBCLK)是经过分频之后,一次计数的时间。频率计算公式为TBCLK=EPWMCLK/(HSPCLKDTV*CLKDIV),再取倒数就是周期。

TB模块配置程序:

// Setup TBCLK
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;       // Set timer period,这里设置为20k
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
    EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;       // Phase is 0
    EPwm1Regs.TBCTR = 0x0000;                  // Clear counter
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;   // Clock ratio to SYSCLKOUT,采用2分频
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2;      //TBCLK=EPWMCLK/(HSPCLKDIV*CLKDIV)=200M/(2*2)=50M,所以PWM周期为(20k+1)/50M=400us

其中采用向上计数的模式;EPWM1_TIMER_TBPRD预先宏定义为20k;没有预先相位,相位为;HSPCLKDIV 和CLKDIV 都采用2分频,28377D的系统频率为200M Hz,所以TBCLK为50M Hz,周期为1/50M s;经过计数PWM周期为400us。

1.4 CC模块

CC模块可以用于控制PWM的脉宽
在这里插入图片描述
对于向上计数模式或者向下计数模式,在一个PWM周期中,比较只能计数一次,就是单边沿触发;对于向上-向下计数模式,在一个PWM周期中,比较会计数两次,就是双边沿触发。

CC模块配置程序:

// Setup shadow register load on ZERO
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    // Set Compare values
    EPwm1Regs.CMPA.bit.CMPA = EPWM1_MIN_CMPA;    // Set compare A value
    EPwm1Regs.CMPB.bit.CMPB = EPWM1_MAX_CMPB;    // Set Compare B value

这里采用了影子寄存器的方式,给CC寄存器进行配置,当计数器为0时进行载入。同时设置CMPA和CMPB的比较值,当计数器到达这两个比较值时,会发出脉冲给AQ模块,进而调整输出电平。因此CMPA和CMPB的比较值将会影响PWM的脉宽大小。

1.5 AQ模块

AQ模块用于控制输出PWM的动作,当CC模块触发或者软件触发时,可以响应触发,选择对PWM波形进行置高、置底或者翻转等操作。
在这里插入图片描述

AQ模块配置程序:

// Set actions
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A, up count

    EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;            // Set PWM1B on Zero
    EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;          // Clear PWM1B on event B, up count

当计数器为0时,设置EPWM1A为高电平;当计数器等于CMPA的比较值时,设置EPWM1A为低电平。对于EPWM1B的设置也是同理。

// AQCTLA and AQCTLB (Action Qualifier Control)
//=============================================
// ZRO, PRD, CAU, CAD, CBU, CBD bits
#define	AQ_NO_ACTION	0x0
#define	AQ_CLEAR		0x1
#define	AQ_SET			0x2
#define	AQ_TOGGLE		0x3

在ti官方给的F2837xD_EPwm_defines.h中可以看到,AQ动作有4种方式。其中AQ_NO_ACTION为无事发生;AQ_CLEAR为置低;AQ_SET为置高;AQ_TOGGLE为翻转。AQ可以动作的时间也有很多,还包括计数器计满等情况。

二、程序介绍

#include "F28x_Project.h"

#define EPWM1_TIMER_TBPRD  20000
#define EPWM1_MAX_CMPA     19500
#define EPWM1_MIN_CMPA       500
#define EPWM1_MAX_CMPB     19500
#define EPWM1_MIN_CMPB       500

void InitEPwm1Example(void);

void main(void)
{
    //初始化系统时钟
    InitSysCtrl();

    //使能PWM1
    CpuSysRegs.PCLKCR2.bit.EPWM1=1;

    //初始化pwm1的gpio
    InitEPwm1Gpio();

    //Disable CPU interrupts
    DINT;

    //Initialize the PIE control registers to their default state.
    InitPieCtrl();

    // Disable CPU interrupts and clear all CPU interrupt flags:
    IER = 0x0000;
    IFR = 0x0000;

    //Initialize the PIE vector table with pointers to the shell Interrupt
    //Service Routines (ISR).
    InitPieVectTable();

    EALLOW;

    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =0;

    EDIS;

    //初始化EPWM
    InitEPwm1Example();

    EALLOW;

    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =1;

    EDIS;

    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

    int duty_cycle = 0; //用于控制pwm0的占空比
    int num = 0;  //用于记录duty_cycle是增加还是减少

    while(1)
    {
        if(num == 0)  //duty_cycle处于增长
        {
            duty_cycle++;

            if(duty_cycle == 100)
            {
                num = 1;
            }
        }
        else          //duty_cycle处于减少
        {
            duty_cycle--;
            if(duty_cycle == 0)
            {
                num = 0;
            }
        }

        EPwm1Regs.CMPA.bit.CMPA = (int) EPWM1_TIMER_TBPRD /100 * duty_cycle;          // Set compare A value
        EPwm1Regs.CMPB.bit.CMPB = (int) EPWM1_TIMER_TBPRD /100 * (100-duty_cycle);    // Set Compare B value

        DELAY_US(40 * 1000);  //延迟20ms
    }
}


void InitEPwm1Example(void)
{
    // Setup TBCLK
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm1Regs.TBPRD = EPWM1_TIMER_TBPRD;       // Set timer period,这里设置为20k
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;    // Disable phase loading
    EPwm1Regs.TBPHS.bit.TBPHS = 0x0000;       // Phase is 0
    EPwm1Regs.TBCTR = 0x0000;                  // Clear counter
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV2;   // Clock ratio to SYSCLKOUT,采用2分频
    EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV2;      //TBCLK=EPWMCLK/(HSPCLKDIV*CLKDIV)=200M/(2*2)=50M,所以PWM周期为(20k+1)/50M=400us

    // Setup shadow register load on ZERO
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    // Set Compare values
    EPwm1Regs.CMPA.bit.CMPA = EPWM1_MIN_CMPA;    // Set compare A value
    EPwm1Regs.CMPB.bit.CMPB = EPWM1_MAX_CMPB;    // Set Compare B value

    // Set actions
    EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;            // Set PWM1A on Zero
    EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;          // Clear PWM1A on event A, up count

    EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;            // Set PWM1B on Zero
    EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;          // Clear PWM1B on event B, up count

}

呼吸灯的主程序,其中在while循环中每20ms改变PWM的占空比,由0逐渐增加1至100,再减一至0,另一路则相反。

void InitEPwm1Gpio(void)
{
    EALLOW;

    //
    // Disable internal pull-up for the selected output pins
    // for reduced power consumption
    // Pull-ups can be enabled or disabled by the user.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;    // enable pull-up on GPIO0 (EPWM1A)
    GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0;    // enable pull-up on GPIO1 (EPWM1B)
    // GpioCtrlRegs.GPEPUD.bit.GPIO145 = 1;    // Disable pull-up on GPIO145 (EPWM1A)
    // GpioCtrlRegs.GPEPUD.bit.GPIO146 = 1;    // Disable pull-up on GPIO146 (EPWM1B)

    //
    // Configure EPWM-1 pins using GPIO regs
    // This specifies which of the possible GPIO pins will be EPWM1 functional
    // pins.
    // Comment out other unwanted lines.
    //
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1;   // Configure GPIO0 as EPWM1A
    GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1;   // Configure GPIO1 as EPWM1B
    // GpioCtrlRegs.GPEMUX2.bit.GPIO145 = 1;   // Configure GPIO145 as EPWM1A
    // GpioCtrlRegs.GPEMUX2.bit.GPIO146 = 1;   // Configure GPIO0146 as EPWM1B

    EDIS;
}

在配置GPIO的时候需要注意的是,GPIO的状态可以设置为上拉状态或者非上拉状态,二者都可以。一般来说为了避免功率浪费,默认为非上拉状态,但是这次实验要求GPIO作为输出引脚控制LED的亮灭,所以需要设置为上拉状态。将GpioCtrlRegs.GPAPUD.bit.GPIO0设置为0.

标签:CC,TMS320F28377D,day4,AQ,模块,ePWM,EPwm1Regs,bit,PWM
From: https://blog.csdn.net/qq_45897521/article/details/140225306

相关文章

  • 代码训练营 DAY4打卡
      本文由GarfieldTheOldCat原创,转载请标明dekkyandlappy-CSDN博客今天学习了链表的第二课时,链表基础内容在代码训练营DAY3打卡 本文由GarfieldTheOldCat原创,转载请标明两两交换链表中的节点这道题目的第一个难点在于对题目意思的理解,什么是两两交换?举个例子:【A,B,C,D】......
  • Java进阶学习|Day4.Java多线程,线程池
    文章目录了解多线程CPU进程(Process)线程多线程开发多线程优点实现方式继承Thread类实现Runnable接口实现Callable接口线程状态转换线程状态线程调度调整线程优先级线程睡眠线程等待线程让步线程加入线程唤醒线程同步线程同步方式多线程间通信线程池了解线程池定义......
  • SpringCloud学习Day4
    熔断与限流:Sentinel1.概念Sentinel是面向分布式、多语言异构化服务架构的流量治理组件2.基本使用1.在应用中导入相关jar包,即在pom.xml添加以下依赖<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.......
  • 机器学习Day4
    决策树1.概念决策树是一种用于解决分类问题的算法,希望通过从给定数据训练一个模型用来对新示例进行分类决策树顾名思义是树结构,其结点可以划分为三类:根结点、内部结点、叶结点根节点:一般是区分度最高(基尼指数最小)的属性(纯度最高)内部结点:是父结点下基尼系数最小的结点......
  • LeetCode刷题day4——链表part2
    24.两两交换链表中的节点用pre代表第1个节点,cur代表它后面的相邻节点,tmp存储cur->next。但是问题找不到怎么返回新的节点。想着就循环一次,在第一次交换的时候就确认新的头结点。但还存在很多问题,具体如下:classSolution{public:ListNode*swapPairs(ListNode*he......
  • TMS320F28377D学习日志:day2点亮LED
    文章目录一、28377开发板的led电路分析二、28377的GPIO相关寄存器介绍2.1前言2.2GPySET寄存器介绍2.3GPyCLEAR寄存器介绍三、程序介绍3.1引入库3.2配置GPIO引脚功能3.2.1GPIO_SetupPinMux函数3.2.1GPIO_SetupPinOptions函数3.3系统初始化3.4循环程序参考文......
  • MySQL-Day4
    学习目标MySQL的内置函数concat拼接字符串函数把12,34,‘ab’,拼接成‘1234ab’selectconcat(12,34,'ab')length返回字符串字符的个数计算字符串长度‘abc’selectlength('abc')返回3一个utf-8,一个汉字表示3个长度selectlength(‘我和you’) 返回9内置函数可以......
  • DAY4-力扣刷题
    1.四数之和18.四数之和-力扣(LeetCode)给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a],nums[b],nums[c],nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):0<=a,b,c,d <na......
  • 运维必备Linux学习day4(Vmware磁盘扩容)
    虚拟机添加磁盘与linux逻辑卷扩容1.1 虚拟机添加磁盘1.1.1. 检查linux系统的磁盘分区及逻辑卷的相关信息是否正常(1)cat/etc/redhat-release查看系统版本【适用于RHEL及CentOS】:我已自己电脑上的虚拟机,50G内存2G运行内存为例>>>(2)df -h看挂载点空间使用率情况:(3)blkid查看......
  • Day49 代码随想录打卡|二叉树篇---二叉搜索树中的搜索
    题目(leecodeT700):给定二叉搜索树(BST)的根节点 root 和一个整数值 val。你需要在BST中找到节点值等于 val 的节点。返回以该节点为根的子树。如果节点不存在,则返回 null 。方法:递归法:本题考察了二叉搜索树的特性,二叉搜索树指的是在这个二叉树中,他的每一个根节点......