drv_rs485.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-07-22 kurisaw first version
  9. */
  10. #include <rtdevice.h>
  11. #include <hal_data.h>
  12. #include "drv_rs485.h"
  13. #define DBG_TAG "drv.rs485"
  14. #define DBG_LVL DBG_LOG
  15. #include <rtdbg.h>
  16. #ifdef BSP_USING_RS485
  17. #define RS485_OUT rt_pin_write((rt_base_t)RS485_DE_PIN, PIN_HIGH)
  18. #define RS485_IN rt_pin_write((rt_base_t)RS485_DE_PIN, PIN_LOW)
  19. static rt_device_t rs485_serial = RT_NULL;
  20. static struct rt_semaphore rs485_rx_sem;
  21. static struct rt_ringbuffer rs485_rx_rb;
  22. static rt_uint8_t rs485_rx_buffer[RS485_RX_BUFFER_SIZE];
  23. /* uart receive data callback function */
  24. static rt_err_t rs485_input(rt_device_t dev, rt_size_t size)
  25. {
  26. if (size > 0)
  27. {
  28. rt_uint8_t ch;
  29. while (rt_device_read(dev, 0, &ch, 1) == 1)
  30. {
  31. rt_ringbuffer_put_force(&rs485_rx_rb, &ch, 1);
  32. }
  33. rt_sem_release(&rs485_rx_sem);
  34. }
  35. return RT_EOK;
  36. }
  37. /* send data */
  38. int rs485_send_data(const void *tbuf, rt_uint16_t t_len)
  39. {
  40. RT_ASSERT(tbuf != RT_NULL);
  41. /* change rs485 mode to transmit */
  42. RS485_OUT;
  43. /* send data */
  44. rt_size_t sent = rt_device_write(rs485_serial, 0, tbuf, t_len);
  45. if (sent != t_len)
  46. {
  47. /* Transmission failed, switch back to receive mode */
  48. RS485_IN;
  49. return -RT_ERROR;
  50. }
  51. /* Note: We don't switch back to receive mode here -
  52. that will be done in the tx_complete callback (rs485_output) */
  53. LOG_I("send==>>");
  54. for (int i = 0; i < t_len; i++)
  55. {
  56. LOG_I(" %d: %c ", i, ((rt_uint8_t *)tbuf)[i]);
  57. }
  58. RS485_IN;
  59. return RT_EOK;
  60. }
  61. #ifndef BSP_USING_LED_MATRIX_RS485_DEMO
  62. static void rs485_thread_entry(void *parameter)
  63. {
  64. rt_uint8_t ch;
  65. rt_size_t length;
  66. while (1)
  67. {
  68. /* Wait for data */
  69. rt_sem_take(&rs485_rx_sem, RT_WAITING_FOREVER);
  70. /* Process all available data in the ring buffer */
  71. while (length = rt_ringbuffer_get(&rs485_rx_rb, &ch, 1))
  72. {
  73. if (length == 1)
  74. {
  75. LOG_I("recv data:%c", ch);
  76. }
  77. }
  78. }
  79. }
  80. #endif
  81. /* rs485 rts pin init */
  82. int rs485_init(void)
  83. {
  84. /* Initialize ring buffer */
  85. rt_ringbuffer_init(&rs485_rx_rb, rs485_rx_buffer, RS485_RX_BUFFER_SIZE);
  86. /* find uart device */
  87. rs485_serial = rt_device_find(RS485_UART_DEVICE_NAME);
  88. if (!rs485_serial)
  89. {
  90. LOG_E("find %s failed!", RS485_UART_DEVICE_NAME);
  91. return -RT_ERROR;
  92. }
  93. /* Open device in interrupt mode with DMA support if available */
  94. rt_device_open(rs485_serial, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_RX);
  95. /* set receive data callback function */
  96. rt_device_set_rx_indicate(rs485_serial, rs485_input);
  97. /* Initialize RTS pin */
  98. rt_pin_mode((rt_base_t)RS485_DE_PIN, PIN_MODE_OUTPUT);
  99. RS485_IN;
  100. /* Initialize semaphore */
  101. rt_sem_init(&rs485_rx_sem, "rs485_rx_sem", 0, RT_IPC_FLAG_FIFO);
  102. rt_thread_t thread = rt_thread_create("rs485", rs485_thread_entry, RT_NULL,
  103. 1024, 25, 10);
  104. if (thread != RT_NULL)
  105. {
  106. rt_thread_startup(thread);
  107. }
  108. else
  109. {
  110. return -RT_ERROR;
  111. }
  112. return RT_EOK;
  113. }
  114. INIT_DEVICE_EXPORT(rs485_init);
  115. void rs485_cmd(int argc, char **argv)
  116. {
  117. if (argc == 1)
  118. {
  119. LOG_I("Usage:");
  120. LOG_I("rs485_cmd -t <message> -- send message via RS485");
  121. }
  122. else if (argc == 3 && rt_strcmp(argv[1], "-t") == 0)
  123. {
  124. char *str = argv[2];
  125. rs485_send_data(str, rt_strnlen(str, 32));
  126. }
  127. return;
  128. }
  129. MSH_CMD_EXPORT(rs485_cmd, rs485 transmission cmd);
  130. #endif /* BSP_USING_RS485 */