refactor: use dc-motor driver as low level layer

This commit is contained in:
zys 2026-03-20 21:02:04 +08:00
parent 9de7db11f6
commit ab818974f3
3 changed files with 100 additions and 80 deletions

View File

@ -1,25 +1,21 @@
/ { / {
zephyr,user { dc_motor: dc-motor0 {
in3-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
in4-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
enb-gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
};
};
&uart0 {
status = "okay"; status = "okay";
protocal: uart-com-protocal { compatible = "st,l298n";
compatible = "uart-com-protocal"; freq-hz = <1000>;
in1-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
in2-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
en-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
};
aliases {
modbus-server-pc = &modbus_pc;
};
};
&uart1 {
status = "okay";
current-speed = <115200>;
modbus_pc: modbus-server0 {
status = "okay"; status = "okay";
header = <0x7e 0xe7>;
crc16 = "none";
freq{
id = <0x00>;
};
switch{
id = <0x01>;
};
status{
id = <0x02>;
};
}; };
}; };

View File

@ -7,4 +7,6 @@ CONFIG_CONSOLE=y
CONFIG_SERIAL=y CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_MODBUS=y
CONFIG_MODBUS_ROLE_SERVER=y
CONFIG_LOG=y CONFIG_LOG=y

View File

@ -1,74 +1,96 @@
#include <uart_com/protocal.hpp> #include <dc_motor/motor.hpp>
#include <zephyr/drivers/gpio.h>
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/modbus/modbus.h>
namespace { namespace {
enum Cmd {
kFreq = 0x00, class ModbusServer {
kSwitch = 0x01,
kStatus = 0x02,
};
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
const gpio_dt_spec in3 = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, in3_gpios);
const gpio_dt_spec in4 = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, in4_gpios);
const gpio_dt_spec enb = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, enb_gpios);
volatile uint8_t duty_cycle_event{50};
volatile bool is_enable{false};
class Motor {
public: public:
Motor() { struct Addr {
gpio_pin_configure_dt(&in3, GPIO_OUTPUT_INACTIVE); enum Coil : uint16_t { MOTOR_RUNNING = 0 };
gpio_pin_configure_dt(&in4, GPIO_OUTPUT_INACTIVE); enum Reg : uint16_t {
gpio_pin_configure_dt(&enb, GPIO_OUTPUT_INACTIVE); SPEED = 0,
}
auto Rotate() -> void {
gpio_pin_set_dt(&in3, 1);
gpio_pin_set_dt(&in4, 0);
}; };
auto Reverse() {
gpio_pin_set_dt(&in3, 0);
gpio_pin_set_dt(&in4, 1);
}; };
auto Stop() { ModbusServer() {
gpio_pin_set_dt(&in3, 0); m_iface =
gpio_pin_set_dt(&in4, 0); modbus_iface_get_by_name(DEVICE_DT_NAME(DT_ALIAS(modbus_server_pc)));
} modbus_init_server(m_iface, m_param);
};
Motor motor{};
} // namespace
auto main(void) -> int {
auto &protocal = ZPP_DRV_GET(uart_com::Protocal, DT_NODELABEL(protocal));
protocal.SetRxCallback(kSwitch, [](uart_com::DataType data) {
if (data[0] == 0) {
motor.Stop();
} else {
motor.Rotate();
} }
printk("set switch: %d\n", data[0]); private:
is_enable = data[0]; static auto CoilWr(uint16_t addr, bool state) -> int {
}); switch (addr) {
protocal.SetRxCallback(kFreq, [](uart_com::DataType data) { case Addr::Coil::MOTOR_RUNNING: {
printk("set freq: %d\n", data[0]); if (0 == state) {
m_motor.SetSpeed(0);
uint8_t freq = 0; }
if (data[0] == 100) { return 0;
freq = 100; }
} default:
freq = data[0]; return -EINVAL;
duty_cycle_event = freq; }
}); }
static auto CoilRd(uint16_t addr, bool *state) -> int {
while (1) { switch (addr) {
if (is_enable) { case Addr::Coil::MOTOR_RUNNING: {
printk("duty circle %d\n", duty_cycle_event); const auto s = m_motor.GetState();
gpio_pin_set_dt(&enb, 1); *state = (s == driver::DcMotorState::RUNNING);
k_sleep(K_MSEC(duty_cycle_event)); return 0;
gpio_pin_set_dt(&enb, 0); }
k_sleep(K_MSEC(100 - duty_cycle_event)); default:
} return -EINVAL;
}
}
static auto RegWr(uint16_t addr, uint16_t reg) -> int {
switch (addr) {
case Addr::Reg::SPEED: {
m_current_speed = reg;
return int(m_motor.SetSpeed(reg).code_id());
}
default:
return -EINVAL;
}
}
static auto RedRd(uint16_t addr, uint16_t *reg) -> int {
switch (addr) {
case Addr::Reg::SPEED:
*reg = m_current_speed;
return 0;
default:
return -EINVAL;
}
}
inline static modbus_user_callbacks m_cbs = {.coil_rd = CoilRd,
.coil_wr = CoilWr,
.holding_reg_rd = RedRd,
.holding_reg_wr = RegWr};
inline static modbus_iface_param m_param = {
.mode = MODBUS_MODE_RTU,
.server =
{
.user_cb = &m_cbs,
.unit_id = 1,
},
.serial =
{
.baud =
DT_PROP(DT_PARENT(DT_ALIAS(modbus_server_pc)), current_speed),
.parity = UART_CFG_PARITY_NONE,
},
};
inline static int m_iface;
inline static int m_current_speed{0};
inline static auto &m_motor =
ZPP_DRV_GET(driver::DcMotor, DT_NODELABEL(dc_motor));
};
} // namespace
auto main(void) -> int {
ModbusServer server{};
while (1) {
} }
return 0; return 0;
} }