求助,怎样让ad采样不会影响程序的继续执行,即可以多线程-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

楼主: peter1999516

[未解决] 求助,怎样让ad采样不会影响程序的继续执行,即可以多线程

[复制链接]
 楼主| 发表于 2022-4-14 14:07 | 显示全部楼层
顶一下帖子,希望有大佬救援
 楼主| 发表于 2022-4-15 22:55 | 显示全部楼层
顶一下帖子
 楼主| 发表于 2022-4-19 15:28 | 显示全部楼层
顶一下帖子
发表于 2022-4-20 07:43 | 显示全部楼层
看你不断地顶,看来真的很想要帮助。但我看了两遍也没看懂你要做什么。是PWM触发中断进行AD采样,还是根据AD采样值输出PWM。最好再描述清楚些你要做什么,同时把全部代码贴出来。否则别人很难帮到你。
 楼主| 发表于 2022-4-20 19:58 | 显示全部楼层
ifeue 发表于 2022-4-20 07:43
看你不断地顶,看来真的很想要帮助。但我看了两遍也没看懂你要做什么。是PWM触发中断进行AD采样,还是根据A ...

感谢大佬的回复,我重新描述一下问题
 楼主| 发表于 2022-4-20 20:04 | 显示全部楼层
#include <ADC.h>
#include <Arduino.h>
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0,SCL,SDA,U8X8_PIN_NONE);

int potPin = A1;
int potPin1 = A2;
float temperature = 0;
float voltage = 0;
long value = 0;
long value1 = 0;
int i=0;
int flag=0;//启动标志位
int Buttonpin=2;
int pwm_xunhuancishu=0;//合闸信号,中断开始
int ledPinwendu=4;//温度报警用
int interval=100;//非delay 100us
int sensorvalue=0;

unsigned long previousMillis = 0;
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);   // OLEDs without Reset of the Display

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);//中断用
  Serial.begin(9600);
   u8g2.begin();

attachInterrupt(0,pwmhezha,LOW); //pwm发生中断子程序用于控制光耦开合
attachInterrupt(1,pwmfenzha,LOW);
  /* U8g2 Project: SSD1306 Test Board */
  //pinMode(10, OUTPUT);
  //pinMode(9, OUTPUT);
  //digitalWrite(10, 0);
  //digitalWrite(9, 0);   
  
  /* U8g2 Project: KS0108 Test Board */
  //pinMode(16, OUTPUT);
  //digitalWrite(16, 0);  
  
  u8x8.begin();
  u8x8.setPowerSave(0);
  
  
}

void loop()
{
  while(flag==0)
  {     
  value = analogRead(potPin); //读取模拟输入
delay(300);
  //电压与摄氏度转换:
  //0.00488125=5/1024,0~5V对应模拟口读数1~1024,每10毫伏对应1℃
  temperature = (value * 0.0048828125 * 100);
  Serial.println(temperature);                                  //因为上限是5v,而线圈驱动电压是220v,因此用分压电阻99欧和1欧,上限是222v最低是219v
  if (temperature<50)
  {
    value1=analogRead(potPin1);
    voltage =  value1* 0.48828125;
    if((voltage>=0)&&(voltage<230))
    {
      int flag=1;
      u8g2.clearBuffer();  //清除缓存         
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"Ready to action!");  
  u8g2.drawStr(0,20,"Please choose Mode!");  
  u8g2.drawStr(0,30,"OPEN OR CLOSE!");
   u8g2.drawStr(100,40,"V");
  u8g2.setCursor(55,40);//位置
  u8g2.print(voltage);
  u8g2.sendBuffer();  //显示      
  delay(1000);
      break;//标志位
        }
  else
  {
    while(1)
    {
  int flag=0;//标志位
  analogWrite(17, 255);
  delay(1000);
  analogWrite(17, 0);
  delay(1000);
  u8g2.clearBuffer();  //清除缓存         
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"WRONG VOLTAGE!");
  u8g2.drawStr(100,40,"V");  
  u8g2.setCursor(55,40);//位置
  u8g2.print(voltage);
  u8g2.sendBuffer();  //显示      
  delay(1000);   
    }

   }
  }//启动标志位清零
  else
  {
  while(1)
  {
    for(int fadevalue=0; fadevalue<=255;fadevalue+=50)
   {
    analogWrite(ledPinwendu,fadevalue);
  u8g2.clearBuffer();  //清除缓存         
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"HIGH TEM!");   
  u8g2.sendBuffer();  //显示      
  delay(1000);
    }
      for(int fadevalue=255; fadevalue>=0;fadevalue-=50)
   {
    analogWrite(ledPinwendu,fadevalue);
  
       // only required for SSD1606/7  

  
    }
    //触发超温保护,且不会停止除非重启排除故障
    }
  }
   
  }
  //若是flag为0说明电压不对,重新自检
