Lu Blog

Segment fault!

STM32F042使用HAL库DMA TIM实现Dshot600协议

什么是DShot

DShot是无人机控制器和ESC之间新的通信协议,可以替代Oneshot和Multishot。DShot全称为Digital Shot。

DShot的优势

与Oneshot和Multishot相比,DShot更好,因为:
无需校准ESC(无振荡器漂移)
更准确的ESC信号,更强大的抗电噪声,有2048 steps的高分辨率
比Oneshot更快,更安全,每个信号ESC都可以校验是否正确

DShot速率

DShot600 - 600,000 bits/秒
DShot300 - 300,000 bits/秒
DShot150 - 150,000 bits/秒

Dshot_logo.png
DShot数据包由总共16位组成:油门值11位(2048步),遥测请求1位,CRC校验和4位(循环冗余校验)。发送一组数据大约需要26.7us。
QQ截图20190212045642.png
DShot600一个周期为:1/600 ≈ 1667ns
某位为0的时候,脉冲宽度为625ns(T0H - 当位值为0时,脉冲为高电平的时间)
某位为1的时候,脉冲宽度为1250ns(T1H - 当位值为1时,脉冲为高电平的时间)

我这里使用STM32F042,APB1时钟频率为48MHz

#define ESC_BIT_0     30
#define ESC_BIT_1     60

static uint32_t esc_cmd[ESC_CMD_BUFFER_LEN]={0};

uint16_t add_checksum_and_telemetry(uint16_t packet, uint16_t telem)
{
  uint16_t packet_telemetry = (packet << 1) | (telem & 1);
  uint16_t csum = 0;
  uint16_t csum_data = packet_telemetry;

  uint8_t i;
  for (i = 0; i < 3; i++) {
    csum ^=  csum_data;   // xor data by nibbles
    csum_data >>= 4;
  }
  csum &= 0xf;
  return (packet_telemetry << 4) | csum;    //append checksum
}
void pwmWriteDigital(uint16_t value)
{
  value = ( (value > 2047) ? 2047 : value );
  value = add_checksum_and_telemetry(value, 0);
  esc_cmd[0]  = (value & 0x8000) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[1]  = (value & 0x4000) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[2]  = (value & 0x2000) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[3]  = (value & 0x1000) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[4]  = (value & 0x0800) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[5]  = (value & 0x0400) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[6]  = (value & 0x0200) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[7]  = (value & 0x0100) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[8]  = (value & 0x0080) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[9]  = (value & 0x0040) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[10] = (value & 0x0020) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[11] = (value & 0x0010) ? ESC_BIT_1 : ESC_BIT_0;     
  esc_cmd[12] = (value & 0x8) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[13] = (value & 0x4) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[14] = (value & 0x2) ? ESC_BIT_1 : ESC_BIT_0;
  esc_cmd[15] = (value & 0x1) ? ESC_BIT_1 : ESC_BIT_0;
}

评论卡