使用Ardunio STM32F103C8T6的中断来解码SYN500R信号

STM32F103C8T6 for Ardunio IDE

在某宝上购买的STM32F103C8T6最小核心板,通过网上的资料将其应用在Ardunio ID上。网上资料很多,最详细的https://blog.csdn.net/bobo184/article/details/84349184,但是他使用的不是某宝上的核心板。当你需要下载ST Microelectronics flash loader需要注册,然后到邮箱的邮件连接才能下载。不过有其他网友提到可以使用另外的烧写软件。在刷写时注意boot0与boot1的条线(两个都接高电平)。要不然总提示找不到芯片。完成后再将跳线都接低电平,下载安装STM32的库文件复制到Ardunio IDE的安装目录**\libraries**。就可以直接再Ardunio IDE中下载到STM32,除了资料少一些之外与Ardunio AVR之类的开发板没什么两样。

SYN500R芯片4支脚不带解码超外差接收模块

我这是公司之前定制的!不过某宝上也有这类模块。至于是315还是433其实并没多大关系。主要看遥控器的发射频率是否与接收器一致。我当时定制的也不清楚到底是哪个频率的了,所以只好把原来的解码芯片取掉了。然后将信号用引线接出来,输出引脚在SYN500的第10脚(DO)syn500R 输出引脚
照片-SYN500引脚实物在这里插入图片描述

关于STM32 在Ardunio 里使用中断事件获得信号脚的电平持续时间

在网上查了N多资料基本没怎么说如何使用中断的。最后只能使用笨办法。也许是我查找的方法不对吧。也或许英文资料应该是有的,只是我的水平不足而已。但也没关系了,最后还是解决了!在[WWW.ARDUNIO.CC]官网里的https://www.arduino.cc/reference/en/#functions 说明里找到了对应关于中断的解答。但是那也只是针对AVR的。没有对SMT32的说明。毕竟没有AVR和STM32的说明书。看来只好去测试了。先用一个红外线感应器来测试中断引脚。发现可以将某个引脚当中断使用,并不像AVR或51那样只能在特定的引脚才能使用中断。因为接收到的信号时单一的没有时钟同步。必须通过判断高低电平持续时间来决定传输的是0还是1。但是Ardunio只有pulseIn(pin, value, timeout)pulseIn(pin, value)它的功能是需要一直等待设定的高低电平后返回持续时间。这个看起来挺合适的。但是它反应好慢,导致我在这个过程中耽误了好长的时间(一天),之后参考了RCLSwitch库和IRremote库,总算能够读取到对应持续时间的高低电平了。

信号时序

信号时序

代码

#include <MapleFreeRTOS821.h>   //freeRTOS是嵌入式实时操作系
#include <EEPROM.h>

#define BOARD_LED_PIN PC13      //定义板载LED(呼吸灯,运行中信号)为数字引脚2  
#define SensorINPUT PB12        //定义感应器开关信号为数字引脚25
#define RC_Switch_INPUT PB13    //定义遥控接收信号为数字引脚26
#define StepMotorer_Dir PB14    //定义步进马达方向为数字引脚27
#define StepMotorer_En PB15     //定义步进马达使能开关为数字引脚28
#define StepMotorer_Step PA8    //定义步进马达步数频率为数字引脚29
#define Speeker_Out PB6         //蜂鸣器信号输出42

#define Stop 0                  //定义停止状态为0
#define Run 1                   //定义运行状态为1
#define CCW 0                   //定义正转状态为0
#define CW 1                    //定义反转状态为1

char SPEEK_MODE=0;              //蜂鸣器鸣叫模式:0:停止 1:嘀一声 2:嘀嘀两声 3:一长一短间隔1秒重复3次 4:低鸣一声

unsigned long Rc_Start_5MS_MinTime = 4800;
unsigned long Rc_Start_5MS_MaxTime = 5500;
unsigned long Rc_Start_600us_MinTime = 530;
unsigned long Rc_Start_600us_MaxTime = 750;
unsigned long Rc_Data_600us = 500;
unsigned long Rc_Data_200us = 240;

#define RC_GROUP_LEN 8 //8帧数据
#define RC_DATA_LEN  8 //八字节
#define RC_BIT_LEN   8 //八位
volatile unsigned char Rf_buf[RC_GROUP_LEN][RC_DATA_LEN + 1], INDEX_GROUP = 0, INDEX_BUFFER = 0;

unsigned long Rc_Signal_Time = 0;
unsigned long Elapsed_Time = 0;
char Rc_Signal_Pin_Level = LOW;
bool WeillRead[2] = {false};
unsigned long High_Level_Time = 0; 	//RC_Switch数据段的高低电平时间
unsigned long Low_Level_Time = 0; 	//RC_Switch数据段的高低电平时间
char Input_i = 0; 					//输入信号电平变化数组索引
char Do_Input_i = 0; 				//在任务中处理输入信号电平变化数组索引
unsigned char RC_BIT = 0;
uint16 AddressWrite = 0x10;  		//分配遥控器ID保持到EEPROM的地址
char Old_RC_CMD=0,Public_Key_Cmd=0; //让其他任务处理的按键值,当其他任务处理后可以将清空

