STM32 Code Examples

ตัวอย่างโค้ดสาธิต CircuitPython สำหรับบอร์ดไมโครคอนโทรลเลอร์ STM32

โค้ดตัวอย่างที่ 1 PWM-based RGB LED Dimming

ตัวอย่างนี้สาธิตการสร้างสัญญาณ PWM แบบ 3 ช่องเอาต์พุต ความถี่คงที่ เช่น 500Hz โดยใช้คลาส pwmio สัญญาณ PWM นี้ จะถูกนำไปใช้ในการปรับความสว่างของ RGB LED (active-low, common anode) และได้เลือกใช้ขา A0 / PA00, A1 / PA01, A2 / PA02 ตามลำดับ สำหรับบอร์ด STM32F411CE BlackPill

เมื่อทดสอบการทำงานของโค้ด จะเห็นว่า โมดูล RGB LED จะค่อย ๆ สว่างขึ้นและดับลง เลือกสี (Red, Green, Blue) ไปตามลำดับ

import time
import board
import math
import pwmio

###########################################################
class PWMArray:
    def __init__(self,pwm_objects):
        self.pwm_objects = pwm_objects
    def __iter__(self):
        self.index = 0
        return self
    def __next__(self):
        current = self.index
        self.index = (self.index+1) % len(pwm_objects)
        return pwm_objects[current]
###########################################################

led_pins = [board.A0, board.A1, board.A2]
pwm_objects = [
    pwmio.PWMOut(pin=led_pin,duty_cycle=65535,frequency=500)
    for led_pin in led_pins ]
# create an iterator for the list of three PWMOut objects
pwm_iter = iter(PWMArray(pwm_objects))

# create a table of (N+1) sine-wave values
N=128
sine_int = lambda i: int(65535*(1-math.sin(math.pi*i/N)))
values = [sine_int(i) for i in range(N+1)]

try:
    level = 0 # 0..N
    pwm = next(pwm_iter) # select the first PWM output
    t = int(1000*time.monotonic()) # time in msec
    while True:
        now = int(1000*time.monotonic()) # time in msec
        if now - t < 15:
            continue
        t = now # update timestamp
        pwm.duty_cycle = values[level]
        if level == N:
            level = 0
            pwm = next(pwm_iter) # select next PWM output 
        else:
            level += 1
except KeyboardInterrupt:
    pass
for pwm in pwm_objects:
    pwm.deinit()
print('Done')

โค้ดตัวอย่างที่ 2: RGB LED + Push Button

ตัวอย่างนี้สาธิตการตรวจสอบการกดปุ่มจำนวน 1 ปุ่ม เมื่อมีการกดปุ่มแต่ละครั้ง จะทำให้ RGB LED เปลี่ยนสีไปตามลำดับ วงจรปุ่มกดภายนอกที่ได้นำมาต่อเพิ่มนั้นรับอินพุตแบบดิจิทัลที่ขา B8 / PB08 และขาเอาต์พุตสำหรับ RGB LED (active-low, common anode) คือ A0 / PA00, A1 / PA01, A2 / PA02 ตามลำดับ

คำสั่งที่ใช้สำหรับ Digital I/O มาจากไลบรารี digitalio (API)

import time
import board
import digitalio

button_pin = board.B8
button = digitalio.DigitalInOut(button_pin)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP

led_pins = [board.A0, board.A1, board.A2]
leds = [ digitalio.DigitalInOut(pin) for pin in led_pins]
for led in leds:
    led.direction =  digitalio.Direction.OUTPUT
    led.drive_mode = digitalio.DriveMode.PUSH_PULL
    led.value = True

try:
    index = 0
    while True:
        if button.value == 0: # button pressed
            while button.value != 1: # wait until released
                pass
            leds[index].value = True
            index = (index+1) % len(leds)
            leds[index].value = False
        time.sleep(0.05)
except KeyboardInterrupt:
    pass
button.deinit()
for led in leds:
    led.value = True
    led.deinit()
print('Done')

โค้ดตัวอย่างที่ 3: PCF8574 I/O Expander (Output)

ตัวอย่างนี้สาธิตการใช้งานโมดูล PCF8574 I/O Expander ขนาด 8 บิต โดยใช้ในโหมดเอาต์พุตทั้ง 8 ขา และใช้ควบคุมสถานะลอจิกของ LED Bar (active-low, common-anode) ที่มีทั้งหมด 8 ดวง

โมดูลนี้ใช้ไอซี PCF8574 ที่เชื่อมต่อข้อมูลด้วยวิธีบัส I2C (default address 0x20) ดังนั้นเราจะใช้คำสั่งจากไลบรารี busio (API)

