MSPM0开发学习笔记:TIMER-PWM
讲解 MSPM0 定时器 PWM 原理与 SysConfig 配置,附基础启动代码及按键切换双通道占空比的进阶示例。
MSPM0开发学习笔记
第一章 初步安装与配置
第二章 GPIO
第三章 TIMER
第四章 TIMER-PWM
一、Timer-Pwm原理与作用介绍
PWM通过定时器(TIMER)实现周期性脉冲信号的精确控制,其本质是利用计数器与比较寄存器协同工作生成可调占空比的方波。定时器以系统时钟为基准,通过分频器调整计数频率后驱动计数器循环累加(或递减),当计数值达到预设的自动重载值(ARR)时复位并触发周期更新。在此过程中,比较寄存器(CCRx)设定阈值,当计数值低于阈值时输出高电平,高于阈值时输出低电平,从而通过调节CCRx与ARR的比值动态控制高电平持续时间(占空比)。PWM的核心功能在于将数字信号转化为模拟控制量,通过调节占空比实现电压、功率或机械位置的连续控制,例如驱动电机调速、LED亮度调节、舵机角度控制等场景。多路PWM通道可共享同一定时器,在统一频率下独立调节各通道占空比
二、syscfg配置
1、TIMER-PWM

在TIMER-PWM中进行配置
1、可以看到,黄色的部分都是上节课TIMER中配置过的,这边就不赘述了,不了解的朋友可以在文章顶部访问上篇文章进行学习。
2、接下来看绿色部分,可以看到这边可以通过设置PWM Period Count 的值来调整生成PWM波的频率,他们的乘积是上面的Calculated Clock Frequency (Hz)
3、再看下面一个绿色的部分 PWM Mode 这个地方是对于波的相位的控制,因为是一下控制多个波输出的(下面白色部分选择了Channel0和Channel2),如果不同波的占空比不同,他们的初始相位就需要我们进行设置,这边选择的Edge-aligned Down Counting边缘对齐,初次之外还有Center-aligned(中心对齐)等方式。可以通过文档中的图来看一下二者的区别

Edge-aligned Down Counting对齐
Center-aligned中心对齐
但是除非我们使用的涉及到无刷电机,否则这个其实并没有什么影响,所以我们这边先选择默认的Edge-aligned Down Counting就好
4、再往下看,灰色部分的就是可以对其中的一个波形进行单独调整的地方,值得注意的是,在同一个TIMER控制的PWM输出不同波中,频率是一定相同的,能改变的只有占空比之类的数据

5、再继续看一下这边的红色部分,可以配置pwm波的具体输出引脚
配置完之后就可以开始程序的设计了
三、程序设计
具体代码如下:
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
while (1) {
//__WFI();
}
}
这个的代码还是比较简单的
SYSCFG_DL_init()进行初始化
DL_TimerG_startCounter(PWM_0_INST)开始计时
值得一提的是为什么我要将例程中的__WFI()给注释掉,原因是这个实际上是让板子进入一个低功耗的状态,是好事但是我们在电赛的控制题中是不注重这个低功耗的,并且如果经常在状态转换中出现意想不到的错误,为了避免不必要的麻烦,我们就直接选择不考虑低功耗相关问题了。
四、进阶:按钮控制PWM占空比
我们可以基于这个改一个比较难一点的项目
1、syscfg配置
首先肯定要添加一个按钮的GPIO,这个具体内容在第二章GPIO里面已经讲过了,这边也再过一下,只需要设置下图中圈起来的几个地方就可以了。我们就把GPIO连接到这个PB21上面去了

2、程序设计
我们要如何在程序中设置/修改PWM波的占空比呢,这个是之前没有涉及到的内容,我们在syscfg中配置之后,我们可以按以下步骤在Debug/ti_msp_dl_config.c中找到我们需要的函数:


可以看到这边的DL_TimerG_setCaptureCompareValue就是我们需要的函数
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
while (1) {
if(DL_GPIO_readPins(GPIO_GRP_0_PORT, GPIO_GRP_0_PIN_0_PIN))
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 22400, DL_TIMER_CC_0_INDEX);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 9599, DL_TIMER_CC_1_INDEX);
}
else
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 9599, DL_TIMER_CC_0_INDEX);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 22400, DL_TIMER_CC_1_INDEX);
}
}
}
DL_TimerG_setCaptureCompareValue的传入参数不会写得话,可以直接在syscfg里面配置完然后按刚才的方法去Debug/ti_msp_dl_config.c里面复制一份就可以,在syscfg里面配置成30% 70%这样然后过去复制 就得到9599 22400这样的Value数据
GPIO按钮那边的传入参数不知道名称的话可以在Debug/ti_msp_dl_config.h里面进行查找(配置完需要编译下才可以)

