This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] EK-TM4C123GXL:使用 PF0的 PWM - CAN't 使其工作

Guru**** 645330 points
Other Parts Discussed in Thread: LM4120, EK-TM4C123GXL, TM4C123GH6PM
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1233242/ek-tm4c123gxl-pwm-using-pf0---can-t-get-it-working

器件型号:EK-TM4C123GXL
主题中讨论的其他器件: TM4C123、LM4120、 TM4C123GH6PM

我正在尝试使用端口 PF0使 PWM 在 EK-TM4C123GXL Launchchapd 上正常工作。 我知道这是用于 NMI 目的的锁定引脚、并已将所需代码放入其中以解锁引脚。 然而、我滞留在等待  SysCtlPeripheralReady (SYSCTL_Periph_PWM1)变为真。 我会卡在突出显示的环路中。 我已经尝试了一切、甚至将其复制并粘贴到另一个项目、然后重新编译。 我只是不知道代码哪里出了问题。 这段代码基于使用 PF1的 TM4C1294代码、此代码非常有效。 我改变了处理器 和端口、但它应该能正常工作!

TM4C123G 的 PF0 PWM 详细信息如下:  

下面是完整的代码:

#包含
#包含
#包含
#包含
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_GPIO.h"
#include "inc/hw_types.h"
#include "driverlib/pwm.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "utils/ustdlib.h"
#include "driverlib/pin_map.h"
#include "driverlib/SysTick。h"

int main (空)
{
//将系统时钟设置为以 PLL 的80 MHz 频率运行,以外部晶体作为参考。
SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHz | SYSCTL_OSC_MAIN);

