AM32 电调学习--tenKhzRoutine()函数分析

AM32 电调学习–输入获取分析

#define INTERVAL_TIMER TIM2 ; 过零时间测量
psc=31
#define TEN_KHZ_TIMER TIM6 ;tenKhzRoutine frq=1M load=1M/20k
psc=63
#define UTILITY_TIMER TIM17
#define COM_TIMER TIM14 //PeriodElapsedCallback 过零后等待时间中断
psc=31
#define IC_TIMER_REGISTER TIM3
psc=0
PB4 tim3_chn1

一、使用到的变量

dma1chan1 interrupt transfercomplete:

  1. uint16_t signaltimeout = 0;
  2. out_put: 0:receiveDshotDma1:
    1:sendDshotDma
  3. char dshot_telemetry = 0; dshort检测到标志
processDshot(EXTI4_15_IRQHandler)<--DMA1_Channel1_IRQHandler
  1. ic_timer_prescaler char ic_timer_prescaler = CPU_FREQUENCY_MHZ / 5;
  2. output_timer_prescaler
        if (CPU_FREQUENCY_MHZ > 100) {
            output_timer_prescaler = 1;
        } else {
            output_timer_prescaler = 0;
        }

  1. char inputSet = 0; 输入方式是否已经决定标志

二、输入端口设置

  1. PB4设置为tim3 channel1.
  2. dma1 channel1 ,方向per(halfword)–>memory(word)
  3. 分频为0
  4. 双沿触发

三、开始处理

  1. 在main初始化中调用receiveDshotDma().
  2. 在dma中断中处理transfercomplete()
void transfercomplete()
{
    signaltimeout = 0;
    if (armed && dshot_telemetry) {
        if (out_put) {
            receiveDshotDma();
            compute_dshot_flag = 2;
            return;
        } else {
            sendDshotDma();
            compute_dshot_flag = 1;
            return;
        }
    }
    if (inputSet == 0) {
        detectInput();
        receiveDshotDma();
        return;
    }
    if (inputSet == 1) {

        if (dshot_telemetry) {
            if (out_put) {
                make_dshot_package(e_com_time);
                computeDshotDMA();
                receiveDshotDma();
                return;
            } else {
                sendDshotDma();
                return;
            }
        } else {

            if (dshot == 1) {
                computeDshotDMA();
                receiveDshotDma();
            }
            if (servoPwm == 1) {
                if (getInputPinState()) {
                    buffersize = 3;
                } else {
                    buffersize = 2;
                    computeServoInput();
                }
                receiveDshotDma();
            }
        }
        if (!armed) {
            if (dshot && (average_count < 8) && (zero_input_count > 5)) {
                average_count++;
                average_packet_length = average_packet_length + (dma_buffer[31] - dma_buffer[0]);
                if (average_count == 8) {
                    dshot_frametime_high = (average_packet_length >> 3) + (average_packet_length >> 7);
                    dshot_frametime_low = (average_packet_length >> 3) - (average_packet_length >> 7);
                }
            }
            if (adjusted_input < 0) {
                adjusted_input = 0;
            }
            if (adjusted_input == 0 && calibration_required == 0) { // note this in input..not newinput so it
                                                                    // will be adjusted be main loop
                zero_input_count++;
            } else {
                zero_input_count = 0;
                if (adjusted_input > 1500) {
                    if (getAbsDif(adjusted_input, last_input) > 50) {
                        enter_calibration_count = 0;
                    } else {
                        enter_calibration_count++;
                    }

                    if (enter_calibration_count > 50 && (!high_calibration_set)) {
                        playBeaconTune3();
                        calibration_required = 1;
                        enter_calibration_count = 0;
                    }
                    last_input = adjusted_input;
                }
            }
        }
    }
}

  1. 判定输入方式
    (A) PPM信号的最小间隔在150us–1500us之间
    (B) dshot600的最小间距在100ns-700ns
    dshot300的最小间隔城200-1400ns之间
