1 /*
2  * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-12-30     CDT          first version
9  */
10 
11 /*
12  * 程序清单: Pulse encoder 设备使用例程, 请在图形化配置界面打开pulse encoder device,
13  * 并使能tmra_1和tmr6_1.
14  * 例程导出了 encoder_sample 命令到控制终端, 通过串口可查看当前的count数值
15  * 命令调用格式:pulse_encoder_sample devname [option1] [option2]
16  *                                  devname: [pulse_a1/pulse_61] 编码器单元名称
17  *                                  option1: 正转脉冲数
18  *                                  option2: 反转脉冲数
19  * eg:encoder_sample pulse_a1 2000 1000
20  * 编码器的分辨率是1000
21  * 硬件IO查看对应board/board_config.h中相关端口定义,并且需要正确连接到对应模拟脉冲生成的端口
22  * 程序功能:
23  */
24 
25 #include <rtthread.h>
26 #include <rtdevice.h>
27 #include <stdlib.h>
28 #include "board_config.h"
29 #include <board.h>
30 
31 #ifdef BSP_USING_PULSE_ENCODER
32 
33 #if defined (HC32F4A0)
34     #define TEST_IO_A_PIN GET_PIN(A, 5)
35     #define TEST_IO_B_PIN GET_PIN(A, 6)
36 #else
37     #define TEST_IO_A_PIN GET_PIN(B, 0)
38     #define TEST_IO_B_PIN GET_PIN(B, 1)
39 #endif
40 
41 static rt_device_t pulse_encoder_dev = RT_NULL;
42 
printf_connect(void)43 static void printf_connect(void)
44 {
45 #if defined (HC32F4A0)
46 #if defined(BSP_USING_PULSE_ENCODER_TMRA_1)
47     rt_kprintf("  [tmra]*connect PA5-->PA8 PA6-->PA9\n");
48 #endif
49 #if defined(BSP_USING_PULSE_ENCODER_TMR6_1)
50     rt_kprintf("  [tmr6]*connect PA5-->PB9 PA6-->PB8\n");
51 #endif
52 #endif
53 #if defined (HC32F460)
54 #if defined(BSP_USING_PULSE_ENCODER_TMRA_1)
55     rt_kprintf("  [tmra]*connect PB0-->PA8 PB1-->PA9\n");
56 #endif
57 #if defined(BSP_USING_PULSE_ENCODER_TMR6_1)
58     rt_kprintf("  [tmr6]*connect PB0-->PE9 PB1-->PE8\n");
59 #endif
60 #endif
61 #if defined (HC32F448)
62 #if defined(BSP_USING_PULSE_ENCODER_TMRA_1)
63     rt_kprintf("  [tmra]*connect PB0-->PA8 PB1-->PA9\n");
64 #endif
65 #if defined(BSP_USING_PULSE_ENCODER_TMR6_1)
66     rt_kprintf("  [tmr6]*connect PB0-->PB5 PB1-->PB13\n");
67 #endif
68 #endif
69 #if defined (HC32F472)
70 #if defined(BSP_USING_PULSE_ENCODER_TMRA_1)
71     rt_kprintf("  [tmra]*connect PB0-->PA0 PB1-->PA1\n");
72 #endif
73 #if defined(BSP_USING_PULSE_ENCODER_TMR6_1)
74     rt_kprintf("  [tmr6]*connect PB0-->PA3 PB1-->PA7\n");
75 #endif
76 #endif
77 }
78 
_pulse_cmd_print_usage(void)79 static void _pulse_cmd_print_usage(void)
80 {
81     rt_kprintf("encoder_sample devname [option1] [option2]\n");
82     rt_kprintf("  devname: [pulse_a1/pulse_61..] pulse uint\n");
83     rt_kprintf("  option1: number of positive pulses\n");
84     rt_kprintf("  option2: number of reversal pulses\n");
85     rt_kprintf("    e.g. MSH >encoder_sample pulse_a1 2000 1000\n");
86     printf_connect();
87 }
88 
GenClkUp(const uint16_t cnt)89 static void GenClkUp(const uint16_t cnt)
90 {
91     uint32_t i, j;
92     rt_int32_t count;
93     const uint8_t bAin[4U] = {1U, 1U, 0U, 0U};
94     const uint8_t bBin[4U] = {0U, 1U, 1U, 0U};
95     for (j = 0UL; j < cnt; j++)
96     {
97         for (i = 0UL; i < 4UL; i++)
98         {
99             if (0U == bAin[i])
100             {
101                 rt_pin_write(TEST_IO_A_PIN, PIN_LOW);
102             }
103             else
104             {
105                 rt_pin_write(TEST_IO_A_PIN, PIN_HIGH);
106             }
107             if (0U == bBin[i])
108             {
109                 rt_pin_write(TEST_IO_B_PIN, PIN_LOW);
110             }
111             else
112             {
113                 rt_pin_write(TEST_IO_B_PIN, PIN_HIGH);
114             }
115             rt_thread_mdelay(1UL);
116         }
117         rt_device_read(pulse_encoder_dev, 0, &count, 1);
118         rt_kprintf("%d\r\n", count);
119     }
120 }
121 
GenClkDown(const uint16_t cnt)122 static void GenClkDown(const uint16_t cnt)
123 {
124     uint32_t i, j;
125     rt_int32_t count;
126     const uint8_t bAin[4U] = {0U, 1U, 1U, 0U};
127     const uint8_t bBin[4U] = {1U, 1U, 0U, 0U};
128     for (j = 0UL; j < cnt; j++)
129     {
130         for (i = 0UL; i < 4UL; i++)
131         {
132             if (0U == bAin[i])
133             {
134                 rt_pin_write(TEST_IO_A_PIN, PIN_LOW);
135             }
136             else
137             {
138                 rt_pin_write(TEST_IO_A_PIN, PIN_HIGH);
139             }
140             if (0U == bBin[i])
141             {
142                 rt_pin_write(TEST_IO_B_PIN, PIN_LOW);
143             }
144             else
145             {
146                 rt_pin_write(TEST_IO_B_PIN, PIN_HIGH);
147             }
148             rt_thread_mdelay(1UL);
149         }
150         rt_device_read(pulse_encoder_dev, 0, &count, 1);
151         rt_kprintf("%d\r\n", count);
152     }
153 }
154 
encoder_sample(int argc,char ** argv)155 static int encoder_sample(int argc, char **argv)
156 {
157     rt_int32_t count;
158 
159     if ((argc != 4))
160     {
161         _pulse_cmd_print_usage();
162         return -RT_ERROR;
163     }
164 
165     rt_pin_mode(TEST_IO_A_PIN, PIN_MODE_OUTPUT);
166     rt_pin_mode(TEST_IO_B_PIN, PIN_MODE_OUTPUT);
167 
168     pulse_encoder_dev = rt_device_find(argv[1]);
169     if (pulse_encoder_dev == RT_NULL)
170     {
171         rt_kprintf("encoder_sample run failed! can't find %s device!\n", argv[1]);
172         _pulse_cmd_print_usage();
173         return -RT_ERROR;
174     }
175     rt_device_open(pulse_encoder_dev, RT_DEVICE_OFLAG_RDONLY);
176     rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_CLEAR_COUNT, RT_NULL);
177     rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_ENABLE, RT_NULL);
178 
179     /* 自测DISABLE和CLEAR功能 */
180     GenClkUp(100);
181     rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_DISABLE, RT_NULL);
182     /* 测试DISABLE后是否还会计数 */
183     GenClkUp(10);
184     rt_device_read(pulse_encoder_dev, 0, &count, 1);
185     rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_CLEAR_COUNT, RT_NULL);
186     if (count != 100)
187     {
188         rt_kprintf("**************Self-test failed**************\n");
189         rt_device_close(pulse_encoder_dev);
190         _pulse_cmd_print_usage();
191         return -RT_ERROR;
192     }
193     else
194     {
195         rt_kprintf("**************Self-test success**************\n");
196         rt_device_control(pulse_encoder_dev, PULSE_ENCODER_CMD_ENABLE, RT_NULL);
197         GenClkUp(atoi(argv[2]));
198         GenClkDown(atoi(argv[3]));
199 
200         rt_device_read(pulse_encoder_dev, 0, &count, 1);
201         if (count == (atoi(argv[2]) - atoi(argv[3])))
202         {
203             rt_kprintf("encoder_sample test success\n");
204         }
205         else
206         {
207             rt_kprintf("encoder_sample test failed\n");
208         }
209 
210         rt_device_close(pulse_encoder_dev);
211     }
212 
213     return RT_EOK;
214 }
215 
216 /* 导出到 msh 命令列表中 */
217 MSH_CMD_EXPORT(encoder_sample, encoder sample devname [option1] [option2]);
218 #endif
219