//启用所有 GPIO 外设。
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOF)
{

//解锁 PF0,它是一个锁定引脚(NMI)
HWREG (GPIO_PORTF_BASE + GPIO_O_LOCK)= GPIO_LOCK_KEY;
HWREG (GPIO_PORTF_BASE + GPIO_O_CR)|= GPIO_PIN_0;
HWREG (GPIO_PORTF_BASE + GPIO_O_LOCK)= 0;//重新锁定以防止进一步更改
//配置 PWM 时钟
SysCtlPWMClockSet (SYSCTL_PWMDIV_1);//配置 PWM 时钟
SysCtlPeripheralEnable (SYSCTL_Periph_PWM1);//启用 PWM 模块1
while (!SysCtlPeripheralReady (SYSCTL_Periph_PWM1))
{

GPIOPinTypePWM (GPIO_PORTF_BASE、GPIO_PIN_0);
GPIOPinConfigure (GPIO_PF0_M1PWM4);
PWMGenConfigure (PWM1_BASE、PWM_GEN_2、PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
PWMGenPeriodSet (PWM1_BASE、PWM_GEN_2、SysCtlClockGet ()/ 10);//设置默认周期以提供10Hz
PWMPulseWidthSet (PWM1_BASE、PWM_OUT_4、SysCtlClockGet ()/ 20);//设置默认脉冲宽度以提供50%占空比
PWMOutputState (PWM1_BASE、PWM_OUT_4_BIT、false);//需要时启用
PWMGenEnable (PWM1_base、PWM_GEN_2);//启动发生器2中的计时器

while (1)
{

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     在线路之外运行没有任何问题。 我可以看到 PF0上使用以下代码生成了 PWM。 您可以试试另一款电路板吗? 您还可以尝试以下代码吗?

    #include <stdint.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdbool.h>
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_gpio.h"
    #include "inc/hw_types.h"
    #include "driverlib/pwm.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/gpio.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/timer.h"
    #include "utils/ustdlib.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/systick.h"
    
    int main(void)
    {
        // Set the system clock to run at 80Mhz off PLL with external crystal as reference.
        SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
    
        // Enable all the GPIO peripherals.
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF))
        {
        }
        // Unlock PF0, which is a locked pin (NMI)
    //    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    //    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= GPIO_PIN_0;
    //    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0; // re-lock it to prevent further changes
    
        GPIOUnlockPin(GPIO_PORTF_BASE, GPIO_PIN_0);
        // Configure PWM clock
        SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // configure the PWM clock
        SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1); // enable PWM Module 1
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_PWM1))
        {
        }
        GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_0);
        GPIOPinConfigure(GPIO_PF0_M1PWM4);
        PWMGenConfigure(PWM1_BASE, PWM_GEN_2, PWM_GEN_MODE_DOWN | PWM_GEN_MODE_NO_SYNC);
        PWMGenPeriodSet(PWM1_BASE, PWM_GEN_2, SysCtlClockGet() / 250); // set default period to give 10 Hz
        PWMPulseWidthSet(PWM1_BASE, PWM_OUT_4, PWMGenPeriodGet(PWM1_BASE, PWM_GEN_2) / 4); // set default pulse width to give 50% duty cycle
        PWMOutputState(PWM1_BASE, PWM_OUT_4_BIT, true); // enabled when required
        PWMGenEnable(PWM1_BASE, PWM_GEN_2); // Start the timers in Generator 2
    
        while(1)
        {
        }
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢 Charles、

    这很有趣。 我尝试了另一个 LaunchPad 板、但仍然有问题。 这两个板都是 最初问世时购买的 Stellaris LaunchPad 板。 它真的是第一天。  然后、我试用了全新购买的 Tiva C 系列 LaunchPad 板、它可以正常工作。  两种板类型的固件版本均为12630。

    好消息是、我可以继续推进我的开发工作。 坏消息是任何较旧的 LaunchPad 都将锁定。 我们有混合物、用户不知道发生了什么。

    在一个相关的问题上、我 将对 GPIOUnlockPin 发表一些评论。 首先、当我尝试使用它时、我得到"unresolved symbol GPIOUnlockPin"、这很奇怪、因为我可以按住 Ctrl 键单击该函数、它会将我带到 GPIO.h 中的.h 文件。 但是、查看 GPIOUnlockPin 的 GPIO.c 代码时、我不喜欢它、因为它使用我使用的前两个 HWREG 命令、但不会在完成后重新锁定。 我想我将坚持我的三条线、至少现在是这样。

    总之、问题仅出现在 Stellaris LaunchPad 上。 是否有使旧 LaunchPad 和新 LaunchPad 均正常运行的权变措施。 (我开始怀疑基于 HWREG 的解锁 PF0对于旧版 LaunchPad 需要有所不同。)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    另一条信息。 Stellaris LaunchPad 上的芯片是 LX4F120H5QRF1GA3。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    这两个电路板都是 首次上市时购买的 Stellaris LaunchPad 电路板。 [/报价]

     在您的原始帖子中、您从未提及 Stellaris LaunchPad。

    我试过购买新版本的 Tiva C 系列 LaunchPad 板后可以正常工作。  两种板类型的固件版本均为12630。

    好消息是、我可以继续推进我的开发工作。 坏消息是任何较旧的 LaunchPad 都将锁定。

    我强烈建议您使用 Tiva LaunchPad 板继续进行软件开发。 我真的不知道 Stellaris 板有什么问题。 该板内置了 LM4120 MCU。 LM4F MCU 并不存在很长时间 、 可能在十年前已被 Tiva TM4C123取代。 我没有在 LM4F120上工作。  最新的 TM4C123器件版本为第7版。 我认为 LM4F120是一个早期工程样片。   在从 LM4F120到 TM4C123的过程中修复了一些勘误表/错误、我也不奇怪。 您可以使用 LM 闪存编程器来解锁器件并查看您是否可以恢复电路板、但我仍然强烈建议您改用 Tiva LaunchPad、而不是投资在旧电路板上花时间。 如果您认为值得这样做、则可以通过将已知良好的 TM4C123芯片交换到 Stellaris 板来进行 AB 交换。 如果问题已解决、则您可以使用额外的电路板。 Tiva LaunchPad 的价格仅为16.99美元、一开始并不昂贵。  

    [/quote]
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    发布原帖时、我 认为原帖版本 LaunchPad 并不相关。 板上的其他一切都运行良好。 问题是、我们混合使用了新旧 LaunchPad、我无法确保没有早期版本运行。

    鉴于 原始 版本 LaunchPad 似乎存在故障、最好将其记录在勘误表中。

    在适当的时候、我将尝试查看 LM 闪存编程器是否可以帮助我。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Stellaris LaunchPad 上的芯片是 LX4F120H5QRF1GA3。

    查看 LM4F120H5QR 数据表的存档副本 、  寄存器31:脉宽调制器外设存在(PPPWM)显示复位值为零、这意味着 LM4F120H5QR 中的 PWM0和 PWM1模块*不*存在。 这就是为什么 SysCtlPeripheralReady (SYSCTL_Periph_PWM1)被卡在过时的  Stellaris LaunchPad 上的原因。

     TM4C123GH6PM 数据表显示  PWM0和 PWM1存在、因此如果您获取的是 EK-TM4C123GXL、它应该起作用。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、Chester、我们现在提供了答案。 LM4F120H5QR 没有 PWM 模块。 很高兴知道。 我仍然可以通过 使用 捕获比较 PWM (CCP)功能获得 PWM 功能。  幸运的是、PF0具有 T0CCP0函数。

    为了推进工作、我将使用 EK-TM4C123GXL 完成该项目。 我刚刚又购买了两个  EK-TM4C123GXL、以获得足够的项目开发和测试仪使用。|

    感谢 Chester 找出问题的根本原因、

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    最终、我决定使用 CCP 功能来获取 PWM 信号。 该方法适用于 Stellaris LaunchPad (LM4F120H5QR)和 Tiva LaunchPad (TM4C123GH6PM)。 规范如下:

    uint32_t PWMPeriod = 20000;  // 20000周期的 PWMPeriod、提供4kHz 的 PWM 速率(针对80MHz CPU 时钟)
    uint32_t dutyCycle = 50;   //初始占空比百分比为50%

    //解锁 PF0,它是一个锁定引脚(NMI)
    HWREG (GPIO_PORTF_BASE + GPIO_O_LOCK)= GPIO_LOCK_KEY; //使用器件锁定密钥解锁端口
    HWREG (GPIO_PORTF_BASE + GPIO_O_CR)|= GPIO_PIN_0;   //提交引脚以保持 GPO 模式
    HWREG (GPIO_PORTF_BASE + GPIO_O_LOCK)= 0;        //重新锁定以防止进一步更改
    //将 PF1作为 T0CCP0
    SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);      //启用计时器0
    while (!SysCtlPeripheralReady (SYSCTL_Periph_TIMER0)){}//等待 foir Timer0模块准备就绪
    GPIOPinConfigure (GPIO_PF0_T0CCP0);//将 PF0配置为计时器0A 的输出
    GPIOPinTypeTimer (GPIO_PORTF_BASE、GPIO_PIN_0);      //启用 PF0作为分配给它的计时器输出
    TimerConfigure (TIMER0_BASE、(TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM)); //计时器0作为1 x 16位 PWM
    TimerControlLevel (TIMER0_BASE、TIMER_A、0);
    TimerLoadSet (TIMER0_BASE、TIMER_A、PWMPeriod - 1);//设置周期
    TimerMatchSet (TIMER0_BASE、Timer_A、(PWMPeriod - 1)* dutyCycle /100);
    TimerEnable (TIMER0_BASE、TIMER_A);            //启动计时器0A

    要更改频率和占空比、只需调用以下两行:

    TimerLoadSet (TIMER0_BASE、TIMER_A、PWMPeriod - 1);//设置周期
    TimerMatchSet (TIMER0_BASE、Timer_A、(PWMPeriod - 1)* dutyCycle /100);

    唯一的问题是定时器为16位、这意味着 在一个80 MHz 的 CPU 时钟上、最低频率 为1221 Hz。 尝试使用宽计数器、但似乎没有 GPIO PF0计数器。 以上代码可用于我的目的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Vito:

     利用预分频器、您可以将 timerA 扩展到24位。 通过结合 timerA 和 timerB、可扩展到48位。  

    11.3.2.5 PWM 模式
    GPTM 支持简单的 PWM 生成模式。 在 PWM 模式中、定时器被配置为
    24位或48位递减计数器、初值由 GPTMTnILR 定义、并
    GPTMTnPR 寄存器。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的答复 Charles。 剧情变暗了。 我之前尝试过 TimerConfigure 之前的 TimerPrescaleSet (TIMER0_BASE、TIMER_A、X)、但无法实现预期行为。 例如、 当 PWMPeriod = 40,000 (CPU 时钟80 MHz)时、我得到以下周期:

    TimerPresscaleSet  生成的  周期预期周期  偏差

        0          500 μ s       500 μ s        0%

        1          1350 μ s       1000 μ s       +35%

        2          2150us       2000 μ s       +8%

        3          3000 μ s       4000 μ s       -25%

        4          3750 μ s       8000us       -47%

    同样、处于低电平状态的时间(大概由  TimerMatchSet (TIMER0_BASE、TIMER_A、(PWMPeriod - 1)* 0.5)保持不变、而不管 TimerPrescaleSet  的值如何。

    我本来以为  TimerPrescaleSet  会成比例地影响结果周期(大致会 影响)和 TimerMatchSet (不会影响)。  TivaWare 外设驱动程序库对 TimerLoadSet 和 TimerMatchSet 的解释不够充分。 讲解很浅。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Vito:

     有关扩展预分频器的示例、请参阅下面的示例。  

    TimerControlLevel (Timer1_base、Timer_B、true);

    //
    TimerConfigure (Timer1_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PWM);

    //设置 Timer1B 预加载  
    TimerPrescaleSet (Timer1_base、Timer_B、123);
    //
    //设置 Timer1B 装载值
    //
    TimerLoadSet (Timer1_base、Timer_B、45678);

    Period = TimerLoadGet (Timer1_base、timer_B)+ TimerPrescaleGet (Timer1_base、timer_B)* 65536;
    占空比=周期/2;

    ////
    ////将 Timer1B 匹配值设置为加载值/2。
    //

    TimerPrescaleMatchSet (Timer1_base、Timer_B、
    占空比/65536);
    //
    TimerMatchSet (Timer1_base、Timer_B、
    占比65536);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的及时回应 Charles。 我认为我们已经得出了一个很好的解决方案。 刚才提到 TimerPrescaleSet、现在我有了一个解决方案、其中 PWM 可以在低至5Hz 的频率下工作、这对于音频应用来说绰绰有余。 最后、解决方案很简单。 我已经包含了两个新函数  TimerLoadSet24和 TimerMatchSet24 、它们用于替代  TimerLoadSet 和  TimerMatchSet。

    //*****
    // 24位 TimerLoadSet 版本
    //*****
    空 TimerLoadSet24 (uint32_t base、uint32_t timer、uint32_t 值)
    {
    TimerPrescaleSet (基础、定时器、值>> 16);
    TimerLoadSet (BASE、Timer、Value 和0xFFFF);

    //绩效指标问题
    // 24位 TimerMatchSet 版本
    //绩效指标问题
    空 TimerMatchSet24 (uint32_t base、uint32_t timer、uint32_t 值)
    {
    TimerPrescaleMatchSet (base、计时器、值>> 16);
    TimerMatchSet (base、计时器、值和0xFFFF);

    一切都运行良好(尽管有一个小错误修复来实现正确的占空比(以红色突出显示):

      TimerMatchSet24 (TIMER0_BASE、TIMER_A、(PWMPeriod - 1)*(100-dutyCycle)/100);