void detectInput()
{
    smallestnumber = 20000;
    average_signal_pulse = 0;
    int lastnumber = dma_buffer[0];
    for (int j = 1; j < 31; j++) {
        if (dma_buffer[j] - lastnumber > 0) {
            if ((dma_buffer[j] - lastnumber) < smallestnumber) {
                smallestnumber = dma_buffer[j] - lastnumber;
            }
            average_signal_pulse += (dma_buffer[j] - lastnumber);
        }
        lastnumber = dma_buffer[j];
    }
    average_signal_pulse = average_signal_pulse / 32;

    if (dshot == 1) {
        checkDshot();
    }
    if (servoPwm == 1) {
        checkServo();
    }

    if (!dshot && !servoPwm) {
        checkDshot();
        checkServo();
    }
}

void checkServo()
{
    if (smallestnumber > 200 && smallestnumber < 20000) {
        servoPwm = 1;
        ic_timer_prescaler = CPU_FREQUENCY_MHZ - 1;
        buffersize = 2;
        inputSet = 1;
    }
}

void checkDshot()
{
    if ((smallestnumber > 1) && (smallestnumber <= 4) && (average_signal_pulse < 60)) {
        ic_timer_prescaler = 0;
        if (CPU_FREQUENCY_MHZ > 100) {
            output_timer_prescaler = 1;
        } else {
            output_timer_prescaler = 0;
        }
        //	dshot_runout_timer = 1000;
        dshot = 1;
        buffer_padding = 14;
        buffersize = 32;
        inputSet = 1;
    }
    if ((smallestnumber > 4) && (smallestnumber <= 8) && (average_signal_pulse < 100)) {
        dshot = 1;
        ic_timer_prescaler = 1;
        if (CPU_FREQUENCY_MHZ > 100) {
            output_timer_prescaler = 3;
        } else {
            output_timer_prescaler = 1;
        }
        buffer_padding = 7;
        buffersize = 32;
        inputSet = 1;
    }
}

四、dma的输入和输出

  1. 输入
void receiveDshotDma()
{
#ifdef USE_TIMER_3_CHANNEL_1
    RCC->APBRSTR1 |= LL_APB1_GRP1_PERIPH_TIM3;
    RCC->APBRSTR1 &= ~LL_APB1_GRP1_PERIPH_TIM3;
    IC_TIMER_REGISTER->CCMR1 = 0x61;  //fdts/4  N=6,  fdts 是clk_int/ckd[cr1]
    IC_TIMER_REGISTER->CCER = 0xa;   //cc1np cc1p =11,双沿触发  output disable
#endif
#ifdef USE_TIMER_16_CHANNEL_1
    LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM16); // de-init timer 2
    LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM16);
    IC_TIMER_REGISTER->CCMR1 = 0x61;
    IC_TIMER_REGISTER->CCER = 0xa;
#endif

    IC_TIMER_REGISTER->PSC = ic_timer_prescaler;
    IC_TIMER_REGISTER->ARR = 0xFFFF;
    IC_TIMER_REGISTER->EGR |= TIM_EGR_UG;
    out_put = 0;
    IC_TIMER_REGISTER->CNT = 0;
    DMA1_Channel1->CMAR = (uint32_t)&dma_buffer;
    DMA1_Channel1->CPAR = (uint32_t)&IC_TIMER_REGISTER->CCR1;
    DMA1_Channel1->CNDTR = buffersize;
    DMA1_Channel1->CCR = 0x98b;     //9:m-32b p-16b 8:  minc  接收   b: en/tc/te
    IC_TIMER_REGISTER->DIER |= TIM_DIER_CC1DE;    //dma int enable
    IC_TIMER_REGISTER->CCER |= IC_TIMER_CHANNEL;
    IC_TIMER_REGISTER->CR1 |= TIM_CR1_CEN;  //counter enable
}

  1. 输出:
void sendDshotDma()
{
#ifdef USE_TIMER_3_CHANNEL_1
    RCC->APBRSTR1 |= LL_APB1_GRP1_PERIPH_TIM3;
    RCC->APBRSTR1 &= ~LL_APB1_GRP1_PERIPH_TIM3;
    IC_TIMER_REGISTER->CCMR1 = 0x60;
    IC_TIMER_REGISTER->CCER = 0x3;  //output enable ,activate low
#endif
#ifdef USE_TIMER_16_CHANNEL_1
    LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM16); // de-init timer 2
    LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM16);
    IC_TIMER_REGISTER->CCMR1 = 0x60;
    IC_TIMER_REGISTER->CCER = 0x3;