char Run_Stop = Stop;
char CCW_CW = CCW;
unsigned long AlowyTime = 0;
unsigned long End_Time = 0;
bool RC_Data_Frame_Status = false; //接收到数据帧是否结束标记

/FreeRTOS 任务函数/
static void vLEDFlashTask(void *pvParameters)
{
  //
  // Flash led every 200 ms.
  for (;;)
  {
    if (AlowyTime > 2000)
    {
      digitalWrite(BOARD_LED_PIN, LOW);    // Turn LED off.
      Run_Stop = Stop;
      CCW_CW = CW;
    } else
    {
      if (digitalRead(SensorINPUT) == HIGH)
      {
        if (Run_Stop == Stop)
        {
          digitalWrite(BOARD_LED_PIN, HIGH);    // Turn LED on.
          vTaskDelay((1000 * configTICK_RATE_HZ) / 1000L);// Sleep for 50 milliseconds.
          digitalWrite(BOARD_LED_PIN, LOW); // Turn LED off.
          vTaskDelay((1000 * configTICK_RATE_HZ) / 1000L); // Sleep for 150 milliseconds.
        } else
        {
          if (CCW_CW == CW)
          {
            digitalWrite(BOARD_LED_PIN, HIGH);    // Turn LED on.
            vTaskDelay((50 * configTICK_RATE_HZ) / 1000L);// Sleep for 50 milliseconds.
            digitalWrite(BOARD_LED_PIN, LOW); // Turn LED off.
            vTaskDelay((50 * configTICK_RATE_HZ) / 1000L); // Sleep for 150 milliseconds.
          } else
          {
            digitalWrite(BOARD_LED_PIN, HIGH);    // Turn LED on.
            vTaskDelay((200 * configTICK_RATE_HZ) / 1000L);// Sleep for 50 milliseconds.
            digitalWrite(BOARD_LED_PIN, LOW); // Turn LED off.
            vTaskDelay((200 * configTICK_RATE_HZ) / 1000L); // Sleep for 150 milliseconds.
          }
        }
      }
    }
  }
}

void SensorInter() {               //感应器开关信号中断函数SensorInter()
  unsigned long  Stat_T = 0;
  Stat_T = millis(); //micros();
  if (digitalRead(SensorINPUT) == HIGH)
  {
    AlowyTime = Stat_T - End_Time;
    //Serial.println(AlowyTime);
    Run_Stop = !Run_Stop;
    if (Run_Stop == Stop) CCW_CW = !CCW_CW;
  }
  End_Time = Stat_T;
}

uint16 RC_Write_ID(char ID0,char ID1)
{
  uint16 DataWrite=ID0;
  DataWrite<<=8;
  DataWrite+=ID1;
  Serial.print("W_ID:");Serial.print(ID0,HEX);Serial.print(",");Serial.println(ID1,HEX);
  uint16 Status = EEPROM.write(AddressWrite, DataWrite);
  return(Status);  
}