这个代码的逻辑还是比较清晰的,按下按钮和松开按钮来调节Channel1和Channel0的占空比。
MSPM0開發學習筆記:TIMER-PWM
講解 MSPM0 定時器 PWM 原理與 SysConfig 配置,附基礎啟動程式碼及按鍵切換雙通道占空比的進階範例。
來源:https://blog.csdn.net/2403_87969572/article/details/148110990
抓取時間(ISO本地):2026-05-18 05:16:58
MSPM0開發學習筆記
第一章 初步安裝與配置
第二章 GPIO
第三章 TIMER
第四章 TIMER-PWM
文章目錄
一、Timer-Pwm原理與作用介紹
PWM通過定時器(TIMER)實現週期性脈衝信號的精確控制,其本質是利用計數器與比較寄存器協同工作生成可調佔空比的方波。定時器以系統時鐘為基準,通過分頻器調整計數頻率後驅動計數器循環累加(或遞減),當計數值達到預設的自動重載值(ARR)時復位並觸發週期更新。在此過程中,比較寄存器(CCRx)設定閾值,當計數值低於閾值時輸出高電平,高於閾值時輸出低電平,從而通過調節CCRx與ARR的比值動態控制高電平持續時間(佔空比)。PWM的核心功能在於將數字信號轉化為模擬控制量,通過調節佔空比實現電壓、功率或機械位置的連續控制,例如驅動電機調速、LED亮度調節、舵機角度控制等場景。多路PWM通道可共享同一定時器,在統一頻率下獨立調節各通道佔空比
二、syscfg配置
1、TIMER-PWM

在TIMER-PWM中進行配置
1、可以看到,黃色的部分都是上節課TIMER中配置過的,這邊就不贅述了,不瞭解的朋友可以在文章頂部訪問上篇文章進行學習。
2、接下來看綠色部分,可以看到這邊可以通過設置PWM Period Count 的值來調整生成PWM波的頻率,他們的乘積是上面的Calculated Clock Frequency (Hz)
3、再看下面一個綠色的部分 PWM Mode 這個地方是對於波的相位的控制,因為是一下控制多個波輸出的(下面白色部分選擇了Channel0和Channel2),如果不同波的佔空比不同,他們的初始相位就需要我們進行設置,這邊選擇的Edge-aligned Down Counting邊緣對齊,初次之外還有Center-aligned(中心對齊)等方式。可以通過文檔中的圖來看一下二者的區別

Edge-aligned Down Counting對齊
Center-aligned中心對齊
但是除非我們使用的涉及到無刷電機,否則這個其實並沒有什麼影響,所以我們這邊先選擇默認的Edge-aligned Down Counting就好
4、再往下看,灰色部分的就是可以對其中的一個波形進行單獨調整的地方,值得注意的是,在同一個TIMER控制的PWM輸出不同波中,頻率是一定相同的,能改變的只有佔空比之類的數據

5、再繼續看一下這邊的紅色部分,可以配置pwm波的具體輸出引腳
配置完之後就可以開始程序的設計了
三、程序設計
具體代碼如下:
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
while (1) {
//__WFI();
}
}
這個的代碼還是比較簡單的
SYSCFG_DL_init()進行初始化
DL_TimerG_startCounter(PWM_0_INST)開始計時
值得一提的是為什麼我要將例程中的__WFI()給註釋掉,原因是這個實際上是讓板子進入一個低功耗的狀態,是好事但是我們在電賽的控制題中是不注重這個低功耗的,並且如果經常在狀態轉換中出現意想不到的錯誤,為了避免不必要的麻煩,我們就直接選擇不考慮低功耗相關問題了。
四、進階:按鈕控制PWM佔空比
我們可以基於這個改一個比較難一點的項目
1、syscfg配置
首先肯定要添加一個按鈕的GPIO,這個具體內容在第二章GPIO裡面已經講過了,這邊也再過一下,只需要設置下圖中圈起來的幾個地方就可以了。我們就把GPIO連接到這個PB21上面去了