#endif
    IC_TIMER_REGISTER->PSC = output_timer_prescaler;
    IC_TIMER_REGISTER->ARR = 92;
    out_put = 1;
    LL_TIM_GenerateEvent_UPDATE(IC_TIMER_REGISTER);

    DMA1_Channel1->CMAR = (uint32_t)&gcr;
    DMA1_Channel1->CPAR = (uint32_t)&IC_TIMER_REGISTER->CCR1;
    DMA1_Channel1->CNDTR = 23 + buffer_padding;
    DMA1_Channel1->CCR = 0x99b;   //9:m-32b p-16b 9:  minc 发送  b: en/tc/te
    IC_TIMER_REGISTER->DIER |= TIM_DIER_CC1DE;
    IC_TIMER_REGISTER->CCER |= IC_TIMER_CHANNEL;
    IC_TIMER_REGISTER->BDTR |= TIM_BDTR_MOE;  //输出enable
    IC_TIMER_REGISTER->CR1 |= TIM_CR1_CEN;
}

五、ppm解码

void computeServoInput()
{
    if (((dma_buffer[1] - dma_buffer[0]) > 800) && ((dma_buffer[1] - dma_buffer[0]) < 2200)) {

        if (calibration_required) {
            if (!high_calibration_set) {
                if (high_calibration_counts == 0) {
                    last_high_threshold = dma_buffer[1] - dma_buffer[0];
                }
                high_calibration_counts++;
                if (getAbsDif(last_high_threshold, servo_high_threshold) > 50) {
                    calibration_required = 0;
                } else {
                    servo_high_threshold = ((7 * servo_high_threshold + (dma_buffer[1] - dma_buffer[0])) >> 3);
                    if (high_calibration_counts > 50) {
                        servo_high_threshold = servo_high_threshold - 25;
                        eepromBuffer[33] = (servo_high_threshold - 1750) / 2;
                        high_calibration_set = 1;
                        playDefaultTone();
                    }
                }
                last_high_threshold = servo_high_threshold;
            }
            if (high_calibration_set) {
                if (dma_buffer[1] - dma_buffer[0] < 1250) {
                    low_calibration_counts++;
                    servo_low_threshold = ((7 * servo_low_threshold + (dma_buffer[1] - dma_buffer[0])) >> 3);
                }
                if (low_calibration_counts > 75) {
                    servo_low_threshold = servo_low_threshold + 25;
                    eepromBuffer[32] = (servo_low_threshold - 750) / 2;
                    calibration_required = 0;
                    saveEEpromSettings();
                    low_calibration_counts = 0;
                    playChangedTone();
                }
            }
            signaltimeout = 0;
        } else {
            if (bi_direction) {
                if (dma_buffer[1] - dma_buffer[0] <= servo_neutral) {
                    servorawinput = map((dma_buffer[1] - dma_buffer[0]),
                        servo_low_threshold, servo_neutral, 0, 1000);
                } else {
                    servorawinput = map((dma_buffer[1] - dma_buffer[0]), servo_neutral + 1,
                        servo_high_threshold, 1001, 2000);
                }
            } else {
                servorawinput = map((dma_buffer[1] - dma_buffer[0]), servo_low_threshold,
                    servo_high_threshold, 47, 2047);
                if (servorawinput <= 48) {
                    servorawinput = 0;
                }
            }
            signaltimeout = 0;
        }
    } else {
        zero_input_count = 0; // reset if out of range
    }

    if (servorawinput - newinput > max_servo_deviation) {
        newinput += max_servo_deviation;
    } else if (newinput - servorawinput > max_servo_deviation) {
        newinput -= max_servo_deviation;
    } else {
        newinput = servorawinput;
    }
}

六、dshot解码

