Pythonでビット演算子のビットシフトに触れるまでの記事でビット演算に触れてきた。

一通り触れたことで、SPI通信についてを見る準備が出来た。


SPI通信を見る前に、擬似的なUARTのやりとりをビット演算で振り返ってみる。


rpi2bit


uart_serial_basic_structure2


UARTは上記のようなビット列で、送受信を開始していない時は 1 になっていて、送信を開始した時に スタートビットとして 0 、その後に8ビットの値が続き、必要であればパリティビット、最後にストップビットの 1 になっている。

UARTについてを知る2


最初に擬似的にスタートビット + 8ビットで値が 0 のビット列 + パリティビット(奇パリティ) + ストップビットをPythonで再現してみる。

b = 1
print(bin(b))
b <<= 1 	# スタートビット
print(bin(b))

cnt = 0	# 奇数を集計する
for i in range(8):
	b <<= 1
	print(bin(b))

# パリティビット
b <<= 1
if cnt % 2 == 1:
	parityBit = 1
else:
	parityBit = 0

b |= parityBit
print(bin(b))

# ストップビット
b <<= 1
b |= 0x1
print(bin(b))

上記のコードを実行してみると、

0b1
0b10
0b100
0b1000
0b10000
0b100000
0b1000000
0b10000000
0b100000000
0b1000000000
0b10000000000
0b100000000001

になった。

最後の行の太文字の 0 の列が、UARTで送信する8ビットの箇所になる。




今回は一つのマシンでの擬似的なUARTになるので、送受信の箇所をランダムにしてみる。

import random

b = 1
print(bin(b))
b <<= 1 	# スタートビット
print(bin(b))

cnt = 0	# 奇数を集計する
for i in range(8):
	b <<= 1
	if random.randint(0,1) % 2 == 0:
		b |= 0x1
		cnt += 1
	print(bin(b))

# パリティビット
b <<= 1
if cnt % 2 == 1:
	parityBit = 1
else:
	parityBit = 0

b |= parityBit
print(bin(b))

# ストップビット
b <<= 1
b |= 0x1
print(bin(b))

上記のコードを実行してみると、

0b1
0b10
0b100
0b1000
0b10000
0b100001
0b1000010
0b10000101
0b100001011
0b1000010110
0b10000101101
0b100001011011

になった。

8ビットの箇所の 1 の個数が奇数なので、パリティ・ビットも効いている。


if random.randint(0,1) % 2 == 0:

実際のコードでは上記の箇所はGPIOでHIGH(1)かLOW(0)の判定になる。

ビット演算をイメージできるようになることで、SPI通信のコードも読めるようになってくる。