//查询合闸?分闸?


}
void pwmhezha() //中断子程序 pwm方波输出
{

  do
{
   int sensorvalue=ADC_8bit(0)/12;//ad程序,总是在判定哪个角发出对应方波前进行采样
    if(sensorvalue>15) //3.7v
  {
//-1态
delayMicroseconds(100);
   pwm_xunhuancishu=pwm_xunhuancishu+1;//用来退出中断用
   // Approximately 10% duty cycle @ 1KHz
   
   
       //标志位加1,每5个循环一个采集
       }
else  if(sensorvalue<5) //后期加入与或运算,满足合闸或者分闸需求。先与后或 1.3v
{
  digitalWrite(13, HIGH);// 1态
  digitalWrite(12, HIGH);
  unsigned long currentMillis = micros();
if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  digitalWrite(13, LOW);
  digitalWrite(12, LOW);
pwm_xunhuancishu=pwm_xunhuancishu+1;
   // Approximately 10% duty cycle @ 1KHz
    }


pwm_xunhuancishu=pwm_xunhuancishu+1;
   // Approximately 10% duty cycle @ 1KHz
    }
    else if((sensorvalue>5)&&(sensorvalue<15))//后期加入与或运算,满足合闸或者分闸需求。先与后或 1.5v-3.5v
{
  
  digitalWrite(13, HIGH); // 0态
unsigned long currentMillis = micros();
if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
  digitalWrite(13, LOW);// 78角管分闸
  
pwm_xunhuancishu=pwm_xunhuancishu+1;
}
      
}
}
while(pwm_xunhuancishu<50000);//这块为了方便观察室大概10s结束中断,后面会改成100ms,每10000大约是1s  pwm_xunhuancishu<100000
   }

   void pwmfenzha()
   {

  do
{

  int sensorvalue=ADC_8bit(0)/12;

   // Approximately 10% duty cycle @ 1KHz
   //ad程序,总是在判定哪个角发出对应方波前进行采样
    if(sensorvalue>15) //3.7v
  {
//-1态加反压
delayMicroseconds(100);
   pwm_xunhuancishu=pwm_xunhuancishu+1;//计时器用于结束中断
   // Approximately 10% duty cycle @ 1KHz
   
   
       //标志位加1,每5个循环一个采集
       }
else if(sensorvalue<5) //后期加入与或运算,满足合闸或者分闸需求。先与后或 1.3v
{
   digitalWrite(7, HIGH);// 1态
  digitalWrite(8, HIGH);
  unsigned long currentMillis = micros();
if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
pwm_xunhuancishu=pwm_xunhuancishu+1;
   // Approximately 10% duty cycle @ 1KHz
    }
}

        else if((sensorvalue>5)&&(sensorvalue<15))//后期加入与或运算,满足合闸或者分闸需求。先与后或 1.5v-3.5v
{
  digitalWrite(8, HIGH); // 0态
unsigned long currentMillis = micros();
if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
  previousMillis = currentMillis;
  digitalWrite(8, LOW);
pwm_xunhuancishu=pwm_xunhuancishu+1;
   // Approximately 10% duty cycle @ 1KHz
    }


   
}
}
while(pwm_xunhuancishu<50000);//这块为了方便观察室大概10s结束中断,后面会改成100ms,每10000大约是1s  pwm_xunhuancishu<100000
   }
   
 楼主| 发表于 2022-4-20 20:27 | 显示全部楼层
由于不能上传Proteus工程文件,所以我附上一段问题描述的视频。不需要看我的主函数,主要就是中断子程序void pwmfenzha()中ADC和通过数字口模拟pwm方波那里有些问题。以下是问题描述https://www.bilibili.com/video/BV14a411v7QF/
 楼主| 发表于 2022-4-20 20:29 | 显示全部楼层
https://www.bilibili.com/video/BV14a411v7QF/
链接:https://pan.baidu.com/s/1rHDPn-n2lzrqb66nabWY0g
提取码:ia2d
以上是度盘Proteus 8工程文件
 楼主| 发表于 2022-4-20 20:38 | 显示全部楼层
#include <ADC.h>
#include <Arduino.h>
#include <U8x8lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0,SCL,SDA,U8X8_PIN_NONE);

int potPin = A1;
int potPin1 = A2;
float temperature = 0;
float voltage = 0;
long value = 0;
long value1 = 0;
int i=0;
int flag=0;//启动标志位
int Buttonpin=2;
int pwm_xunhuancishu=0;//合闸信号,中断开始
int ledPinwendu=4;//温度报警用



U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);   // OLEDs without Reset of the Display

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(2,INPUT_PULLUP);
  pinMode(3,INPUT_PULLUP);
  Serial.begin(9600);
   u8g2.begin();

attachInterrupt(0,pwmhezha,LOW); //pwm发生中断子程序用于控制光耦开合
attachInterrupt(1,pwmfenzha,LOW);
  /* U8g2 Project: SSD1306 Test Board */
  //pinMode(10, OUTPUT);
  //pinMode(9, OUTPUT);
  //digitalWrite(10, 0);
  //digitalWrite(9, 0);   
  
  /* U8g2 Project: KS0108 Test Board */
  //pinMode(16, OUTPUT);
  //digitalWrite(16, 0);  
  
  u8x8.begin();
  u8x8.setPowerSave(0);
  
  
}