void computeDshotDMA()
{
    int j = 0;
    dshot_frametime = dma_buffer[31] - dma_buffer[0];
    halfpulsetime = dshot_frametime >> 5;
    if ((dshot_frametime > dshot_frametime_low) && (dshot_frametime < dshot_frametime_high)) {
        for (int i = 0; i < 16; i++) {
            dpulse[i] = ((dma_buffer[j + (i << 1) + 1] - dma_buffer[j + (i << 1)]) > (halfpulsetime));
        }
        uint8_t calcCRC = ((dpulse[0] ^ dpulse[4] ^ dpulse[8]) << 3 | (dpulse[1] ^ dpulse[5] ^ dpulse[9]) << 2 | (dpulse[2] ^ dpulse[6] ^ dpulse[10]) << 1 | (dpulse[3] ^ dpulse[7] ^ dpulse[11]));
        uint8_t checkCRC = (dpulse[12] << 3 | dpulse[13] << 2 | dpulse[14] << 1 | dpulse[15]);

        if (!armed) {
            if (dshot_telemetry == 0) {
                if (getInputPinState()) { // if the pin is high for 100 checks between
                                          // signal pulses its inverted
                    high_pin_count++;
                    if (high_pin_count > 100) {
                        dshot_telemetry = 1;
                    }
                }
            }
        }
        if (dshot_telemetry) {
            checkCRC = ~checkCRC + 16;
        }

        int tocheck = (dpulse[0] << 10 | dpulse[1] << 9 | dpulse[2] << 8 | dpulse[3] << 7 | dpulse[4] << 6 | dpulse[5] << 5 | dpulse[6] << 4 | dpulse[7] << 3 | dpulse[8] << 2 | dpulse[9] << 1 | dpulse[10]);

        if (calcCRC == checkCRC) {
            signaltimeout = 0;
            dshot_goodcounts++;
            if (dpulse[11] == 1) {
                send_telemetry = 1;
            }
            if (tocheck > 47) {
                if (EDT_ARMED) {
                    newinput = tocheck;
                    dshotcommand = 0;
                    command_count = 0;
                    return;
                }
            }

            if ((tocheck <= 47) && (tocheck > 0)) {
                newinput = 0;
                dshotcommand = tocheck; //  todo
            }
            if (tocheck == 0) {
                if (EDT_ARM_ENABLE == 1) {
                    EDT_ARMED = 0;
                }
                newinput = 0;
                dshotcommand = 0;
                command_count = 0;
            }

            if ((dshotcommand > 0) && (running == 0) && armed) {
                if (dshotcommand != last_command) {
                    last_command = dshotcommand;
                    command_count = 0;
                }
                if (dshotcommand < 5) { // beacons
                    command_count = 6; // go on right away
                }
                command_count++;
                if (command_count >= 6) {
                    command_count = 0;
                    switch (dshotcommand) { // todo

                    case 1:
                        play_tone_flag = 1;
                        break;
                    case 2:
                        play_tone_flag = 2;
                        break;
                    case 3:
                        play_tone_flag = 3;
                        break;
                    case 4:
                        play_tone_flag = 4;
                        break;
                    case 5:
                        play_tone_flag = 5;
                        break;
                    case 7:
                        dir_reversed = 0;
                        forward = 1 - dir_reversed;
                        //	play_tone_flag = 1;
                        break;
                    case 8:
                        dir_reversed = 1;
                        forward = 1 - dir_reversed;
                        //	play_tone_flag = 2;
                        break;
                    case 9:
                        bi_direction = 0;
                        break;
                    case 10:
                        bi_direction = 1;
                        break;
                    case 12:
                        saveEEpromSettings();
                        play_tone_flag = 1 + dir_reversed;
                        //	NVIC_SystemReset();
                        break;
                    case 13:
                        dshot_extended_telemetry = 1;
                        send_extended_dshot = 0b111000000000;
                        if (EDT_ARM_ENABLE == 1) {
                            EDT_ARMED = 1;
                        }
                        break;
                    case 14:
                        dshot_extended_telemetry = 0;
                        send_extended_dshot = 0b111011111111;
                        //	make_dshot_package();
                        break;
                    case 20:
                        forward = 1 - dir_reversed;
                        break;
                    case 21:
                        forward = dir_reversed;
                        break;
                    }
                    last_dshot_command = dshotcommand;
                    dshotcommand = 0;
                }
            }
        } else {
            dshot_badcounts++;
        }
    }
}

stm32定时器学习

  1. 定时器复位
     RCC->APBRSTR1 |= LL_APB1_GRP1_PERIPH_TIM3;
    RCC->APBRSTR1 &= ~LL_APB1_GRP1_PERIPH_TIM3;

  1. ppm 信号,每个脉宽是0.5ms (15us — 1500us)
    在这里插入图片描述
  2. dshot信号
    在这里插入图片描述
    dshot600: frq: 600k 周期: 1s/600k = 1667ns T0h=625ns T1h=1250ns
    dshot100: 1s/100k=10000ns
    dshot300: 1s/300k = 3300ns
    dshot1200: 1s/1200k = 832ns
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值