Since it is assumed that you have experience in electronic circuits and know the words GPIO and I2C, we will omit the terminology in that area.
A device that can control GPIO via serial communication Numato Labs' USB GPIO (digital input / output) board can be purchased from Elefine mail order in Japan. https://www.elefine.jp/SHOP/USBGPIO8.html It also comes with an AD converter, which is convenient for various unit experiments.
http://www.picfun.com/f1/f06.html This explanation is very easy to understand.
Control serial communication with python, control USBGPIO8, write 1 byte to EEPROM, and then check that it is read and written. The EEPROM uses 24LC64. 24LC64 is this product → http://akizukidenshi.com/catalog/g/gI-00194/
Let SDA be port 0 of USBGPIO8. Let SCL be port 1 of USBGPIO8. Pull up with 10kΩ each. It is connected on the breadboard with the above configuration.
You can download the manual from the Elefine website or officially, so please refer to that for details. It is recommended to perform control experiments from serial terminal software such as Teraterm instead of program control from the beginning.
gpio [command] [arg]\r
The format is, arg may or may not be present, be careful not to forget the trailing \ r. When you send a write command
[Command sent]\n\r>
#For example gpio set 0\n\r>
Will be returned with a prompt. Also, when you send a read command
[Command sent]\n\r[Return value]\n\r>
#For example gpio read 0\n\r1\n\r>
# \n\1 sandwiched between r is the return value
And returns with a return value and prompt.
Use the clear command to set port 0 to LOW
SerialInstance = serial.Serial("COM4", 115200, timeout=0.01)
SerialInstance.write("gpio clear 0\r".encode())
Use the set command to set port 0 to HIGH
SerialInstance = serial.Serial("COM4", 115200, timeout=0.01)
SerialInstance.write("gpio set 0\r".encode())
command
Set the timeout as timeout = 0.01, otherwise it will not return a response for the rest of your life, so it is better to set it.
To read the LOW-HIGH status of port 0
SerialInstance = serial.Serial("COM4", 115200, timeout=0.01)
SerialInstance.write("gpio read 0\r".encode())
will do
gpio read 0\n\r0\n\r>
If the response is returned, the GPIO status is 0 (LOW).
0=LOW 1=HIGH 2 = read clock Is defined as. Create an array according to the definition and control SCL and SDA according to the array.
Example When writing 1 byte EEPROM device address 0x50 Write address 0xa0 Write data 0x33 Under this condition, create the following array
[
1, 0, 1, 0, 0, 0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 0, 2,
1, 0, 1, 0, 0, 0, 0, 0, 2,
0, 0, 1, 1, 0, 0, 1, 1, 2
]
Explain each line [1, 0, 1, 0, 0, 0, 0, 0, 2] The first 7 bits represent the address of 0x50, the 8th bit is the write flag, and the 9th bit is the read of ACK. [0, 0, 0, 0, 0, 0, 0, 0, 2] The first 8 bits are the upper byte of the write address, and the 9th bit is the read of ACK. [1, 0, 1, 0, 0, 0, 0, 0, 2] The first 8 bits are the lower bytes of the write address, and the 9th bit is the read of ACK. [0, 0, 1, 1, 0, 0, 1, 1, 2] The first 8 bits are 1-byte data to be written, and the 9th bit is ACK read.
When reading 1 byte next
[
1, 0, 1, 0, 0, 0, 0, 1, 0,
2, 2, 2, 2, 2, 2, 2, 2, 1
]
Explain each line [1, 0, 1, 0, 0, 0, 0, 0, 0] Represents the address of the first 7 bits 0x50, the 8th bit is the read flag, and the 9th bit is the transmission of ACK. [2, 2, 2, 2, 2, 2, 2, 2, 1] The first 8 bits are read, and the 9th bit is NOACK transmission (notification of read completion).
The SDA pattern is arranged as described above, and the clock and data are transmitted / received according to the arrangement.
# i2c_byte_write_and_read.py
import serial
import sys
import time
import threading
SerialInstance = None
def SerialInit(comString):
global SerialInstance
SerialInstance = serial.Serial(comString, 115200, timeout=0.01)
#SerialInstance = serial.Serial(comString, 19200, timeout=0.1)
def SerialEnd():
SerialInstance.close()
def SerialTalk(cmd, response=False):
readLen = len(cmd) + 1 # gpio read 0\n\r #From the beginning\Because it has r+Not 2+1 do
if response == True:
readLen += 3 # N\n\r
readLen += 1 # >
cnt = SerialInstance.write(cmd.encode())
res = SerialInstance.read(readLen)
res = res.decode("utf-8").strip()
return res
#Accurately read the number of characters returned, and if there is an excess or deficiency of even one character, the response waiting state will continue.
def gpioHigh(n):
SerialTalk("gpio set {}\r".format(n))
def gpioLow(n):
SerialTalk("gpio clear {}\r".format(n))
def gpioRead(n):
res = SerialTalk("gpio read {}\r".format(n), response=True)
return res
def ByteToLH(b):
lh = []
for i in range(8):
if (b << i & 128) == 0:
lh.append(0)
else:
lh.append(1)
return lh
def SDA_LOW():
gpioLow(0)
def SDA_HIGH():
gpioHigh(0)
def SCL_LOW():
gpioLow(1)
def SCL_HIGH():
gpioHigh(1)
def READ_DATA():
return gpioRead(0)
def parseData(all):
res = []
for l in all:
a = l.split("\n\r")
res.append(a[1])
return res
# 0 = LOW
# 1 = HIGH
# 2 = READ
#Start condition:Set SDA LOW while SCL is HIGH
#Stop condition:Set SCL to HIGH and then SDA to HIGH
def WriteProc():
ctrlByte = ByteToLH(constDeviceAddress << 1)
addrHigh = ByteToLH((constDataAdress >> 8) & 0xff)
addrLow = ByteToLH(constDataAdress & 0xff)
write1Byte = ByteToLH(constData)
cmdWrite = ctrlByte + [2] + addrHigh + [2] + addrLow + [2] + write1Byte + [2]
# START CONDITION
SCL_HIGH()
SDA_LOW()
size = len(cmdWrite)
data = []
for i in range(size):
SCL_LOW()
d = cmdWrite[i]
if d == 0:
SDA_LOW()
elif d == 1:
SDA_HIGH()
SCL_HIGH()
if d == 2:
response = READ_DATA()
data.append(response)
SCL_LOW() #Return to LOW
SDA_LOW() #Return to LOW
# STOP CONDITION
SDA_LOW()
SCL_HIGH()
SDA_HIGH()
#Waiting for writing, 5ms by specification, but wait for a long time
time.sleep(0.1)
print(parseData(data))
print("write end")
def ReadProc():
#
#
# set address
ctrlByte = ByteToLH(constDeviceAddress << 1)
addrHigh = ByteToLH((constDataAdress >> 8) & 0xff)
addrLow = ByteToLH(constDataAdress & 0xff)
cmdSetAddress = ctrlByte + [2] + addrHigh + [2] + addrLow + [2]
# START CONDITION
SCL_HIGH()
SDA_LOW()
size = len(cmdSetAddress)
data = []
for i in range(size):
SCL_LOW()
#print(i)
d = cmdSetAddress[i]
if d == 0:
SDA_LOW()
elif d == 1:
SDA_HIGH()
SCL_HIGH()
if d == 2:
response = READ_DATA()
data.append(response)
SCL_LOW() #Return to LOW
SDA_LOW() #Return to LOW
# STOP CONDITION
SCL_HIGH()
SDA_HIGH()
print(parseData(data))
#
#
# read data
ctrlByte = ByteToLH((constDeviceAddress << 1) | 0x01)
readByte = [2] * 8
cmdReadByte = ctrlByte + [0] + readByte + [1]
# START CONDITION
SCL_HIGH()
SDA_LOW()
size = len(cmdReadByte)
data = []
for i in range(size):
SCL_LOW()
#print(i)
d = cmdReadByte[i]
if d == 0:
SDA_LOW()
elif d == 1:
SDA_HIGH()
SCL_HIGH()
if d == 2:
response = READ_DATA()
data.append(response)
SCL_LOW() #Return to LOW
SDA_LOW() #Return to LOW
# STOP CONDITION
SCL_HIGH()
SDA_HIGH()
print(parseData(data))
print("read end")
# defines
constDeviceAddress = 0x50 #Follow the IC settings
constDataAdress = 0x0a88 #Determine appropriately within the address range of the IC, this time up to 2 bytes (0)-Code assumed to be 65535), code correction is required for 3-byte address
constData = 0x44 # 0-Determine appropriately within the range of 255
def run(comString):
SerialInit(comString)
WriteProc()
ReadProc()
SerialEnd()
if __name__ == "__main__":
run(sys.argv[1])
# python i2c_byte_write_and_read.py COM4
For Linux
python i2c_byte_write_and_read.py /dev/ttyUSB0
For Windows
python i2c_byte_write_and_read.py COM4
['0', '0', '0', '0'] #Control byte ACK, address upper byte ACK, address lower byte ACK, write data ACK
write end
['0', '0', '0'] #Control byte ACK, address upper byte ACK, address lower byte ACK
['0', '0', '1', '1', '0', '0', '1', '1'] #Read 8-bit state
read end
Recommended Posts