switch.rst 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. The Switch, callbacks and interrupts
  2. ====================================
  3. The pyboard has 2 small switches, labelled USR and RST. The RST switch
  4. is a hard-reset switch, and if you press it then it restarts the pyboard
  5. from scratch, equivalent to turning the power off then back on.
  6. The USR switch is for general use, and is controlled via a Switch object.
  7. To make a switch object do::
  8. >>> sw = pyb.Switch()
  9. Remember that you may need to type ``import pyb`` if you get an error that
  10. the name ``pyb`` does not exist.
  11. With the switch object you can get its status::
  12. >>> sw.value()
  13. False
  14. This will print ``False`` if the switch is not held, or ``True`` if it is held.
  15. Try holding the USR switch down while running the above command.
  16. There is also a shorthand notation to get the switch status, by "calling" the
  17. switch object::
  18. >>> sw()
  19. False
  20. Switch callbacks
  21. ----------------
  22. The switch is a very simple object, but it does have one advanced feature:
  23. the ``sw.callback()`` function. The callback function sets up something to
  24. run when the switch is pressed, and uses an interrupt. It's probably best
  25. to start with an example before understanding how interrupts work. Try
  26. running the following at the prompt::
  27. >>> sw.callback(lambda:print('press!'))
  28. This tells the switch to print ``press!`` each time the switch is pressed
  29. down. Go ahead and try it: press the USR switch and watch the output on
  30. your PC. Note that this print will interrupt anything you are typing, and
  31. is an example of an interrupt routine running asynchronously.
  32. As another example try::
  33. >>> sw.callback(lambda:pyb.LED(1).toggle())
  34. This will toggle the red LED each time the switch is pressed. And it will
  35. even work while other code is running.
  36. To disable the switch callback, pass ``None`` to the callback function::
  37. >>> sw.callback(None)
  38. You can pass any function (that takes zero arguments) to the switch callback.
  39. Above we used the ``lambda`` feature of Python to create an anonymous function
  40. on the fly. But we could equally do::
  41. >>> def f():
  42. ... pyb.LED(1).toggle()
  43. ...
  44. >>> sw.callback(f)
  45. This creates a function called ``f`` and assigns it to the switch callback.
  46. You can do things this way when your function is more complicated than a
  47. ``lambda`` will allow.
  48. Note that your callback functions must not allocate any memory (for example
  49. they cannot create a tuple or list). Callback functions should be relatively
  50. simple. If you need to make a list, make it beforehand and store it in a
  51. global variable (or make it local and close over it). If you need to do
  52. a long, complicated calculation, then use the callback to set a flag which
  53. some other code then responds to.
  54. Technical details of interrupts
  55. -------------------------------
  56. Let's step through the details of what is happening with the switch
  57. callback. When you register a function with ``sw.callback()``, the switch
  58. sets up an external interrupt trigger (falling edge) on the pin that the
  59. switch is connected to. This means that the microcontroller will listen
  60. on the pin for any changes, and the following will occur:
  61. 1. When the switch is pressed a change occurs on the pin (the pin goes
  62. from low to high), and the microcontroller registers this change.
  63. 2. The microcontroller finishes executing the current machine instruction,
  64. stops execution, and saves its current state (pushes the registers on
  65. the stack). This has the effect of pausing any code, for example your
  66. running Python script.
  67. 3. The microcontroller starts executing the special interrupt handler
  68. associated with the switch's external trigger. This interrupt handler
  69. get the function that you registered with ``sw.callback()`` and executes
  70. it.
  71. 4. Your callback function is executed until it finishes, returning control
  72. to the switch interrupt handler.
  73. 5. The switch interrupt handler returns, and the microcontroller is
  74. notified that the interrupt has been dealt with.
  75. 6. The microcontroller restores the state that it saved in step 2.
  76. 7. Execution continues of the code that was running at the beginning. Apart
  77. from the pause, this code does not notice that it was interrupted.
  78. The above sequence of events gets a bit more complicated when multiple
  79. interrupts occur at the same time. In that case, the interrupt with the
  80. highest priority goes first, then the others in order of their priority.
  81. The switch interrupt is set at the lowest priority.
  82. Further reading
  83. ---------------
  84. For further information about using hardware interrupts see
  85. :ref:`writing interrupt handlers <isr_rules>`.