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}