发 帖  
原厂入驻New
[问答] TM4C123GXL PWM模块在没有使用锁相环的情况下修改外部时钟频率,下进板子后的PWM频率仍未改变的原因?
2020-8-26 13:38:08  22 PWM模块
分享
单片机 TM4C123GXL,芯片GH6PM
CCS 版本6.0.1
之前程序时钟设置为: SysCtlclockSet(SYSCTL_SYSDIV_64|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
在将时钟改为18MHz时,即SysCtlClockSet(SYSCTL_SYSDIV_64|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_18MHZ);
使用示波器观察对应GPIO口,PWM波频率没有改变,这是为什么呢?
附程序如下:
/*利用PWMO,PWM1产生200HZ和400Hz 50%占空比的方波*/
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/gpio.h"
#include "driverlib/pwm.h"
#include "driverlib/fpu.h"
#include "driverlib/pin_map.h"
int main (void)
[
//使能FPU
FPUEnable();
FPULazyStackingEnable();
//设置系统时钟为16MHz
SysCtlClockSet(SYSCTL_SYSDIV_64|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
//使能PWM0模块,使能PWM0和PWM1输出所在GPIO
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
GPIOPinConfigure(GPIO_PB6_M0PWM0);
GPIOPinConfigure(GPIO_PB7_M0PWM1);
GPIOPinConfigure(GPIO_PB4_M0PWM2);
GPIOPinConfigure(GPIO_PB5_M0PWM3);
//驱动电流8MA,推挽输出
GPIOPadConfigSet(GPIO_PORTB_BASE,GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,
GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_STD);
// PWM时钟配置
SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
// SysCtlPWMClockSet(SYSCTL_PWMDIV_32);
//配置PWM发生器0:加减计数,不同步
PWMGenConfigure(PWM0_BASE,PWM_GEN_0,PWM_GEN_MODE_UP_DOWN| PWM_GEN_MODE_NO_SYNC);
PWMGenConfigure(PWM0_BASE,PWM_GEN_1,PWM_GEN_MODE_UP_DOWN| PWM_GEN_MODE_NO_SYNC);
//设置PWM发生器0的频率,时钟频率/PWM分频数/n,16M/64/1250=200HZ
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 1250);
//设置PWM发生器1的频率,时钟频率/PWM分频数/n,16M/16/625=400HZ
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, 625);
//设置PWM0/PWM1输出的脉冲宽度
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0,1250/2);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1,1250/2);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2,625/2);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3,625/2);
//使能PWM0和PWM1的输出
PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT| PWM_OUT_2_BIT| PWM_OUT_3_BIT), true);
//使能PWM发生器
PWMGenEnable(PWM0_BASE, PWM_GEN_0);
PWMGenEnable(PWM0_BASE, PWM_GEN_1);
while(1)
[
]
]
0
2020-8-26 13:38:08   评论 分享淘帖
8 个讨论
SysCtlClockSet(SYSCTL_SYSDIV_64|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
SYSCTL_SYSDIV_64改变这个配置来修改其频率
SYSCTL_XTAL_16MHZ 这个参数只是你外部接的晶振频率 
详细你可以参考TI数据手册上具体描述
//*****************************************************************************
//
//! Sets the clocking of the device.
//!
//! \param ui32Config is the required configuration of the device clocking.
//!
//! This function configures the clocking of the device. The input crystal
//! frequency, oscillator to be used, use of the PLL, and the system clock
//! divider are all configured with this function.
//!
//! The \e ui32Config parameter is the logical OR of several different values,
//! many of which are grouped into sets where only one can be chosen.
//!
//! The system clock divider is chosen with one of the following values:
//! \b SYSCTL_SYSDIV_1, \b SYSCTL_SYSDIV_2, \b SYSCTL_SYSDIV_3, ...
//! \b SYSCTL_SYSDIV_64.
//!
//! The use of the PLL is chosen with either \b SYSCTL_USE_PLL or
//! \b SYSCTL_USE_OSC.
//!
//! The external crystal frequency is chosen with one of the following values:
//! \b SYSCTL_XTAL_4MHZ, \b SYSCTL_XTAL_4_09MHZ, \b SYSCTL_XTAL_4_91MHZ,
//! \b SYSCTL_XTAL_5MHZ, \b SYSCTL_XTAL_5_12MHZ, \b SYSCTL_XTAL_6MHZ,
//! \b SYSCTL_XTAL_6_14MHZ, \b SYSCTL_XTAL_7_37MHZ, \b SYSCTL_XTAL_8MHZ,
//! \b SYSCTL_XTAL_8_19MHZ, \b SYSCTL_XTAL_10MHZ, \b SYSCTL_XTAL_12MHZ,
//! \b SYSCTL_XTAL_12_2MHZ, \b SYSCTL_XTAL_13_5MHZ, \b SYSCTL_XTAL_14_3MHZ,
//! \b SYSCTL_XTAL_16MHZ, \b SYSCTL_XTAL_16_3MHZ, \b SYSCTL_XTAL_18MHZ,
//! \b SYSCTL_XTAL_20MHZ, \b SYSCTL_XTAL_24MHZ, or \b SYSCTL_XTAL_25MHz.
//! Values below \b SYSCTL_XTAL_5MHZ are not valid when the PLL is in
//! operation.
//!
//! The oscillator source is chosen with one of the following values:
//! \b SYSCTL_OSC_MAIN, \b SYSCTL_OSC_INT, \b SYSCTL_OSC_INT4,
//! \b SYSCTL_OSC_INT30, or \b SYSCTL_OSC_EXT32. \b SYSCTL_OSC_EXT32 is only
//! available on devices with the hibernate module, and then only when the
//! hibernate module has been enabled.
//!
//! The internal and main oscillators are disabled with the
//! \b SYSCTL_INT_OSC_DIS and \b SYSCTL_MAIN_OSC_DIS flags, respectively.
//! The external oscillator must be enabled in order to use an external clock
//! source. Note that attempts to disable the oscillator used to clock the
//! device is prevented by the hardware.
//!
//! To clock the system from an external source (such as an external crystal
//! oscillator), use \b SYSCTL_USE_OSC \b | \b SYSCTL_OSC_MAIN. To clock the
//! system from the main oscillator, use \b SYSCTL_USE_OSC \b |
//! \b SYSCTL_OSC_MAIN. To clock the system from the PLL, use
//! \b SYSCTL_USE_PLL \b | \b SYSCTL_OSC_MAIN, and select the appropriate
//! crystal with one of the \b SYSCTL_XTAL_xxx values.
//!
//! \note This function should only be called on TM4C123 devices. For
//! all other devices use the SysCtlClockFreqSet() function.
//!
//! \note If selecting the PLL as the system clock source (that is, via
//! \b SYSCTL_USE_PLL), this function polls the PLL lock interrupt to
//! determine when the PLL has locked. If an interrupt handler for the
//! system control interrupt is in place, and it responds to and clears the
//! PLL lock interrupt, this function delays until its timeout has occurred
//! instead of completing as soon as PLL lock is achieved.
//!
//! \return None.
//
//*****************************************************************************
void
SysCtlClockSet(uint32_t ui32Config)
[
uint32_t ui32Delay, ui32RCC, ui32RCC2;
//
// Get the current value of the RCC and RCC2 registers.
//
ui32RCC = HWREG(SYSCTL_RCC);
ui32RCC2 = HWREG(SYSCTL_RCC2);
//
// Bypass the PLL and system clock dividers for now.
//
ui32RCC |= SYSCTL_RCC_BYPASS;
ui32RCC &= ~(SYSCTL_RCC_USESYSDIV);
ui32RCC2 |= SYSCTL_RCC2_BYPASS2;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
//
// See if the oscillator needs to be enabled.
//
if((ui32RCC & SYSCTL_RCC_MOSCDIS) && !(ui32Config & SYSCTL_MAIN_OSC_DIS))
[
//
// Make sure that the required oscillators are enabled. For now, the
// previously enabled oscillators must be enabled along with the newly
// requested oscillators.
//
ui32RCC &= (~SYSCTL_RCC_MOSCDIS | (ui32Config & SYSCTL_MAIN_OSC_DIS));
//
// Clear the MOSC power up raw interrupt status to be sure it is not
// set when waiting below.
//
HWREG(SYSCTL_MISC) = SYSCTL_MISC_MOSCPUPMIS;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
//
// Timeout using the legacy delay value.
//
ui32Delay = 524288;
while((HWREG(SYSCTL_RIS) & SYSCTL_RIS_MOSCPUPRIS) == 0)
[
ui32Delay--;
if(ui32Delay == 0)
[
break;
]
]
//
// If the main oscillator failed to start up then do not switch to
// it and return.
//
if(ui32Delay == 0)
[
return;
]
]
//
// Set the new crystal value and oscillator source. Because the OSCSRC2
// field in RCC2 overlaps the XTAL field in RCC, the OSCSRC field has a
// special encoding within ui32Config to avoid the overlap.
//
ui32RCC &= ~(SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
ui32RCC |= ui32Config & (SYSCTL_RCC_XTAL_M | SYSCTL_RCC_OSCSRC_M);
ui32RCC2 &= ~(SYSCTL_RCC2_USERCC2 | SYSCTL_RCC2_OSCSRC2_M);
ui32RCC2 |= ui32Config & (SYSCTL_RCC2_USERCC2 | SYSCTL_RCC_OSCSRC_M);
ui32RCC2 |= (ui32Config & 0x00000008) << 3;
//
// Write the new RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
//
// Set the PLL configuration.
//
ui32RCC &= ~SYSCTL_RCC_PWRDN;
ui32RCC |= ui32Config & SYSCTL_RCC_PWRDN;
ui32RCC2 &= ~SYSCTL_RCC2_PWRDN2;
ui32RCC2 |= ui32Config & SYSCTL_RCC2_PWRDN2;
//
// Clear the PLL lock interrupt.
//
HWREG(SYSCTL_MISC) = SYSCTL_MISC_PLLLMIS;
//
// Write the new RCC value.
//
if(ui32RCC2 & SYSCTL_RCC2_USERCC2)
[
HWREG(SYSCTL_RCC2) = ui32RCC2;
HWREG(SYSCTL_RCC) = ui32RCC;
]
else
[
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
]
//
// Set the requested system divider and disable the appropriate
// oscillators. This value is not written immediately.
//
ui32RCC &= ~(SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_MOSCDIS);
ui32RCC |= ui32Config & (SYSCTL_RCC_SYSDIV_M | SYSCTL_RCC_USESYSDIV |
SYSCTL_RCC_MOSCDIS);
ui32RCC2 &= ~(SYSCTL_RCC2_SYSDIV2_M);
ui32RCC2 |= ui32Config & SYSCTL_RCC2_SYSDIV2_M;
if(ui32Config & SYSCTL_RCC2_DIV400)
[
ui32RCC |= SYSCTL_RCC_USESYSDIV;
ui32RCC2 &= ~(SYSCTL_RCC_USESYSDIV);
ui32RCC2 |= ui32Config & (SYSCTL_RCC2_DIV400 | SYSCTL_RCC2_SYSDIV2LSB);
]
else
[
ui32RCC2 &= ~(SYSCTL_RCC2_DIV400);
]
//
// See if the PLL output is being used to clock the system.
//
if(!(ui32Config & SYSCTL_RCC_BYPASS))
[
//
// Wait until the PLL has locked.
//
for(ui32Delay = 32768; ui32Delay > 0; ui32Delay--)
[
if((HWREG(SYSCTL_PLLSTAT) & SYSCTL_PLLSTAT_LOCK))
[
break;
]
]
//
// Enable use of the PLL.
//
ui32RCC &= ~(SYSCTL_RCC_BYPASS);
ui32RCC2 &= ~(SYSCTL_RCC2_BYPASS2);
]
//
// Write the final RCC value.
//
HWREG(SYSCTL_RCC) = ui32RCC;
HWREG(SYSCTL_RCC2) = ui32RCC2;
//
// Delay for a little bit so that the system divider takes effect.
//
SysCtlDelay(16);
]
2020-8-26 13:52:01 评论

举报

guigui_7044 发表于 2020-8-26 13:52
SysCtlClockSet(SYSCTL_SYSDIV_64|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
SYSCTL_SYSDIV_64改变这个配置来修改其频率
SYSCTL_XTAL_16MHZ 这个参数只是你外部接的晶振频率 

Maka:
您好,
您的意思指的是在不改变分频数的情况下,修改外接晶振频率是无法改变时钟频率的吗?请问是否就意味着输出时钟频率要么是16MHz要么是锁相环的200MHz?
谢谢!
2020-8-26 14:04:03 评论

举报

kuangbendetuzi 发表于 2020-8-26 14:04
Maka:
您好,
您的意思指的是在不改变分频数的情况下,修改外接晶振频率是无法改变时钟频率的吗?请问是否就意味着输出时钟频率要么是16MHz要么是锁相环的200MHz?

问题是你的晶振频率在物理上改变没有
                                                                         Holly
2020-8-26 14:21:13 评论

举报

ctx1129 发表于 2020-8-26 14:21
问题是你的晶振频率在物理上改变没有
                                                                         Holly

HG:
您好,
我只是在程序上去选择外接的晶振(可以这样说吗?),用SysCtlClockSet选择不同的外接。您说晶振频率在物理上的改变是像更换晶振这类的吗?
谢谢
2020-8-26 14:26:20 评论

举报

kuangbendetuzi 发表于 2020-8-26 14:04
Maka:
您好,
您的意思指的是在不改变分频数的情况下,修改外接晶振频率是无法改变时钟频率的吗?请问是否就意味着输出时钟频率要么是16MHz要么是锁相环的200MHz?

不好意思,我的理解错了,我以为你使用PLL, 如果没用PLL的话, 改变外接晶振应该是可以改变System Clock的。 
如下图所示,问题应该是在分频设置为64,你将这个改为1试试。
2020-8-26 14:36:56 评论

举报

guigui_7044 发表于 2020-8-26 14:36
不好意思,我的理解错了,我以为你使用PLL, 如果没用PLL的话, 改变外接晶振应该是可以改变System Clock的。 
如下图所示,问题应该是在分频设置为64,你将这个改为1试试。

Maka:
您好,
我确实没有使用PLL,但是我把分频设置(时钟和PWM)都置为1,时钟设置为12MHz时,PB6和PB4分别仍是8KHz和24KHz(时钟改变之前16MHz时计算得到的频率)。换用其它板子也是这种情况。
谢谢!
附程序如下:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/gpio.h"
#include "driverlib/pwm.h"
#include "driverlib/fpu.h"
#include "driverlib/pin_map.h"
int main (void)
[
//使能FPU
FPUEnable();
FPULazyStackingEnable();
//设置系统时钟为12MHz
SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_12MHZ);
SysCtlDelay(3000);
//使能PWM0模块,使能PWM0和PWM1输出所在GPIO
SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
GPIOPinTypePWM(GPIO_PORTB_BASE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
GPIOPinConfigure(GPIO_PB6_M0PWM0);
GPIOPinConfigure(GPIO_PB7_M0PWM1);
GPIOPinConfigure(GPIO_PB4_M0PWM2);
GPIOPinConfigure(GPIO_PB5_M0PWM3);
//驱动电流8MA,推挽输出
GPIOPadConfigSet(GPIO_PORTB_BASE,GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,
GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_STD);
// PWM时钟配置
SysCtlPWMClockSet(SYSCTL_PWMDIV_1);
//配置PWM发生器0:加减计数,不同步
PWMGenConfigure(PWM0_BASE,PWM_GEN_0,PWM_GEN_MODE_UP_DOWN| PWM_GEN_MODE_NO_SYNC);
PWMGenConfigure(PWM0_BASE,PWM_GEN_1,PWM_GEN_MODE_UP_DOWN| PWM_GEN_MODE_NO_SYNC);
//设置PWM发生器0的频率,时钟频率/PWM分频数/n,12M/1/2000=6KHZ
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_0, 2000);
//设置PWM发生器1的频率,时钟频率/PWM分频数/n,12M/1/2000*3=18KHZ
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, 2000/3);
//设置PWM0/PWM1输出的脉冲宽度
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_0, 2000/2);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_1, 2000/2);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2,2000/3/2);
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_3,2000/3/2);
//使能PWM0和PWM1的输出
PWMOutputState(PWM0_BASE, (PWM_OUT_0_BIT |PWM_OUT_1_BIT| PWM_OUT_2_BIT| PWM_OUT_3_BIT), true);
//使能PWM发生器
PWMGenEnable(PWM0_BASE, PWM_GEN_0);
PWMGenEnable(PWM0_BASE, PWM_GEN_1);
while(1)
[
]
]
2020-8-26 14:48:07 评论

