ESP32S3模拟输出Sbus协议

前提资料:

  1. Futaba S-BUS controlled by mbed | Mbed

  2. 一文看懂Sbus协议 | CSDN

必须看啊,不看不懂

源代码:

这段代码可以实现在地面站上前四个通道按一定顺序变化的效果,但不能直接封装为库进行调用

只是为了了解如何调用,不想了解具体实现过程,那就别看代码了,往下看调用说明

//常量定义区域
#define Bytecount 25
#define ChanneldataCount 11
#define DATA_SIZE 8  // 8 bytes is lower than the default 120 bytes of RX FIFO FULL
#define BAUD 100000  // Any baudrate from 300 to 100 000
#define RXPIN 4      // No mean
#define TXPIN 12     // GPIO 12 => TX for Serial1
#define ChannelFlagcount 5
#define ChannelflagPlustwo 4
#define ChannelflagPlusone 3
#define Channelflagzero 2
#define ChannelflagMinusone 1
#define ChannelflagMinustwo 0

struct Channel_defaultData {
  int Minimum;
  int Maximum;
  int Median;
  int Finetuning_Value;
};
struct Channel_flagVariables {
  int one;
  int two;
};
//各通道的默认值常量,放在这里方便查找(需要通过接收机实际测量得到数据)
//分别对应 1260  1502  1760
Channel_defaultData chan1dd = { 608, 1408, 996, 0 };  //横滚
Channel_defaultData chan2dd = { 608, 1408, 996, 0 };  //俯仰
Channel_defaultData chan3dd = { 608, 1408, 996, 0 };  //油门
Channel_defaultData chan4dd = { 608, 1408, 996, 0 };  //方向
//定义各通道在各个标志值时的通道数据变化常量(根据对速度的要求自行更改,值越大越快)
Channel_flagVariables chan1fv = { 200, 500 };
Channel_flagVariables chan2fv = { 200, 500 };
Channel_flagVariables chan3fv = { 200, 500 };
Channel_flagVariables chan4fv = { 200, 500 };

//全局变量定义区域
uint8_t Send_data[Bytecount];
int chan1data[ChannelFlagcount], chan2data[ChannelFlagcount];
int chan3data[ChannelFlagcount], chan4data[ChannelFlagcount];

//全局函数声明区域
void Allinit();
void SetChannel_1();
void ChanneldataInit();
void ChanneldataApply();
void Finetuning_changeValue();
int Equate_2(int);
void SetChannel_1(int);
void SetChannel_2(int);
void SetChannel_3(int);
void SetChannel_4(int);

void setup() {
  Allinit();
}

void loop() {
  static unsigned long preview = millis(), preview2 = millis();
  if (millis() - preview >= 14) {
    preview = millis();
    size_t sentBytes = Serial1.write(Send_data, sizeof(Send_data));
    sentBytes = sentBytes;
  }
  static int i = 0;
  if (millis() - preview2 >= 2000) {
    preview2 = millis();
    SetChannel_1(i);
    SetChannel_2(i);
    SetChannel_3(i);
    SetChannel_4(i);
    i++;
    if (i == 5) {
      i = 0;
    }
  }
}

/*********************************************************************
@name        :void Allinit(void)
@function    :开机启动时初始化程序都放在这里
@parameters  :none
@retvalue    :none
----------------------------------------------------------------------*/
void Allinit() {
  Serial.begin(115200);
  Serial1.begin(BAUD, SERIAL_8E2, RXPIN, TXPIN);
  //初始化数据
  for (int i = 0; i < Bytecount; i++) {
    Send_data[i] = 200;
  }
  Send_data[0] = 15;  //0x0F  Sbus协议为高位先行,发送结果为0xF0
  Send_data[23] = 0;  //flag标志位
  Send_data[24] = 0;  //0x00

  ChanneldataInit();
}

/*********************************************************************
@name        :void ChanneldataInit()
@function    :通道数据初始化
@parameters  :none
@retvalue    :none
----------------------------------------------------------------------*/
void ChanneldataInit() {
  ChanneldataApply(&chan1dd, &chan1fv, chan1data);
  ChanneldataApply(&chan2dd, &chan2fv, chan2data);
  ChanneldataApply(&chan3dd, &chan3fv, chan3data);
  ChanneldataApply(&chan4dd, &chan4fv, chan4data);
}

