gpt4 book ai didi

c - 没有延迟地写定时器()

转载 作者:太空狗 更新时间:2023-10-29 17:13:51 25 4
gpt4 key购买 nike

我写了这段代码来在输入为高电平时发送 SMS,正如您在其中看到的那样,但问题是我有 4 个输入并且 delay()s 是致命的,如果我一次需要做不止一件事(我使用 4 个输入)。

所以我需要在 void loop() ,Send_SMS( )initia()

谁能帮帮我,在此先谢谢你。

const int DI = 2;
const int DT = 3;
const int DGP1 = 4;
const int DGP2 = 5;

int value1_old = 0;
int value2_old = 0;
int value3_old = 0;
int value4_old = 0;

unsigned long previousMillis = 0;
unsigned long interval=100;

#include<SoftwareSerial.h>
SoftwareSerial SIM900 (7, 8);

void setup() {
pinMode(DI, INPUT);
pinMode(DT, INPUT);
pinMode(DGP1, INPUT);
pinMode(DGP2, INPUT);

SIM900.begin(19200);
SIM900power();
delay(20000);

}

void SIM900power(){
digitalWrite(9 ,HIGH);
delay(1000);
digitalWrite(9 ,LOW);
delay(5000);
}

void initia(){
SIM900.print("AT+CMGF=1\r");
delay(100);
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
delay(100);
}

void Send_SMS(){
SIM900.println((char)26);
delay(100);
SIM900.println();
delay(100);
SIM900power();
}

void loop() {
int value1 = digitalRead (DI);
int value2 = digitalRead (DT);
int value3 = digitalRead (DGP1);
int value4 = digitalRead (DGP2);

if (value2 != value2_old && value2 == HIGH) {
initia();
SIM900.println("Station 85: Defaut electrique");
delay(100);
Send_SMS();
value2_old = value2;
}

if (value3 != value3_old && value3 == HIGH)
{
initia();
SIM900.println("Station 85: DefautGP1");
delay(100);
Send_SMS();
value3_old = value3;
}

if (value4 != value4_old && value4 == HIGH)
{
initia();
SIM900.println("Station 85:DD>1000");
delay(100);
Send_SMS();
value4_old = value4;
}
value2_old = value2;
value3_old = value3;
value4_old = value4;
}

最佳答案

正如 mclopez 指出的那样,最好提供一个好的答案,而不是仅仅指出其他答案的缺陷,所以...我们开始吧。

在我看来,ISR 解决方案不是一个好的选择,因为 ISR 会阻止正常执行。使用中断的唯一可行实现是记录引脚变化,然后发送 SMS。

然而,在我看来,这不是一个好的解决方案。对于这个问题,我会使用状态机来发送短信;因为你有状态,你可以在做其他事情的同时等待转换,比如检查按钮。

我不知道 SIM900 是如何发送短信的,所以我采用了你的工作流程并在状态机中实现它。我不确定这是最佳解决方案,特别是因为我不认为您实际上每次都需要重新启动模块,但您可以稍后调整它。

现在,工作流有七个必须执行的操作,每个操作后都需要等待。我把它写在这里是为了更容易看到每个 Action :

SIM900.print("AT+CMGF=1\r");
delay(100);
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
delay(100);
SIM900.println("Message you want");
delay(100);
SIM900.println((char)26);
delay(100);
SIM900.println();
delay(100);
digitalWrite(9 ,HIGH);
delay(1000);
digitalWrite(9 ,LOW);
delay(5000);

所以我们有八个状态:一个空闲状态(当您等待状态机启动时,名为 SIM_IDLE),然后是五个“发送”状态(我将它们命名为 SIM_SEND1..5)和两个重置状态电源(名为 SIM_POW1 和 SIM_POW2)。您通常处于空闲状态;当按下一个或多个按钮时,您会切换到第一个发送,循环通过它们,然后重置电源并返回空闲状态。

按下的按钮仅更改状态 SIM_SEND3(当您实际发送消息时),因此每当检测到按钮按下时,都会设置一个 bool 变量(在状态机执行期间也会检测到按钮按下)并且仅在该状态下重置发送正确消息后的状态。

现在,这是实现它的代码:

const uint8_t DI = 2;
const uint8_t DT = 3;
const uint8_t DGP1 = 4;
const uint8_t DGP2 = 5;

const uint8_t SIMPOW = 9;

uint8_t value1_old = 0;
uint8_t value2_old = 0;
uint8_t value3_old = 0;
uint8_t value4_old = 0;

boolean value1_changed = false;
boolean value2_changed = false;
boolean value3_changed = false;
boolean value4_changed = false;