举报

kuangbendetuzi 发表于 2020-8-26 14:48
Maka:
您好,
我确实没有使用PLL,但是我把分频设置(时钟和PWM)都置为1,时钟设置为12MHz时,PB6和PB4分别仍是8KHz和24KHz(时钟改变之前16MHz时计算得到的频率)。换用其它板子也是这种情况。

SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_12MHZ)
是不是你理解错了,SYSCTL_XTAL_12MHZ 这个是指外部时钟源配置,并不是系统时钟。
如果你选择SYSCTL_XTAL_12MHZ,外部晶振必须接12MHz晶振。
如果你选变时钟,你可以选择PPL倍频后再分频。如果不用PPL,你就需要改变外部晶振,并配置一致。
2020-8-26 14:56:04 评论

举报

guigui_7044 发表于 2020-8-26 14:56
SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_OSC_MAIN |SYSCTL_XTAL_12MHZ)
是不是你理解错了,SYSCTL_XTAL_12MHZ 这个是指外部时钟源配置,并不是系统时钟。
如果你选择SYSCTL_XTAL_12MHZ,外部晶振必须接12MHz晶振。

Maka:
您好!
我理解错了,谢谢您。
2020-8-26 15:05:46 评论

举报

只有小组成员才能发言,加入小组>>

1448个成员聚集在这个小组

加入小组

创建小组步骤

关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表