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.

[参考译文] CCS/EK-TM4C123GXL:未正确遵循代码

Guru**** 2466550 points
Other Parts Discussed in Thread: TM4C123GH6PM

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/666395/ccs-ek-tm4c123gxl-it-does-not-follow-the-code-correctly

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

工具/软件:Code Composer Studio

您好!

我正在使用基于 ARMRegisteredCortexRegistered-M4F 的 MCU TM4C123G LaunchPadTm评估套件,我编写了一个代码,以更好地展示 TM4C123GH6PM 和 Tiva API 的工作方式。

我从资源探索中导入了闪烁代码、并对其进行了修改。 当我调试代码时、它不能像我预期的那样工作。 PF_2每20ms 更改一次它的状态(正如我所期望的那样)、但 PF_1有一种陌生的行为、在 PF_2变为高电平10ms 后变为高电平、20ms 后变为低电平并返回高电平、20ms 后变为低电平。 在 PF_2的"低电平"状态下也会发生同样的情况。  

我认为我的代码有错误、但我不知道这是 GPIO 函数问题还是其他问题。

代码:

/*
* PORT_A:PORT_B:PORT_C:
*
* VALV_3 PA_5 VALV_1 PB_0 VALV_11 PC_7
* VALV_4 PA_6 VALV_2 PB_1 VALV_13 PC_6
* VALV_5 PA_7 VALV_12 PB_6 VALV_15 PC_4
* VALV_7 PA_3 VALV_14 PB_7 VALV_16 PC_5
* VALV_8 PA_2 VALV_18 PB_3
* VALV_9 PA_6 VALV_20 PB_2
*
* PORT_F:PORT_D:
*
* VALV_6 PF_1 VALV_9 PD_6
* VALV_17 PF_3
* VALV_19 PF_2
*

*

#include
#include
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"

#define VALV_1 GPIO_PIN_0
#define VALV_2 GPIO_PIN_1
#define VALV_3 GPIO_PIN_5
#define VALV_4 GPIO_PIN_6
#define VALV_5 GPIO_PIN_7
#define VALV_6 GPIO_PIN_1
#define VALV_7 GPIO_PIN_3
#define VALV_8 GPIO_PIN_2
#define VALV_9 GPIO_PIN_6
#define VALV_10 GPIO_PIN_4
#define VALV_11 GPIO_PIN_7
#define VALV_12 GPIO_PIN_6
#define VALV_13 GPIO_PIN_6
#define VALV_14 GPIO_PIN_7
#define VALV_15 GPIO_PIN_4
#define VALV_16 GPIO_PIN_5
#define VALV_17 GPIO_PIN_3
#define VALV_18 GPIO_PIN_3
#define VALV_19 GPIO_PIN_2
#define VALV_20 GPIO_PIN_2

#define VALV_A VALV_3|VALV_4|VALV_5|VALV_7|VALV_8|VALV_9
#define VALV_B VALV_1|VALV_2|VALV_12|VALV_14|VALV_18|VALV_20
#define VALV_C VALV_11|VALV_13|VALV_15|VALV_16
#define VALV_D VALV_9
#define VALV_F VALV_6|VALV_17|VALV_19

volatile int timer = 0;
volatile signed int Flag1 = 1;
volatile signed int flag2 = 1;
volatile int32_t x;

空 Timer0Isr(){
Timer++;
TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT);

空 TimerInit(){
SysCtlPeripheralEnable (SYSCTL_Periph_TIMER0);
while (!SysCtlPeripheralReady (SYSCTL_Periph_TIMER0)){}

TimerConfigure (TIMER0_BASE、TIMER_CFG_PERIODICASE);

TimerIntRegister (TIMER0_BASE、TIMER_A、Timer0Isr);
内部使能(INT_TIMER0A);
TimerIntEnable (TIMER0_BASE、TIMER_TINA_TIMEOUT);
IntPrioritySet (INT_TIMER0A、0x00);

void GPIOInit(){

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOA);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOA)){}

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOB)){}

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOC);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOC)){}

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOD)){}

SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
while (!SysCtlPeripheralReady (SYSCTL_Periph_GPIOF)){}

GPIOPinTypeGPIOOutput (GPIO_Porta_base、VALV_A);
GPIOPinTypeGPIOOutput (GPIO_PORTB_BASE、VALV_B);
GPIOPinTypeGPIOOutput (GPIO_PORTC_BASE、VALV_C);
GPIOPinTypeGPIOOutput (GPIO_PORTD_base、VALV_D);
GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、VALV_F);


int main (空)

SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHz);
IntMasterEnable();

GPIOInit();
TimerInit();

TimerEnable (TIMER0_BASE、TIMER_A);
TimerLoadSet (TIMER0_BASE、TIMER_A、SysCtlClockGet ()/ 100000);

while (1){
如果(计时器= 1000){
Flag1 =-Flag1;
if (Flag1 = 1){
GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、VALV_6);}
否则{
GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、0x00);}

如果(定时器==2000){
flag2 =-flag2;
计时器= 0;
if (flag2 ==1){
GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、VALV_19);

否则{
GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、0x00);}


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

    一些建议:

    1.在 main()中,将对 IntMasterEnable()的调用移动到所有初始化之后,即在 GPIOInit()、TimerInit()、TimerEnable()之后, 和 TimerLoadSet()。 这样、中断服务例程在所有内容初始化后才会开始调用。

    2.在 Timer0Isr()中,将对 TimerIntClear()的调用移动到函数的起始位置。

    3、由于定时器在中断中递增时与主上下文操作异步、因此可能会错过"如果(定时器= 1000)"等条件。 现在可能不会发生这种情况、但如果程序增长并变得更加复杂、主循环中发生的其他操作可能会导致您错过这些事件。 例如、当处理器执行此 if 语句时、定时器可能为999;下次处理器执行此语句时、定时器可能为1001。 因此、您将无法获得预期的结果。

    处理项目3的最简单的方法是在中断服务程序中检查计时器= 1000和计时器= 2000。 由于计时器在那里递增、因此您不会错过该事件。 然后设置一个标志、告知主上下文执行某项操作。 例如:

    (笑声)
    
    
    volatile bool handle_flag1 = false;
    volatile bool handle_flag2 = false;
    
    
    void Timer0Isr (){
    TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT);
    
    timer++;
    
    switch (timer){
    case 1000:
    handle_flag1 = true;
    break;
    
    case 2000:handle_state_timer
    2 = true;
    timer = true;timer = break
    
    
    
    
    
    }默认值
    
    
    :break;break}:break
    
    
    int main (void)
    {
    SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_main | SYSCTL_XTAL_16MHz);
    
    GPIOInit();
    TimerInit();
    
    TimerInEnable (TIMER0_BASE、TIMER_A);
    TimerLoadSet (TIMER0_BASE、TIMER_A、SysCtlClockGet ()/100000);
    
    IntMasterEnable ();
    
    while (1){
    if (handle_Flag1){
    handle_Flag1 = false;
    
    Flag1 =-Flag1;
    if (Flag1 = 1){
    GPIOPinWrite (GPIO_PORTF =
    
    
    0x6)、flag2
    
    
    
    
    }=-flag2;if
    
    (gpin2);flag2 =-al2 = 0xALVAL = false);gpinal2;gb = 0xal2 = 0xal2 = 0xal2)
    if (flag2 ==1){
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、VALV_19);
    }
    else{
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、0x00);
    }
    
    }
    }
    

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

    您的代码难以识别。

    也许您可以更轻松地说明您所期望的行为类型和所获得的行为。

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

    12ve12pm 说:
    可能会错过诸如"if (timer =1000)"之类的条件、因为计时器在与主上下文操作异步的中断中递增。

    我们是否可以称之为"出色?"    尤其是当您花时间/努力描述"如何及为什么"(有限)这种情况时、可能会"错过"。

    "增加稳健性"的另一种方法是使用"if  (timer >= 1000)" 、因为这样可以消除(过于严格)"匹配的独特性!"      (这种独特性-有什么关键原因?)

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

    [引用 USER="CB1_MOBILE"]

    12时12分
    由于定时器在与主上下文操作异步的中断中递增、因此可能会错过诸如"IF (定时器= 1000)"之类的条件。

    我们是否可以称之为"出色?"    尤其是当您花时间/努力描述"如何及为什么"(有限)这种情况时、可能会"错过"。

    "增加稳健性"的另一种方法是使用"if  (timer >= 1000)" 、因为这样可以消除(过于严格)"匹配的独特性!"      (这种独特性-有什么关键原因?)

    [/报价]

    我最初的想法是使用"if (timer >= 1000)"、但这有问题。 从观察 OP 的代码来看、预期行为是"边沿触发"而不是"电平触发"。 通过询问"if (timer >= 1000)"、可以对该条件进行高达1000次的处理、直到计时器重置为0。

    计时器仅在中断处理程序中递增。 它不会在其他任何地方进行修改。  因此,中断处理程序不能"错过"计时器通过1000状态的比较"="--除非:

    除非编程人员忘记了程序的正确操作取决于从未在其他任何地方修改过计时器、并且在未来的某个时间引入了进行此类修改的代码。 然后,所有赌注都被关闭了。 因此、为了更确切地确定没有其他代码会由于此类错误而修改计时器、可以在中断处理程序函数内将其设置为静态变量、以便其他代码不会对其可见。 对这方面的评论也会有帮助:-)

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

    您已做出了关键/关键的观察-我没有在海报的代码中深入阅读过这方面的内容。

    也就是说、他"真的"需要这样的"边缘检测吗?" 这本身可能会发出信号:"设计不够周到-正如您巧妙地注意到的-打开了"当前和未来的代码审阅者"-以灾难... (除非正确注释了代码段、尤其是注释了代码段!)

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

    [引述 USER="CB1_MOBILE]您已经做出了关键/关键的观察-我没有在海报的代码中读到这么远的内容。

    也就是说、他"真的"需要这样的"边缘检测吗?" 这本身可能会发出信号:"设计不够周到-正如您巧妙地注意到的-打开了"当前和未来的代码审阅者"-以灾难... (除非已正确-尤其是-注释掉了该代码段!)

    [/报价]

    我无法告诉您、当我只想对一次转换做出反应时、我无意中导致了多少次"级别触发"行为。

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

    [引用 user="12ve12pm"]……很多时候,当我想要时,我无意中导致了“级别触发”行为...“边沿触发”

    先生,你是对的。    也就是说、使用"放弃测试"(即>=)可能会立即"设置一些标志"、从而实现(两者都是)代码稳健性和"一次性(即边缘)执行"的"双重目标"。

    我们经常遇到(并解决)客户问题、尤其是在"噪声丰富"环境中、通过使用此类"放弃测试"。

    此外-当此类"放弃测试"为"命中"时-不能发生该事件-"清除和/或重新加载"-测试值-确保"边缘响应?"

    如果有人因任何原因"错过"一人一人一人"(过于关键)测试-您"预订了泰坦尼克号上的头等舱通道!" (水还在... (非常)冷/波涛汹涌(结冰)-我们被告知...)

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

    [引用 USER="CB1_MOBILE"]

    12时12分
    ...很多时候、当我想要时、我无意中导致了"电平触发"行为..."边沿触发"

    [/报价]

    我同意这一点更强大、我认为值得添加。 也就是说,12你应该对你的职位有一种喜欢的感觉。 在这方面,我们再次非常同意 CB1。

    Robert

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

    由于您的代码格式不正确,以下是重新格式化的 while ()循环-希望它能使您的分析更简单一点:

    while (1){
    Timer+=1;
    如果(计时器= 1000){
    Flag1 =-Flag1;
    if (Flag1 = 1){
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、VALV_6);
    } 否则{
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、0x00);
    }
    }
    如果(计时器= 2000){
    flag2 =-flag2;
    计时器= 0;
    if (flag2 ==1){
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、VALV_19);
    } 否则{
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、0x00);
    }
    }
    
    

    对它的分析相当简单。

    假设在时间0/timer=0时 Flag1=flag2=-1:

    time0/timer=0:Flag1=-1/PIN6=0、flag2=-1/pin19=0;

    time1000/timer=1000:Flag1=1/PIN6=1、flag2=-1/pin19=0;

    time2000/timer=0:Flag1=1/PIN6=1、flag2=1/pin19=1;

    time3000/timer=1000:Flag1=-1/PIN6=0、flag2=1/pin19=1;

    time4000/timer=0:Flag1=-1/PIN6=0、flag2=-1/pin19=0;

    (笑声)

    因此、基本上每2000次计数计时器、PIN6/19被翻转(周期= 4000次计数)、除了 PIN6/19是90度(关闭1000次计数)。

    对 AVR 进行的快速仿真显示了相同的结果。

    现在、我不知道这是否是您想要的行为-因为您没有告诉我们。 但是、如果这不是您观察到的结果、您的问题就在其他地方。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢大家的回复!
    我的兴趣只是引脚有一个4000个计数周期和一个1000个计数周期的延迟(只有我感兴趣的状态)、这只是让我记住如何使用 GPIO、中断等、这实际上没有用处。
    很抱歉、我上次编程的代码是3年前、无法复制缩进的代码。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引述 user="Matheus Nogueira]感谢大家的回复!
    我感兴趣的只是引脚具有4000个计数周期和1000个计数之间的延迟(只有状态是我感兴趣的)

    [/报价]

    在这种情况下、请忘记主循环并在具有易失性标志的中断和主循环之间组织"事件"。 简化整个过程并在中断中执行所有操作... 如下所示:

    void Timer0Isr ()
    {
    static uint32_t timer = 0;
    static uint32_t state = 0;
    
    TimerIntClear (TIMER0_BASE、TIMER_TINA_TIMEOUT);
    
    timer++;
    if (timer >= 1000){
    timer = 0;
    
    statD+;
    state &= 0x3;
    
    switch (state){
    case 0:pinORT_pin
    
    、GPIOVAL (pin 0)、GPIOVAL (pinORT_base、GPIOVAL)、GPIOVAL (pin 6、pinORT_VAL) 0x00);
    break;
    
    case 1:
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、VALV_6);
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、0x00);
    break;
    
    case 2:
    GPIOPinWrite (GPIO_PORTF_BASE、 Valv_6、VALV_6);
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_19、VALV_19);
    中断;
    
    情况3:
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、0x00);
    GPIOPinWrite (GPIO_PORTF_BASE、 Valv_19、VALV_19);
    break;
    }
    
    
    
    
    }}int main (void)
    {
    SysCtlClockSet (SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_MAIN | SYSCTL_XTAL_16MHz);
    
    GPIOInit ();
    TimerInit ();TimerInit
    
    ();TimerInst_0_base (TIMER0);TimerTimerA (TimerA)
    TimerLoadSet (TIMER0_BASE、TIMER_A、SysCtlClockGet ()/100000);
    
    //从这些引脚开始状态为0
    GPIOPinWrite (GPIO_PORTF_BASE、VALV_6、0x00);
    GPIOPINWrite (GPIO_PORTF_BASE、VALV_19、 0x00);
    
    IntMasterEnable();
    
    while (1){
    // VALV_6和 VALV_19在 Timer0中断中处理
    //可能在此执行其他操作
    //...
    }
    }
    

    注意:这只是一个展示我所讨论内容的示例。 我实际上没有在硬件上测试过这种情况、但它可能会提供接近所需结果的结果。 :-)

    此代码包含 CB1_MOBILE 和 Robert Adsett 关于"放弃"">="测试的建议。 它还使意图更加具体:也就是说,我们希望以循环的方式逐一通过这四个不同的国家。

    现在、如果用户想要氮化镓:

    *严格地说,switch 语句应该具有一个“缺省”子句,该子句从导致“状态”变量包含垃圾的任何无法解释的情况中执行一些恢复。 由于我们按位执行、并且在交换机之前的行中执行0x3、因此很难执行默认值、因为如果"状态"确实包含垃圾、那么它现在将是0到3范围内的垃圾。

    *有人肯定会指出、我的"timer"和"state"变量不会被声明为易失性变量。 我在 Timer0Isr()函数内将它们声明为静态的,这意味着:(1)它们的内容在调用之间保留,(2)从 Timer0Isr()外部看不出这些变量。 由于缺少可见性、任何代码都不应以异步方式访问这些变量到中断。 当从不同的上下文(主上下文、线程上下文、中断上下文)进行异步访问时、必须使用易失性。 它告诉编译器优化器不要对该变量进行智能处理。

    如果您真的需要额外的积分、请考虑去掉计时器变量并完全针对1000进行测试、并设置计时器的周期以匹配所需的波形。 然后、您的中断只会使"状态"递增、并使用0x3递增、并根据"状态"更改引脚状态。

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

    做得很好-希望我们的海报能够得到赞赏。   至於“额外信贷”,严厉的工作人员指出,这种“信贷”(甚至是“额外信贷”)不能满足加拿大或芝加哥 的“电力与照明”。  (员工"期望"愉悦的(白炽灯)"头顶发光"(在我们的"后房"中)继续...)

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

    [引用 USER="CB1_MOBILE"]

    做得很好-希望我们的海报能够得到赞赏。   至於“额外信贷”,严厉的工作人员指出,这种“信贷”(甚至是“额外信贷”)不能满足加拿大或芝加哥 的“电力与照明”。  (员工"期望"愉悦的(白炽灯)"头顶发光"(在我们的"后房"中)继续...)

    [/报价]

    没关系。 在潜艇业务中、您可以获得潜水的零信用。 您只能获得返回到活动表面的点。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    可使用定时器/比较匹配来生成正交输出。 您可以指定相位差、设置完成后、无需 CPU 参与即可完成、从而将其释放为执行其他操作。

    下面是一个示例: dannyelectronics.wordpress.com/.../

    芯片不同、但基本概念相同。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    和... 在水下保持"灯亮"(甚至)有助于"表面恢复"。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    
    

    "如下所示:"

    您不需要这种复杂性:您可以在主循环中执行它、并且可以直接使用计时器计数、如下所示:

    开关(定时器){
    情况1000://使用 GPIO 执行某些操作
    情况2000://使用 GPIO 执行某些操作
    案例3000://使用 GPIO 执行某些操作
    案例4000://使用 GPIO 执行某些操作
    //复位计时器
    Timer=0;
    }
    

    您还可以将其放入 ISR 中、但在我看来、它更干净、更可读、以便将其放入主循环中。

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

    [引用用户="Danny F"]

    
    

    "如下所示:"

    您不需要这种复杂性:您可以在主循环中执行它、并且可以直接使用计时器计数、如下所示:

    开关(定时器){
    情况1000://使用 GPIO 执行某些操作
    情况2000://使用 GPIO 执行某些操作
    案例3000://使用 GPIO 执行某些操作
    案例4000://使用 GPIO 执行某些操作
    //复位计时器
    Timer=0;
    }
    

    您还可以将其放入 ISR 中、但在我看来、它更干净、更可读、以便将其放入主循环中。

    [/报价]

    如果您这样做、那么您将遇到问题、您可能"错过"相当于1000、2000、3000和4000的计时器。

    今天可能不会发生这种情况。 但是、明天将添加额外的代码来执行其他操作、该代码的执行时间将更长。 当计时器为999时、您可以执行"switch (timer)"语句、当计时器为1001时、您可以再次执行该语句。 得到的波形将不正确。 这将全部发生、因为计时器异步更改为主循环的执行。 如果您在中断中执行此操作、则它将起作用、因为计时器会与"switch (timer)"语句同步递增。

    我同意你先前的发言:

    [引用 user="Danny F">可以使用计时器/比较匹配来生成正交输出。 您可以指定相位差、设置完成后、无需 CPU 参与即可完成、从而将其释放为执行其他操作。

    下面是一个示例: dannyelectronics.wordpress.com/.../

    芯片不同、但基本概念相同。

    [/报价]

    如果可能、波形应由硬件外设生成、因为这会导致比软件生成的波形更准确(时序更好、抖动更少)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我通常抵制在 ISR 中执行大量操作的诱惑。

    当计时器为999时、您可以执行"switch (timer)"语句、当计时器为1001时、您可以再次执行该语句。 "

    解决该问题的两种方法:

    1) 1)在 ISR 中使用标志并执行 ISR 中的标志;
    2) 2)以较长的持续时间增量。 因此、与现在的1ms (=1计数)相比、增量为1s (=1000计数)。 因此、您可以降低长时间任务导致输出抖动的风险。 在这种情况下,您的计时器将从0->1->2->3->4/0->1...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    梅斯·阿米斯,   我们不 是所有人, 只是听到这只可怜的(也是非常)死马——“为安静而哭?”
    你们都做得很好-让我们来讨论一些真正的问题。    (但不在「此」马坟墓场中……)

    请注意、此主题/标题"有问题"几乎可以保证您继续努力、"几乎没有经过审核"。    他们应该更好!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我阅读了大家发布的所有内容、真的很有帮助。 我从未在 TI 的论坛上发布任何内容、因此我不知道对我有用的所有内容是否都应标记为"这已解决了我的问题"。 嗯、如果你说这个帖子应该关闭、我同意、但我不认为这里的所有内容都是我"很少评论"的。

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

    作为线程的发起者/作者-您"很可能"审查它。

    然而、其他人-当"搜索与其(特定)需求相关的帖子(某种程度上)"时、不太可能在附近的任何地方"输入关键字"、"未正确遵循代码"。   这里有很多价值-但"主题/标题"(如上所述)将此主题改为"发现的可能性低"。

    过度加载线程-这不太可能-"再次拨号"-似乎不是展示"海报人才"的最佳方式-这里有很多证据...

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

    做得很好的十二、状态机是一个好主意。

    只有一条警告、我认为我们在这里不知道如何在这种情况下遵循它。 构建状态图以关注问题、而不是遵循偶然计时。 即、如果有两个输出在功能上独立于它们、即使输出变化与部分时序一致(即使该部分全部相同)、也会为它们单独实施状态机。 这使得维护更加简单。

    像 Yakindu 这样的产品也使这种维护和文档制作变得更容易。

    [引用 user="12ve12pm"]现在,如果用户想使用 nitpick

    如果您坚持的话

    [引用 user="12ve12pm">严格地说,switch 语句应具有一个“默认”子句,该子句可从导致“状态”变量包含垃圾的任何无法解释的情况中执行一些恢复。 [/报价]

    是的、某些质量标准(例如 MISRA 和多种安全标准)规定这是强制性的。 这是一个很好的做法、而且成本很低。 一个良好的静态分析器也将支持这一点。

    [引用 user="12ve12pm"]有人肯定会指出,我的“计时器”和“状态”变量没有声明为易失性。

    不可以、有两种方法不正确地使用易失性

    1. 在需要时不使用它
    2. 在不需要时使用它

    您似乎没有提交任何一个故障。 在这里使用易失性会是一个错误、不必要地限制编译器。

    [引用 user="12ve12pm"]由于缺少可见性,任何代码都不应以异步方式访问这些变量[/引用]

    这实际上不是易失性的功能。 在这种情况下使用它是其担保的副产品,而不是其本身的担保。

     Robert