rs485_demo.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /**
  2. @file
  3. rs485_demo.c
  4. @brief
  5. quectel rs485_demo.
  6. */
  7. /*================================================================
  8. Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  9. Quectel Wireless Solution Proprietary and Confidential.
  10. =================================================================*/
  11. /*=================================================================
  12. EDIT HISTORY FOR MODULE
  13. This section contains comments describing changes made to the module.
  14. Notice that changes are listed in reverse chronological order.
  15. WHEN WHO WHAT, WHERE, WHY
  16. ------------ ------- -------------------------------------------------------------------------------
  17. 07/06/2021 Neo Init version
  18. =================================================================*/
  19. /*===========================================================================
  20. * include files
  21. ===========================================================================*/
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "ql_api_osi.h"
  26. #include "ql_log.h"
  27. #include "ql_uart.h"
  28. #include "ql_gpio.h"
  29. #include "ql_pin_cfg.h"
  30. /*===========================================================================
  31. *Definition
  32. ===========================================================================*/
  33. #define QL_RS485_DEMO_LOG_LEVEL QL_LOG_LEVEL_INFO
  34. #define QL_RS485_DEMO_LOG(msg, ...) QL_LOG(QL_RS485_DEMO_LOG_LEVEL, "ql_rs485_demo", msg, ##__VA_ARGS__)
  35. #define QL_RS485_TASK_STACK_SIZE 4096
  36. #define QL_RS485_TASK_PRIO APP_PRIORITY_HIGH //ensure the priority of the task
  37. #define QL_RS485_TASK_EVENT_CNT 10
  38. #define QL_RS485_WRITE_WAIT_TIMEOUT 500 //send timeout
  39. #define QL_UART_RX_BUFF_SIZE 2048
  40. #define QL_UART_TX_BUFF_SIZE 2048
  41. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  42. /*===========================================================================
  43. * Variate
  44. ===========================================================================*/
  45. ql_task_t rs485_task = NULL;
  46. /*===========================================================================
  47. * Functions
  48. ===========================================================================*/
  49. void ql_rs485_notify_cb(unsigned int ind_type, ql_uart_port_number_e port, unsigned int size)
  50. {
  51. //QL_RS485_DEMO_LOG("UART port %d receive ind type:0x%x, receive data size:%d", port, ind_type, size);
  52. ql_event_t event;
  53. switch(ind_type)
  54. {
  55. case QUEC_UART_RX_OVERFLOW_IND: //rx buffer overflow
  56. {
  57. QL_RS485_DEMO_LOG("rx overflow");
  58. }
  59. case QUEC_UART_RX_RECV_DATA_IND:
  60. {
  61. QL_RS485_DEMO_LOG("rx data coming");
  62. if(size > 0)
  63. {
  64. event.id = QUEC_UART_RX_RECV_DATA_APP_IND;
  65. event.param1 = size;
  66. ql_rtos_event_send(rs485_task, &event);
  67. }
  68. break;
  69. }
  70. case QUEC_UART_TX_FIFO_COMPLETE_IND:
  71. {
  72. QL_RS485_DEMO_LOG("tx fifo complete");
  73. event.id = QUEC_UART_TX_COMPLETE_APP_IND;
  74. ql_rtos_event_send(rs485_task, &event);
  75. break;
  76. }
  77. }
  78. }
  79. int ql_rs485_init(ql_uart_port_number_e port, ql_uart_config_s *dcb, ql_uart_callback uart_cb)
  80. {
  81. int ret = 0;
  82. ql_uart_config_s dcb_uart;
  83. ret = ql_uart_set_dcbconfig(port, dcb);
  84. if(QL_UART_SUCCESS != ret)
  85. {
  86. QL_RS485_DEMO_LOG("ret: 0x%x", ret);
  87. return 1;
  88. }
  89. ret = ql_uart_open(port);
  90. if(QL_UART_SUCCESS != ret)
  91. {
  92. QL_RS485_DEMO_LOG("ret: 0x%x", ret);
  93. return 1;
  94. }
  95. ret = ql_uart_register_cb(port, uart_cb);
  96. if(QL_UART_SUCCESS != ret)
  97. {
  98. QL_RS485_DEMO_LOG("ret: 0x%x", ret);
  99. return 1;
  100. }
  101. memset(&dcb_uart, 0, sizeof(ql_uart_config_s));
  102. ret = ql_uart_get_dcbconfig(port, &dcb_uart);
  103. if(QL_UART_SUCCESS != ret)
  104. {
  105. QL_RS485_DEMO_LOG("ret: 0x%x", ret);
  106. return 1;
  107. }
  108. QL_RS485_DEMO_LOG("ret: 0x%x, baudrate=%d, flow_ctrl=%d, data_bit=%d, stop_bit=%d, parity_bit=%d",
  109. ret, dcb_uart.baudrate, dcb_uart.flow_ctrl, dcb_uart.data_bit, dcb_uart.stop_bit, dcb_uart.parity_bit);
  110. return 0;
  111. }
  112. int ql_rs485_deinit(ql_uart_port_number_e port)
  113. {
  114. int ret = 0;
  115. ret = ql_uart_close(port);
  116. if(ret)
  117. {
  118. QL_RS485_DEMO_LOG("ret: 0x%x", ret);
  119. return 1;
  120. }
  121. return 0;
  122. }
  123. //when the module is in the write state, the data sent by host will be lost
  124. int ql_rs485_write(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len)
  125. {
  126. int write_len = 0;
  127. ql_uart_tx_status_e tx_status;
  128. ql_uart_errcode_e ret;
  129. ql_gpio_set_level(QL_RS485_GPIO_NUM, LVL_HIGH);
  130. write_len = ql_uart_write(port, data, data_len);
  131. while(1)
  132. {
  133. //wait for FIFO data transmission to complete
  134. ret = ql_uart_get_tx_fifo_status(port, &tx_status);
  135. if(ret)
  136. {
  137. break;
  138. }
  139. if(tx_status == QL_UART_TX_COMPLETE)
  140. {
  141. break;
  142. }
  143. }
  144. //UART FIFO is counted in bytes. When FIFO is empty, there may still be several bits that are not sent out in the hardware circuit,
  145. //including stop bits, so it takes some time to delay at low baud rate
  146. //The baud rate is 115200 without delay. The baud rate is 9600. It is recommended to delay 180us.
  147. //The specific delay time needs to be combined with the actual test
  148. //ql_delay_us(180);
  149. //after writing, pull down directly to make the module in the state of receiving data
  150. ql_gpio_set_level(QL_RS485_GPIO_NUM, LVL_LOW);
  151. return write_len;
  152. }
  153. //the serial port cache is only 4K bytes. after receiving the data, it should be taken away as soon as possible. If the cache is full, it will lose the data
  154. int ql_rs485_read(ql_uart_port_number_e port, unsigned char *data, unsigned int data_len)
  155. {
  156. ql_gpio_set_level(QL_RS485_GPIO_NUM, LVL_LOW);
  157. return ql_uart_read(port, data, data_len);
  158. }
  159. static void ql_rs485_demo_thread(void *param)
  160. {
  161. int ret = 0;
  162. QlOSStatus err = 0;
  163. ql_event_t event;
  164. ql_uart_config_s uart_cfg = {0};
  165. int write_len = 0, read_len = 0;
  166. unsigned int real_size = 0, size = 0;
  167. uint32_t event_mask = 0;
  168. unsigned char data[] = "hello rs485 demo\r\n";
  169. unsigned char *recv_buff = calloc(1, QL_UART_RX_BUFF_SIZE+1);
  170. //step1:uart pin init
  171. //1. If QL_UART_PORT_1 is selected for use, there is no need to set TX and RX pin and function
  172. //2. According to the QuecOpen GPIO table, user should select the correct PIN to set function
  173. ret = ql_pin_set_func(QL_UART2_TX_PIN, QL_UART2_TX_FUNC);
  174. if(QL_GPIO_SUCCESS != ret)
  175. {
  176. goto exit;
  177. }
  178. ret = ql_pin_set_func(QL_UART2_RX_PIN, QL_UART2_RX_FUNC);
  179. if(QL_GPIO_SUCCESS != ret)
  180. {
  181. goto exit;
  182. }
  183. //step2:gpio pin init, default pull down, 485 needs a gpio pin to control the converter send or receive
  184. ret = ql_pin_set_func(QL_RS485_PIN_GPIO, QL_RS485_PIN_GPIO_FUNC_GPIO);
  185. if(QL_GPIO_SUCCESS != ret)
  186. {
  187. goto exit;
  188. }
  189. ql_gpio_deinit(QL_RS485_GPIO_NUM);
  190. ql_gpio_init(QL_RS485_GPIO_NUM, GPIO_OUTPUT, QUEC_PIN_NONE, LVL_LOW);
  191. //step3:set event mask
  192. event_mask = QL_UART_EVENT_RX_ARRIVED | QL_UART_EVENT_RX_OVERFLOW;
  193. ret = ql_uart_set_event_mask(QL_UART_PORT_2, event_mask);
  194. if(QL_UART_SUCCESS != ret)
  195. {
  196. goto exit;
  197. }
  198. //step4:rs485 init, baud rate and other parameters need to be configured
  199. uart_cfg.baudrate = QL_UART_BAUD_115200;
  200. uart_cfg.flow_ctrl = QL_FC_NONE;
  201. uart_cfg.data_bit = QL_UART_DATABIT_8;
  202. uart_cfg.stop_bit = QL_UART_STOP_1;
  203. uart_cfg.parity_bit = QL_UART_PARITY_NONE;
  204. ret = ql_rs485_init(QL_UART_PORT_2, &uart_cfg, ql_rs485_notify_cb);
  205. if(ret)
  206. {
  207. goto exit;
  208. }
  209. //step5:test rs485 read and write function
  210. while(1)
  211. {
  212. ql_event_try_wait(&event);
  213. if (event.id == QUEC_UART_RX_RECV_DATA_APP_IND)
  214. {
  215. size = event.param1;
  216. while(size > 0)
  217. {
  218. memset(recv_buff, 0, QL_UART_RX_BUFF_SIZE+1);
  219. real_size= MIN(size, QL_UART_RX_BUFF_SIZE);
  220. read_len = ql_rs485_read(QL_UART_PORT_2, recv_buff, real_size);
  221. QL_RS485_DEMO_LOG("read_len=%d, recv_data=%s", read_len, recv_buff);
  222. if((read_len > 0) && (size >= read_len))
  223. {
  224. size -= read_len;
  225. }
  226. else
  227. {
  228. break;
  229. }
  230. }
  231. }
  232. write_len = ql_rs485_write(QL_UART_PORT_2, data, strlen((char *)data));
  233. QL_RS485_DEMO_LOG("write_len:%d", write_len);
  234. }
  235. exit:
  236. QL_RS485_DEMO_LOG("ret: 0x%x", ret);
  237. free(recv_buff);
  238. err = ql_rtos_task_delete(NULL);
  239. if(err != QL_OSI_SUCCESS)
  240. {
  241. QL_RS485_DEMO_LOG("task deleted failed");
  242. }
  243. }
  244. void ql_rs485_app_init(void)
  245. {
  246. QlOSStatus err = 0;
  247. err = ql_rtos_task_create(&rs485_task, QL_RS485_TASK_STACK_SIZE, QL_RS485_TASK_PRIO, "QRS485DEMO", ql_rs485_demo_thread, NULL, QL_RS485_TASK_EVENT_CNT);
  248. if (err != QL_OSI_SUCCESS)
  249. {
  250. QL_RS485_DEMO_LOG("demo task created failed");
  251. return;
  252. }
  253. }