/*********************************************************************
@name        :void ChanneldataApply(struct, struct, int)
@function    :通道数据应用
@parameters  :Channel_defaultData *chanXdd | Channel_flagVariables *chanXfv | int chanXdata[]
@retvalue    :none
----------------------------------------------------------------------*/
void ChanneldataApply(struct Channel_defaultData *chanXdd, struct Channel_flagVariables *chanXfv, int chanXdata[]) {
  chanXdata[ChannelflagMinustwo] = chanXdd->Median - chanXfv->two + chanXdd->Finetuning_Value;
  chanXdata[ChannelflagMinusone] = chanXdd->Median - chanXfv->one + chanXdd->Finetuning_Value;
  chanXdata[Channelflagzero] = chanXdd->Median + chanXdd->Finetuning_Value;
  chanXdata[ChannelflagPlusone] = chanXdd->Median + chanXfv->one + chanXdd->Finetuning_Value;
  chanXdata[ChannelflagPlustwo] = chanXdd->Median + chanXfv->two + chanXdd->Finetuning_Value;
}

/*********************************************************************
@name        :void Finetuning_changeValue()
@function    :改变微调值并重新进行通道数据初始化
@parameters  :Channel_defaultData *chanXdd | int value
@retvalue    :none
----------------------------------------------------------------------*/
void Finetuning_changeValue(struct Channel_defaultData *chanXdd, int value) {
  chanXdd->Finetuning_Value = value;
  ChanneldataInit();
}

