元驭机器人元驭机器人Hall 传感器教学下载原文件
1/*!2    \file    main.c3    \brief   三路霍尔角度或直线位置,RTT 调试,RS485 对外通信45    角度模式每 50 ms 打一行:6      adc <U1> <U2> <U4> ang <度.百分度> amp <峰值>7    直线模式打:8      adc <U1> <U2> <U4> pos <毫米.百分毫米> mm amp <峰值>9    amp 太小会额外带 weak。直线位置超出阵列两端时带 out。10    PB4 驱动状态灯,低电平点亮,约 500 ms 翻转一次。11    PB5 是 RS485 方向,上电先拉低,随后由协议模块控制。12*/1314#include "gd32e23x.h"15#include "systick.h"16#include "hall_encoder.h"17#include "hall_line.h"18#include "rs485_proto.h"19#include "SEGGER_RTT.h"2021/*!22    \brief      状态灯和 RS485 方向脚23    \param[in]  none24    \param[out] none25    \retval     none26*/27static void board_gpio_init(void)28{29    rcu_periph_clock_enable(RCU_GPIOB);3031    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5);32    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN_4 | GPIO_PIN_5);33    gpio_bit_set(GPIOB, GPIO_PIN_4);34    /*! 收发器默认接收。rs485_proto_init 会再次配置这只脚。 */35    gpio_bit_reset(GPIOB, GPIO_PIN_5);36}3738/*!39    \brief      把一帧霍尔结果打到 RTT40    \param[in]  sample: 原码和角度41    \param[out] none42    \retval     none43*/44static void hall_rtt_print(const hall_sample_t *sample)45{46    int32_t whole = sample->angle_cdeg / 100;47    int32_t frac = sample->angle_cdeg % 100;4849    if(sample->amplitude < HALL_AMP_WEAK) {50        SEGGER_RTT_printf(0, "adc %u %u %u ang %d.%02d amp %d weak\r\n",51                          (unsigned)sample->raw[0], (unsigned)sample->raw[1], (unsigned)sample->raw[2],52                          (int)whole, (int)frac, (int)sample->amplitude);53    } else {54        SEGGER_RTT_printf(0, "adc %u %u %u ang %d.%02d amp %d\r\n",55                          (unsigned)sample->raw[0], (unsigned)sample->raw[1], (unsigned)sample->raw[2],56                          (int)whole, (int)frac, (int)sample->amplitude);57    }58}5960/*!61    \brief      把直线位置打到 RTT,负数的小数部分取绝对值62    \param[in]  sample: 位置在 angle_cdeg,单位 0.01 mm63    \retval     none64*/65static void hall_rtt_print_pos(const hall_sample_t *sample)66{67    int32_t value = sample->angle_cdeg;68    int32_t whole;69    int32_t frac;70    uint8_t flags = hall_line_flags(sample);71    const char *sign = "";72    const char *note = "";7374    if(value < 0) {75        sign = "-";76        value = -value;77    }78    whole = value / 100;79    frac = value % 100;80    if((0U != (flags & HALL_FLAG_WEAK)) && (0U != (flags & HALL_FLAG_OUT))) {81        note = " weak out";82    } else if(0U != (flags & HALL_FLAG_WEAK)) {83        note = " weak";84    } else if(0U != (flags & HALL_FLAG_OUT)) {85        note = " out";86    }87    SEGGER_RTT_printf(0, "adc %u %u %u pos %s%d.%02d mm amp %d%s\r\n",88                      (unsigned)sample->raw[0], (unsigned)sample->raw[1], (unsigned)sample->raw[2],89                      sign, (int)whole, (int)frac, (int)sample->amplitude, note);90}9192/*!93    \brief      应用入口94    \param[in]  none95    \param[out] none96    \retval     不返回97*/98int main(void)99{100    hall_sample_t sample;101    uint32_t rtt_ms = 0U;102    uint32_t led_ms = 0U;103104    systick_config();105    SEGGER_RTT_Init();106    SEGGER_RTT_printf(0, "hall U1 U2 U4\r\n");107    board_gpio_init();108    hall_encoder_init();109    rs485_proto_init();110    SEGGER_RTT_printf(0, "rs485 id %u baud %u mode %u type %u\r\n",111                      (unsigned)rs485_proto_id(),112                      (unsigned)rs485_proto_baud(),113                      (unsigned)rs485_proto_mode(),114                      (unsigned)rs485_proto_type());115116    while(1) {117        uint32_t now = systick_get_ms();118        uint8_t linear = (RS485_TYPE_HALL_POSITION == rs485_proto_type()) ? 1U : 0U;119120        /*! 主循环持续采样。角度模式记峰峰值,直线模式记零磁场平均。 */121        if(0U != linear) {122            hall_line_read(&sample);123        } else {124            hall_encoder_read(&sample);125        }126        rs485_proto_poll();127128        if((now - rtt_ms) >= 50U) {129            rtt_ms = now;130            if(0U != linear) {131                hall_rtt_print_pos(&sample);132            } else {133                hall_rtt_print(&sample);134            }135        }136        if((now - led_ms) >= 500U) {137            led_ms = now;138            gpio_bit_toggle(GPIOB, GPIO_PIN_4);139        }140    }141}