พฤติกรรมการทำงานของโค้ดตัวอย่างมีดังนี้ เริ่มต้นให้ LED หนึ่งดวงอยู่ในสถานะ ON (ตรงกับตำแหน่ง LSB) จากนั้นตำแหน่งของ LED ที่อยู่ในสถานะ ON จะเลื่อนไปทางซ้ายทีละตำแหน่ง เมื่อไปจนถึงซ้ายสุด (ตรงกับตำแหน่ง MSB) ให้เลื่อนกลับไปทางขวา และทำในลักษณะนี้ซ้ำไปเรื่อย ๆ

import time
import busio
from board import SCL, SDA

PCF8574_ADDR = 0x20
i2c = busio.I2C(SCL, SDA,frequency=100000) # 100kHz speed

# attempt to lock the i2c bus
while not i2c.try_lock():
    pass
addr_found = []
addr_found = i2c.scan()
print("I2C found:", [hex(addr) for addr in addr_found])
i2c.unlock()


if PCF8574_ADDR not in addr_found:
    print('PCF8574 not found')

shift_left  = lambda x: ((x << 1) | (x >> 7)) & 0xff
shift_right = lambda x: ((x >> 1) | (x << 7)) & 0xff

try:
    data = 0x01
    direction = 1 # shift left
    buf = bytearray(1)
    while True:
        if i2c.try_lock():
            buf[0] = data ^ 0xff # inverting output
            i2c.writeto(PCF8574_ADDR, buffer=buf,start=0,end=1)
            i2c.unlock()
        if data == 0x80:   # MSB is 1.
            direction = 0 # change direction to shift-right
        elif data == 0x01: # LSB is 1.
            direction = 1  # change direction to shift-left
        if direction == 1:
            data = shift_left(data)
        else:
            data = shift_right(data)
        time.sleep(0.1)
except KeyboardInterrupt:
    pass
i2c.deinit()

หรือเราอาจใช้คำสั่งของไลบรารี adafruit_bus_device (API) สำหรับ I2C Device จาก Adafruit Library Bundle ก็ได้ดังนี้

import time
import busio
from board import *
from adafruit_bus_device.i2c_device import I2CDevice

PCF8574_ADDR = 0x20
i2c = busio.I2C(SCL, SDA, frequency=100000) 
dev = I2CDevice(i2c, PCF8574_ADDR)

shift_left  = lambda x: ((x << 1) | (x >> 7)) & 0xff
shift_right = lambda x: ((x >> 1) | (x << 7)) & 0xff

try:
    data = 0x01
    direction = 1 # shift left
    buf = bytearray(1)
    while True:
        buf[0] = data ^ 0xff # inverting output
        with dev:
            dev.write(buf)
        if data == 0x80:   # MSB is 1.
            direction = 0  # change direction to shift-right
        elif data == 0x01: # LSB is 1.
            direction = 1  # change direction to shift-left
        if direction == 1:
            data = shift_left(data)
        else:
            data = shift_right(data)
        time.sleep(0.1)
except KeyboardInterrupt:
    pass
i2c.deinit()

โค้ดตัวอย่างที่ 4: PCF8574 I/O Expander (Input)

ตัวอย่างนี้สาธิตการใช้โมดูล PCF8574 ตรวจสอบสถานะของปุ่มกดภายนอก (Push Buttons) เช่น จำนวน 3 ปุ่ม ซึ่งทำงานแบบ Active-Low และรับอินพุตที่ขา P0, P1, P2 ตามลำดับของไอซี PCF8474

import time
import busio
from board import *
from adafruit_bus_device.i2c_device import I2CDevice

PCF8574_ADDR = 0x20
i2c = busio.I2C(SCL, SDA, frequency=100000) 
dev = I2CDevice(i2c, PCF8574_ADDR)

STATES = ['LOW','HIGH']
try:
    buf = bytearray(1)
    t = int(1000*time.monotonic()) # time in msec
    last_value = 0xff
    while True: # press Ctrl+C to stop
        now = int(1000*time.monotonic()) # time in msec
        if now - t < 50:
            continue
        # update every 50 msec
        t = now
        buf[0] = 0xff # must be 1's for input checking
        with dev:
            dev.readinto(buf)
        value  = buf[0]
        change = value ^ last_value
        if change != 0: # state change detected
            if change & 1 != 0: # SW1 
                print('SW1:', STATES[value & 1])
            if change & 2 != 0: # SW2
                print('SW2:', STATES[value>>1 & 1])
            if change & 4 != 0: # SW3
                print('SW3:', STATES[value>>2 & 1])
        last_value = value
except KeyboardInterrupt:
    pass
i2c.deinit()
print('Done')

เผยแพร่ภายใต้ลิขสิทธิ์ Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)

Last updated