how to write UART interrupt callback code?

class ExtInt – configure I/O pins to interrupt on external events
“There are a total of 22 interrupt lines. 16 of these can come from GPIO pins and the remaining 6 are from internal sources.”

my code :

# Hello World Example
#
# Welcome to the OpenMV IDE! Click on the green run arrow button below to run the script!

import sensor, image, time
#import time
from pyb import Pin, ExtInt
from pyb import UART
from pyb import LED
red_led   = LED(1)
green_led = LED(2)
blue_led  = LED(3)
ir_led    = LED(4)
sensor.reset()                      # Reset and initialize the sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.VGA)   # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000)     # Wait for settings take effect.
clock = time.clock()                # Create a clock object to track the FPS.
uart = UART(3, 19200)
buf=66
data = bytearray(10)  # create a buffer
def print_X1(line):
    red_led.toggle()#print("X1 is pressed")
    print("X1 is pressed")
ext = ExtInt(Pin('P5'), ExtInt.IRQ_FALLING, Pin.PULL_NONE, print_X1)
ext.enable()
while(True):
    clock.tick()                    # Update the FPS clock.
    img = sensor.snapshot()         # Take a picture and return the image.
    img.draw_rectangle((100,100,100,100),128)#设置坐标(10,10)的像素点为红色(255,0,0)

    print(clock.fps())              # Note: OpenMV Cam runs about half as fast when connected
                                    # to the IDE. The FPS should increase once disconnected.

but when I send “a”,I saw 3 lines print(“X1 is pressed”) on IDE Serial Terminal.
So I think my “ExtInt” codes do not work as UART interrupt.

Hi, to print to the UART you need to do:

def print_X1(line):
    red_led.toggle()#print("X1 is pressed")
    uart.write("X1 is pressed")

That said… the UART blocks when it’s full of bytes and you’re going to crash the system with that code.

Also, make sure to initialize the uart like so:

uart = UART(3, 19200, timeout_char = 1000)

Anyway, if you want to send data on an interrupt do that in the main loop and only set a flag to go high in the interrupt. In particular, code like this works great for passing state:

In the interrupt handler:

if not flag: flag = True

And in the main loop:

if flag:
    flag = False
    # do something
import sensor, image, time
#import time
from pyb import Pin, ExtInt
from pyb import UART
from pyb import LED
red_led   = LED(1)
uart = UART(3, 19200)
def flag_True(line):
    red_led.toggle()
ext = ExtInt(Pin('P5'), ExtInt.IRQ_FALLING, Pin.PULL_NONE,flag_True)
ext.enable()
while(True):
    pass

These codes works.but when my codes like this:

import sensor, image, time
#import time
from pyb import Pin, ExtInt
from pyb import UART
from pyb import LED
red_led   = LED(1)
uart = UART(3, 19200, timeout_char = 1000)
flag = False
def flag_True(line):
    if not flag: flag = True
ext = ExtInt(Pin('P5'), ExtInt.IRQ_FALLING, Pin.PULL_NONE,flag_True)
ext.enable()
while(True):
    if flag:
        flag = False
        red_led.toggle()# do something

IDE Serial Terminal display:
Uncaught exception in ExtInt interrupt handler line 11
NameError:

I want to know why.

Hi, python requires you to make a variable as global if you are changing a variable outside of function.

So do:

Global flag

As the first line of the interrupt call back method.

Thanks.
I add global_list.py as:

flag = False
counter=1

and main.py as:

import global_list
import sensor, image, time
from pyb import Pin, ExtInt
from pyb import UART
from pyb import LED
red_led   = LED(1)
uart = UART(3, 19200, timeout_char = 1000)
def flag_True(line):
	if not global_list.flag: global_list.flag = True
	global_list.counter=global_list.counter+1
ext = ExtInt(Pin('P5'), ExtInt.IRQ_FALLING, Pin.PULL_NONE,flag_True)
ext.enable()
while(True):
	if global_list.flag:
		global_list.flag = False
		red_led.toggle()
		print("counter=",global_list.counter)

Not quite sure what you are doing.

And then I want to konw how to receive a frame like"AA 56 FF FC FF"(AA:frame head, FF FC FF:frame end).
……I need help again.

Hi,

See the uart class docs here:

http://docs.micropython.org/en/v1.9.2/pyboard/library/pyb.UART.html

Also, see the struct module: 7.3. struct — Interpret strings as packed binary data — Python 2.7.18 documentation

The above use of ExtInt() is confusing, as this bounds an interrupt handler to a GPIO interrupt, rather than a UART, i.e. reception of a character interrupt.
What really happens above is that the start-bit (which is always a falling-edge bit) will fire the interrupt, even before the character itself is transmitted in full.
Checking for uart.any() would yield ZERO for a while, until the full character is received and cleared off the shift-register to the HW Rx buffer.
I’d suggest to set to ExtInt.IRQ_RISING so that the interrupt is fired closer to the end of the character. (For the value of 0x00 and no parity, the interrupt would fire on the arrival of the stop-bit).
I couldn’t find any way for the UART itself to fire the interrupt once a character is pending for handling and I wonder if there is a way to do it.
Is there a way to do that?

Yes, but, not in python. This requires editing the C code. Until that’s added… poll any().