2、程序設計
我們要如何在程序中設置/修改PWM波的佔空比呢,這個是之前沒有涉及到的內容,我們在syscfg中配置之後,我們可以按以下步驟在Debug/ti_msp_dl_config.c中找到我們需要的函數:


可以看到這邊的DL_TimerG_setCaptureCompareValue就是我們需要的函數
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
while (1) {
if(DL_GPIO_readPins(GPIO_GRP_0_PORT, GPIO_GRP_0_PIN_0_PIN))
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 22400, DL_TIMER_CC_0_INDEX);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 9599, DL_TIMER_CC_1_INDEX);
}
else
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 9599, DL_TIMER_CC_0_INDEX);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 22400, DL_TIMER_CC_1_INDEX);
}
}
}
DL_TimerG_setCaptureCompareValue的傳入參數不會寫得話,可以直接在syscfg裡面配置完然後按剛才的方法去Debug/ti_msp_dl_config.c裡面複製一份就可以,在syscfg裡面配置成30% 70%這樣然後過去複製 就得到9599 22400這樣的Value數據
GPIO按鈕那邊的傳入參數不知道名稱的話可以在Debug/ti_msp_dl_config.h裡面進行查找(配置完需要編譯下才可以)

這個代碼的邏輯還是比較清晰的,按下按鈕和鬆開按鈕來調節Channel1和Channel0的佔空比。
MSPM0 Dev Notes: TIMER-PWM
Covers MSPM0 timer PWM theory, SysConfig setup, starter code, and a button-driven example that swaps duty cycles on two channels.
Captured at (local ISO): 2026-05-18 05:16:58
MSPM0 Development Notes
Chapter 1 Initial Install and Configuration
Chapter 2 GPIO
Chapter 3 TIMER
Chapter 4 TIMER-PWM
I. Timer-PWM Principle and Role
PWM uses a TIMER to generate periodic pulses. A counter runs from the system clock (optionally prescaled); when it hits the auto-reload value (ARR) it resets. A compare register (CCRx) sets the threshold: output is high while count < CCRx and low otherwise. Duty cycle = CCRx / ARR.
PWM turns digital signals into analog-like control—motor speed, LED brightness, servo angle, etc. Multiple PWM channels can share one timer at the same frequency with independent duty cycles.
II. SysConfig Setup
1. TIMER-PWM

Configure in TIMER-PWM:
- Yellow fields match the previous TIMER lesson (see the series intro).
- Green: PWM Period Count sets frequency together with Calculated Clock Frequency (Hz).
- PWM Mode controls phase when multiple channels run (e.g. Channel0 and Channel2). Edge-aligned down counting is selected here; center-aligned is another option—see the docs:

Edge-aligned down counting
Center-aligned
For most uses (unless brushless motors need center alignment), edge-aligned down counting is fine.
- Gray area: per-channel duty settings. Channels on the same TIMER share frequency; only duty/phase differ.

- Red: assign PWM output pins.
After configuration, write the application.
III. Application Code
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
while (1) {
//__WFI();
}
}
SYSCFG_DL_init() initializes hardware; DL_TimerG_startCounter(PWM_0_INST) starts the timer.
__WFI() is commented out—it puts the MCU in low power. For competition control tasks we skip low-power modes to avoid odd state transitions during frequent start/stop.
IV. Advanced: Button-Controlled PWM Duty Cycle
1. SysConfig
Add a button GPIO (see Chapter 2). Configure the circled options and connect to PB21.

2. Application Code
To change duty at runtime, find helpers in Debug/ti_msp_dl_config.c after SysConfig generate:


DL_TimerG_setCaptureCompareValue is what you need.
#include "ti_msp_dl_config.h"
int main(void)
{
SYSCFG_DL_init();
DL_TimerG_startCounter(PWM_0_INST);
while (1) {
if(DL_GPIO_readPins(GPIO_GRP_0_PORT, GPIO_GRP_0_PIN_0_PIN))
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 22400, DL_TIMER_CC_0_INDEX);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 9599, DL_TIMER_CC_1_INDEX);
}
else
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 9599, DL_TIMER_CC_0_INDEX);
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 22400, DL_TIMER_CC_1_INDEX);
}
}
}
Copy argument names from SysConfig-generated code, or set 30%/70% in SysConfig and copy values (e.g. 9599, 22400).
GPIO pin macros are in Debug/ti_msp_dl_config.h after build.

Logic: press swaps duty on Channel0 vs Channel1.