# Serielle 8-Bit-Ausgabe MSB-first per PIO
# Raspberry Pi Pico (RP2040), MicroPython
#
# GP15 = Datenausgang
# GP14 = Takt CP (steigende Flanke übernimmt das Bit)
# Clockpuls high: 0,01 µs (10 ns)
import rp2
from machine import Pin
import utime
from time import sleep
import time
from sys import exit
# --- PIO-Programm -----------------------------------------------
# out_shiftdir=SHIFT_LEFT -> Bit 31 wird zuerst ausgegeben (MSB first)
# out_init -> GP15 (out_base) als Ausgang, Startpegel low
# sideset_init -> GP14 (sideset_base) als Ausgang, Startpegel low
@rp2.asm_pio(out_init=rp2.PIO.OUT_LOW,
sideset_init=rp2.PIO.OUT_LOW,
out_shiftdir=rp2.PIO.SHIFT_LEFT)
def shift_out():
wrap_target()
pull() .side(0) # Byte-Wort aus FIFO holen, CP low
set(x, 7) .side(0) # Bitzähler: 8 Bits
label("bitloop")
out(pins, 1) .side(0) # MSB auf GP15 ausgeben, CP noch low
nop() .side(1) # steigende Flanke: CP high (10 ns)
jmp(x_dec, "bitloop") .side(0) # CP low, nächstes Bit
wrap()
# --- State-Machine einrichten -----------------------------------
sm = rp2.StateMachine(0, shift_out,
freq=800_000, # 1 PIO-Zyklus = exakt 10 ns
out_base=Pin(15), # Datenausgang = GP15
sideset_base=Pin(14)) # Takt CP = GP14
sm.active(1)
# --- Funktion: ein Byte ausgeben --------------------------------
def ByteOut(value):
"""8-Bit-Integer MSB-first auf GP15 ausgeben, Takt auf GP14."""
sm.put(value << 24) # Byte ins oberste Byte -> MSB first
# Digits
D0 = (1<<0)
D1 = (1<<1)
D2 = (1<<2)
D3 = (1<<3)
D4 = (1<<4)
D5 = (1<<5)
D6 = (1<<6)
D7 = (1<<7)
#pgfedcba
LED_C = 0b11000110
LED_0 = 0b11000000
LED_1 = 0b11111001
LED_2 = 0b10100100
LED_3 = 0b10110000
LED_4 = 0b10011001
LED_5 = 0b10010010
LED_6 = 0b10000010
LED_7 = 0b11111000
LED_8 = 0b10000000
LED_9 = 0b10010000
Digits = [LED_0, LED_1, LED_2, LED_3, LED_4, LED_5, LED_6, LED_7, LED_8, LED_9]
def WordOut(digit, bytevalue):
ByteOut(bytevalue)
ByteOut(digit)
ShowTime = 1000 #us time to show Digits
def MySleep():
global Showtime
utime.sleep_us(ShowTime)
# --- Test --------------------------------------------------------
if __name__ == "__main__":
# shift_out_byte(0b10101010) # 0xAA
# shift_out_byte(0x3C) # 0b00111100
# Beliebiges Muster auf dem Oszilloskop sichtbar machen:
while True:
hour = int(time.localtime()[3])
hour_l = hour % 10
hour_f = int (hour/10)
minute = int(time.localtime()[4])
minute_l = minute % 10
minute_f = int (minute/10)
seconds = int(time.localtime()[5])
seconds_l = seconds % 10
seconds_f = int (seconds/10)
print("hh:mm:ss= ", hour_f, hour_l, minute_f, minute_l, seconds_f, seconds_l)
WordOut(D0, Digits[hour_f])
MySleep()
WordOut(D1, Digits[hour_l])
MySleep()
WordOut(D2, Digits[minute_f])
MySleep()
WordOut(D3, Digits[minute_l])
MySleep()
WordOut(D4, Digits[seconds_f])
MySleep()
WordOut(D5, Digits[seconds_l])
MySleep()
#WordOut(D7, LED_C)
#MySleep()
'''
Zusammenfassung der Funktionsteile:
Teil
Aufgabe
'@rp2.asm_pio(...)
Definiert das PIO-Programm; out_init/sideset_init setzen GP15/GP14 als Ausgänge auf low
pull()
Holt das Byte aus dem TX-FIFO
set(x, 7)
Zählt die 8 Bits mit (7 → 0)
out(pins, 1)
Legt das MSB an GP15 an
nop().side(1)
CP high für genau einen Taktzyklus = 10 ns (bei 100 MHz)
jmp(...).side(0)
Fallende Flanke + nächstes Bit
sm.put(value << 24)
Byte nach oben geschoben, damit mit Shift-Left das MSB zuerst kommt
Die Endlosschleife am Ende dient nur zum Testen –
am Oszilloskop sieht man dann den wiederholten Datenstrom mit 0xA5.
Für den realen Einsatz kannst du sie streichen und shift_out_byte()
einfach aus deinem Programm aufrufen.
'''