void loop()
{
  while(flag==0)
  {     
  value = analogRead(potPin); //读取模拟输入

  //电压与摄氏度转换:
  //0.00488125=5/1024,0~5V对应模拟口读数1~1024,每10毫伏对应1℃
  temperature = (value * 0.0048828125 * 100);
  Serial.println(temperature);                                  //因为上限是5v,而线圈驱动电压是220v,因此用分压电阻99欧和1欧,上限是222v最低是219v
  if (temperature<50)
  {
    value1=analogRead(potPin1);
    voltage =  value1* 0.48828125;
    if((voltage>210)&&(voltage<230))
    {
      int flag=1;
      u8g2.clearBuffer();  //清除缓存         
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"Ready to action!");  
  u8g2.drawStr(0,20,"please choose!");  
  u8g2.sendBuffer();  //显示      
  delay(1000);
      break;//标志位
        }
  else
  {
     while(1)
     {
  int flag=0;//标志位
  analogWrite(17, 255);
  delay(1000);
  analogWrite(17, 0);
  delay(1000);
  u8g2.clearBuffer();  //清除缓存         
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"WRONG VOLTAGE!");   
  u8g2.sendBuffer();  //显示      
  delay(1000);   
     }
   }
  }//启动标志位清零
  else
  {
  while(1)
  {for(int fadevalue=0; fadevalue<=255;fadevalue+=50)
   {analogWrite(ledPinwendu,fadevalue);
  u8g2.clearBuffer();  //清除缓存         
  u8g2.setFont(u8g2_font_ncenB08_tr);
  u8g2.drawStr(0,10,"HIGH TEM!");   
  u8g2.sendBuffer();  //显示      
  delay(1000);
    }
      for(int fadevalue=255; fadevalue>=0;fadevalue-=50)
   {
    analogWrite(ledPinwendu,fadevalue);
  
       // only required for SSD1606/7  

  
    }
    //触发超温保护,且不会停止除非重启排除故障
    }
  }
   
  }
  //若是flag为0说明电压不对,重新自检
//查询合闸?分闸?


}
[color=Red]void pwmhezha() //中断子程序 pwm方波输出
{

  do
{
   int sensorvalue=ADC_8bit(0)/12;//ad程序,总是在判定哪个角发出对应方波前进行采样
    if(sensorvalue>15) //3.7v
  {
//-1态
delayMicroseconds(100);
   pwm_xunhuancishu=pwm_xunhuancishu+1;//用来退出中断用
   // Approximately 10% duty cycle @ 1KHz
   
   
       //标志位加1,每5个循环一个采集
       }
else if(sensorvalue<5) //后期加入与或运算,满足合闸或者分闸需求。先与后或 1.3v
{
  digitalWrite(13, HIGH);// 1态
  digitalWrite(12, HIGH);
  delayMicroseconds(100);
  digitalWrite(13, LOW);
  digitalWrite(12, LOW);
pwm_xunhuancishu=pwm_xunhuancishu+1;
   // Approximately 10% duty cycle @ 1KHz
    }
    else if((sensorvalue>5)&&(sensorvalue<15))//后期加入与或运算,满足合闸或者分闸需求。先与后或 1.5v-3.5v
{
  digitalWrite(13, HIGH); // 0态

  delayMicroseconds(100);
  digitalWrite(13, LOW);// 78角管分闸
  
pwm_xunhuancishu=pwm_xunhuancishu+1;
}
      
}
while(pwm_xunhuancishu<50000);//这块为了方便观察室大概10s结束中断,后面会改成100ms,每10000大约是1s  pwm_xunhuancishu<100000
   }
   void pwmfenzha()
   {

  do
{
   int sensorvalue=ADC_8bit(0)/12;//ad程序,总是在判定哪个角发出对应方波前进行采样
    if(sensorvalue>15) //3.7v
  {
//-1态加反压
delayMicroseconds(100);
   pwm_xunhuancishu=pwm_xunhuancishu+1;//计时器用于结束中断
   // Approximately 10% duty cycle @ 1KHz
   
   
       //标志位加1,每5个循环一个采集
       }
else if(sensorvalue<5) //后期加入与或运算,满足合闸或者分闸需求。先与后或 1.3v
{
   digitalWrite(7, HIGH);// 1态
  digitalWrite(8, HIGH);
  delayMicroseconds(100);
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
pwm_xunhuancishu=pwm_xunhuancishu+1;
   // Approximately 10% duty cycle @ 1KHz
    }
        else if((sensorvalue>5)&&(sensorvalue<15))//后期加入与或运算,满足合闸或者分闸需求。先与后或 1.5v-3.5v
{
  digitalWrite(8, HIGH); // 0态

  delayMicroseconds(100);
  digitalWrite(8, LOW);// 78角管分闸
  
pwm_xunhuancishu=pwm_xunhuancishu+1;
}


   
}
while(pwm_xunhuancishu<50000);//这块为了方便观察室大概10s结束中断,后面会改成100ms,每10000大约是1s  pwm_xunhuancishu<100000
   }

此代码也可以使用,都是同一个意思,没有调用Millis函数,直接用delay做延时模拟Pwm了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 09:34 , Processed in 0.105021 second(s), 13 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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