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-TM4C1294XL 电路板 、需要从其中一条 GPIO 线路生成5MHz 信号。 我正在使用 TIMERA、并且能够通过 GPIO 线路生成1.17Mhz 信号。 我的 TIMERA ISR 只有以下两行:
G_ui32Flags = 1 - g_ui32Flags;
GPIOPinWrite (GPIO_PORTL_base、GPIO_PIN_0、 g_ui32Flags);
是否有方法生成5MHz 信号? 我假设使用120MHz 的系统时钟时、我可以这样做、但我想知道即使我必须以其他方式这样做、这是否可能。
感谢你的帮助。
Jorge Gonzalez
您好!
为了增加频率,您需要直接写入 GPIO 数据寄存器,因为 GPIOPinWrite()函数在写入数据之前执行一些移位运算来计算地址。 您 的 g_ui32Flags = 1 - g_ui32Flags 也需要一些周期来完成。 查看反汇编窗口、您可以找到生成的汇编指令并推算所需的周期数。 如果您知道要写入的确切值和寄存器地址、则可以通过如下方式直接写入寄存器来降低延迟:
HWREG (GPIOPx_ADDR、0x55);//示例写入值为0x55的任意地址 GPIOx_ADDR
但是、您永远无法精确地确定您将获得的频率。 要获得一致的5MHz 频率、您应生成 PWM 信号。 定时器模块可被配置为 PWM。 您所需的只是设置周期和占空比、为您提供所需的5MHz 周期性信号。
请参阅示例 C:\ti\TivaWare_C_Series-2.2.0.295\examples\peripheral\timer\PWM.c
无效
GPIOPinWrite (uint32_t ui32Port、uint8_t ui8引脚、uint8_t ui8Val)
{
//
//检查参数。
//
assert (_GPIOBaseValid (ui32Port));
//
//写入引脚。
//
HWREG (ui32Port +(GPIO_O_DATA +(ui8引脚<< 2)))= ui8Val;
}
非常感谢 Charles。 我将尝试您的建议。
查尔斯
我找到 了 EK-TM4C1294XL 电路板的 PWM 示例、但我可以生成的最快周期是千赫兹范围。 我想使用120MHz 系统时钟时、我可以生成5MHz、但我开始认为我无法生成。 我是对的吗?
感谢你的所有帮助。
Jorge Gonzalez
下面是一个5MHz PWM 示例。 PWM 周期为5MHz、占空比在25%和75%之间变化。
#include <stdbool.h> #include <stdint.h> #include "inc/hw_memmap.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/pin_map.h" #include "driverlib/pwm.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" //***************************************************************************** // // The variable g_ui32SysClock contains the system clock frequency in Hz. // //***************************************************************************** uint32_t g_ui32SysClock; //***************************************************************************** // // The error routine that is called if the driver library encounters an error. // //***************************************************************************** #ifdef DEBUG void __error__(char *pcFilename, uint32_t ui32Line) { } #endif //***************************************************************************** // // Configure PWM for a 25% duty cycle signal running at 250Hz. // //***************************************************************************** int main(void) { uint32_t ui32PWMClockRate; // // Run from the PLL at 120 MHz. // Note: SYSCTL_CFG_VCO_240 is a new setting provided in TivaWare 2.2.x and // later to better reflect the actual VCO speed due to SYSCTL#22. // g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_240), 120000000); // // The PWM peripheral must be enabled for use. // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM0); // // Enable the GPIO port that is used for the PWM output. // MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); // // Configure the PWM function for this pin. // MAP_GPIOPinConfigure(GPIO_PF2_M0PWM2); MAP_GPIOPinTypePWM(GPIO_PORTF_BASE, GPIO_PIN_2); // // Set the PWM clock to be SysClk / 8. // MAP_PWMClockSet(PWM0_BASE, PWM_SYSCLK_DIV_1); // // Use a local variable to store the PWM clock rate which will be // 120 MHz / 8 = 15 MHz. This variable will be used to set the // PWM generator period. // ui32PWMClockRate = g_ui32SysClock / 1; // // Configure PWM2 to count up/down without synchronization. // MAP_PWMGenConfigure(PWM0_BASE, PWM_GEN_1, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); // // Set the PWM period to 5Mhz. To calculate the appropriate parameter // use the following equation: N = (1 / f) * PWMClk. Where N is the // function parameter, f is the desired frequency, and PWMClk is the // PWM clock frequency based on the system clock. // MAP_PWMGenPeriodSet(PWM0_BASE, PWM_GEN_1, (ui32PWMClockRate / 5000000)); // // Set PWM2 to a duty cycle of 25%. You set the duty cycle as a function // of the period. Since the period was set above, you can use the // PWMGenPeriodGet() function. For this example the PWM will be high for // 25% of the time or (PWM Period / 4). // MAP_PWMPulseWidthSet(PWM0_BASE, PWM_OUT_2, MAP_PWMGenPeriodGet(PWM0_BASE, PWM_GEN_1) / 4); // // Enable PWM Out Bit 2 (PF2) output signal. // MAP_PWMOutputState(PWM0_BASE, PWM_OUT_2_BIT, true); // // Enable the PWM generator block. // MAP_PWMGenEnable(PWM0_BASE, PWM_GEN_1); // // Loop forever while the PWM signals are generated. // while(1) { // // This function provides a means of generating a constant length // delay. The function delay (in cycles) = 3 * parameter. Delay // 2 seconds arbitrarily. // MAP_SysCtlDelay((g_ui32SysClock * 2) / 3); // // Invert PWM2 signal. // MAP_PWMOutputInvert(PWM0_BASE, PWM_OUT_2_BIT, true); // // This function provides a means of generating a constant length // delay. The function delay (in cycles) = 3 * parameter. Delay // 2 seconds arbitrarily. // MAP_SysCtlDelay((g_ui32SysClock * 2) / 3); // // Switch PWM2 signal back to regular operation. // MAP_PWMOutputInvert(PWM0_BASE, PWM_OUT_2_BIT, false); } }
如果您希望使用计时器模块生成 PWM、下面是另一个生成5MHz PWM 的示例。
#include <stdbool.h> #include <stdint.h> #include "inc/hw_gpio.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_timer.h" #include "inc/hw_types.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" //***************************************************************************** // // The g_ui32SysClock contains the system clock frequency // //***************************************************************************** uint32_t g_ui32SysClock; //***************************************************************************** // // Configure Timer3A as a 16-bit PWM with a duty cycle of 66%. // //***************************************************************************** int main(void) { // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal on your board. // g_ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); // // The Timer1 peripheral must be enabled for use. // SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3); // // For this example T3CCP0 is used with port B pin 2 or port M pin 2. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM); // // Configure the GPIO pin muxing for the Timer/CCP function. // This is only necessary if your part supports GPIO pin function muxing. // Study the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PM2_T3CCP0); // // Configure the ccp settings for CCP pin. This function also gives // control of these pins to the SSI hardware. Consult the data sheet to // see which functions are allocated per pin. // TODO: change this to select the port/pin you are using. // GPIOPinTypeTimer(GPIO_PORTM_BASE, GPIO_PIN_2); // // Configure Timer3A as a 16-bit periodic timer. // TimerConfigure(TIMER3_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM); // // Set the Timer3A load value to (120000000/5000000=24) - 1 // TimerLoadSet(TIMER3_BASE, TIMER_A, g_ui32SysClock / 5000000 - 1); // // Set the Timer3A match value to load value / 2. // TimerMatchSet(TIMER3_BASE, TIMER_A, TimerLoadGet(TIMER3_BASE, TIMER_A) / 2); // // Enable Timer3A. // TimerEnable(TIMER3_BASE, TIMER_A); // // Loop forever while the Timer3A PWM runs. // while(1) { } }