Thread 中讨论的其他器件:EK-TM4C123GXL
我想 使用 计时器的捕获模式测量4通道 PWM、下面是我的配置:
但不知怎么说、我无法进入中断、我是否犯了一些错误?
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.
我想 使用 计时器的捕获模式测量4通道 PWM、下面是我的配置:
但不知怎么说、我无法进入中断、我是否犯了一些错误?
是的,我在 initClock()之后将其写入 initrC()之前。
#include "userDef精细.h"
u8 all_init()
{
initClock();
initSysTick();
initLED();
initPWM();
initKey();
initEEPROM();
initFlag();
initUART();
blueLed();//蓝色 LED 表示"initAll is ok"
返回1;
}
void initClock()
{
ROM_FPUEnable();
ROM_FPULazyStackingEnable();//中断处理程序的怠惰堆栈。 这允许在中断处理程序中使用浮点指令、
//但代价是额外使用栈。
ROM_SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTAL_16MHz | SYSCTL_OSC_MAIN);
ROM_IntMasterEnable ();//<---
}
void initerTick ()
{
ROM_SysTickPeriodSet (ROM_SysCtlClockGet ()/SysTickPeriod);
ROM_Event TickIntEnable ();
SysTickIntRegister (SysTickIntHandler);//寄存器 SysCtlClockGet 中断 ROM_SysTickEnable
(
)
;}SysTickIntEnable
();SysTick Timer_TimerB_Timerbt (ROM_WCTR
);/TIMER_WCTR 0_TIMER_TIMER_CAP_CAP_TIMER_CAP_TIMER_CAP_CAP_CAP_CAP_CAP1 (ROM_TIMER_INT_WCTR)
Timer_event_both _edge);
ROM_TimerControlEvent (WTIMER 1_base、Timer_B、timer_event_both _edge);
ROM_TimerLoadSet (WTIMER 0_BASE、 Timer_A、2000000-1);
ROM_TimerLoadSet (WTIMER 0_BASE、Timer_B、2000000-1);
ROM_TimerLoadSet (WTIMER 1_base、TIMER_A、2000000-1);
ROM_TimerLoadSet (WTIMER 1_base、TIMER_B、 GPIO_SysCtlPeripheralEnable
(SYSCTL_Periph_GPIOC);//为 PC4567启用 gpioConfigPadSet
(GPIO_PORTC_BASE、GPIO_PIN_4、GPIO_FORMENT_2mA、GPIO_PIN_STD_WPD_PHIN);
GPIO_PWCT_PHIN_PW0_GPIO_PST_PIN_PHIN_GPIO_P0_GPIO_PST_GPIO_P0_PHIN
、GPIO_PHIN_GPIO_P0_GPIO_P0_GPIO_P0_GPIO_PST_PIN_PROBLE_GPIO_PHIN、GPIO_P0_PIN_GPIO_P0_GPIO_P0_GPIO_PHIN、GPIO_P0_GPIO_PHIN、GPIO_P0_GPIO_P0_PROBLE_GPIO_P0_PIN_GPIO_PHIN、GPIO_P0_PIN_GPIO_P0_GPIOP_GPIO_P0_PIN_GPIO_PHIN、GPIO_P0_PIN_GPIOP_GPIO_P_GPIO_P0_PIN_GPIO_P_GPIO_P_PRO
ROM_GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
TimerIntRegister (WTIMER 0_BASE、TIMER_A、WTimer0AIntHandler);
//TimerIntRegister (WTIMER 0_BASE、TIMER_B、WTimer0BIntHandler);
//TimerIntRegister (WTIMER 1_BASE、TIMER_A、 WTimer1AIntHandler);
//TimerIntRegister (WTIMER1_base、TIMER_B、WTimer1BIntHandler);
ROM_IntMasterEnable ();
ROM_TimerIntEnable (WTIMER 0_BASE、TIMER_CAPA_EVENT);
ROM_TimerIntEnable (WTIMER 0_BASE、TIMER_CAPB_EVENT);
ROM_TimerIntEnable (WTIMER 1_BASE、 Timer_CAP_EVENT);
ROM_TimerIntEnable (WTIMER 1_BASE、TIMER_CAPB_EVENT);
ROM_IntEnable (INT_WTIMER 0A);
ROM_IntEnable (INT_WTIMER 0B);
ROM_IntEnable (INT_WTIMEER1A);
ROM_IntEnable (INT_WTIMEER1B);
ROM_TIMEREnable (WTIMER 0_BASE、TIMER_A);
ROM_TIMEREnable (WTIMER 0_BASE、 Timer_B);
ROM_TimerEnable (WTIMER 1_BASE、Timer_A);
ROM_TimerEnable (WTIMER 1_BASE、Timer_B);
}
//INTHANDLER
void WTimer0AIntHandler (void)
{
TimerIntClear (WTIMEER0_BASE、TimerIntStatus (WTIMER 0_BASE、TIMER_CAP_EVENT));
A=TimerValueGet (WTIMER 0_BASE、TIMER_A);
printf ("ok");
//if (GPIOPinRead (GPIO_PORTC_BASE、GPIO_PIN_4)=GPIO_PIN_4)
//a=A1/(A1+TimerValueGet (WTIMEER0_BASE、TIMER_A));
//else
//a1=TimerValueGet (A1+TIMERValueGet)
(WTIME_BASE);// TIMER0}
#include "userDef精细.h" u8 all_init() { initClock(); initrC(); return 1; } void initClock() { ROM_FPUEnable(); ROM_FPULazyStackingEnable(); ROM_SysCtlClockSet (SYSCTL_SYSDIV_2_5 | SYSCTL.US_PL-|-|SYSC_UST_ROM- void initRRC () { ROM_SysCtlPeripheralEnable (SYSCTL_Periph_WTIME0);//启用 Wtimer0 ROM_CCPCtlPeripheralEnable (SYSCTL_Periph_WTIMER 1);//启用 Wtimer1 ROM_SysCTL PeripheralEnable (SYSCTL_Periph_CCPIPC_ROM );//配置 GPIO0_GPIO_PM_GPIO0_GPIO0_GPIO0_GPT (GP0_GPIO_1);//为 GPIO0_GPIO0_GPIO0_GPIO_PM_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPIO0_GPI GPIO_PIN_4); ROM_GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_5); ROM_GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_6); ROM_GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_7); ROM_GPIOPadConfigSet (GPIO_PORTC_BASE、GPIO_PIN_4、GPIO_Strength _2mA、GPIO_PIN_TYPE_STD_WPD); ROM_GPIOPTC_BASE、GPIO_PST_PHIN 、GPIO_PHIN_PWM_BASE、GPIO_6_PHIN、GPIO_PHIN_PHIN_GPIO_PHIN_PWPLE_GPIO_PHIN、GPIO_PST_PWPD ROM_GPIOPadConfigSet (GPIO_PORTC_BASE、GPIO_PIN_7、GPIO_FORM_2mA、GPIO_PIN_TYPE_STD_WPD); ROM_TimerConfigure (WTIMER 0_BASE、TIMER_CFG_SPLIT);ROM_TIMERCFG_RATE_TIME_UP (ROM_TIMER );ROM_TIMER_TIMER 0_BASE (ROM_TIMER_TIMER)、ROM_TIMER WTRIE_TIMER 0_TIMER)、ROM_TIMER (ROM_TRIE_TIME_TIMER)| ROM_TIMER 1、ROM_TRIP_TIME_TIME_TIMER (ROM_PROTOP_TIMER 0_TIMER 1、ROM_TIME_TIMER 1) Timer_event_both _edge); ROM_TimerControlEvent (WTIMER 1_base、Timer_B、timer_event_both _edge); ROM_TimerLoadSet (WTIMER 0_BASE、 Timer_A、2000000-1); ROM_TimerLoadSet (WTIMER 0_BASE、Timer_B、2000000-1); ROM_TimerLoadSet (WTIMER 1_base、TIMER_A、2000000-1); ROM_TimerLoadSet (WTIMER 1_base、TIMER_B、 2000000-1); ROM_IntEnable (INT_WTIME0A); ROM_IntEnable (INT_WTIME0B); ROM_IntEnable (INT_WTIMEER1A); ROM_IntEnable (INT_WTIME1B); TimerIntRegister (WTIMER 0_BASE、TIMER_A、WTimer0AIntHandler); TimerIntRegister (WTIMER 0_BASE、TIMER_B、 WTimer0BIntHandler); TimerIntRegister (WTIMER1_base、TIMER_A、WTimer1AIntHandler); TimerIntRegister (WTIMER1_base、 Timer_B、WTimer1BIntHandler); ROM_TimerIntEnable (WTIMER 0_BASE、TIMER_CAP_EVENT); ROM_TimerIntEnable (WTIMER 0_BASE、 Timer_CAPB_EVENT); ROM_TimerIntEnable (WTIMER 1_BASE、TIMER_CAPA_EVENT); ROM_TimerIntEnable (WTIMER 1_BASE、TIMER_CAPB_EVENT); ROM_TimerEnable (WTIMER 0_BASE、TIMER_A); ROM_TimerEnable (WTIMER 0_BASE、TIMER_B); ROM_TimerEnable (WTIMER 1_BASE、 Timer_A); ROM_TimerEnable (WTIMER 1_BASE、Timer_B); } void WTimer0AIntHandler (void) { TimerIntClear (WTIMER 0_BASE、TimerIntStatus (WTIMER 0_BASE、TIMER_CAP_EVENT); A= TimerInter (WTIMER 0) Timer1 (void WTIMER 1)、TimerInter 1 (WTIMER 1)、TimerBTimer1 (TimerInter 1)、TimerBTimerBTimer1 (Timer1) TimerBTimerInter 1 (void TimerBTimer1)、Timer1 (TimerBTimerBTimerBTimer1)、TimerIntTimerIntTimer1 (TimerBTimerBTimer1)、TimerIntTimer1 (TimerBTimerA (TimerBTimerBTimer1)、TimerBTimer1 (TimerBTimerBTimerBTimer1)、TimerBTimerIntTimerIntTimer1 (Timer1
经过一些修改后、我获得了一些数据。但是 、仅显示了 Timer0B 和 Timer1B (通过调试观察窗口)。 屏幕截图如下:
如您所见、2通道数据 不稳定。 但是、我 可以确保输入是与 机型飞机接收器相同的4通道7% 50Hz PWM。
我仍然不知道哪里是我的错,我无法获得正确的数据
[报价用户="Rongze li"]我仍然不知道我的故障在哪里,我无法获得正确的数据...
实际上、正如这里经常显示的那样、当"多个程序元素(所有)聚集在一起时-这种情况(很少)-"开箱即用"-同时大大增加了"正确有效"故障排除的时间和精力!
"kiss"-(有利的)构建的纪律、"一次一个可衡量的功能"-然后"测试/验证"-然后(仅在那时)继续执行功能2 -已经(反复)证明- 可以更好地工作!
一个简化方法-我已经建议(在这里重复)使用两个计时器-一个用于检测信号的"上升沿"-第二个是"下降沿"。 (您必须将 PWM 信号"捕获"到两个计时器输入。) 在这两种情况下、您都可以采用"边沿计时模式"的计时器、它会自动为您记录每个"事件"。 如果您"读取并安全存储"每个计时器的内容(在下一个信号边沿到达之前)、则可以简单地从"下降边沿"中减去"上升边沿"的值(前提是两个计时器都没有"滚动")、从而显示(实际上是礼品包装)您的 PWM 信号的占空比和频率。
使用论坛的搜索框(在论坛页面顶部)可确保显示"多张海报成功-通过这种(当然)"亲吻"方法...
您好 CB1
感谢您的建议。
我已经阅读过许多相关文章、但我确实想使用一个 GPIOPIN 测量单通道 PWM。 因为在我的整个四转子设计中、EK-TM4C123G LaunchPad 没有太多 GPIO 可供我使用。
我 在手册中注意到了这一点、其中说 TIMERA 和 TIMERB 是自由运行的。我想它们是独立的。
再次感谢你。 很抱歉我的英语不好。 我是一名中国学生,我很长时间以来一直对这个问题感到困扰。
正如您所说、我正在尝试进行单元测试。
谢谢您-请注意以下事项:
但不在这里-现在也不在这里! 您的第一个工作不是能够实现基本测量? " 负担沉重且复杂的方法带来的许多复杂问题"-已"提高 (阻止)您的进度"-您只说了"-您的英语(相当好)...
事实证明、"通过复杂的设计进行馈送"变得更加容易、 方法是将其简化为 :"多个、小得多、更可测量的组成(不同)部件"-这种部件可能 更快速、更容易 被探测/检查 -从而进行测试和验证! 仅"然后"(如果成功、则成功)-加入"扩展整体"。
"使用2个计时器"、每个计时器专用于"反边沿、GPIO 触发的中断"、可提供"轻松快捷"、"设置阶段" (通过提供"概念证明"和构建高度集中的见解) 、以便于以后的"最终结果" ... 例如、能够 完全/正确管理两个到达信号边沿的单个计时器。 这种方法早已被称为"通过细化进行"、或更具色彩的"亲吻"。 (KISS 显然有效-即使在这里被禁止-特别是在这里被禁止!) (如'w/'like -由于从未有正当理由(因此可疑)。)
在您的开发和实验过程中-我建议您使用(另一个) MCU 分离计时器(配置为 PWM 输出@ 50%占空比)作为"已知且易于编程的信号发生器"-它为2个计时器引脚(即捆绑到2个)提供信号 -加快并简化"边沿时间增量计算"。 (消除"外部"信号发生器引入的所有不确定性(可能产生噪声!))
您应该调用一次并使用"timer_both "、而不是针对计时器的每一半分别调用 TimerEnable
而不是:
ROM_TimerEnable (WTIMER 0_BASE、TIMER_A); ROM_TimerEnable (WTIMER 0_BASE、TIMER_B); ROM_TimerEnable (WTIMER 1_BASE、Timer_A); ROM_TimerEnable (WTIMER 1_BASE、Timer_B);
使用:
ROM_TimerEnable (WTIMER 0_BASE、TIMER_Both); ROM_TimerEnable (WTIMER 1_base、TIMER_Both);
同样、对 TimerConfigure 的调用应为每个计时器一次。
而不是:
ROM_TimerConfigure (WTIMEER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP); ROM_TimerConfigure (WTIMEER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_TIME_UP); ROM_TimerConfigure (WTIMEER1_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP); ROM_TimerConfigure (WTIMEER1_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_TIME_UP);
使用:
ROM_TimerConfigure (WTIMER 0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_CAP_TIME_UP); ROM_TimerConfigure (WTIMER 1_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_B_CAP_TIME_UP);
Hola Bob、
您是否建议使用 以下 函数:"两个这样的函数调用-序列化函数调用和单独的"计时器配置"函数调用- 例如:
ROM_TimerConfigure (WTIMEER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP);
ROM_TimerConfigure (WTIMEER0_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_TIME_UP);
可能会导致"第一个函数调用的影响"过度写入"? (通过 第二次调用?) 如果为 true -则海报的参数"TIMER_CFG_A_CAP_TIME_UP"(意外且毫无根据)已"移动!" 显然这不是很好!
或者-您只是寻求"编程效率"吗? (虽然"早期参数的意外损失/损坏"确实值得清楚注意、但没有任何问题!) (并且-我们不能告诉您、"损失/腐败"是否 是您的帖子旨在防止的...)
您好 CB1、
库函数的一个优点是它们隐藏了硬件详细信息。 库函数的一个缺点是它们隐藏了硬件详细信息。 我尝试将一个简单示例组合在一起、该示例使用宽定时器0来创建两个 PWM、并使用宽定时器1来测量高周期和低周期。 我使用 EK-TM4C123GXL launchpad 和两根跳线将宽定时器0引脚连接到宽定时器1引脚。 我发现覆盖 TimerControlEvent()函数非常麻烦,我使用 HWREG 读取和写入从上升沿切换到下降沿触发器。 可能有一种更巧妙的方法来实现它、也许总是在两个边沿触发并检查引脚电平以确定它是上升还是下降。 这个简单的示例不涵盖脉冲相位长于32位定时器捕捉的情况、也不涵盖脉冲如此短以至于中断例程无法及时设置第二个边沿的情况。
#include
#include
include "inc/tm4c123gh6m.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/debug.h"
#include "driverlib/wm.pine"
#include "driverlib.hw_timer.h"
;#include "driverlib.interverlib_timer.h"#include "driverlib"#include "driverlib.interver.h";#include "driverlib_timerlib.interver.h"#include "driverlib"#include "driverlib"#include "ine"
下降
};
unsigned int a_RisingEdge、A_FallingEdge、B_FallingEdge、B_FallingEdge;
volatile unsigned int a_LowPeriod、A_HighPeriod、B_LowPeriod、B_HighPeriod;
enum edge A_Edge、 b_Edge;
void main (void)
{
SysCtlClockSet (SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHz);
//使用宽定时器0生成两个 PWM
SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC);
SysCtlDelay(3);
GPIOPinConfigure (GPIO_PC5_WT0CCP1);
GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_5);
GPIOPinConfigure (GPIO_PC4_WT0CCP0);
GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_4);
SysCtlPeripheralEnable (SYSCTL_Periph_WTIME0);
SysCtlDelay(3);
TimerConfigure (WTIMER 0_BASE、TIMER_CFG_SPLIT_PAIRGE|TIMER_CFG_A_PWM|TIMER_CFG_B_PWM);
TimerLoadSet (WTIMER 0_BASE、TIMER_A、80000);
TimerMatchSet (WTIMER 0_BASE、TIMER_A、30000);
TimerLoadSet (WTIMER 0_BASE、TIMER_B、70000);
TimerMatchSet (WTIMER 0_BASE、TIMER_B、20000);
TimerControlStall (WTIMER 0_BASE、TIMER_Both、TRUE);
TimerEnable (WTIMER 0_BASE、TIMER_Both);
//使用宽定时器1捕获来自 WTIME0的边沿
GPIOPinConfigure (GPIO_PC6_WT1CCP0);
GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_6);
GPIOPinConfigure (GPIO_PC7_WT1CCP1);
GPIOPinTypeTimer (GPIO_PORTC_BASE、GPIO_PIN_7);
SysCtlPeripheralEnable (SYSCTL_Periph_WTIME1);
SysCtlDelay(3);
TimerConfigure (WTIMER1_BASE、TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_CAP_TIME_UP | TIMER_CFG_A_PERIODICRACRACY_|
TIMER_CFG_B_CAP_TIME_UP | TIMER_CFG_B_PERIODICRACRACY_UP);
TimerControlEvent (WTIMER1_BASE、TIMER_Both、TIMER_EVENT_NEG_EDGE);
A_Edge =下降;
B_Edge =下降;
TimerIntRegister (WTIMER 1_BASE、Timer_A、WTimer1AIntHandler);
TimerIntRegister (WTIMER 1_BASE、Timer_B、WTimer1BIntHandler);
TimerIntEnable (WTIMER 1_BASE、TIMER_CAPA_EVENT | TIMER_CAPB_EVENT);
IntEnable (INT_WTIME1A);
IntEnable (INT_WTIME1B);
IntMasterEnable();
TimerControlStall (WTIMER1_BASE、TIMER_Both、TRUE);
TimerEnable (WTIMER 1_BASE、TIMER_Both);
while (1)
{
}
}
void WTimer1AIntHandler()
{
if (A_Edge ==下降)
{
A_FallingEdge = TimerValueGet (WTIMEer1_base、timer_A);
A_HighPeriod = A_FallingEdge - A_RisingEdge;
//将计时器 A 更改为上升沿
HWREG (WTIMER 1_BASE + TIMER_O_CTL)&&~0x0000000C;
A_Edge =上升;
}
其他
{
A_RisingEdge = TimerValueGet (WTIMEer1_base、timer_A);
A_LowPeriod = A_RisingEdge - A_FallingEdge;
//将计时器 A 更改为下降沿
HWREG (WTIMER1_BASE + TIMER_O_CTL)|= 0x00000004;
A_Edge =下降;
}
TimerIntClear (WTIMER1_BASE、TIMER_CAP_EVENT);
}
void WTimer1BIntHandler ()
{
if (B_Edge ==下降)
{
B_FallingEdge = TimerValueGet (WTIMER 1_BASE、Timer_B);
B_HighPeriod = B_FallingEdge - B_RisingEdge;
//将定时器 B 更改为上升沿
HWREG (WTIMER 1_BASE + TIMER_O_CTL)&&~0x00000C00;
B_Edge =上升;
}
其他
{
B_RisingEdge = TimerValueGet (WTIMER 1_BASE、Timer_B);
B_LowPeriod = B_RisingEdge - B_FallingEdge;
//将定时器 B 更改为下降沿
HWREG (WTIMER 1_BASE + TIMER_O_CTL)|= 0x00000400;
B_Edge =下降;
}
TimerIntClear (WTIMER 1_BASE、TIMER_CAPB_EVENT);
}
尊敬的 Bob:
非常棒! 资源丰富、展示了不同的方法和运营目标。
正如(大多数)技术公司的情况一样、我们寻求"已知/成熟的规范"、这几乎可以无限重复使用。 和提供各种"钩子"、以防止"使用"、同时在每次出现的独特条件下优化性能(尽可能最佳)。
"特殊条件"(如计时器过流)或"受保护"输入信号的(适当)管理也必须"预先考虑并安全防护"。
由于是夏季中旬、您的公司(和我们的公司)都"拥有丰富的工程实习生"、我们对您巧妙的代码的运用证明了 TM4C (123)是"天才"的少数人的"入门"。
具体而言:您的"不涵盖案例" 、其中:
crüe 您的代码是资源丰富且巧妙的-但我的 n ü r 可能希望(稍微)修改:
我们欢迎您使用 MCU (其他)计时器(作为 PWM 信号发生器)-这证明了最高效(以及无限可控/可编程)和(或许只是)-已经(过去)...