/********************************/
// SIM STATES
#define SIM_IDLE 0
//SEND1: SIM900.print("AT+CMGF=1\r");delay(100);
#define SIM_SEND1 1
//SEND2: SIM900.println("AT + CMGS = \"+212xxxxxxx\"");delay(100);
#define SIM_SEND2 2
//SEND3: SIM900.println("Message you want");delay(100);
#define SIM_SEND3 3
//SEND4: SIM900.println((char)26);delay(100);
#define SIM_SEND4 4
//SEND5: SIM900.println();delay(100);
#define SIM_SEND5 5
//POW1: digitalWrite(SIMPOW,HIGH);delay(1000);
#define SIM_POW1 6
//POW2: digitalWrite(SIMPOW,LOW);delay(5000);
#define SIM_POW2 7
/********************************/

unsigned long previousMillis;
uint8_t currentSimState;

#include<SoftwareSerial.h>
SoftwareSerial SIM900 (7, 8);

void setup()
{
pinMode(DI, INPUT);
pinMode(DT, INPUT);
pinMode(DGP1, INPUT);
pinMode(DGP2, INPUT);
pinMode(SIMPOW, OUTPUT);

SIM900.begin(19200);

digitalWrite(SIMPOW,HIGH);
delay(1000);
digitalWrite(SIMPOW,LOW);
delay(25000);
currentSimState = -1; // Force a state transition
}

void loop()
{
uint8_t value1 = digitalRead (DI);
uint8_t value2 = digitalRead (DT);
uint8_t value3 = digitalRead (DGP1);
uint8_t value4 = digitalRead (DGP2);

unsigned long currentMillis = millis();

if (value2 != value2_old && value2 == HIGH)
value2_changed = true;
if (value3 != value3_old && value3 == HIGH)
value3_changed = true;
if (value4 != value4_old && value4 == HIGH)
value4_changed = true;

value1_old = value1;
value2_old = value2;
value3_old = value3;
value4_old = value4;

// Check if a state transition is needed
uint8_t newSimState = currentSimState;
switch (currentSimState)
{
case SIM_IDLE: // Start sending if a value changed
if ((value2_changed) || (value3_changed) || (value4_changed))
newSimState = SIM_SEND1;
break;
case SIM_SEND1: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND2;
break;
case SIM_SEND2: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND3;
break;
case SIM_SEND3: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND4;
break;
case SIM_SEND4: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_SEND5;
break;
case SIM_SEND5: // Wait 100 ms
if ((currentMillis - previousMillis) >= 100)
newSimState = SIM_POW1;
break;
case SIM_POW1: // Wait 1000 ms
if ((currentMillis - previousMillis) >= 1000)
newSimState = SIM_POW2;
break;
case SIM_POW2: // Wait 1000 ms
if ((currentMillis - previousMillis) >= 1000)
newSimState = SIM_IDLE;
break;
default:
newSimState = SIM_IDLE;
break;
}

// If there was a transition, do the appropriate action
if (newSimState != currentSimState)
{
case SIM_IDLE:
// Do nothing
break;
case SIM_SEND1:
SIM900.print("AT+CMGF=1\r");
previousMillis = millis();
break;
case SIM_SEND2:
SIM900.println("AT + CMGS = \"+212xxxxxxx\"");
previousMillis = millis();
break;
case SIM_SEND3:
if (value2_changed)
{
SIM900.println("Station 85: Defaut electrique");
value2_changed = false;
}
else if (value3_changed)
{
SIM900.println("Station 85: DefautGP1");
value2_changed = false;
}
else if (value4_changed)
{
SIM900.println("Station 85:DD>1000");
value2_changed = false;
}
else
{
// Should never arrive here. Just in case, you
// can either abort the SMS sending if you can
// or send another message
}
previousMillis = millis();
break;
case SIM_SEND4:
SIM900.println((char)26);
previousMillis = millis();
break;
case SIM_SEND5:
SIM900.println();
previousMillis = millis();
break;
case SIM_POW1:
digitalWrite(SIMPOW,HIGH);
previousMillis = millis();
break;
case SIM_POW2:
digitalWrite(SIMPOW,LOW);
previousMillis = millis();
break;
}
}

// Advance state
currentSimState = newSimState;
}

看似复杂,其实很简单。循环由三个“ block ”构成。

第一个是按钮检查。如果按下任何按钮,则会设置相应的 valueX_changed 标志。这是一个非常微不足道的部分,只需检查是否有任何按钮具有不同的状态,然后设置标志。

第二部分是检查状态转换。在此 switch 语句中,程序确定是否需要更改状态机的状态。如果在状态为空闲时按下按钮,或者在发送 SMS 的过程中经过了指定的时间,就会发生这种情况。

第三部分是状态改变时要执行的 Action 。因此,如果状态发生变化,则执行状态操作,这对空闲状态没有任何意义,为 SIM_SENDx 状态发送一些内容并更改 SIM_POWx 状态的引脚。

请注意:在设置中,您添加了 20 秒的延迟,这不会出现在正常工作流程中。如果要删除它,只需从执行重置的设置中删除四行,然后修改第一个开关中的 default 案例以设置 newSimState = SIM_POW1; SIM_IDLE

此代码中可能存在小错误,因为我尚未对其进行测试,但它应该可以满足您的需求

关于c - 没有延迟地写定时器(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29716979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com