/*********************************************************************
@name        :void SetChannel_1(int channelflag_) 
@function    :设置通道一【横滚】的具体数值(通过标志位)
@parameters  :int channelflag_ 0~4
@retvalue    :none
-----------------------------------------------------------------------*/
void SetChannel_1(int channelflag_) {
  int temp = chan1data[channelflag_];
  int binaryarry[ChanneldataCount] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  for (int i = 0; temp > 0; i++) {
    binaryarry[i] = temp % 2;
    temp /= 2;
  }

  uint8_t tempdata = 0;
  for (int i = 0; i < 8; i++) {
    tempdata += (Equate_2(i) * binaryarry[i]);
  }
  Send_data[1] = tempdata;

  tempdata = 0;
  for (int i = 8; i < 11; i++) {
    tempdata += (Equate_2(i - 8) * binaryarry[i]);
  }
  Send_data[2] |= tempdata;  //赋1 必须得 或1
  tempdata |= 0xF8;
  Send_data[2] &= tempdata;  //赋0 必须得 和0
}
/*********************************************************************
@name        :void SetChannel_2(int channelflag_) 
@function    :设置通道二【俯仰】的具体数值(通过标志位)
@parameters  :int channelflag_ 0~4
@retvalue    :none
-----------------------------------------------------------------------*/
void SetChannel_2(int channelflag_) {
  int temp = chan2data[channelflag_];
  int binaryarry[ChanneldataCount] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  for (int i = 0; temp > 0; i++) {
    binaryarry[i] = temp % 2;
    temp /= 2;
  }

  uint8_t tempdata = 0;
  for (int i = 0; i < 5; i++) {
    tempdata += (Equate_2(i + 3) * binaryarry[i]);
  }
  Send_data[2] |= tempdata;  //赋1 必须得 或1
  tempdata |= 0x07;
  Send_data[2] &= tempdata;  //赋0 必须得 和0

  tempdata = 0;
  for (int i = 5; i < 11; i++) {
    tempdata += (Equate_2(i - 5) * binaryarry[i]);
  }
  Send_data[3] |= tempdata;  //赋1 必须得 或1
  tempdata |= 0xC0;
  Send_data[3] &= tempdata;  //赋0 必须得 和0
}
/*********************************************************************
@name        :void SetChannel_3(int channelflag_) 
@function    :设置通道三【油门】的具体数值(通过标志位)
@parameters  :int channelflag_ 0~4
@retvalue    :none
-----------------------------------------------------------------------*/
void SetChannel_3(int channelflag_) {
  int temp = chan3data[channelflag_];
  int binaryarry[ChanneldataCount] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  for (int i = 0; temp > 0; i++) {
    binaryarry[i] = temp % 2;
    temp /= 2;
  }

  uint8_t tempdata = 0;
  for (int i = 0; i < 2; i++) {
    tempdata += (Equate_2(i + 6) * binaryarry[i]);
  }
  Send_data[3] |= tempdata;  //赋1 必须得 或1
  tempdata |= 0x3F;
  Send_data[3] &= tempdata;  //赋0 必须得 和0

  tempdata = 0;
  for (int i = 2; i < 10; i++) {
    tempdata += (Equate_2(i - 2) * binaryarry[i]);
  }
  Send_data[4] = tempdata;

  tempdata = 0;
  for (int i = 10; i < 11; i++) {
    tempdata += (Equate_2(i - 10) * binaryarry[i]);
  }
  Send_data[5] |= tempdata;  //赋1 必须得 或1
  tempdata |= 0xFE;
  Send_data[5] &= tempdata;  //赋0 必须得 和0
}
/*********************************************************************
@name        :void SetChannel_4(int channelflag_) 
@function    :设置通道四的【方向】具体数值(通过标志位)
@parameters  :int channelflag_ 0~4
@retvalue    :none
-----------------------------------------------------------------------*/
void SetChannel_4(int channelflag_) {
  int temp = chan4data[channelflag_];
  int binaryarry[ChanneldataCount] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  for (int i = 0; temp > 0; i++) {
    binaryarry[i] = temp % 2;
    temp /= 2;
  }

  uint8_t tempdata = 0;
  for (int i = 0; i < 7; i++) {
    tempdata += (Equate_2(i + 1) * binaryarry[i]);
  }
  Send_data[5] |= tempdata;  //赋1 必须得 或1
  tempdata |= 0x01;
  Send_data[5] &= tempdata;  //赋0 必须得 和0

  tempdata = 0;
  for (int i = 7; i < 11; i++) {
    tempdata += (Equate_2(i - 7) * binaryarry[i]);
  }
  Send_data[6] = tempdata;
}
/*********************************************************************
@name        :int Equate_2(int count)
@function    :计算2的count次方并返回
@parameters  :int count
@retvalue    :int
-----------------------------------------------------------------------*/
int Equate_2(int count) {
  int temp = 1;
  for (int i = 0; i < count; i++) {
    temp *= 2;
  }
  return temp;
}

调用说明:

  1. /***********

@name :void Allinit(void)

@function :开机启动时初始化程序都放在这里

@parameters :none

@retvalue :none

----------------------------------------------------------------------*/

  1. /***********

@name :void Finetuning_changeValue(struct Channel_defaultData *chanXdd, int value)

@function :改变微调值并重新进行通道数据初始化

@parameters :Channel_defaultData *chanXdd | int value

@retvalue :none

----------------------------------------------------------------------*/

以下函数参数channelflag_说明:

0 —— 比中值小两级

1 —— 比中值小一级

2 —— 等于

3 —— 比中值大一级

4 —— 比中值大两级

  1. /***********

@name :void SetChannel_1(int channelflag_)

@function :设置通道一【横滚】的具体数值(通过标志位)

@parameters :int channelflag_ 0~4

@retvalue :none

-----------------------------------------------------------------------*/

  1. /***********

@name :void SetChannel_2(int channelflag_)

@function :设置通道二【俯仰】的具体数值(通过标志位)

@parameters :int channelflag_ 0~4

@retvalue :none

-----------------------------------------------------------------------*/

  1. /***********

@name :void SetChannel_3(int channelflag_)

@function :设置通道三【油门】的具体数值(通过标志位)

@parameters :int channelflag_ 0~4

@retvalue :none

-----------------------------------------------------------------------*/

  1. /***********

@name :void SetChannel_4(int channelflag_)

@function :设置通道四的【方向】具体数值(通过标志位)

@parameters :int channelflag_ 0~4

@retvalue :none

-----------------------------------------------------------------------*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幻酌

爸爸真帅!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值