You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

490 lines
15 KiB

  1. # ���ζ��������̵Ĺ���
  2. ���ںܶ�����˵���ƻ����̿ɲ�ֻ�������ĵ��Է����㰴���Ǹ�����ô�򵥡����϶���ʵ�ֱȼ򵥰����ͺ������ӵĹ��ܡ�QMK��������ע�������Ĺ���, ���ǹ���, ���⣬�������Զ��������ڲ�ͬ�����µ���Ϊ��
  3. ��ҳ���ٶ��κ�������QMK֪ʶ�����Ķ�[����QMK](understanding_qmk.md)�����ڸ������IJ����������ⷢ����ʲô��
  4. ## A Word on Core vs ���� vs ����
  5. ���ǰ�qmk��֯��һ�����νṹ��
  6. * Core (`_quantum`)
  7. * Keyboard/Revision (`_kb`)
  8. * Keymap (`_user`)
  9. ����������ÿһ�������������ڶ����ϼ�һ��`_kb()`�� `_user()` ��׺�� �����ڼ���/�޶���ʹ��`_kb()`��׺���ڲ��ֲ�ʹ��`_user()`��׺��
  10. �ڼ���/�޶��㶨�庯��ʱ��`_kb()`��ִ���κδ���ǰ�ȵ���`_user()`�DZ�Ҫ�ģ���Ȼ���ֲ㺯���Ͳ�Ҫ�����á�
  11. <!-- �������⣺�����Ǿ䷭���IJ�̫��-->
  12. # �Զ�������
  13. ��ĿǰΪֹ������������Ǹ������м�������Ϊ�򴴽��µļ��롣�Ӵ����Ƕ�������Щ�����������ơ�
  14. ## ����һ���¼���
  15. ����������һ������ö�ٳ���ȫ����Ҳ���Ǹ������������ֲ�����Ψһ��ֵ��QMKû��ֱ��������������ֵ��С�������ṩ��һ��`SAFE_RANGE`�ꡣ��������ö��ʱ��`SAFE_RANGE`����֤��ȡ����Ψһ�ļ���ֵ��
  16. ����ö���������������ӡ��������ӵ�`keymap.c`�Ļ������ڲ���������`FOO`��`BAR`�ˡ�
  17. ```c
  18. enum my_keycodes {
  19. FOO = SAFE_RANGE,
  20. BAR
  21. };
  22. ```
  23. ## ������������
  24. ���㸲��һ���Ѵ��ڰ�������Ϊʱ������������Ϊ�����¼�ʱ����Ҫ��`process_record_kb()`��`process_record_user()`���������������ڼ���������ʵ���¼�������ǰ��QMK���á�����������������`true`��QMK�����������ķ�ʽ�������롣�������Ժܷ�������չ�����Ĺ��ܶ������滻����������������`false` QMK������������������Ȼ�����ͼ���̧�����ǰ����¼������������ˡ�
  25. ��ij�������»��ͷ�ʱ���������ᱻ���á�
  26. ### process_record_user()`����ʾ��ʵ��
  27. �����������������¡��Զ�����һ������`FOO`�ļ�������Ϊ�����������ڰ��»س�ʱ����������
  28. ```c
  29. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  30. switch (keycode) {
  31. case FOO:
  32. if (record->event.pressed) {
  33. // ����ʱ��Щʲô
  34. } else {
  35. // �ͷ�ʱ��Щʲô
  36. }
  37. return false; // �����˼������н�һ������
  38. case KC_ENTER:
  39. // �����»س�ʱ��������
  40. if (record->event.pressed) {
  41. PLAY_NOTE_ARRAY(tone_qwerty);
  42. }
  43. return true; // ��QMK�����س�����/�ͷ��¼�
  44. default:
  45. return true; // ����������������
  46. }
  47. }
  48. ```
  49. ### `process_record_*` �����ĵ�
  50. * ����/�޶�: `bool process_record_kb(uint16_t keycode, keyrecord_t *record)`
  51. * ����: `bool process_record_user(uint16_t keycode, keyrecord_t *record)`
  52. `keycode(����)`�������ڲ����϶����ģ�����`MO(1)`, `KC_L`, �ȵȡ� ��Ҫ�� `switch...case` ����������Щ�¼���
  53. `record`��������ʵ�ʰ�������Ϣ��
  54. ```c
  55. keyrecord_t record {
  56. keyevent_t event {
  57. keypos_t key {
  58. uint8_t col
  59. uint8_t row
  60. }
  61. bool pressed
  62. uint16_t time
  63. }
  64. }
  65. ```
  66. # LED����
  67. qmk�ṩ�˶�ȡHID�淶������5��LED�ķ�����:
  68. * `USB_LED_NUM_LOCK`
  69. * `USB_LED_CAPS_LOCK`
  70. * `USB_LED_SCROLL_LOCK`
  71. * `USB_LED_COMPOSE`
  72. * `USB_LED_KANA`
  73. ������������Ӧ������LED״̬��λ��λ��
  74. �����ַ������Ի�������LED״̬��
  75. * ͨ��ִ�� `led_set_user()`
  76. * ͨ������ `host_keyboard_leds()`
  77. ## `led_set_user()`
  78. ��5��LED���κ�һ����״̬��Ҫ�ı�ʱ���˺����������á��˺���ͨ����������LED������
  79. ʹ��`IS_LED_ON(usb_led, led_name)`��`IS_LED_OFF(usb_led, led_name)`��������������LED״̬��
  80. !> `host_keyboard_leds()`���ܻ���`led_set_user()`������ǰ������ֵ��
  81. ### `led_set_user()`����ʾ��ʵ��
  82. ```c
  83. void led_set_user(uint8_t usb_led) {
  84. if (IS_LED_ON(usb_led, USB_LED_NUM_LOCK)) {
  85. writePinLow(B0);
  86. } else {
  87. writePinHigh(B0);
  88. }
  89. if (IS_LED_ON(usb_led, USB_LED_CAPS_LOCK)) {
  90. writePinLow(B1);
  91. } else {
  92. writePinHigh(B1);
  93. }
  94. if (IS_LED_ON(usb_led, USB_LED_SCROLL_LOCK)) {
  95. writePinLow(B2);
  96. } else {
  97. writePinHigh(B2);
  98. }
  99. if (IS_LED_ON(usb_led, USB_LED_COMPOSE)) {
  100. writePinLow(B3);
  101. } else {
  102. writePinHigh(B3);
  103. }
  104. if (IS_LED_ON(usb_led, USB_LED_KANA)) {
  105. writePinLow(B4);
  106. } else {
  107. writePinHigh(B4);
  108. }
  109. }
  110. ```
  111. ### `led_set_*`�����ĵ�
  112. * ����/�޶�: `void led_set_kb(uint8_t usb_led)`
  113. * ����: `void led_set_user(uint8_t usb_led)`
  114. ## `host_keyboard_leds()`
  115. �������������᷵�������յ���LED״̬������������`led_set_*`֮����ȡLED״̬ʱ�����ã�������[`matrix_scan_user()`](#����ɨ������).
  116. Ϊ�˱��ݣ���������`IS_HOST_LED_ON(led_name)`��`IS_HOST_LED_OFF(led_name)` �꣬����ֱ�ӵ��úͼ���`host_keyboard_leds()`��
  117. ## ��������LED״̬
  118. һЩ����ʵ����Ϊ��������LED��״̬�ṩ�˷����ķ�����
  119. ### Ergodox Boards
  120. Ergodoxʵ�����ṩ`ergodox_right_led_1`/`2`/`3_on`/`off()`����ÿ��LED������, Ҳ������ `ergodox_right_led_on`/`off(uint8_t led)` �������򿪻��ر����ǡ�
  121. ���⣬������ʹ��`ergodox_led_all_set(uint8_t n)`ָ������LED�����ȼ���������ÿ��LED��`ergodox_right_led_1`/`2`/`3_set(uint8_t n)`��ʹ�������Ļ���`ergodox_right_led_set(uint8_t led, uint8_t n)`��
  122. Ergodox boards ͬʱ�������������ȼ���`LED_BRIGHTNESS_LO`���������ȼ���`LED_BRIGHTNESS_HI`(Ĭ������).
  123. # ���̳�ʼ������
  124. ���̳�ʼ�������м������衣�������Ǹ�����ȡ��������Ҫ��ʲô��
  125. ��������Ҫ��ʼ��������������˳���г���
  126. * `keyboard_pre_init_*` - ���ڴ�����������������ǰ���С���������Щ��Ҫ��ǰ���е�Ӳ����ʼ����
  127. * `matrix_init_*` - �ڹ̼����������м䱻���á���ʱӲ���ѳ�ʼ����������δ��ʼ����
  128. * `keyboard_post_init_*` - �ڹ̼������������󱻵��á������������£����ġ����ƻ������붼���Է������
  129. !> ���ڴ���������˵`keyboard_post_init_user`������Ҫ���õĺ���������, ��ʱ����������RGB�Ʒ��⡣
  130. ## ����Ԥ��ʼ������
  131. �����뼫�����У���������USB��ʼ��ǰ���С�
  132. ����֮�󲻾þ����ͱ���ʼ���ˡ�
  133. ���ڴ������û���˵,���ò�������Ϊ����Ҫ����������Ӳ���ij�ʼ����
  134. ����������Ӳ����ʼ���Ļ����������ٺò�����(������ʼ��LED����һ����).
  135. ### `keyboard_pre_init_user()`����ʾ��ʵ��
  136. �������ڼ��̼������趨 B0, B1, B2, B3, �� B4 ��LED���š�
  137. ```c
  138. void keyboard_pre_init_user(void) {
  139. // ���ü���Ԥ��ʼ������
  140. // ����LED����Ϊ����ģʽ
  141. setPinOutput(B0);
  142. setPinOutput(B1);
  143. setPinOutput(B2);
  144. setPinOutput(B3);
  145. setPinOutput(B4);
  146. }
  147. ```
  148. ### `keyboard_pre_init_*` �����ĵ�
  149. * ����/�޶�: `void keyboard_pre_init_kb(void)`
  150. * ����: `void keyboard_pre_init_user(void)`
  151. ## ������ʼ������
  152. �⽫���ھ�����ʼ��ʱ�����ã���ijЩӲ�����úú󣬵���һЩ���ܱ���ʼ��ǰ��
  153. ���������������ط����õ��Ķ�����ʱ���������ã�����Ӳ���޹أ�Ҳ����������������λ�á�
  154. ### `matrix_init_*`�����ĵ�
  155. * ����/�޶�: `void matrix_init_kb(void)`
  156. * ����: `void matrix_init_user(void)`
  157. ## ���̺���ʼ������
  158. ���Ǽ��̳�ʼ�������е�����һ��������������������ijЩ���ԣ����������ã���Ϊ��ʱӦ�ö����ǽ��г�ʼ����
  159. ### `keyboard_post_init_user()`ʾ��ʵ��
  160. ��ʾ�������г�ʼ�����ɺ����У�����RGB�ơ�
  161. ```c
  162. void keyboard_post_init_user(void) {
  163. // ���ú���ʼ������
  164. rgblight_enable_noeeprom(); // ʹ��Rgb������������
  165. rgblight_sethsv_noeeprom(180, 255, 255); // ����ɫ���õ�����ɫ(��ɫ)������
  166. rgblight_mode_noeeprom(RGBLIGHT_MODE_BREATHING + 3); // ���ÿ��ٺ���ģʽ������
  167. }
  168. ```
  169. ### `keyboard_post_init_*` �����ĵ�
  170. * ����/�޶�: `void keyboard_post_init_kb(void)`
  171. * ����: `void keyboard_post_init_user(void)`
  172. # ����ɨ������
  173. ���ܵĻ���Ҫ��`process_record_*()`�Զ������̣������ַ�ʽ���ӵ��¼��У���ȷ�����벻���Լ��̲�������������Ӱ�졣Ȼ�����ڼ����������£��б�Ҫ���о���ɨ�衣����Щ������Ҫ�ر�ע�����������ܣ���Ϊ��ÿ�����ٱ�����10�Ρ�
  174. ### `matrix_scan_*`ʾ��ʵ��
  175. �������ӱ�����ʡ���ˡ���hook����һ�������ܼ������е�����֮ǰ����Ӧ���㹻�˽�qmk���ڲ��ṹ���Ա���û��ʾ���������±�д����������Ҫ��������[����һ��issue](https://github.com/qmk/qmk_firmware/issues/new)��[��Discord�������ǽ���](https://discord.gg/Uq7gcHh).
  176. ### `matrix_scan_*` �����ĵ�
  177. * ����/�޶�: `void matrix_scan_kb(void)`
  178. * ����: `void matrix_scan_user(void)`
  179. �ú�����ÿ�ξ���ɨ��ʱ�����ã���������MCU��������������ͬ��������д����Ҫ��������Ϊ�������кܶ��Ρ�
  180. �������Զ�������ɨ������ʱ�õ�������������Ҳ���������Զ���״̬����(����LED�ƻ�����Ļ)�������������û���������Ҳ�붨�����еĹ��ܡ�
  181. # ���� ����/���� ����
  182. ��������֧�־Ϳ���ͨ��ֹͣһ��Ʊ�������ﵽ"����"��RGB�ƺͱ������Ǻܺõ����ӡ������Խ�Լ�ܺģ�Ҳ�����������̷�ζ���ѡ�
  183. ��������������: `suspend_power_down_*`��`suspend_wakeup_init_*`, �ֱ���ϵͳ�����кͻ���ʱ���á�
  184. ### suspend_power_down_user()��suspend_wakeup_init_user()ʾ��ʵ��
  185. ```c
  186. void suspend_power_down_user(void) {
  187. rgb_matrix_set_suspend_state(true);
  188. }
  189. void suspend_wakeup_init_user(void) {
  190. rgb_matrix_set_suspend_state(false);
  191. }
  192. ```
  193. ### ���� ����/���� �����ĵ�
  194. * ����/�޶�: `void suspend_power_down_kb(void)` ��`void suspend_wakeup_init_user(void)`
  195. * ����: `void suspend_power_down_kb(void)` �� `void suspend_wakeup_init_user(void)`
  196. # ���ı�����
  197. ÿ�����ı����������д��롣�����ڲ�ָʾ���Զ����㴦�������á�
  198. ### `layer_state_set_*` ʾ��ʵ��
  199. ����ʹ����Planck����ʾ������������ [RGB������](feature_rgblight.md)ʹ֮������Ӧ
  200. ```c
  201. uint32_t layer_state_set_user(uint32_t state) {
  202. switch (biton32(state)) {
  203. case _RAISE:
  204. rgblight_setrgb (0x00, 0x00, 0xFF);
  205. break;
  206. case _LOWER:
  207. rgblight_setrgb (0xFF, 0x00, 0x00);
  208. break;
  209. case _PLOVER:
  210. rgblight_setrgb (0x00, 0xFF, 0x00);
  211. break;
  212. case _ADJUST:
  213. rgblight_setrgb (0x7A, 0x00, 0xFF);
  214. break;
  215. default: // for any other layers, or the default layer
  216. rgblight_setrgb (0x00, 0xFF, 0xFF);
  217. break;
  218. }
  219. return state;
  220. }
  221. ```
  222. ### `layer_state_set_*` �����ĵ�
  223. * ����/�޶�: `uint32_t layer_state_set_kb(uint32_t state)`
  224. * ����: `uint32_t layer_state_set_user(uint32_t state)`
  225. ��`״̬`�ǻ����bitmask, ����[���ָ���](keymap.md#���ֵIJ�״̬)
  226. # ���籣������ (EEPROM)
  227. �������������ó��ڵı����ڼ����С���Щ���ñ����������ص�EEPROM����粻����ʧ�� ���ÿ�����`eeconfig_read_kb`��`eeconfig_read_user`��ȡ��������`eeconfig_update_kb`��`eeconfig_update_user`д�롣��������ϣ���ܹ��л��Ĺ��ܺ�����(�����л�RGB��ָʾ�����⣬��������`eeconfig_init_kb`��`eeconfig_init_user`������EEPROMĬ��ֵ��
  228. ��ӵIJ��ֿ����ǣ��кܶ෽������ͨ��EEPROM�洢�ͷ������ݣ����Ҳ�û�������ַ����ǡ�������ȷ���ġ���ÿ������ֻ��һ��˫��(���ֽ�)�ռ䡣
  229. ��סEEPROM����д�������ġ�����д�������ܸߣ����Dz�����ֻ������д��EEPROM�С�������д��Ƶ��������MCU�����������̡�
  230. * �������������������ӣ���ô������ϣ������ʹ���������ԣ���Ϊ���൱���ӡ�
  231. ### ʾ��ʵ��
  232. ���������������������ã����Ҷ�д������ʹ�����û����֡�����һ�����ӵĺ������кܶ�����Ҫ����ʵ���ϣ���ʹ���˺ܶ�����������������
  233. ������keymap.c�ļ��У������´�������������:
  234. ```c
  235. typedef union {
  236. uint32_t raw;
  237. struct {
  238. bool rgb_layer_change :1;
  239. };
  240. } user_config_t;
  241. user_config_t user_config;
  242. ```
  243. ���ϴ��뽨����һ���ṹ�壬�ýṹ�����Դ洢���ò�������д��EEPROM���������㽫���趨����������Ϊ�ڽṹ������Ȼ���塣Ҫ��ס`bool` (����)ֵʹ��1λ, `uint8_t`ʹ��8λ, `uint16_t`ʹ��16λ�������Ի��ϴ���ʹ�ã�����˳���Ǵ����ܻ������鷳����Ϊ�ǻ��ı�д��д����ֵ��
  244. `layer_state_set_*`������ʹ����`rgb_layer_change`��ʹ����`keyboard_post_init_user`��`process_record_user`������һ�С�
  245. ����Ҫʹ��`keyboard_post_init_user����Ҫ����`eeconfig_read_user()`���������ոմ����Ľṹ�塣Ȼ������������ʹ�������ṹ���������IJ����еĹ��ܡ�����������
  246. ```c
  247. void keyboard_post_init_user(void) {
  248. // ���ò��ּ����ľ�����ʼ��
  249. // ��EEPROM���û�����
  250. user_config.raw = eeconfig_read_user();
  251. // ��ʹ�ܣ�����Ĭ�ϲ�
  252. if (user_config.rgb_layer_change) {
  253. rgblight_enable_noeeprom();
  254. rgblight_sethsv_noeeprom_cyan();
  255. rgblight_mode_noeeprom(1);
  256. }
  257. }
  258. ```
  259. ���Ϻ������ڶ�EEPROM���ú�����ʹ�ø�����������Ĭ�ϲ�RGB��ɫ��"raw"��ֵ�Ǵ�����������"union"�����Ľṹ����ת�����ġ�
  260. ```c
  261. uint32_t layer_state_set_user(uint32_t state) {
  262. switch (biton32(state)) {
  263. case _RAISE:
  264. if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_magenta(); rgblight_mode_noeeprom(1); }
  265. break;
  266. case _LOWER:
  267. if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_red(); rgblight_mode_noeeprom(1); }
  268. break;
  269. case _PLOVER:
  270. if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_green(); rgblight_mode_noeeprom(1); }
  271. break;
  272. case _ADJUST:
  273. if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_white(); rgblight_mode_noeeprom(1); }
  274. break;
  275. default: // ������������Ĭ�ϲ�
  276. if (user_config.rgb_layer_change) { rgblight_sethsv_noeeprom_cyan(); rgblight_mode_noeeprom(1); }
  277. break;
  278. }
  279. return state;
  280. }
  281. ```
  282. ��������ֵʹ��ʱ���ı�RGB�����ơ�������������ֵ, Ϊ`process_record_user`����һ���¼�������`RGB_LYR`������Ҫȷ��������ʹ��������RGB���룬ʹ��������ʾ�������رգ��뽫������Ϊ��
  283. ```c
  284. bool process_record_user(uint16_t keycode, keyrecord_t *record) {
  285. switch (keycode) {
  286. case FOO:
  287. if (record->event.pressed) {
  288. // ����ʱ����ʲô
  289. } else {
  290. // �ͷ�ʱ����ʲô
  291. }
  292. return false; // �����˼��Ľ�һ������
  293. case KC_ENTER:
  294. // �ڰ��»س�ʱ��������
  295. if (record->event.pressed) {
  296. PLAY_NOTE_ARRAY(tone_qwerty);
  297. }
  298. return true; // ��QMK�����س�����/�ͷ��¼�
  299. case RGB_LYR: // ������underglow��Ϊ��ָʾ��������ʹ�á�
  300. if (record->event.pressed) {
  301. user_config.rgb_layer_change ^= 1; // �л�״̬
  302. eeconfig_update_user(user_config.raw); // ��EEPROMд����״̬
  303. if (user_config.rgb_layer_change) { // ������״̬��ʹ��
  304. layer_state_set(layer_state); // ��ô���̸��²���ɫ
  305. }
  306. }
  307. return false; break;
  308. case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // �������е�RGB���� (see quantum_keycodes.h, L400 ���Բο�)
  309. if (record->event.pressed) { //����ʧ�ܲ�ָʾ���������ı�����������Ҫ��������
  310. if (user_config.rgb_layer_change) { // ����ʹ��ʱ
  311. user_config.rgb_layer_change = false; // ʧ�ܣ�Ȼ��
  312. eeconfig_update_user(user_config.raw); // ��EEPROM�����
  313. }
  314. }
  315. return true; break;
  316. default:
  317. return true; // ������������
  318. }
  319. }
  320. ```
  321. ������Ҫ����`eeconfig_init_user`���������Ե�EEPROM����ʱ������ָ��Ĭ��ֵ, �����Զ�����������ǿ������EEPROM������`EEP_RST`������[Bootmagic](feature_bootmagic.md)���������磬����Ҫ��Ĭ������������RGB��ָʾ��������Ĭ��ֵ
  322. ```c
  323. void eeconfig_init_user(void) { // EEPROM��������
  324. user_config.raw = 0;
  325. user_config.rgb_layer_change = true; // ������ҪĬ��ʹ��
  326. eeconfig_update_user(user_config.raw); // ��EEPROMд��Ĭ��ֵ
  327. // use the non noeeprom versions, ��Ҫ��EEPROMд����Щֵ
  328. rgblight_enable(); // Ĭ��ʹ��RGB
  329. rgblight_sethsv_cyan(); // Ĭ��������ɫ
  330. rgblight_mode(1); // Ĭ�����ó���
  331. }
  332. ```
  333. Ȼ���������ˡ�RGB��ָʾ����������������ʱ�������������û�һֱ���棬���������¼��̡�������ʹ������RGB���룬��ָʾ��ʧ�ܣ��������������������ˡ�
  334. ### 'EECONFIG' �����ĵ�
  335. * ����/�޶�: `void eeconfig_init_kb(void)`, `uint32_t eeconfig_read_kb(void)`��`void eeconfig_update_kb(uint32_t val)`
  336. * ����: `void eeconfig_init_user(void)`, `uint32_t eeconfig_read_user(void)`��`void eeconfig_update_user(uint32_t val)`
  337. `val` ������д��EEPROM��ֵ��`eeconfig_read_*`��������EEPROM����һ��32λ(˫��)��ֵ��
  338. # �Զ�������-�����ٽ�ֵ(TAPPING_TERM)
  339. Ĭ��������,����-�����ٽ�ֵ��ȫ��ͳһ�ģ����Ҳ���ͨ�����������á����ڴ������û���˵���ܺá���������Щ�����£�����`LT`����˵������ʱ��˫���ܼ����������󣬿�������Ϊ��Щ���������ļ������װ�ס��Ϊ�˲���ÿ�����Զ������룬�����ܿ���Ϊÿ��������`TAPPING_TERM`��
  340. ��ʹ���������ܵĻ�, Ҫ����`config.h`����`#define TAPPING_TERM_PER_KEY`��
  341. ## `get_tapping_term`ʾ��ʵ��
  342. ��Ҫ�޸Ļ��ڼ�����`TAPPING TERM`,��Ҫ��`keymap.c`�ļ��������´���:
  343. ```c
  344. uint16_t get_tapping_term(uint16_t keycode) {
  345. switch (keycode) {
  346. case SFT_T(KC_SPC):
  347. return TAPPING_TERM + 1250;
  348. case LT(1, KC_GRV):
  349. return 130;
  350. default:
  351. return TAPPING_TERM;
  352. }
  353. }
  354. ```
  355. ### `get_tapping_term` �����ĵ�
  356. ������ƪ����������,��������Ҫquantum���߼��̼����ĺ�����ֻҪ�û����������ɡ