bool RC_Cmp_ID(char ID0,char ID1)   //比较遥控器的ID号,查看是否与本机匹配
{
  uint16 EepRom_Data,ID=0;
  uint16 Status = EEPROM.read(AddressWrite, &EepRom_Data);
  ID=ID0;
  ID<<=8;
  ID+=ID1;
  if(EepRom_Data==0xFFFF || EepRom_Data==0)
  {
    //Serial.println("Free ID");
    return(true);
  }
  if(ID==EepRom_Data)return(true);
  else return(false);
}
315/433MHZ 自定义信号协议//
/*
    起始头5毫秒高电平600微秒低电平   1(600微秒高电平200微秒低电平)    0(200微秒高电平600微秒低电平)
       ______________________          ____________       _________          _____
  |    |  5000US            |          |600US     |       |200US  |          |   |
  S    0                    1 600US    2          3 200US 4       5 600US    6   |
  |____|                    |__________|          |_______|       |__________|   |___
  
*/
void RC_Switch_Inter() //遥控接收信号中断函数RC_Switch_Inter()
{
  unsigned char ei,crc,RC_CMD;
  unsigned long Now_Time = micros();
  Rc_Signal_Pin_Level = digitalRead(RC_Switch_INPUT);
  Elapsed_Time = Now_Time - Rc_Signal_Time;
  Rc_Signal_Time = Now_Time;
  if (Elapsed_Time > 6000) Elapsed_Time = 6000;
  //判断高低电平信号持续时间
  if (Rc_Signal_Pin_Level == LOW)  //获得时序:1,3,5 下降沿,其实为高电平的持续时间,此时获得的信号引脚是低电平
  {
    High_Level_Time = Elapsed_Time;  //上一次到现在的时间
  }
  else {//Rc_Signal_Pin_Level==HIGH//获得时序:1,4,6 上升沿,其实为低电平的持续时间,此时获得的信号引脚是高电平
    Low_Level_Time = Elapsed_Time;
  }//上一次到现在的时间

  //检测信号起始帧
  if (!WeillRead[1])
  {
    if (Rc_Signal_Pin_Level == HIGH && High_Level_Time <= Rc_Start_5MS_MaxTime && High_Level_Time >= Rc_Start_5MS_MinTime)
    {
      WeillRead[0] = true;
    }
    if (WeillRead[0] && Rc_Signal_Pin_Level == LOW)
    { if (Low_Level_Time <= Rc_Start_600us_MaxTime  && Low_Level_Time >= Rc_Start_600us_MinTime)
      {
        WeillRead[1] = true;
        RC_BIT = 0;
        //Serial.println("^_^");
      } else  {
        WeillRead[0] = false;
      }
    }
  } else
  {
    //解析数据
    digitalWrite(BOARD_LED_PIN, Rc_Signal_Pin_Level);
    if (WeillRead[1] && Rc_Signal_Pin_Level == HIGH)  //起始帧已经准备好,开始检测数据段和解析数据,并且信号引脚需要为高电平
    { //引脚为高电平的时候,其实已经表示获得了分别高低的各一次的信号,程序是在2,3或4,5之间做处理
      Rf_buf[INDEX_GROUP][INDEX_BUFFER] <<= 1;
      if (High_Level_Time >= Rc_Data_600us) Rf_buf[INDEX_GROUP][INDEX_BUFFER] += 1; //如果高电平持续时间大于数据帧定义的600us则表示为1 否则表示为0
      else Rf_buf[INDEX_GROUP][INDEX_BUFFER] += 0;
      RC_BIT++;      
      if (RC_BIT >= RC_BIT_LEN)
      {
        RC_BIT = 0;
        //Serial.println(Rf_buf[INDEX_GROUP][INDEX_BUFFER]);
        INDEX_BUFFER++;  //下一字节
        if (INDEX_BUFFER >= RC_DATA_LEN)
        { //数据接收结束准备下一帧的接收,清楚起始帧完成标记
          INDEX_BUFFER = 0;
          WeillRead[0] = false;
          WeillRead[1] = false;
          //校验数据是否接收正确
          crc=0;
          for(ei=1;ei<RC_DATA_LEN-1;ei++)//计算校验码
          {
            crc+=Rf_buf[INDEX_GROUP][ei];
          }
          if(crc==Rf_buf[INDEX_GROUP][ei] && 0x3A==Rf_buf[INDEX_GROUP][0])//匹配校验码
          {
            Rf_buf[INDEX_GROUP][ei+1]=1;
            RC_CMD=Rf_buf[INDEX_GROUP][6];
            if(RC_CMD!=36 && Old_RC_CMD != RC_CMD) //指令36表示按键松开
            {
              Old_RC_CMD = RC_CMD;
              if(RC_Cmp_ID(Rf_buf[INDEX_GROUP][2],Rf_buf[INDEX_GROUP][3]))  //比较遥控ID是否与本机匹配
              {
                SPEEK_MODE=1;
                Public_Key_Cmd=RC_CMD;  //返回共有按键值,让其他任务进行判断按键处理
                Serial.print("Key:");Serial.println(RC_CMD);
              }else{
                SPEEK_MODE=4;   //遥控器与本机不匹配,但收到信号(低鸣一声)
                //Serial.print("IDErr:");Serial.println(RC_CMD);
              }
            }else
            {     //按键松开处理
                Old_RC_CMD=0;
            }
            if(RC_CMD==0x55)//配对遥控器,将遥控器的ID写入本机
            {              
              RC_Write_ID(Rf_buf[INDEX_GROUP][2],Rf_buf[INDEX_GROUP][3]);
              SPEEK_MODE=2;   //嘀嘀两声
            }
          }
          else{  //如果当前接收帧校验不对,表示接收不正确
            INDEX_GROUP++;
            RC_BIT = 0;
            INDEX_BUFFER = 0;
            if(INDEX_GROUP>RC_GROUP_LEN-1)INDEX_GROUP=0;
          }
        }
      }
    }
  }
}

void setup() {

  pinMode(BOARD_LED_PIN, OUTPUT);
  pinMode(Speeker_Out, OUTPUT);
  Serial.begin(115200);
  uint16 Status = EEPROM.init();
  
  attachInterrupt(digitalPinToInterrupt(SensorINPUT), SensorInter, CHANGE); //RISING);  //创建中断
  attachInterrupt(digitalPinToInterrupt(RC_Switch_INPUT), RC_Switch_Inter, CHANGE); //FALLING);
  //创建线程
  xTaskCreate(vLEDFlashTask,
              "Task1",
              configMINIMAL_STACK_SIZE,
              NULL,
              tskIDLE_PRIORITY + 2,
              NULL);

  vTaskStartScheduler();
}

void loop() {
}

一点心得和结晶,希望对各位网友能够有帮助吧!
相应的连接:CSDN 网友的 Arduino - 315/433MHz RF无线收发模块
CSDN 网友的 STM32F103C8T6在Arduino IDE里编程
使用Arduino解码并发送433MHz RF无线射频信号

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值